Return-Path: Delivered-To: apmail-incubator-jspwiki-commits-archive@minotaur.apache.org Received: (qmail 32154 invoked from network); 30 Aug 2009 08:34:47 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 30 Aug 2009 08:34:47 -0000 Received: (qmail 90424 invoked by uid 500); 30 Aug 2009 08:34:46 -0000 Delivered-To: apmail-incubator-jspwiki-commits-archive@incubator.apache.org Received: (qmail 90407 invoked by uid 500); 30 Aug 2009 08:34:46 -0000 Mailing-List: contact jspwiki-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: jspwiki-dev@incubator.apache.org Delivered-To: mailing list jspwiki-commits@incubator.apache.org Received: (qmail 90398 invoked by uid 99); 30 Aug 2009 08:34:46 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 30 Aug 2009 08:34:46 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED,OBSCURED_EMAIL X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 30 Aug 2009 08:34:37 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 65B632388871; Sun, 30 Aug 2009 08:34:15 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r809270 [1/2] - in /incubator/jspwiki/trunk: ChangeLog src/WebContent/scripts/jspwiki-common.js src/WebContent/templates/default/jspwiki.css src/java/org/apache/wiki/Release.java Date: Sun, 30 Aug 2009 08:34:15 -0000 To: jspwiki-commits@incubator.apache.org From: brushed@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090830083415.65B632388871@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: brushed Date: Sun Aug 30 08:34:14 2009 New Revision: 809270 URL: http://svn.apache.org/viewvc?rev=809270&view=rev Log: v3.0.0-svn-149: * JSPWIKI-577: Fixed the 'jumping' behavior of clicking this wide tabs. * Open/Close of collapsible boxes is now only possible by clicking the +/- icon. * Implemented the standard css overflow treatment of the 'diff' body. Modified: incubator/jspwiki/trunk/ChangeLog incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-common.js incubator/jspwiki/trunk/src/WebContent/templates/default/jspwiki.css incubator/jspwiki/trunk/src/java/org/apache/wiki/Release.java Modified: incubator/jspwiki/trunk/ChangeLog URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/ChangeLog?rev=809270&r1=809269&r2=809270&view=diff ============================================================================== --- incubator/jspwiki/trunk/ChangeLog (original) +++ incubator/jspwiki/trunk/ChangeLog Sun Aug 30 08:34:14 2009 @@ -1,3 +1,21 @@ +2009-08-30 Dirk Frederickx + + * 3.0.0-svn-149 - align with 2.8.3-svn-16 + + * JSPWIKI-577: tabbed sections with many tabs with long names will float the + tabs to a next line. Fixed the 'jumping' behavior of clicking this wide tabs, + which was caused by a superfluous bottom-border css style. + + * Open/Close of collapsible boxes is now only possible by clicking the +/- icon. + Any clicks on the header-bar will not change the status of the + collapsible box anymore. E.G. in the Info tab, when looking at page + differences between 2 versions, you can now click the version drop-downs + without changing the status of the collapsible box. + + * Implemented the standard css overflow treatment of the 'diff' body. Horizontal + scroll-bars will only be shown when looking at wide content. + This is the same overflow treatment as the page content. + 2009-08-25 Dirk Frederickx * 3.0.0-svn-148 Modified: incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-common.js URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-common.js?rev=809270&r1=809269&r2=809270&view=diff ============================================================================== --- incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-common.js (original) +++ incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-common.js Sun Aug 30 08:34:14 2009 @@ -1,4 +1,4 @@ -/*! +/*! JSPWiki - a JSP-based WikiWiki clone. Licensed to the Apache Software Foundation (ASF) under one @@ -16,7 +16,7 @@ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations - under the License. + under the License. */ /* @@ -35,10 +35,10 @@ * Effects(ex. Scroll), Drag(Base), Remote, Plugins(Hash.Cookie, Tips, Accordion) Core JS Routines: - * [Wiki] object (page parms, UserPrefs and setting focus) + * [Wiki] object (page parms, UserPrefs and setting focus) * [WikiSlimbox] * [SearchBox]: remember 10 most recent search topics - * [HighlightWords] + * [HighlightWords] Core Wiki plugins, implementing JSPWiki Dynamic Styles: * Wiki.registerPlugin( ) @@ -47,7 +47,7 @@ * [WikiSlimbox] (attachment viewer) * [TabbedSection] including all accordion variants * [Colors], [GraphBar] - * [Collapsible] list and box + * [Collapsible] list and box * [TableAdds] with %%sortable, %%tablefilter (excel like column filters) and %%zebra-table * [Popup] DOM based popup, replacing alert(), prompt(), confirm() @@ -69,7 +69,7 @@ /* Function: deCamelize Convert camelCase string to space-separated set of words. - + Example: > "CamelCase".deCamelize(); /returns "Camel Case" */ @@ -78,9 +78,9 @@ }, /* - Function: trunc + Function: trunc Truncate a string to a maximum length - + Arguments: size - maximum length of the string elips - (optional) the elips indicates when the string was truncacted (defaults to '...') @@ -90,7 +90,7 @@ */ trunc: function(size, elips){ - return (this.length var myString = "Hello, World."; - > myString.stripScripts(); //Returns "Hello, World." + > myString.stripScripts(); //Returns "Hello, World." */ stripScripts: function(){ return this.replace(/]*>([\s\S]*?)<\/script>/gi, ''); @@ -144,7 +144,7 @@ Resulting HTML >
>
- >
+ > */ wraps: function(el){ while( el.firstChild ) this.appendChild( el.firstChild ); @@ -179,7 +179,7 @@ (element) - This Element Examples: - > $('thisElement').hide(); + > $('thisElement').hide(); */ hide: function() { return this.setStyle('display','none'); @@ -193,7 +193,7 @@ (element) - This Element Examples: - > $('thisElement').show(); + > $('thisElement').show(); */ show: function() { return this.setStyle('display',''); @@ -207,12 +207,12 @@ (element) - This Element Examples: - > $('thisElement').toggle(); + > $('thisElement').toggle(); */ toggle: function() { - return this.visible() ? this.hide() : this.show(); + return this.visible() ? this.hide() : this.show(); }, - + /* Function: addHover Shortcut function to add 'hover' css class to an element. @@ -225,7 +225,7 @@ (element) - This Element Examples: - > $('thisElement').addHover(); + > $('thisElement').addHover(); */ addHover: function(clazz){ if(!clazz) clazz = 'hover'; @@ -234,7 +234,7 @@ 'mouseleave': function(){ this.removeClass(clazz) } }); }, - + /* Function: getDefaultValue Returns the default value of a form element. @@ -244,7 +244,7 @@ (element) - This Element Examples: - > $('thisElement').getDefaultValue(); + > $('thisElement').getDefaultValue(); */ getDefaultValue: function(){ switch(this.getTag()){ @@ -265,8 +265,8 @@ Returns the real offsets of the element. Arguments: - overflown - optional, an array of nested scrolling containers for - scroll offset calculation, use this if your element is inside + overflown - optional, an array of nested scrolling containers for + scroll offset calculation, use this if your element is inside any element containing scrollbars Example: @@ -300,7 +300,7 @@ /* Class: Observer Class to observe a dom element for changes. - + Example: > $(formInput).observe(function(){ > alert('my value changed to '+this.getValue() ); @@ -349,16 +349,16 @@ }); -/* -Global: LocalizedString +/* +Global: LocalizedString The __LocalizedStrings__ object is the store of all {{name:value}} pairs - with the localisation values. + with the localisation values. The name of each entry starts with the prefix {{javascript}}. The value of each entry may contain parameters like this: {{ {0},{1},... }} - + Examples: (start code) - LocalizedStrings = { + LocalizedStrings = { "javascript.some.resource.key":"localised resource key {0}" , "javascript.moreInfo":"More", "javascript.imageInfo":"Image {0} of {1}" @@ -380,12 +380,12 @@ */ String.extend({ localize: function(){ - var s = LocalizedStrings["javascript."+this], + var s = LocalizedStrings["javascript."+this], args = arguments; if(!s) return("???" + this + "???"); - return s.replace(/\{(\d)\}/g, function(m){ + return s.replace(/\{(\d)\}/g, function(m){ return args[m.charAt(1)] || "???"+m.charAt(1)+"???"; }); } @@ -401,27 +401,27 @@ /* Function: initialize Initialize main Wiki properties. - + It reads all the "meta" dom elements, prefixed with "wiki", - such as + such as * wikiContext : jspwiki requestcontext variable (view, edit, info, ...) - * wikiBaseUrl + * wikiBaseUrl * wikiPageUrl: page url template with dummy pagename "%23%24%25" * wikiEditUrl : edit page url * wikiJsonUrl : JSON-RPC url * wikiPageName : pagename without blanks - * wikiUserName + * wikiUserName * wikiTemplateUrl : path of the jsp template * wikiApplicationName It parses the {{JSPWikiUserPrefs}} cookie. - + All registered js plugins are invoked for both the main page and the favorites block. - - When the 'referrer' url (previous page) contains a "section=" parameter, + + When the 'referrer' url (previous page) contains a "section=" parameter, the wiki page will be scrolled to the right section. - + */ initialize: function(){ @@ -436,19 +436,19 @@ if( n.indexOf('wiki') == 0 ) this[n.substr(4)] = el.getProperty('content'); }, self); - self.BasePath = (self.BaseUrl) ? + self.BasePath = (self.BaseUrl) ? self.BaseUrl.slice(self.BaseUrl.indexOf(host)+host.length,-1) : ''; // if JSPWiki is installed in the root, then we have to make sure that - // the cookie-cutter works properly here. + // the cookie-cutter works properly here. if(self.BasePath == '') self.BasePath = '/'; - + self.prefs = new Hash.Cookie('JSPWikiUserPrefs', {path:Wiki.BasePath, duration:20}); - + self.allowEdit = !!$E('a.edit'); //deduct permission level self.url = null; self.parseHash.periodical(500); - + /* reusable dialog object for alert, prompt, confirm */ //FIXME: lazy creation ??? self.dialog = new Dialog({ @@ -463,7 +463,7 @@ self.renderPage( $('page'), Wiki.PageName); self.renderPage( $('favorites'), "Favorites"); - + //self.addCollapsableFavs(); self.splitbar(); @@ -484,22 +484,22 @@ /* Function: getSections - Returns the list of all section headers, excluding the header of the + Returns the list of all section headers, excluding the header of the Table Of Contents. */ getSections: function(){ - return $$('#pagecontent *[id^=section]').filter( + return $$('#pagecontent *[id^=section]').filter( function(item){ return(item.id != 'section-TOC') } ); }, - /* + /* Function: alert Show the alert popup. Any html fragment can be displayed. Arguments: msg - html text fragment - + Example: > Wiki.alert( "alert message"); */ @@ -515,7 +515,7 @@ /* Function: confirm Replaces the standard confirm dialog, supporting any html fragment. - If the user clicks "OK", the box returns true. + If the user clicks "OK", the box returns true. If the user clicks "Cancel", the box returns false. The return value (true/false) is handled via the callback function. @@ -527,16 +527,16 @@ this.dialog .setBody( new Element('p').setHTML(msg) ) - .setButtons({ + .setButtons({ Ok:function(){ callback(true); }, Cancel:function(){ callback(false); } }) .show(); }, - /* + /* Function: prompt - Show the prompt prompt, with standard 'Ok' and 'Cancel' buttons. + Show the prompt prompt, with standard 'Ok' and 'Cancel' buttons. Replaces the standard prompt handling, supporting any html fragment. The return value is handled via the callback function. @@ -546,22 +546,22 @@ callback - (function) invoke when pressing the Ok button Example: - > Wiki.prompt("sometext","defaultvalue", callback-function(result) ); + > Wiki.prompt("sometext","defaultvalue", callback-function(result) ); */ prompt: function(msg, defaultreply, callback){ //return callback( prompt( msg, defaultreply ) ); //standard js var input; - + this.dialog.setBody([ new Element('p').setHTML(msg), - new Element('form').adopt( - input = new Element('input',{ - name:'prompt', - type:'text', - value: defaultreply, - size: 24 - }) + new Element('form').adopt( + input = new Element('input',{ + name:'prompt', + type:'text', + value: defaultreply, + size: 24 + }) ) ]) .setButtons({ @@ -574,7 +574,7 @@ /* Function: registerPlugin - Register a jspwiki javascript plugin. + Register a jspwiki javascript plugin. */ registerPlugin: function(fn){ if(!this.plugins) this.plugins = []; @@ -584,9 +584,9 @@ /* Function: renderPage Invoke all registered wiki js plugins. - + Arguments: - page - dom element + page - dom element name - wiki page of the page (pagename, or 'Favorites) */ renderPage: function(page, name){ @@ -613,17 +613,17 @@ /* Property: toUrl - Turn a wiki pagename into a full wiki-url + Turn a wiki pagename into a full wiki-url */ toUrl: function(pagename){ return this.PageUrl.replace(/%23%24%25/, pagename); - }, + }, /* Property: toPageName - Parse a wiki-url and return the corresponding wiki pagename + Parse a wiki-url and return the corresponding wiki pagename */ toPageName: function(url){ @@ -636,8 +636,8 @@ /* Property: cleanPageName Remove all not-allowed chars from a *candidate* pagename. - Trim repeated whitespace, allow letters, digits and - following punctuation chars: ()&+,-=._$ + Trim repeated whitespace, allow letters, digits and + following punctuation chars: ()&+,-=._$ Ref com.ecyrd.jspwiki.parser.MarkupParser.cleanPageName() */ cleanPageName: function(p){ @@ -649,10 +649,10 @@ /* Function: makeMenuFx - Make hover menu with fade effect. + Make hover menu with fade effect. */ makeMenuFx: function(btn, menu){ - btn = $(btn); + btn = $(btn); menu = $(menu); if(!btn || !menu) return; @@ -665,7 +665,7 @@ } }); }, - + /* Function: locatemenu TODO @@ -689,8 +689,8 @@ /* Function: parseHash - TODO: periodic screening of the #hash to ensure all screen sections are displayed properly - + TODO: periodic screening of the #hash to ensure all screen sections are displayed properly + FIXME: add handling of BACK button for tabs ?? */ @@ -698,12 +698,12 @@ if(this.url && this.url == location.href ) return; this.url = location.href; - var h = location.hash; + var h = location.hash; if( !h || h=='' ) return; h = $( h.slice(1) ); while( $type( h ) == 'element' ){ - + if( h.hasClass('hidetab') ){ TabbedSection.click.apply($('menu-' + h.id)); @@ -712,7 +712,7 @@ /* accordion -- need to find accordion toggle object */ h.fireEvent('onShow'); - + } else if( h.hasClass('collapsebody') ){ /* collapsible box -- need to find the toggle button */ @@ -721,7 +721,7 @@ var bullet = h.getFirst(); if(bullet) bullet.fireEvent('click'); - + } else if( !h.visible() ){ //alert('not visible'+el.id); //fixme need to find the correct toggler @@ -732,7 +732,7 @@ location = location.href; /* now jump to the #hash */ }, - + /* Function: SubmitOnce Disable all form buttons to avoid double submits. @@ -745,7 +745,7 @@ submitOnce: function(form){ window.onbeforeunload = null; /* regular exit of this page -- see jspwiki-edit.js */ - (function(){ + (function(){ $A(form.elements).each(function(e){ if( (/submit|button/i).test(e.type)) e.disabled = true; }); @@ -758,7 +758,7 @@ Function: submitUpload Support for the upload progressbar. Attached to the attachment upload submit form. - + Returns: Returns via the submitOnce() function. */ @@ -766,10 +766,10 @@ var self = this, bar = $('progressbar').setStyle('visibility','visible'); - + self.progressbar = self.jsonrpc.periodical( - 1000, - self, + 1000, + self, ["progressTracker.getProgress",[progress],function(result){ result = result.stripScripts(); //xss vulnerability if(!result.code) bar.getFirst().setStyle('width',result+'%').setHTML(result+'%'); @@ -780,19 +780,19 @@ /* Property: splitbar - Add a toggle bar next to the main page content block, to + Add a toggle bar next to the main page content block, to show/hide the favorites block with a click of the mouse. The open/close status is saved in the Wiki.prefs cookie. When the user hovers the mouse over the toggle bar, an arrow image is shown to indicate the collapsable effect. - Note: + Note: The toggle bar has css-id 'collapseFavs'. The toggle bar gets a .hover class when the mouse hovers over it. The mouse-pointer image has css-id 'collapseFavsPointer'. The DOM body gets a .fav-slide class when the favorites are collapsed (hidden) - - + + DOM structure: (start code)
@@ -825,7 +825,7 @@ // so the body class will not be set yet. // Should better move server side, for faster rendering. wf-stripes body.addClass( Wiki.prefs.get( pref )||'' ); - + new Element('div',{ 'class':splitbar, 'events':{ @@ -839,21 +839,21 @@ } }).injectTop( $('page') ); - }, + }, addCollapsableFavs: function(){ var body = $('wikibody'), $pref = 'fav-slide', pref = Wiki.prefs.get('ToggleFav'), - tabs = $E('#page .tabs'); - + tabs = $E('#page .tabs'); + if( !tabs ) return; - - // The cookie is not saved to the server's Preferences automatically, + + // The cookie is not saved to the server's Preferences automatically, // so the body class will not be set yet. // Should better move server side, for faster rendering. wf-stripes - (pref==$pref) ? body.addClass($pref) : body.removeClass($pref); + (pref==$pref) ? body.addClass($pref) : body.removeClass($pref); /* Be careful. The .tabs block can not be made relative, cause then the .tabmenu doesn't @@ -862,20 +862,20 @@ TODO: needs probably another IE hack ;-) */ - tabs = new Element('div', { - 'styles': { - 'position':'relative', - 'padding': tabs.getStyle('padding') // take over padding from original .tabs - } - }).wraps(tabs.setStyle('padding','0')); + tabs = new Element('div', { + 'styles': { + 'position':'relative', + 'padding': tabs.getStyle('padding') // take over padding from original .tabs + } + }).wraps(tabs.setStyle('padding','0')); var pointer = new Element('div', {'id':'collapseFavsPointer'}).hide().inject(body), movePointer = function(e){ this.addClass('hover'); pointer.setStyles({ left:this.getPosition().x, top: (e.pageY || e.clientY) }).show(); }; - - new Element('div', { + + new Element('div', { 'id':'collapseFavs', 'events': { 'click': function(){ @@ -884,7 +884,7 @@ }, 'mouseenter': movePointer, 'mousemove': movePointer, - 'mouseleave': function(){ + 'mouseleave': function(){ this.removeClass('hover'); pointer.hide(); } @@ -905,13 +905,13 @@ var url = this.EditUrl; url = url + (url.contains('?') ? '&' : '?') + 'section='; - var aa = new Element('a',{'class':'editsection'}).setHTML('quick.edit'.localize()), + var aa = new Element('a',{'class':'editsection'}).setHTML('quick.edit'.localize()), i = 0; this.getSections().each( function(el){ el.adopt(aa.set({'href':url + i++ }).clone()); }); - + }, /* @@ -920,7 +920,7 @@ FIXME: to be refactored based on Stripes approach to AJAX. Arguments: - + Options: action - stripes event name params - DOM-element or js-object. Will be converted to a query-string @@ -935,22 +935,22 @@ alert('ajax - done'); } }); - (end) + (end) */ ajax: function(url, options){ - //FIXME: under contstruction - var params = options.action+'=&'+options.params.toQueryString(); + //FIXME: under contstruction + var params = options.action+'=&'+options.params.toQueryString(); new Ajax( url, { postBody: params, method: 'post', update: options.update, - onComplete: function( result ){ + onComplete: function( result ){ options.onComplete( result ); } }).request(); - + }, /* @@ -964,7 +964,7 @@ Supported rpc calls: - {{search.findPages}} gets the list of pagenames with partial match - - {{progressTracker.getProgress}} + - {{progressTracker.getProgress}} - {{search.getSuggestions}} gets the list of pagenames with partial match Example: @@ -976,7 +976,7 @@ //stripes approach Wiki.jsonrpc('Search.jsp', { action: 'findPages', - params: js-object, + params: js-object, onComplete: function(result){ ...json result object... }); @@ -990,12 +990,12 @@ new Ajax(this.JsonUrl, { postBody: Json.toString({ - 'id':this.$jsonid++, - 'method':method, + 'id':this.$jsonid++, + 'method':method, 'params':params - }), - method: 'post', - onComplete: function(result){ + }), + method: 'post', + onComplete: function(result){ var r = Json.evaluate(result,true); fn(r.result || r.error || null); /*if( r ){ @@ -1006,7 +1006,7 @@ }).request(); } - } + } } @@ -1016,7 +1016,7 @@ Plugin: WikiSlimbox Credits: - Inspired by Slimbox by Christophe Bleys. (see http://www.digitalia.be/software/slimbox) + Inspired by Slimbox by Christophe Bleys. (see http://www.digitalia.be/software/slimbox) Example: > %%slimbox [...] %% @@ -1026,13 +1026,13 @@ Wiki.registerPlugin( function(page,name){ var i = 0, lnk = new Element('a',{'class':'slimbox'}).setHTML('»'); - + $ES('*[class^=slimbox]',page).each(function(slim){ var group = 'lightbox'+ i++, parm = slim.className.split('-')[1] || 'img ajax', filter = []; - if(parm.test('img')) filter.extend(['img.inline', 'a.attachment']); - if(parm.test('ajax')) filter.extend(['a.wikipage', 'a.external']); + if(parm.test('img')) filter.extend(['img.inline', 'a.attachment']); + if(parm.test('ajax')) filter.extend(['a.wikipage', 'a.external']); $ES(filter.join(','),slim).each(function(el){ var href = el.src||el.href, @@ -1041,7 +1041,7 @@ if((rel=='img') && !href.test('(.bmp|.gif|.png|.jpg|.jpeg)(\\?.*)?$','i')) return; lnk.clone().setProperties({ - 'href':href, + 'href':href, 'rel':group+' '+rel, 'title':el.alt||el.getText() }).injectAfter(el);//.injectBefore(el); @@ -1072,7 +1072,7 @@ - spacebar, down arrow, enter : next image - up arrow : prev image - allow the same picture occuring several times - - add support for external page links => slimbox_ex + - add support for external page links => slimbox_ex */ var Lightbox = { @@ -1123,7 +1123,7 @@ //new Element('a', {'id': 'lbCloseLink', 'href': '#', 'title':'slimbox.close.title'.localize()}).setHTML('slimbox.close'.localize()).inject(this.bottom).onclick = this.overlay.onclick = this.close.bind(this); this.caption = new Element('div', {'id': 'lbCaption'}).inject(this.bottom); - var info = new Element('div').inject(this.bottom); + var info = new Element('div').inject(this.bottom); this.prevLink = new Element('a', {'id': 'lbPrevLink', 'href': '#', 'styles': {'display': 'none'}}).setHTML("slimbox.previous".localize()).inject(info); this.number = new Element('span', {'id': 'lbNumber'}).inject(info); this.nextLink = this.prevLink.clone().setProperties({'id': 'lbNextLink' }).setHTML("slimbox.next".localize()).inject(info); @@ -1132,7 +1132,7 @@ this.error = new Element('div').setProperty('id', 'lbError').setHTML(this.options.errorMessage); new Element('div', {'styles': {'clear': 'both'}}).inject(this.bottom); - + var nextEffect = this.nextEffect.bind(this); this.fx = { overlay: this.overlay.effect('opacity', {duration: 500}).hide(), @@ -1142,7 +1142,7 @@ }; this.fxs = new Fx.Elements([this.center, this.image], $extend({duration: this.options.resizeDuration, onComplete: nextEffect}, this.options.resizeTransition ? {transition: this.options.resizeTransition} : {})); - + this.preloadPrev = new Image(); this.preloadNext = new Image(); }, @@ -1191,7 +1191,7 @@ keyboardListener: function(event){ switch (event.keyCode){ case 27: case 88: case 67: this.close(); break; - case 37: case 38: case 80: this.previous(); break; + case 37: case 38: case 80: this.previous(); break; case 13: case 32: case 39: case 40: case 78: this.next(); break; default: return; } @@ -1225,19 +1225,19 @@ /**/ this.so = this.images[imageNum][0]; this.so.setProperties({ - width: '120px', - height: '120px' + width: '120px', + height: '120px' }); this.so.inject(this.image); this.nextEffect(); - } else { + } else { this.iframeId = "lbFrame_"+new Date().getTime(); // Safari would not update iframe content that has static id. this.so = new Element('iframe').setProperties({ - id: this.iframeId, -// width: this.contentsWidth, -// height: this.contentsHeight, - frameBorder:0, - scrolling:'auto', + id: this.iframeId, +// width: this.contentsWidth, +// height: this.contentsHeight, + frameBorder:0, + scrolling:'auto', src:this.images[imageNum][0] }).inject(this.image); this.nextEffect(); //asynchronous loading? @@ -1250,7 +1250,7 @@ this.image.setHTML('').adopt(this.error.clone()); this.nextEffect(); }, - + nextEffect: function(){ switch (this.step++){ case 1: @@ -1259,7 +1259,7 @@ 'href':this.images[this.activeImage][0], 'title':"slimbox.directLink".localize() }).setHTML(this.images[this.activeImage][1] || '')); - + var type = (this.images[this.activeImage][2]=='img') ? "slimbox.info" : "slimbox.remoteRequest"; this.number.setHTML((this.images.length == 1) ? '' : type.localize(this.activeImage+1, this.images.length)); this.image.style.backgroundImage = 'none'; @@ -1274,13 +1274,13 @@ this.image.style.width = this.bottom.style.width = w+'px'; this.image.style.height = /*this.prevLink.style.height = this.nextLink.style.height = */ h+'px'; - + if( this.images[this.activeImage][2]=='img') { this.image.style.backgroundImage = 'url('+this.images[this.activeImage][0]+')'; if (this.activeImage) this.preloadPrev.src = this.images[this.activeImage-1][0]; if (this.activeImage != (this.images.length - 1)) this.preloadNext.src = this.images[this.activeImage+1][0]; - + this.number.setHTML(this.number.innerHTML+'  ['+this.preload.width+'×'+this.preload.height+']'); } else { this.so.style.width=w+'px'; @@ -1292,7 +1292,7 @@ this.fxs.start({ '0': { height: [this.image.offsetHeight], width: [this.image.offsetWidth], marginLeft: [-this.image.offsetWidth/2] }, '1': { opacity: [1] } - }); + }); break; case 2: @@ -1332,15 +1332,15 @@ /* Class: TabbedSection Creates tabs, based on some css-class information - Use in jspwiki: - > %%tabbedSection - > %%tab-FirstTab .. %% + Use in jspwiki: + > %%tabbedSection + > %%tab-FirstTab .. %% > /% Alternative syntax based on header markup - > %%tabbedSection - > !# First tab title .. - > !# Second tab title .. + > %%tabbedSection + > !# First tab title .. + > !# Second tab title .. > /% @@ -1367,31 +1367,31 @@ // add click handlers to existing tabmenu's, generated by $ES('.tabmenu a',page).each(function(el){ if(!el.href) el.addEvent('click', this.click); - },this); - + },this); + // convert tabbedSections into tabmenu's with click handlers $ES('.tabbedSection',page).each( function(tt){ if(tt.hasClass('tabs')) return; tt.addClass('tabs'); //css styling on tabs - + var menu = new Element('div',{'class':'tabmenu'}).injectBefore(tt); /* var menuItems = this.getTabs(tt); for( var m in menuItems ){ new Element('a', { - //'id':'menu-'+tab.id, + //'id':'menu-'+tab.id, 'class':(i==0) ? 'activetab' : '', //fixme - 'events':{ - 'click': this.click(this,m) + 'events':{ + 'click': this.click(this,m) } - }).appendText( menuItems[m] ).inject(menu); + }).appendText( menuItems[m] ).inject(menu); } */ tt.getChildren().each(function(tab,i) { //find nested %%tab-XXX var clazz = tab.className; - if( !clazz.test('^tab-') ) return; + if( !clazz.test('^tab-') ) return; if( !tab.id || (tab.id=="") ) tab.id = clazz; //unique id @@ -1401,7 +1401,7 @@ var title = clazz.substr(4).deCamelize(); //drop 'tab-' prefix new Element('a', { - 'id':'menu-'+tab.id, + 'id':'menu-'+tab.id, 'class':(i==0) ? 'activetab' : '', 'events':{ 'click': this.click } }).appendText(title).inject(menu); @@ -1409,35 +1409,35 @@ },this); }, this); }, - - /* + + /* Function: getTabs Helper function for TabbedSection. Also used by Accordion. - It will scan the + It will scan the modifies DOM to ensure each TAB section is conform
...
return a set of menu-items : {id:'menu1-title', id:'menu2-title'} (1) %%tab-tabName :
...
(2) !# tab name:

tab name

...
- + Arguments: el - DOM content container - + Returns: {id:'menu1 title', id:'menu2 title', ...} or null */ $id: 1000, getTabs : function( tt ){ var tabs = [], titles=[]; - - var isTabClass = true, isTabHeads = true; - - + + var isTabClass = true, isTabHeads = true; + + el.getChildren().each(function(tab) { - + if( !tab.className.test('^tab-') ) return; var clazz = tab.className; - if( !clazz.test('^tab-') ) return; + if( !clazz.test('^tab-') ) return; if( !tab.id || (tab.id=="") ) tab.id = clazz; //unique id @@ -1447,7 +1447,7 @@ var title = clazz.substr(4).deCamelize(); //drop 'tab-' prefix - //FIXME use class to make tabs visible during printing + //FIXME use class to make tabs visible during printing //(i==0) ? tab.removeClass('hidetab'): tab.addClass('hidetab'); var title = tab.className.substr(4).deCamelize(), @@ -1456,11 +1456,11 @@ toggles.push(t.inject(togglemenu)); } else { toggles.push(t.adopt(bullet.clone()).injectBefore(tab)); - } + } titles.push(title); tabs.push(tab.addClass('tab')); }); - + return {'titles':titles,'tabs':tabs}; @@ -1468,7 +1468,7 @@ if(tt.hasClass('tabs')) return; el.addClass('tabs'); //css styling on tabs contents - + var tt = this.getTabs(el); var menu = new Element('div',{'class':'tabmenu'}).injectBefore(tt); var toggle = new Element('a',{'events':{ 'click': this.click }}); @@ -1480,7 +1480,7 @@ },this); -/**accordion*******/ +/**accordion*******/ var toggles=[], menu=false; @@ -1489,8 +1489,8 @@ else if(tt.hasClass('leftAccordion')){ menu = 'sidemenu left'; } else if(tt.hasClass('rightAccordion')){ menu = 'sidemenu right'; } - if(menu) menu = new (Element('div'),{'class':menu }).injectBefore(tt); - + if(menu) menu = new (Element('div'),{'class':menu }).injectBefore(tt); + var tt = this.getTabs(el); /*build togglemenu*/ tt.titles.each( function(title,i){ @@ -1498,27 +1498,27 @@ menu ? t.inject(menu) : t.adopt(bullet.clone()).injectBefore(tt.tabs[i]); toggles.push(t); }); - new Accordion(toggles, tt.tabs, { /* ... */}); - - }, + new Accordion(toggles, tt.tabs, { /* ... */}); + + }, click: function(){ var menu = $(this).getParent(), tabs = menu.getNext(); - + menu.getChildren().removeClass('activetab'); this.addClass('activetab'); - //skip possible relative wrapper element + //skip possible relative wrapper element var rel = tabs.getFirst(); if(rel.getStyle('position')=='relative') tabs = rel; tabs.getChildren().addClass('hidetab'); //fixme: id needs to be unique , should not be the TAB name - tabs.getElementById( this.id.slice(5) ).removeClass('hidetab'); + tabs.getElementById( this.id.slice(5) ).removeClass('hidetab'); } - + } Wiki.registerPlugin( TabbedSection ); //FIXME: convert to class @@ -1540,18 +1540,18 @@ onPageLoadQuickSearch : function(){ var q = $('query'); if( !q ) return; - this.query = q; - q.observe(this.ajaxQuickSearch.bind(this) ); + this.query = q; + q.observe(this.ajaxQuickSearch.bind(this) ); this.hover = $('searchboxMenu').setProperty('visibility','visible') .effect('opacity', {wait:false}).set(0); - + $(q.form).addEvent('submit',this.submit.bind(this)) //FIXME .addEvent('blur',function(){ this.hasfocus=false; this.hover.start(0) }.bind(this)) //FIXME .addEvent('focus',function(){ this.hasfocus=true; this.hover.start(0.9) }.bind(this)) .addEvent('mouseout',function(){ this.hover.start(0) }.bind(this)) .addEvent('mouseover',function(){ Wiki.locatemenu(this.query, $('searchboxMenu') ); this.hover.start(0.9) }.bind(this)); - + /* use advanced search-input on safari - experimental */ //if(window.webkit){ // q.setProperties({type:"search",autosave:q.form.action,results:"9",placeholder:q.defaultValue}); @@ -1563,9 +1563,9 @@ var ul = new Element('ul',{'id':'recentItems'}).inject($('recentSearches').show()); this.recent.each(function(el){ // xss vulnerability JSPWIKI-384 - el = el.stripScripts(); + el = el.stripScripts(); new Element('a',{ - 'href':'#', + 'href':'#', 'events': {'click':function(){ q.value = el; q.form.submit(); }} }).setHTML(el).inject( new Element('li').inject(ul) ); }); @@ -1575,18 +1575,18 @@ onPageLoadFullSearch : function(){ var q2 = $("query2"); if( !q2 ) return; this.query2 = q2; - + var changescope = function(){ var qq = this.query2.value.replace(/^(?:author:|name:|contents:|attachment:)/,''); this.query2.value = $('scope').getValue() + qq; this.runfullsearch(); }.bind(this); - + q2.observe( this.runfullsearch0.bind(this) ); - + $('scope').addEvent('change', changescope); $('details').addEvent('click', this.runfullsearch.bind(this)); - + if(location.hash){ /* hash contains query:pagination(-1=all,0,1,2...) */ var s = decodeURIComponent(location.hash.substr(1)).match(/(.*):(-?\d+)$/); @@ -1606,13 +1606,13 @@ runfullsearch: function(e){ var q2 = this.query2.value; - if( !q2 || (q2.trim()=='')) { + if( !q2 || (q2.trim()=='')) { $('searchResult2').empty(); - return; + return; } $('spin').show(); - var scope = $('scope'), + var scope = $('scope'), match= q2.match(/^(?:author:|name:|contents:|attachment:)/) ||""; $each(scope.options, function(option){ @@ -1622,21 +1622,21 @@ Wiki.ajax('Search.jsp',{ action:'ajaxSearch', params:$('searchform2'), - update: 'searchResult2', - onComplete: function() { - $('spin').hide(); + update: 'searchResult2', + onComplete: function() { + $('spin').hide(); //FIXME: stripes generates a whole web-page iso of page fragment with searchresults. var x = $E('#searchResult2',$('searchResult2')); $('searchResult2').replaceWith( x ); - GraphBar.render($('searchResult2')); - Wiki.prefs.set('PrevQuery', q2); - } + GraphBar.render($('searchResult2')); + Wiki.prefs.set('PrevQuery', q2); + } }); location.hash = '#'+q2+":"+$('start').value; /* push the query into the url history */ }, - submit: function(){ + submit: function(){ var v = this.query.value.stripScripts(); //xss vulnerability if( v == this.query.defaultValue) this.query.value = ''; if( !this.recent ) this.recent=[]; @@ -1647,7 +1647,7 @@ } }, - clear: function(){ + clear: function(){ this.recent = []; Wiki.prefs.remove('RecentSearch'); $('recentSearches','recentClear').hide(); @@ -1663,13 +1663,13 @@ $('searchSpin').show(); Wiki.jsonrpc('search.findPages', [qv,20], function(result){ - $('searchSpin').hide(); + $('searchSpin').hide(); if(!result.list) return; var frag = new Element('ul'); - + result.list.each(function(el){ - new Element('li').adopt( - new Element('a',{'href':Wiki.toUrl(el.map.page) }).setHTML(el.map.page), + new Element('li').adopt( + new Element('a',{'href':Wiki.toUrl(el.map.page) }).setHTML(el.map.page), new Element('span',{'class':'small'}).setHTML(" ("+el.map.score+")") ).inject(frag); }); @@ -1682,33 +1682,33 @@ navigate: function(url, promptText, clone, search){ var p = Wiki.PageName, defaultResult = (clone) ? p+'sbox.clone.suffix'.localize() : p, - s = this.query.value; + s = this.query.value; if(s == this.query.defaultValue) s = ''; var handleResult = function(s){ if(s == '') return; if(!search) s = Wiki.cleanPageName(s);//remove invalid chars from the pagename - + p=encodeURIComponent(p); s=encodeURIComponent(s); if(clone && (s != p)) s += '&clone=' + p; location.href = url.replace('__PAGEHERE__', s ); }; - + if(s!='') { - handleResult(s); + handleResult(s); } else { Wiki.prompt(promptText, defaultResult, handleResult.bind(this)); - } + } } } -/* +/* Class: Color - Class for creating and manipulating colors in JavaScript. - Minimal variant of the Color class, inspired by mootools + Class for creating and manipulating colors in JavaScript. + Minimal variant of the Color class, inspired by mootools   Syntax: >var myColor = new Color(color[, type]); @@ -1718,7 +1718,7 @@ # type - (string, optional) A string representing the type of the color to create. Color: - There are 2 representations of color: String, RGB. + There are 2 representations of color: String, RGB. For String representation see Element:setStyle for more information. Examples: @@ -1787,7 +1787,7 @@ white:[255,255,255], yellow:[255,255,0] }, - + initialize: function(color, type){ if(!color) return false; @@ -1827,18 +1827,18 @@ rgb = this.copy(), alpha = (($type(colors.getLast()) == 'number') ? colors.pop() : 50)/100, alphaI = 1-alpha; - + colors.each(function(color){ color = new Color(color); for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] * alphaI) + (color[i] * alpha)); }); return new Color(rgb, 'rgb'); }, - + /* Method: invert Inverts the Color. - + Syntax: > var myInvert = myColor.invert(); @@ -1890,7 +1890,7 @@ isHorizontal = true,// horizontal or vertical orientation parms = g.className.substr(9).split('-'), barName = parms.shift(); //first param is optional barName - + parms.each(function(p){ p = p.toLowerCase(); if(p == "vertical") { isHorizontal = false; } @@ -1900,7 +1900,7 @@ else if(p.indexOf("max") == 0) { ubound = p.substr(3).toInt(); } else if(p != "") { p = new Color(p,'hex'); if(!p.hex) return; - if(!color1) color1 = p; + if(!color1) color1 = p; else if(!color2) color2 = p; } }); @@ -1919,17 +1919,17 @@ border = (isHorizontal ? 'borderLeft' : 'borderBottom'); bars.each(function(b,j){ - var bar1 = $H().set(border+'Width',barData[j]), - bar2 = $H(), // 2nd bar only valid ico 'progress' + var bar1 = $H().set(border+'Width',barData[j]), + bar2 = $H(), // 2nd bar only valid ico 'progress' barEL = new Element('span',{'class':'graphBar'}), pb = b.getParent(); // parent of gBar element if(isHorizontal){ barEL.setHTML('x'); - if(isProgress){ + if(isProgress){ bar2.extend(bar1.obj); - bar1.set(border+'Width',ubound-barData[j]).set('marginLeft','-1ex'); - } + bar1.set(border+'Width',ubound-barData[j]).set('marginLeft','-1ex'); + } } else { // isVertical if(pb.getTag()=='td') { pb = new Element('div').wraps(pb); } @@ -1938,22 +1938,22 @@ if( !isProgress ) { b.setStyle('top', (ubound-barData[j])); } bar1.extend({'position':'absolute', 'width':vwidth, 'bottom':'0'}); - if(isProgress){ - bar2.extend(bar1.obj).set(border+'Width', ubound); + if(isProgress){ + bar2.extend(bar1.obj).set(border+'Width', ubound); } } if(isProgress){ if(color1){ bar1.set('borderColor', color1.hex); } - if(color2){ - bar2.set('borderColor', color2.hex); - } else { + if(color2){ + bar2.set('borderColor', color2.hex); + } else { bar1.set('borderColor', 'transparent'); } } else if(color1){ var percent = isGauge ? (barData[j]-lbound)/size : j/(bars.length-1); bar1.set('borderColor', color1.mix(color2, 100 * percent).hex); } - + if(bar2.length > 0){ barEL.clone().setStyles(bar2.obj).injectBefore(b); }; if(bar1.length > 0){ barEL.setStyles(bar1.obj).injectBefore(b); }; @@ -1967,12 +1967,12 @@ Parse bar data types and scale according to lbound and size */ parseBarData: function(nodes, lbound, size){ - var barData=[], - maxValue=Number.MIN_VALUE, + var barData=[], + maxValue=Number.MIN_VALUE, minValue=Number.MAX_VALUE, num=true, ddd=num; - + nodes.each(function(n,i){ var v = n.getText(); barData.push(v); @@ -1982,11 +1982,11 @@ barData = barData.map(function(b){ if( ddd ){ b = new Date(Date.parse(b) ).valueOf(); } else if( num ){ b = b.match(/([+-]?\d+(:?\.\d+)?(:?e[-+]?\d+)?)/)[0].toFloat(); } - + maxValue = Math.max(maxValue, b); minValue = Math.min(minValue, b); return b; - }); + }); if(maxValue==minValue) maxValue=minValue+1; /* avoid div by 0 */ size = size/(maxValue-minValue); @@ -1995,7 +1995,7 @@ }); }, - /* + /* Function: getTableValues Fetch set of gBar values from a table * check first-row to match field-name: return array with col values @@ -2049,27 +2049,27 @@ //var cookie = ""; //activate this line if you want to deactivatie cookie handling if(!this.bullet) { - this.bullet = new Element('div',{'class':'collapseBullet'}).setHTML('•'); + this.bullet = new Element('div',{'class':'collapseBullet'}).setHTML('•'); } this.pims.push({ 'name':cookie, 'value':'', - 'initial': (cookie ? Cookie.get(cookie) : "") + 'initial': (cookie ? Cookie.get(cookie) : "") }); - $ES('.collapse', page).each(function(el){ + $ES('.collapse', page).each(function(el){ if(!$E('.collapseBullet',el)) this.collapseNode(el); // no nesting }, this); - $ES('.collapsebox,.collapsebox-closed', page).each(function(el){ - this.collapseBox(el); + $ES('.collapsebox,.collapsebox-closed', page).each(function(el){ + this.collapseBox(el); }, this); }, collapseBox: function(el){ if($E('.collapsetitle',el)) return; //been here before var title = el.getFirst(); if( !title ) return; - - var body = new Element('div', {'class':'collapsebody'}), + + var body = new Element('div', {'class':'collapsebody'}), bullet = this.bullet.clone(), isclosed = el.hasClass('collapsebox-closed'); @@ -2083,15 +2083,15 @@ /* Function: collapseNode - Modifies the list such that sublists can be hidden/shown by clicking - the listitem bullet. The listitem bullet is a node inserted into the + Modifies the list such that sublists can be hidden/shown by clicking + the listitem bullet. The listitem bullet is a node inserted into the DOM tree as the first child of the listitem contained by the sublist. */ collapseNode: function(node){ $ES('li',node).each(function(li){ var ulol = $E('ul',li) || $E('ol',li); - - //dont insert bullet when LI is 'empty': no text or no non-ul/ol tags + + //dont insert bullet when LI is 'empty': no text or no non-ul/ol tags var emptyLI = true; for( var n = li.firstChild; n ; n = n.nextSibling ) { if((n.nodeType == 3 ) && ( n.nodeValue.trim() == "" ) ) continue; //keep searching @@ -2100,7 +2100,7 @@ break; } if( emptyLI ) return; - + new Element('div',{'class':'collapsebody'}).wraps(li); var bullet = this.bullet.clone().injectTop(li); if(ulol) this.newBullet(bullet, ulol, (ulol.getTag()=='ul')); @@ -2113,18 +2113,18 @@ if(!clicktarget) clicktarget = bullet; var bodyfx = body.setStyle('overflow','hidden') - .effect('height', { + .effect('height', { wait:false, onStart:this.renderBullet.bind(bullet), - onComplete:function(){ if(bullet.hasClass('collapseOpen')) body.setStyle('height','auto'); } + onComplete:function(){ if(bullet.hasClass('collapseOpen')) body.setStyle('height','auto'); } }); bullet.className = (isopen ? 'collapseClose' : 'collapseOpen'); //ready for rendering - clicktarget.addEvent('click', this.clickBullet.bind(bullet, [ck, ck.value.length-1, bodyfx])) + clicktarget.addEvent('click', this.clickBullet.bindWithEvent(bullet, [ck, ck.value.length-1, bodyfx])) .addHover(); - + bodyfx.fireEvent('onStart'); - if(!isopen) bodyfx.set(0); + if(!isopen) bodyfx.set(0); }, renderBullet: function(){ @@ -2135,19 +2135,23 @@ } }, - clickBullet: function( ck, bulletidx, bodyfx){ + clickBullet: function(event, ck, bulletidx, bodyfx){ var collapse = this.hasClass('collapseOpen'), - bodyHeight = bodyfx.element.scrollHeight; + bodyHeight = bodyfx.element.scrollHeight; + + if(event.target==this){ /* don't handle clicks on nested elements */ - if(collapse) bodyfx.start(bodyHeight, 0); else bodyfx.start(bodyHeight); - - ck.value = ck.value.substring(0,bulletidx) + (collapse ? 'c' : 'o') + ck.value.substring(bulletidx+1) ; - if(ck.name) Cookie.set(ck.name, ck.value, {path:Wiki.BasePath, duration:20}); + if(collapse) bodyfx.start(bodyHeight, 0); else bodyfx.start(bodyHeight); + + ck.value = ck.value.slice(0,bulletidx) + (collapse ? 'c' : 'o') + ck.value.slice(bulletidx+1); + if(ck.name) Cookie.set(ck.name, ck.value, {path:Wiki.BasePath, duration:20}); + + } }, /* Function: parseCookie - Parse the initial cookie versus actual document + Parse the initial cookie versus actual document Returns: true if collapse status is open */ @@ -2177,11 +2181,11 @@ Plugin: commentbox This wiki-plugin supports the commentbox dynamic style. -Example: +Example: > %%commentbox ... /% : floating box to the right > %%commentbox-LegendTitle .... /% : make it a legend box -DOM structure +DOM structure >
...
>
> LegendTitle @@ -2194,7 +2198,7 @@ $ES('*[class^=commentbox]',page).each(function(el){ var legend = el.className.split('-')[1]; if( legend ){ - new Element('fieldset',{'class':'commentbox'}).adopt( + new Element('fieldset',{'class':'commentbox'}).adopt( new Element('legend').setHTML( legend.deCamelize() ) ).wraps(el).injectBefore(el); el.remove(); @@ -2235,21 +2239,21 @@ if( !self) { this.table = table; this.head = $A(table.rows[0].cells).filter(function(el){ - return el.getTag()=='th'; - }); + return el.getTag()=='th'; + }); table.TableAdds = self = this; } self.setOptions(options); options = self.options; var head = self.head; - + if(!self.sorted && options.sort){ head.each( function(th,i){ th.set({ 'class': 'sort', title: options.title.sort, - events: { - 'click': self.sort.bind(self,[i]) + events: { + 'click': self.sort.bind(self,[i]) } }); }); @@ -2258,12 +2262,12 @@ if( !self.filters && options.filter){ head.each( function(th,i){ - th.adopt( new Element('select',{ + th.adopt( new Element('select',{ 'class':'filter', - events: { + events: { 'click': function(e){ new Event(e).stopPropagation() }, 'change': self.filter.bind(self,[i]) - } + } }) ); }); self.filters = []; @@ -2275,33 +2279,33 @@ } return self; }, - + /* Function: sort This is a ''click'' event handler to sort tables by a certain column. - Css styling is applied + Css styling is applied to change the appearance of the sortAscending/sortDescending clickable - controls inside the table header. + controls inside the table header. The data-type of the column is auto-recognized to avoid extensive parameterisation. - # Copy the table body rows into a javascript array and guess + # Copy the table body rows into a javascript array and guess the data-type of the column to be sorted. # Do the actual sort or reverse sort # Apply css format to the header cells. # Put the sorted array back into the DOM tree of the document - The [guessDataType] and [doSort] are helper functions for data-type + The [guessDataType] and [doSort] are helper functions for data-type conversion and caching. Following CSS selectors can be changed if needed .. * clickable column headers, not yet sorted: css class = ''.sort'' - * column headers, sorted ascending: css class = ''.sortAscending'' + * column headers, sorted ascending: css class = ''.sortAscending'' * column headers, sorted descending: css clas = ''.sortDescending'' Credits: - The implementation was inspired by the excellent javascript created by + The implementation was inspired by the excellent javascript created by Erik Arvidsson. See http://webfx.eae.net/dhtml/sortabletable/sortabletable.html. Arguments: @@ -2315,10 +2319,10 @@ this.guessDataType(rows, column); - th.hasClass('sort') ? this.doSort(rows, column) : rows.reverse(); + th.hasClass('sort') ? this.doSort(rows, column) : rows.reverse(); // format the header cell - var isdesc = th.hasClass('sortDescending'), + var isdesc = th.hasClass('sortDescending'), title = this.options.title; new Elements(this.head).addClass('sort').removeClass('sortAscending').removeClass('sortDescending'); @@ -2327,26 +2331,26 @@ .addClass( isdesc ? 'sortAscending' : 'sortDescending') .title = isdesc ? title.descending : title.ascending; - //put sorted rows back into the table + //put sorted rows back into the table var frag = document.createDocumentFragment(); rows.each( function(r){ frag.appendChild(r); }); this.table.appendChild(frag); - var zebra = this.zebra; + var zebra = this.zebra; if( zebra ) zebra(); }, /* Function: filter - Filter the table based on the filter column and (selected) filter value. + Filter the table based on the filter column and (selected) filter value. This function is also an onChange event handler linked with a 'select' element. - + Arguments column - index of the column to be used as sort key - filtervalue - (optional) the value to be filtered, if not present, - take the selected value of the dropdown filter + filtervalue - (optional) the value to be filtered, if not present, + take the selected value of the dropdown filter */ - filter: function( column, filtervalue ){ + filter: function( column, filtervalue ){ var rows = this.getRows(), select = this.head[column].getLast(), //get select element @@ -2360,7 +2364,7 @@ if( filters.every( function( filter ,i ){ if( filter.column != column ) return true; - isAll ? filters.splice(i, 1) : filter.value = value; + isAll ? filters.splice(i, 1) : filter.value = value; return false; }) ) filters.push( {value:value, column:column} ); @@ -2370,12 +2374,12 @@ filters.each( function(filter){ - var value = filter.value, + var value = filter.value, column = filter.column; this.buildFilter(column, value); - rows.each( function(r){ + rows.each( function(r){ if( value != r.data[column] ) r.style.display = 'none'; }); @@ -2386,7 +2390,7 @@ /* Function: zebrafy - Add odd/even coloring to the table. + Add odd/even coloring to the table. Arguments: color1 - color specified in hex(without #) or as html color name. @@ -2446,9 +2450,9 @@ /* Function: buildFilter - Build a single column dropdown filter. Only the column values of the + Build a single column dropdown filter. Only the column values of the visible rows will be part of the filter dropdown. - + Arguments: table - table col - column index @@ -2471,7 +2475,7 @@ rows.each( function(r){ if( r.style.display !='none' ) rr.push(r); }); - + this.doSort(rr, column); //build dropdown with all unique column values @@ -2487,7 +2491,7 @@ }); select.value = filterValue || dropdown[0].value; - // disable the dropdown if only one value + // disable the dropdown if only one value select.disabled = (dropdown.length <= 2); }, @@ -2536,8 +2540,8 @@ }); //now convert all cells to sortable values according to the datatype - rows.each( function( r ){ - + rows.each( function( r ){ + var val = r.data[column], z; if( kmgt ){ @@ -2545,9 +2549,9 @@ val = val.match(/([0-9.,]+)\s*([kmgt])b/) || [0,0,'']; z = {m:3, g:6, t:9}[ val[2] ] || 0; val = val[1].replace(/,/g,'').toFloat() * Math.pow(10, z); - + } else if( euro ){ - + val = val.replace(/[^0-9.]/g,'').toFloat(); } else if( ip4 ){ @@ -2558,15 +2562,15 @@ } else if( ddd ){ val = Date.parse( val ); - + } else if( num ){ val = val.match(/([+-]?\d+(:?\.\d+)?(:?e[-+]?\d+)?)/)[0].toFloat(); - - } + + } r.data[column] = val; - + }); }, @@ -2575,20 +2579,20 @@ Function: doSort Helper function to sort an array, previoulsy prepared by [guessDataType] - + Arguments: array - target array to be sorted column - column index to use a sorting key */ - doSort: function( array, column){ + doSort: function( array, column){ - array.sort( function(a, b){ + array.sort( function(a, b){ a = a.data[column]; b = b.data[column]; - return (ab) ? 1 : 0; - }); + return (ab) ? 1 : 0; + }); } - + }); TableAdds.implement(new Options); @@ -2599,19 +2603,19 @@ Table sorting: All tables inside a JSPWiki {{%%sortable}} style are retrieved and processed. - An onclick() handler is added to each column header which points to the + An onclick() handler is added to each column header which points to the heart of the javascript: the [TableAdds.sort] function. Table filtering: Add excel like filter dropdowns to all tables inside a JSPWiki {{%%filtertable}} style. -Odd/Even coloring of tables (zebra style): +Odd/Even coloring of tables (zebra style): - odd rows get css class odd (ref. jspwiki.css ) > %%zebra-table ... /% - odd rows get css style='background=' > %%zebra- ... /% - - odd rows get odd-color, even rows get even-color + - odd rows get odd-color, even rows get even-color > %%zebra-- ... /% */ @@ -2652,7 +2656,7 @@ $ES('.category a.wikipage',page).each(function(link){ - var page = Wiki.toPageName(link.href); + var page = Wiki.toPageName(link.href); if(!page) return; var wrap = new Element('span').injectBefore(link).adopt(link), popup = new Element('div',{'class':'categoryPopup'}).inject(wrap), @@ -2663,7 +2667,7 @@ .addEvent('click', function(e){ new Event(e).stop(); //dont jump to top of page ;-) - new Ajax( Wiki.TemplateUrl + 'AJAXCategories.jsp', { + new Ajax( Wiki.TemplateUrl + 'AJAXCategories.jsp', { postBody: '&page=' + page, update: popup, onComplete: function(){ @@ -2676,14 +2680,14 @@ 'left': link.getPosition().x, 'top': link.getPosition().y+16 }); - popfx.start(0.9); + popfx.start(0.9); - $ES('li,div.categoryTitle',popup).addHover(); + $ES('li,div.categoryTitle',popup).addHover(); } }).request(); }); }); - } + } } Wiki.registerPlugin( Categories ); @@ -2706,14 +2710,14 @@ var q = Wiki.prefs.get('PrevQuery'); Wiki.prefs.set('PrevQuery', ''); if( !q && document.referrer.test("(?:\\?|&)(?:q|query)=([^&]*)","g") ) q = RegExp.$1; - + if( q ){ var words = decodeURIComponent(q).stripScripts(); //xss vulnerability words = words.replace( /\+/g, " " ); words = words.replace( /\s+-\S+/g, "" ); words = words.replace( /([\(\[\{\\\^\$\|\)\?\*\.\+])/g, "\\$1" ); //escape metachars words = words.trim().split(/\s+/).join("|"); - + this.reMatch = new RegExp( "(" + words + ")" , "gi"); this.walkDomTree( $("pagecontent") ); @@ -2729,7 +2733,7 @@ if( !node ) return; for( var nn=null, n = node.firstChild; n ; n = nn ){ - // prefetch nextSibling cause the tree will be modified + // prefetch nextSibling cause the tree will be modified nn = n. nextSibling; this.walkDomTree(n); } @@ -2739,7 +2743,7 @@ if( node.parentNode.className == "searchword" ) return; var s = node.innerText || node.textContent || ''; - s = s.replace(/ element + s = s.replace(/ element if( this.reMatch.test( s ) ){ var tmp = new Element('span').setHTML(s.replace(this.reMatch,"$1")), @@ -2782,14 +2786,14 @@ Example: (start code) (end code) */ @@ -2810,9 +2814,9 @@ }, initialize:function(options){ - + this.setOptions(options); - + var caption, body, self = this; options = self.options; @@ -2829,58 +2833,58 @@ body = new Element('div',{'class':'body'}), buttons = new Element('div',{'class':'buttons'}) ); - + self.caption = caption; self.body = body; self.buttons = buttons; - - if( options.caption ) caption.appendText(options.caption); + + if( options.caption ) caption.appendText(options.caption); self.setBody( options.body ); self.setButtons( options.buttons ); - + if( options.draggable ){ - new Drag.Base(el); + new Drag.Base(el); el.setStyle('cursor','move'); } - + if( options.resize ){ var resize = new Element('div',{'class':'resize'}).inject(el); body.makeResizable({ - handle:resize, + handle:resize, limit:options.resize, onDrag: function(){ self.resize(this.value.now.x) } }) - } + } el.injectInside(document.body); self.resetPosition(); if( options.showNow ) self.show(); }, - + /* Function: toElement */ - toElement: function(){ - return this.element; + toElement: function(){ + return this.element; }, /* Function: show Show the dialog box and fire the 'onShow' event. */ - show: function(){ - this.element.setStyle('display',''); + show: function(){ + this.element.setStyle('display',''); this.fireEvent('onShow', [this]); - return this; + return this; }, /* Function: hide Hide the dialog box and fire the 'onHide' event. */ hide: function(){ - this.element.setStyle('display','none'); + this.element.setStyle('display','none'); this.fireEvent('onHide'); - return this; + return this; }, /* Function: toggle @@ -2912,27 +2916,27 @@ type = $type(content); if( type=='string'){ - body.setHTML(content) + body.setHTML(content) } else if( type=='element'){ body.adopt(content.show()); }; - + return this; }, /* Function: setButtons this.buttons.empty(); if( buttons ){ - + } */ setButtons: function(buttons){ var self = this, buttonDiv = this.buttons.empty(); - + if( buttons ){ - + for(var btn in buttons){ new Element('a',{ 'class':'btn', @@ -2952,7 +2956,7 @@ /* Function: setPosition Position the dialog box. (absolute positioning) - + Arguments: relativeTo: (optional) DOM element. Default is the center of the window. */ @@ -2961,44 +2965,44 @@ if( relativeTo ){ //new Element('span',{'styles':{'position':'relative'}}).injectAfter(relativeTo).adopt(relativeTo,el); - + if( $type(relativeTo) == 'element' ) relativeTo = relativeTo.getCoordinates(); var pos = {left:relativeTo.left, top:relativeTo.top + relativeTo.height} } else { //center dialog box - var w = window.getSize(), + var w = window.getSize(), pos = this.element.getCoordinates(); pos = { left: w.scroll.x + w.size.x/2 - pos.width/2, top: w.scroll.y + w.size.y/2 - pos.height/2 } - } + } this.element.setStyles(pos); - //fixme: centering the dialog box does not yet work + //fixme: centering the dialog box does not yet work //alert(Json.toString(pos)); //alert(Json.toString(this.element.getCoordinates()) ); }, /* Function: resize Resize the dialog body and fire the 'resize' event. - + Arguments: bodywidth - width in px of the body */ resize: function( bodywidth ){ - //fixme: this resize only works for square color-boxes + //fixme: this resize only works for square color-boxes this.element.setStyles({ 'height': bodywidth+28, 'width': bodywidth+20 }); this.body.setStyles({ 'height': bodywidth, 'width':bodywidth }); this.fireEvent('onResize'); return this; } - + }); Dialog.implement(new Options, new Events); //mootools v1.1