jspwiki-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From brus...@apache.org
Subject svn commit: r1573337 [1/5] - in /jspwiki/trunk: ./ jspwiki-war/src/main/config/wro/ jspwiki-war/src/main/java/org/apache/wiki/ jspwiki-war/src/main/resources/templates/ jspwiki-war/src/main/scripts/dialog/ jspwiki-war/src/main/scripts/dynamic-styles/ j...
Date Sun, 02 Mar 2014 18:27:51 GMT
Author: brushed
Date: Sun Mar  2 18:27:50 2014
New Revision: 1573337

URL: http://svn.apache.org/r1573337
Log:
* 2.10.1-svn-10  : This is the second major check-in of the HADDOCK template, 
  with fixes and improvements mainly related to the plain editor.   
  (LivePreview, Suggestion dialog boxes, Section Editing, Font based icons, Find & Replace UI, ..)        
       * [JSPWIKI-382]  Remove posteditor.js
       * [JSPWIKI-482]  Wrong insert from the suggestion box  
       * [JSPWIKI-443]  Full screen editor. 
       * [JSPWIKI-336]  section selection box not working properly. Fixed. 

Added:
    jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/
    jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Buttons.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Chars.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Color.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Find.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Font.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Selection.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Commands.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.old.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/UndoRedo.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Wiki.Snips.js
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/Dialog.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/fontjspwiki/
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/fontjspwiki/FontJspwiki.zip   (with props)
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/fontjspwiki/core.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/fontjspwiki/font-jspwiki.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/fontjspwiki/icons.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/fontjspwiki/path.less
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/fonts/
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/fonts/FontJspwiki.eot   (with props)
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/fonts/FontJspwiki.svg   (with props)
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/fonts/FontJspwiki.ttf   (with props)
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/fonts/FontJspwiki.woff   (with props)
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/images/circle-256.png   (with props)
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/images/color-wheel.png   (with props)
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/images/cursor.gif   (with props)
Modified:
    jspwiki/trunk/ChangeLog
    jspwiki/trunk/jspwiki-war/src/main/config/wro/wro-haddock.xml
    jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/Release.java
    jspwiki/trunk/jspwiki-war/src/main/resources/templates/default.properties
    jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/TableX.Filter.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Element.Extend.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Wiki.Edit.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/wiki/Dynamic-styles.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/wiki/Prefs.js
    jspwiki/trunk/jspwiki-war/src/main/scripts/wiki/Wiki.js
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/TableX.Filter.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/Template.Edit.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/Template.SearchBox.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/Template.View.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/Viewer.Slimbox.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/jspwiki.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/type.less
    jspwiki/trunk/jspwiki-war/src/main/styles/haddock/variables.less
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/EditTemplate.jsp
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/Nav.jsp
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/PageContent.jsp
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/PreferencesTab.jsp
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/SearchBox.jsp
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/UserBox.jsp
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/ViewTemplate.jsp
    jspwiki/trunk/jspwiki-war/src/main/webapp/templates/haddock/editors/plain.jsp

Modified: jspwiki/trunk/ChangeLog
URL: http://svn.apache.org/viewvc/jspwiki/trunk/ChangeLog?rev=1573337&r1=1573336&r2=1573337&view=diff
==============================================================================
--- jspwiki/trunk/ChangeLog (original)
+++ jspwiki/trunk/ChangeLog Sun Mar  2 18:27:50 2014
@@ -1,3 +1,58 @@
+2014-03-02  Dirk Frederickx (brushed AT apache DOT org)
+
+       * 2.10.1-svn-10  
+       
+       This is the second major check-in of the HADDOCK template, with 
+       fixes and improvements mainly related to the plain editor.
+
+       * Livepreview has been fixed, with ajax based on the fly page rendering. 
+         The livepreview area can now also be displayed side-by-side next to the editor textarea, 
+         so you can immediately see the rendered wiki-markup during edit.
+
+       * Suggestion dialog boxes are shown while you type to assist entrance of more advanced 
+         wiki-markup such as links, %%styles, colors, fonts, plugins, and symbols.
+         (but still heavily under development)
+
+       * Section Editing has been improved: you can choose which part of the page you want to edit.
+
+       * All icons are now based on an icon Font, replacing the FamFamFam icon set. 
+         Based on Font Awesome by Dave Gandy - http://fontawesome.iohttp://fontawesome.io/icons/
+
+       * The find & replace UI has been enhanced, showing number of occurrences, 
+         supporting regular expressions, and supporting replacement for the first or all matches.
+
+       * Text is automatically indented based on the indentation level of the previous line.
+
+       * Using the TAB key inside the textarea will indent a line. Use shift+TAB to un-indent.
+         Indentation also works when selecting multiple lines.
+
+       * You can use shift+Enter to quickly insert line-breaks. (\\)
+
+
+       Fixing following editor related JIRA tickets :
+       
+       * [JSPWIKI-382]  Remove posteditor.js
+      
+       * [JSPWIKI-482]  Wrong insert from the suggestion box  
+
+       * [JSPWIKI-443]  Full screen editor. 
+         Added a collapsible sidebar, and a side-by-side display of the live-preview area.
+
+       * [JSPWIKI-336]  section selection box not working properly. Fixed. 
+
+       * Fixed the User-Preference page-unload event. 
+       
+
+       Other changes : 
+
+       * New "layout" user-preference to switch between fluid or fixed-width page layout.
+ 
+       * Added a info drop-down menu with a summary of the page-info. 
+         This is similar to page-footer section, but now accessible at the top of the page.
+          
+       * Replacing all *.png based icons by an icon font.  (eg. slimbox, filter, rss-feed )
+
+
 2014-02-20  Dirk Frederickx (brushed AT apache DOT org)
 
        * 2.10.1-svn-9  

Modified: jspwiki/trunk/jspwiki-war/src/main/config/wro/wro-haddock.xml
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/config/wro/wro-haddock.xml?rev=1573337&r1=1573336&r2=1573337&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/config/wro/wro-haddock.xml (original)
+++ jspwiki/trunk/jspwiki-war/src/main/config/wro/wro-haddock.xml Sun Mar  2 18:27:50 2014
@@ -62,17 +62,25 @@
   </group>
 
   <group name="haddock-edit">
-    <group-ref>haddock</group-ref>
-    <!--TODO
+
     <js>/scripts/moo-extend/Date.Extend.js</js>
+    <js>/scripts/moo-extend/Array.Extend.HSV.js</js>
+    <js>/scripts/dialog/Dialog.js</js>
+    <js>/scripts/dialog/Dialog.Buttons.js</js>
+    <js>/scripts/dialog/Dialog.Color.js</js>
+    <js>/scripts/dialog/Dialog.Selection.js</js>
+    <js>/scripts/dialog/Dialog.Font.js</js>
+    <js>/scripts/dialog/Dialog.Chars.js</js>
+    <js>/scripts/dialog/Dialog.Find.js</js>
+
     <js>/scripts/moo-extend/Textarea.js</js>
-    <js>/scripts/wiki-edit/Dialog.js</js>
-    <js>/scripts/wiki-edit/SnipEditor.js</js>
-    <js>/scripts/wiki-edit/SnipEditor.Commands.js</js>
-    <js>/scripts/wiki-edit/SnipEditor.Sections.js</js>
     <js>/scripts/wiki-edit/UndoRedo.js</js>
-    <js>/scripts/wiki-edit/wiki.edit.js</js>
-    -->
+    <js>/scripts/wiki-edit/Snipe.js</js>
+    <js>/scripts/wiki-edit/Snipe.Commands.js</js>
+    <js>/scripts/wiki-edit/Snipe.Sections.js</js>
+    <js>/scripts/wiki-edit/Wiki.Snips.js</js>
+    <js>/scripts/wiki-edit/Wiki.Edit.js</js>
+
   </group>
 
   <group name="haddock-prefs">

Modified: jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/Release.java
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/Release.java?rev=1573337&r1=1573336&r2=1573337&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/Release.java (original)
+++ jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/Release.java Sun Mar  2 18:27:50 2014
@@ -72,7 +72,7 @@ public final class Release {
      *  <p>
      *  If the build identifier is empty, it is not added.
      */
-    public static final String     BUILD         = "9";
+    public static final String     BUILD         = "10";
     
     /**
      *  This is the generic version string you should use when printing out the version.  It is of 

Modified: jspwiki/trunk/jspwiki-war/src/main/resources/templates/default.properties
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/resources/templates/default.properties?rev=1573337&r1=1573336&r2=1573337&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/resources/templates/default.properties (original)
+++ jspwiki/trunk/jspwiki-war/src/main/resources/templates/default.properties Sun Mar  2 18:27:50 2014
@@ -351,6 +351,9 @@ prefs.user.skin=Skin
 prefs.user.orientation=Favorites style
 prefs.user.orientation.left=Left
 prefs.user.orientation.right=Right
+prefs.user.layout=Page Layout
+prefs.user.layout.fluid=Fluid
+prefs.user.layout.fixed=Fixed Width
 #prefs.user.editorareaheight=Editor area height  //not user anymore
 prefs.user.sectionediting=Section Editing
 prefs.user.sectionediting.text=Enable section editing via <span class="editsection"><a href="#">[edit]</a></span> links
@@ -528,11 +531,16 @@ editor.plain.smartpairs.title= Auto pair
 editor.plain.tabcompletion=Tab Completion (keyword+Tab)
 editor.plain.tabcompletion.title=Auto expansion of keyword to Wiki Markup
 
+editor.plain.autosuggest=Auto Suggest
 #editor.plain.editassist=Edit Assist
 #editor.plain.editassist.title=Toggle Edit Assist buttons
+editor.plain.livepreview=Live Preview
 editor.plain.sneakpreview=Sneak Preview
 editor.plain.sneakpreview.title=Sneak Preview. \
     Click outside the textarea to refresh the sneak preview area.
+
+editor.plain.edit.resize=Drag to resize the text and preview area
+
 editor.plain.tbLink.title=link - Insert wiki link
 editor.plain.tbH1.title=h1 - Insert heading1
 editor.plain.tbH2.title=h2 - Insert heading2
@@ -598,6 +606,7 @@ javascript.sort.click=Click to sort
 javascript.sort.ascending=Ascending order. Click to reverse sort order
 javascript.sort.descending=Descending order. Click to reverse sort order
 javascript.filter.all=( All )
+javascript.filter.hint=Enter filter pattern
 
 javascript.group.validName=Please provide a valid name for the new Group
 
@@ -611,6 +620,8 @@ javascript.slimbox.previous=&laquo;Previ
 javascript.slimbox.next=Next&raquo;
 javascript.slimbox.close=Close &#215;
 javascript.slimbox.close.title=Close [Esc]
+javascript.slimbox.caption= Direct link to {0}
+javascript.slimbox.btn=Click to view {0} 
 
 javascript.sectionediting.label=Section Overview
 

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Buttons.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Buttons.js?rev=1573337&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Buttons.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Buttons.js Sun Mar  2 18:27:50 2014
@@ -0,0 +1,52 @@
+/*
+
+*/
+Dialog.Buttons = new Class({
+
+	Extends: Dialog,
+	options: {
+		buttons:[], //list of button labels
+		//onAction: function(button-label){},
+		autoClose: true
+	},
+	initialize: function(options){
+
+        this.setClass('.buttons',options);
+        console.log("Dialog.Buttons",options);
+		this.parent(options);
+		this.setButtons( this.options.buttons );
+
+	},
+	/*
+	Function: setButtons
+
+	Arguments:
+		buttons - objects with key:value as button-label:callback function
+
+	Example:
+		(start code)
+			myDialog.setButtons(['Ok','Cancel']);
+			
+			//FIXME???
+			myDialog.setButtons({
+				Ok:function(){ callback( input.get('value') ); },
+				Cancel:function(){}
+			});
+		(end)
+	*/
+	setButtons: function( buttons ){
+
+		var self = this,
+		    btns = self.get('.btn-group') || 'div.btn-group'.slick().inject(self.element);
+
+		btns.empty().adopt( buttons.map(function(b){
+
+			return 'a.btn.btn-link.btn-sm'.slick({
+				html: b.localize(),
+				events:{ click: self.action.bind(self,b) }
+			});
+		}) );
+
+		return self;
+	}
+})

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Chars.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Chars.js?rev=1573337&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Chars.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Chars.js Sun Mar  2 18:27:50 2014
@@ -0,0 +1,62 @@
+/*
+Class: Dialog.Chars
+	The Dialog.Chars is a Dialog object, to support selection of special
+	characters.
+
+Arguments:
+	options - optional, see options below
+
+Options:
+	others - see Dialog options
+
+Inherits from:
+	[Dialog]
+*/
+Dialog.Chars = new Class({
+
+	Extends: Dialog.Selection,
+	
+	options: {
+		//onAction: function(value){},
+		items: '.body td',
+		chars: [
+			'nbsp|iexcl|cent|pound|curren|yen|brvbar|sect|uml|copy|ordf',
+			'laquo|not|reg|macr|deg|plusmn|sup2|sup3|acute|micro|para',
+			'middot|cedil|sup1|ordm|raquo|frac14|frac12|frac34|iquest|times|divide',
+			'Agrave|Aacute|Acirc|Atilde|Auml|Aring|AElig|Ccedil|Egrave|Eacute|Ecirc',
+			'Euml|Igrave|Iacute|Icirc|Iuml|ETH|Ntilde|Ograve|Oacute|Ocirc|Otilde',
+			'Ouml|Oslash|Ugrave|Uacute|Ucirc|Uuml|Yacute|THORN|szlig|agrave|aacute',
+			'acirc|atilde|auml|aring|aelig|ccedil|egrave|eacute|ecirc|euml|igrave',
+			'iacute|icirc|iuml|eth|ntilde|ograve|oacute|ocirc|otilde|ouml|oslash',
+			'ugrave|uacute|ucirc|uuml|thorn|yuml|OElig|oelig|Scaron|scaron|Yuml',
+			'ndash|mdash|lsquo|rsquo|ldquo|rdquo|dagger|Dagger|bull|hellip|permil',
+			'euro|trade|larr|uarr|rarr|darr|harr|crarr|loz|diams|infin'
+		]
+	},
+
+	initialize:function(options){
+
+        this.setClass('.chars',options);
+        //options.cssClass = '.chars'+(options.cssClass||'')
+		this.parent(options);
+
+	},
+
+	setBody: function(){
+
+		/* inspired by smarkup */
+		var content = this.options.chars.map(function(line){
+
+			return '<tr>' +
+				line.split('|').map(function(c){
+					return '<td title="&amp;'+ c + ';">&'+ c + ';</td>';
+				}).join('') + '</tr>';
+
+		});
+
+		return this.parent( 
+		    'table'.slick({ html: '<tbody>'+content.join('')+'</tbody>' }) 
+		);
+	}
+
+});

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Color.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Color.js?rev=1573337&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Color.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Color.js Sun Mar  2 18:27:50 2014
@@ -0,0 +1,187 @@
+/*
+Class: Dialog.Color
+	The Dialog.Color is a [Dialog] which allow visual entry of hexadecimal color
+	values.
+
+Inspiration:
+	- http://www.colorjack.com/software/dhtml+color+sphere.html
+	- Chris Esler, http://www.chrisesler.com/mootools
+
+Inherits from:
+	[Dialog]
+
+Example:
+	Dialog.Color with toggle button
+	(start code)
+	<script>
+		var cd = new Dialog.Color( {
+			relativeTo: $('colorButton'),
+			wheelImage:'circle.png',
+			onChange:function(color){ $('mytarget').setStyle('background',color); }
+		});
+		$('colorButton').addEvent('click', cd.toggle.bind(cd));
+	</script>
+	(end code)
+*/
+Dialog.Color = new Class({
+
+	Extends: Dialog, //Dialog.Buttons,
+	options: {
+
+		//onAction: function(color){},
+		//onDrag: function(color){},
+		//onResize: function(){},
+		color:'#ffffff', //initial color
+		//buttons:['Done'],
+		//colors: [],  //todo: colors array with predef pallette
+		//colorImage: 'scripts-dev/main/src/styles/generated-css/images/circle-256.png',
+		resize:{x:[96,256]}  //min/max limits for the resizer
+	},
+
+	initialize: function(options){
+
+		var self = this,
+		    cursor,
+			showNow = options.showNow,
+			setHSV = self.setHSV.bind(this);
+
+        //options.cssClass = '.color'+(options.cssClass||'')
+        this.setClass('.color',options);
+
+		options.caption = 'span.color'.slick();
+		options.body = [
+			'div.cursor',
+			'div.zone' //img = 'img'.slick({'src':options.colorImage||self.options.colorImage})
+		].slick();
+        cursor = self.cursor = options.body[0];
+
+		options.showNow =false;
+		self.parent(options);
+		
+/*		body = self.get('.body').makeResizable({
+			handle: 'div.resize'.slick().inject(self.element),
+			limit: self.options.resize,
+			onDrag: function(){ self.resize(this.value.now.x); }
+		});
+*/
+        
+		new Drag(cursor,{
+			handle:cursor.getNext(),
+			style:false,
+			snap:0,
+			//also update the wheel on mouse-down
+			onStart:setHSV,
+			onDrag:setHSV
+		});
+
+		self.setValue();
+		if(showNow){ self.show(); }
+	},
+
+	setValue:function( color ){
+
+		color = (color||this.options.color).hexToRgb(true) || [255,255,255];
+		this.hsv = color.rgb2hsv();
+		//console.log(color+" "+this.hsv);
+		return this.moveCursor();
+
+	},
+
+	/*
+	Function: resize
+		Resize the dialog body and fire the 'resize' event.
+		Only use one dimension to ensure a square color box
+
+	Arguments:
+		width,height - new dimension of the body in px
+	*/
+	/*
+	resize: function( width ){
+
+		this.get('.body').setStyles({height:width, width:width});
+		this.moveCursor( );
+		this.fireEvent('resize');
+
+	},
+    */
+
+	/*
+	Function: setHSV
+		Recalculate the HSV-color based on x/y mouse coordinates.
+		After recalculation, the color-wheel cursor is repositioned
+		and the 'onChange' event is fired.
+
+	Arguments:
+		cursor - DOM element
+		e - mouse drag event's
+	*/
+	setHSV: function( cursor, e ){
+
+		var self = this,
+			body = self.get('.body').getCoordinates(),
+			v = [e.page.x - body.left, e.page.y - body.top],
+			W = body.width,
+			W2 = W/2,
+			W3 = W2/2,
+			x = v[0]-W2,
+			y = W-v[1]-W2,
+			sat = Math.sqrt(Math.pow(x,2)+Math.pow(y,2)),
+			hue = Math.atan2(x,y)/(Math.PI*2);
+
+		self.hsv = [
+				hue > 0 ? (hue*360) : ((hue*360)+360),
+				sat < W3 ? (sat/W3)*100 : 100,
+				sat >= W3 ? Math.max(0,1-((sat-W3)/(W3)))*100 : 100
+			];
+
+		self.moveCursor( );
+		self.fireEvent('drag', self.getHex() );
+
+	},
+
+	getHex: function(){
+		return this.hsv.hsv2rgb().rgbToHex();
+	},
+
+	action: function(value){
+		//only one button to press: Done/Ok, ...
+		this.parent( this.getHex() );
+	},
+
+	show: function(){
+		return this.parent().moveCursor( );
+	},
+
+	/*
+	Function: moveCursor
+		Reposition the cursor based on the width argument
+		Note: only works when the dialog is visible.
+
+	*/
+	moveCursor: function( ){
+
+		var self = this,
+			hsv = self.hsv,
+			hex = self.getHex(),
+			w2 = self.get('.body').getSize().x/2,
+			radius = (hsv[0] / 360) * (Math.PI*2),
+			hypothenuse = (hsv[1] + (100-hsv[2])) / 100*(w2/2);
+
+		self.get('.color').set({
+			html: hex,
+			styles: {
+				color: new Color(hex).invert().hex,
+				background: hex
+			}
+		});
+
+		self.cursor.setStyles({
+			left:  Math.abs( Math.sin(radius) * hypothenuse + w2 ),
+			top:  Math.abs( Math.cos(radius) * hypothenuse - w2 )
+		});
+
+		return self;
+
+	}
+
+});

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Find.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Find.js?rev=1573337&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Find.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Find.js Sun Mar  2 18:27:50 2014
@@ -0,0 +1,143 @@
+/*
+Function: Dialog.Find
+	Perform the find and replace operation on either the full textarea
+	or the selection of the textarea. It supports
+	regular expressions, case-(in)sensitive replace and global replace.
+	This is an event handler, typically linked with the submit button of the
+	find and replace dialog.
+
+Arguments:
+
+DOM-structure:
+
+*/
+Dialog.Find = new Class({
+
+	Extends: Dialog,
+    Binds: ['find','replace'],
+
+	options: {
+	
+		//dialog: mandatory DOM element, caption and body are not allowed
+		draggable:true,
+		controls:{
+			f:  '[name=tbFIND]',
+			r:  '[name=tbREPLACE]',
+			h:  '.tbHITS', 
+			re: '[name=tbREGEXP]',
+			i:  '[name=tbMatchCASE]',
+			one:'[name=replace]',
+			all:'[name=replaceall]'
+		},
+		data:{
+			get:function(){},
+			set:function(){}
+		}
+	},
+
+	initialize:function(options){
+
+		var self = this.setOptions(options), 
+		    dialog = self.options.dialog,
+			controls; 
+
+        this.setClass('.find',options);
+
+		//convert to $(elements)
+		controls = self.controls = Object.map( self.options.controls, function(el){
+			return dialog.getElement(el);
+		});
+
+		self.parent( options );
+		
+		console.log("Dialog.Find initialize:",controls);
+		
+		controls.f.addEvents({ 
+		    keyup: self.find, 
+		    focus: self.find
+		});
+		dialog.addEvents({
+		    'change:relay([type=checkbox])': function(){ controls.f.focus(); } ,
+		    'click:relay(button)': self.replace  		
+		}); 
+
+	},
+
+	show: function(){
+		//1. make sure the find controls are visible
+		this.parent();
+		//2. focus the find input field, and auto-trigger find()
+		this.controls.f.focus();
+	},
+
+	// keypress, focus
+	find: function(){
+
+		var self = this,
+			controls = self.controls,
+			find = controls.f,
+			hits = controls.h,
+			findText = find.value,
+			result = '';
+
+		if( findText != '' ){
+
+			result = self.buildRE( findText );
+			if( typeOf(result)=='regexp' ){
+				result = self.options.data.get().match( self.buildRE(findText,true) );
+				if(result){ result = result.length; }
+			}
+
+		}
+
+		if( hits ){ hits.set('html',result); }
+		
+		controls.r.ifClass(!result,'disabled');		
+		controls.one.ifClass(!result,'disabled');		
+		controls.all.ifClass(!result,'disabled');
+		//TODO : one,all should remain disabled until r has content ..	
+			
+		find.focus();
+	},
+
+	// click replace or replace-all button
+	replace: function(e){
+
+		var self = this,
+			controls = self.controls,
+			replace = controls.r,
+			find = controls.f,
+			data = self.options.data;
+		
+		data.set(
+			data.get().replace(
+				self.buildRE(find.value, e.target == controls.all), 
+				replace ? replace.value : ''
+			)
+		);
+		find.focus();
+	},
+
+	buildRE: function( findText, global ){
+
+		var controls = this.controls,
+			isRegExp = controls.re && controls.re.checked,
+			reGlobal = global ? 'g':'',
+			reMatchCase	= (controls.i && controls.i.checked) ? '':'i';
+
+		try {
+		
+			return RegExp(
+				isRegExp ? findText : findText.escapeRegExp(),
+				reGlobal + reMatchCase + 'm'
+			);
+
+		} catch(e){
+
+			return "<span title='" + e + "'>!#@</span>";
+
+		}
+
+	}
+
+});
\ No newline at end of file

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Font.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Font.js?rev=1573337&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Font.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Font.js Sun Mar  2 18:27:50 2014
@@ -0,0 +1,61 @@
+/*
+Class: Dialog.Font
+	The Dialog.Font is a Dialog.Selection object, to selecting a font.
+	Each selectable item is redered in its proper font.
+
+Arguments:
+	options - optional, see options below
+
+Options:
+	fonts - (object) set of font definitions with name/value
+	others - see Dialog.Selection options
+
+Inherits from:
+	[Dialog.Selection]
+
+Example
+	(start code)
+	dialog= new Dialog.Font({
+		fonts:{'Font name1':'font1', 'Font name2':'font2'},
+		caption:"Select a Font",
+		onSelect:function(value){ alert( value ); }
+	});
+	(end)
+*/
+Dialog.Font = new Class({
+
+	Extends:Dialog.Selection,
+	
+	options: {
+		fonts: {
+			'arial':'Arial',
+			'comic sans ms':'Comic Sans',
+			'courier new':'Courier New',
+			'garamond':'Garamond',
+			'georgia':'Georgia',
+			'helvetica':'Helvetica',
+			'impact':'Impact',
+			'times new roman':'Times',
+			'tahoma':'Tahoma',
+			'trebuchet ms':'Trebuchet',
+			'verdana':'Verdana'
+		}
+	},
+
+	initialize:function(options){
+
+		var self = this, fonts = options.fonts;
+
+        //options.cssClass = '.font'+(options.cssClass||'')
+        this.setClass('.font',options);
+		options.body = fonts ? fonts : self.options.fonts;
+
+		self.parent(options);
+
+		self.getItems().each(function(li){
+			li.setStyle('font-family', li.get('title') );
+		});
+
+	}
+
+});

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Selection.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Selection.js?rev=1573337&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Selection.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.Selection.js Sun Mar  2 18:27:50 2014
@@ -0,0 +1,132 @@
+/*
+Class: Dialog.Selection
+	A simple selection dialog, with a list of selectable items.
+
+Arguments:
+	options - see [Dialog] object
+
+Options:
+	body - list of selectable items, defined as a string ,array or object.
+	onSelect - callback function when an item is clicked
+	autoClose - (default true) hide the dialog when an iten is clicked
+
+Inherits from:
+	[Dialog]
+
+Example:
+	(start code)
+	new Dialog.Selection({
+		body:"a|b|c|d",
+		caption:"Snippet Dialog",
+		autoClose:true,
+		onClick:function(v){ alert('clicked '+v) }
+	});
+	new Dialog.Selection({
+		body:[a,b,c,d],
+		caption:"Snippet Dialog",
+		onClick:function(v){ alert('clicked '+v) }
+	});
+	new Dialog.Selection({
+		body:{'avalue':'a','bvalue':'b','cvalue':'c'},
+		caption:"Snippet Dialog",
+		onClick:function(v){ alert('clicked '+v) }
+	});
+	(end code)
+*/
+Dialog.Selection = new Class({
+
+	Extends: Dialog,
+	
+	options: {
+		//onAction: function(value){},
+		//selected: <some value>
+		cssClass: 'dialog selection',
+		autoClose: true,
+		items: '.body li'
+	},
+
+	initialize:function( options ){
+
+        this.setClass('.selection',options);
+        this.selected = options.selected || '';
+		this.parent( options );
+
+        console.log('Dialog.Selection ', this.element.className);
+	},
+
+	setBody: function(content){
+
+		var self = this;
+console.log('Dialog.Selection body ',content);
+		if(!content){ content = self.options.body; }
+
+		//turn 'multi|value|string' into [array]
+		if( typeOf(content) == 'string' ){ content = content.split('|'); }
+
+		//turn [array] into {object} with name:value pairs
+		if( typeOf(content) == 'array' ){ content = content.associate(content); }
+
+		//turn {object} in DOM elements (ul/li collection)
+		if( typeOf(content) == 'object' ){
+		
+			content = 'ul'.slick({ 
+				html: Object.keys(content).map( function(key){
+					return '<li title="'+key+'">'+content[key]/*.trunc(36)*/+'</li>';
+				})
+			});
+			
+		}
+
+		if( typeOf(content) == 'element' ){
+
+			//first move the content elements into the body and highlight the selected item
+			self.parent( content ).setValue( self.selected );
+
+			//then add the click & hover event handlers
+			self.getItems().addEvents({
+				//click: self.action.bind(self),
+				click: function(){ self.action( this); },
+				mouseleave: function(){ this.removeClass('hover'); },
+				mouseenter: function(){ this.addClass('hover'); }
+			});
+		}
+		
+		return self;
+	},
+	
+	/*
+	Function: setValue
+		Store the selected value. (this.selected).
+		And highlight the selected item (if any) 
+	*/
+	setValue: function(value){
+
+		var selected = "selected", els;
+
+		//remove previous selected item, if any 
+		els = this.get('.'+selected); 
+		if(els){ els.removeClass(selected); } 
+
+		els = this.getItems('[title^='+value+']');
+		if(els[0]){ els[0].addClass(selected); }
+
+		this[selected] = value;
+
+		return this;	
+	},
+
+	getValue: function(){
+		return this.selected;	
+	},
+
+	action: function(item){
+		var value = item.get('title');
+		this.setValue(value).parent(value);
+	},
+
+
+	getItems: function( filter ){
+		return this.element.getElements(this.options.items+(filter||''));
+	}
+
+});
\ No newline at end of file

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.js?rev=1573337&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/dialog/Dialog.js Sun Mar  2 18:27:50 2014
@@ -0,0 +1,291 @@
+/*jslint forin: true, onevar: true, nomen: true, plusplus: true, immed: true */
+
+/*
+Class: Dialog
+	Implementation of a simple Dialog box.
+	Acts as a base class for other dialog classes.
+	It is asumes mootools v1.2.4 core & more; incl. Drag.
+
+Events:
+	action - user input: click a button, make selection, ...
+	open - show the dialog panel
+	close - hide the dialog panel
+	resize - called when dialogbox is resized
+
+Arguments:
+	options - optional, see options below
+
+Options:
+	dialog - (optional) predefined dialog DOM element/s
+		When present, it overrules the caption and body elements.
+	caption - (optional) DOM element
+	body - (optional) DOM element
+	cssClass - css class for dialog box, default is 'dialog'
+	style - (optional) additional css style for the dialog box
+	relativeTo - DOM element to position the dialog box
+	resize - resize callback, default null which implies no resize.
+	showNow - (default true) show the dialogbox at initialisation time
+	draggable - (default true) make the dialogbox draggable
+
+Events:
+	onOpen- fires when the dialog is shown
+	onClose - fires when the dialog is hidden
+	onResize - fires when the dialog is resized
+
+DOM Structure:
+	(start code)
+	<div class='dialog'>
+		<div class='caption'> ... </div>
+		<a class='close'>&#215<a>
+		<div class='body'> ... dialog main body ... </div>
+		<div class='buttons'> ... dialog buttons ... </div>
+	</div>
+	(end)
+
+Example:
+	(start code)
+	var dialog = new Dialog({
+		caption:self.ApplicationName || 'JSPWiki',
+		showNow:false,
+		relativeTo:$('query')
+	});
+	dialog.setBody( $('some-dialog') ).show();
+
+	(end)
+
+
+	(start code)
+	var button = $('colorButton');
+	var cd = new Dialog.Color({
+		relativeTo:button,
+		onChange:function(color){ $('target').setStyle('background',color);}
+	});
+	button.addEvent('click', cd.toggle.bind(cd));
+
+	cd.dispose();
+	(end)
+*/
+var Dialog = new Class({
+
+	Implements: [Events, Options],
+
+	options:{
+		cssShow: 'show',
+		styles: {},
+		//dialog: DOM-element
+		//caption: ''
+		//body: 'innerHTML' or DOM-element
+		//autoClose: false,
+		//showNow: false,
+		//draggable: false
+		//onShow: function(){},
+		//onHide: function(){},
+		relativeTo: document.body
+	},
+
+	initialize:function(options){
+
+		var self = this, el;
+
+        //options.cssClass = '.dialog'+(options.cssClass||'');
+        this.setClass('.dialog',options);
+        //console.log(options.cssClass);
+
+		this.setOptions(options);
+		console.log("DIALOG Initialize ",this.options.cssClass);
+
+		options = self.options;
+
+		el = self.element = options.dialog || self.build(options);
+
+		el.getElements('.close').addEvent('click', self.hide.bind(self) );
+
+		//make dialog draggable; only possible when el is position absolute
+		if( (el.getStyle('position')=='absolute') && options.draggable ){
+
+			new Drag(el,{
+				handle: (self.get('.caption') || el).setStyle('cursor','move')
+			});
+
+		}
+
+		//CHECKME: self.resetPosition();
+		self[ options.showNow ? "show": "hide"]();
+	},
+
+	toElement: function(){
+		return this.element;
+	},
+	/*
+	Function: get
+		Retrieve DOM elements inside the dialog container, based on a css selector.
+	Example:
+	>	this.get('.body');
+	>	this.get('.body li');
+	*/
+	get: function(selector){
+		return this.element.getElement(selector);
+	},
+
+    setClass: function(clazz,options){
+        options.cssClass = clazz+(options.cssClass||'');
+    },
+
+	destroy: function(){
+		this.element.destroy();
+	},
+
+	show: function(){
+	
+	console.log("DIALOG show",this.options.cssClass,this.element.className);
+		this.fireEvent('beforeOpen', this)
+			.setPosition()
+			.element.addClass(this.options.cssShow);
+		return this.fireEvent('open', this);
+	},
+
+	hide: function(){
+		this.fireEvent('beforeClose', this)
+			.element.removeClass(this.options.cssShow);
+		return this.fireEvent('close', this);
+	},
+
+	isVisible: function(){
+		return this.element.hasClass(this.options.cssShow);
+	},
+
+	toggle: function(){
+		return this[this.isVisible() ? 'hide' : 'show']();
+	},
+
+	/*
+	Function: action
+		Fires the ''action'' event.
+		When the autoClose option is set, the dialog will also be hidden.
+	*/
+	action: function(value){
+		//console.log('action: '+value+" close:"+self.options.autoClose);
+		this.fireEvent('action', value);
+		if( this.options.autoClose ){ this.hide(); }
+	},
+
+	/*
+	Function: build
+		Build new dialog frame based on caption and body options.
+	*/
+	build: function( options ){
+
+        //console.log("DIALOG build ",options.cssClass);
+
+		var element = this.element = [
+		    'div'+options.cssClass, {styles:options.styles}, [
+			    'a.close',{ html:'&#215;'},
+			    'div.body'
+			]
+		].slick().inject(document.body);
+
+        if( options.relativeTo ){
+			//make sure to inject the dialog close to the relativeTo element
+			//so that any relative positioned parent doesn't intervene
+			element.inject($(options.relativeTo), 'before');
+		}
+		
+console.log("DIALOG build ",this.element.className);
+		this.setBody( options.body );
+		if( options.caption ) this.setCaption( options.caption );
+
+console.log("DIALOG build ",this.element.className);
+
+		return element;
+	},
+
+	/*
+	Function: setBody
+		Set the body of the dialog box
+	Arguments:
+		content - string or DOM element
+	Example:
+		> setBody( "this is a new dialog content");
+		> setBody( new Element('span',{'class','error'}).set('html','Error encountered') );
+	*/
+	setBody: function(content){
+
+		var body = this.get('.body') || this.element,
+		    type = typeOf(content);
+
+		body.empty();
+
+		if( type=='string') body.set('html',content);
+		if( type=='element') body.adopt(content);
+		if( type=='elements') body.adopt(content);
+
+		return this;
+	},
+
+
+	setCaption: function(caption){
+
+		var cptn = this.get('.caption') ||'div.caption'.slick().inject(this.element,'top');
+			type = typeOf(caption);
+
+		cptn.empty();
+
+		if( type=='string') cptn.set('html',caption);
+		if( type=='element') cptn.adopt(caption);
+
+		return this;
+	},
+
+	setValue: function(value){
+
+		console.log('DIALOG  '+value);
+		return this.setBody(value);
+
+	},
+
+	/*
+	Function: setPosition
+		Moves the dialog to a specific screen position: x/y coordinates,
+		relative to another DOM element or in the center of the window.
+		Only works when the element is visible.
+
+	Arguments:
+		relativeTo: (optional) DOM element or an object with a getCoordinates() method
+			Defaults to this.options.relativeTo or to the center of the window.
+	*/
+	setPosition: function( relativeTo ){
+
+		var w = window, ws, x, y, pos,
+			el = this.element;
+
+		if(!relativeTo){ relativeTo = this.options.relativeTo; }
+		pos = (relativeTo && 'getCoordinates' in relativeTo) ? relativeTo : document.id(relativeTo);
+		
+		if( el.getStyle('position') == 'absolute' ){
+
+			if( pos ){
+
+				pos = pos.getCoordinates();
+				//console.log(JSON.encode(pos));
+				x = pos.left; y = pos.bottom; //align at the bottom of the relativeTo element
+
+			} else {	// center dialog box
+
+				//todo: should be adjusted everytime the screen is resized or scrolled ?
+				ws = w.getScroll();
+				w = w.getSize();
+				pos = el.getCoordinates();
+				x = ws.x + w.x/2 - pos.width/2;
+				y = ws.y + w.y/2 - pos.height/2;
+
+			}
+
+			el.setPosition({x:x,y:y});
+			//el.morph({left: x, top:y}); -- move this to css/transition
+
+		}
+		return this;
+	}
+
+});
+

Modified: jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/TableX.Filter.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/TableX.Filter.js?rev=1573337&r1=1573336&r2=1573337&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/TableX.Filter.js (original)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/TableX.Filter.js Sun Mar  2 18:27:50 2014
@@ -41,6 +41,7 @@ TableX.Filter = new Class({
             });
 
             ['div.form-group.filter-input',[
+                'span.icon-filter',
                 'input.form-control[type=search][placeholder="'+options.hint+'"]',{
                     attach: [ self, 'input' ],
                     events: {

Modified: jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Element.Extend.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Element.Extend.js?rev=1573337&r1=1573336&r2=1573337&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Element.Extend.js (original)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Element.Extend.js Sun Mar  2 18:27:50 2014
@@ -99,7 +99,7 @@ Element.implement({
     Example
     > $('li.dropdown-menu').onHover('ul');
     */
-    onHover: function( toggle ){
+    onHover: function( toggle, onOpen ){
 
         var element = this;
 
@@ -108,7 +108,7 @@ Element.implement({
              element.fade('hide');
 
              toggle.addEvents({
-                mouseenter: function(){ element.fade(0.9); toggle.addClass('open'); },
+                mouseenter: function(){ element.fade(0.9); toggle.addClass('open'); if(onOpen) onOpen(); },
                 mouseleave: function(){ element.fade(0);   toggle.removeClass('open'); }
             });
 
@@ -157,7 +157,8 @@ Element.implement({
 
         if( toggle == "buttons" ){
         
-            (toggle = function(){
+            (toggle = function(e){
+                //FIXME: differentiate between radioboxes and checkboxes !!
                 element.getElements(".active").removeClass("active");
                 element.getElements(":checked !").addClass("active");
             })();

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Commands.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Commands.js?rev=1573337&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Commands.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Commands.js Sun Mar  2 18:27:50 2014
@@ -0,0 +1,296 @@
+/*
+Class: SnipEditor.Commands
+    This class preprocesses all command triggers, such as
+    suggestion commands, button clicks or tab-completion commands.
+
+    It will make sure that only one dialog is open at the same time.
+    It intializes and caches the dialogs, handles the show/hide/toggle
+    of dialogs, and passes action events back to the SnipEditor.
+
+    Dialogs can be opened by means of
+    - external command triggers: exec
+    - click events on command buttons (.cmd.pop)
+    - suggestion trigger (exec ???)
+
+    FYI - all DIALOGs are created as descendants of the Dialog class.
+    - Dialog : floating dialog panel
+        - FormDialog : predef content with open/close handlers ???
+        - Dialog.Selection : selectable list of items
+            - Dialog.Font : selection list of font items
+            - Dialog.Section : selection list of textarea sections
+        - Dialog.Chars : selection matrix of special character entities
+        - Dialog.Color : color-wheel
+        - Dialog.Find : find and replace dialog
+
+Options:
+    container: DOM element  => contains commands([data-cmd])
+    dialogs - predefined set of dialog initialisators
+    // **event handlers**
+    onOpen - invoked after opening a DIALOG
+    onClose - invoked after closing a DIALOG
+    onAction - action call-back action(cmd,arguments)
+
+Properties
+    - buttons : collection of DOM-elements with click handlers to either
+        action() or toggle()
+    - dialogs : collection of dialog definitions [Dialog-class, {dialog parameters}]
+
+DOM structure:
+    <div class="cmd tICON"><i>action command</i></div>
+    <div class="cmd pop tICON"><i>dialog</i></div>
+
+    <div class="dialog fixed"> ... dialog content </div>
+*/
+Snipe.Commands = new Class({
+
+    Implements: [Events, Options],
+
+    options: {
+        //onAction:function()...s
+        cmds:'cmd' //toolbar button data attribute
+        //dialogs:{ cmd1:dialog1, cmd2:dialog2, ...}
+    },
+    btns: {},     //all cmd:buttons (dom element)
+    dlgs: {},     //all cmd:instantiated dialogs  (lazy activation)
+    dialogs: {},  //all cmd:dialogs
+
+    initialize: function( container, options ){
+
+        var self = this.setOptions(options), 
+            attr = 'data-' + self.options.cmds,
+            command, 
+            dialog,
+            dialogs = options.dialogs||{};
+
+        container.getElements('['+attr+']').each( function(el){
+
+            command = el.get(attr);
+
+            self.btns[command] = el.addEvent('click', self.click.pass(command,self));
+
+            if( dialog = container.getElement('.dialog.' + command) ){
+            
+                if( dialogs[command] ){
+
+                    dialogs[command][1].dialog = dialog;  
+
+                } else {
+
+                    dialogs[command] = dialog;
+
+                }
+            }
+        });
+
+        self.addDialogs( dialogs );
+    },
+
+    /*
+    Funciton: addDialog
+        Add a new dialog.
+        The dialog is only created when invoking the command.
+        This happens through a button click or through the action() method.
+
+    Arguments:
+        dialogs: {cmd1:dialog, cmd2:dialog-def...}
+        (dialog-def : array[Dialog-Class, {dialog parameters}]
+        relativeTo: create a dialog relative to a positioned object (eg. button, textarea-location)
+    */
+    addDialogs: function(newdialogs, relativeTo){
+
+        var self = this,
+            dialog,
+            command
+            dialogs = self.dialogs;
+        
+        for( command in newdialogs ){
+
+            if( dialogs && dialogs[command] ){
+                console.log("AddDialogs - warning: double registration of => " + command);
+            }
+
+            dialog = dialogs[command] = newdialogs[command];  //array of all dialogs
+            if( instanceOf( dialog, Dialog ) ){ self.attach(command,dialog); }
+
+            //checkme ...
+            if( relativeTo ){ self.btns[ command ] = relativeTo; }
+
+        };
+        //console.log('allDialogs: '+Object.keys(self.dialogs) );
+    },
+
+    attach: function(command, dialog){
+
+        var self = this,
+            actionHdl = function(v){ self.fireEvent('action', [command,v]); };
+
+        //console.log('attachDialog: '+command);
+
+        return self.dlgs[command] = dialog.addEvents({
+            onOpen: self.openDialog.bind(self, command),
+            onClose: self.closeDialog.bind(self, command),
+            onAction: actionHdl,
+            onDrag: actionHdl
+        });
+    },
+
+    click: function( command ){
+
+        var dialog = this.dlgs[ command ];
+        dialog ? dialog.toggle() : this.action( command );
+
+    },
+
+    /*
+    Function: action
+        Action handler for a simple command. Pass the 'action' event
+        up to the Snipe Editor.
+
+    Arguments:
+        command : command name
+        value : (optional) initial value of the dialog
+    */
+    action: function( command, value ){
+
+        var self = this, 
+            active = 'active',
+            button = self.btns[command], 
+            dialog = self.dlgs[command];
+
+        //console.log("Commands.action "+command+" value:"+value+" btn="+button+ " dlg="+dialog);
+        if( button ) button = document.id( button);
+
+        if( button && button.match('.disabled') ){
+
+            //nothing to do here
+
+        } else if( self.dialogs[command] ){
+
+            if( !dialog ){ dialog = self.createDialog(command) }
+            if( value ){ dialog.setValue( value ); }
+            dialog.show();
+
+        } else {
+
+            if( button ){ button.addClass(active); }
+            self.fireEvent('action', [command, value] );
+            if( button ){ button.removeClass(active); }
+
+        }
+
+    },
+
+    /*
+    Function: createDialog
+        Create a new dialog.
+        The name of the cmd determines the type (or class) of Dialog to be created
+        - cmd: Dialog[cmd] (eg cmd='font' : Dialog.Font)
+        - the name of the dialog equals the DOM ID of a predefined HTML dialog
+
+        - DOM Element: predefined DOM dialog
+        - [ Dialog-class, { dialog parameters } ]
+        - { dialog parameters } : the cmd determines the type of Dialog to create
+        - "string" : create a Dialog.Selection dialog
+
+
+    Arguments
+        cmd - (string) command
+
+        The open/close handlers will make sure only one dialog is open at the
+        same time. The open dialog is stored in {{this.activeCmd}}.
+
+        The key events 'action', 'drag', 'open' and 'close' are propagated upwards.
+
+    Returns:
+        The created dialog, which is also stored in this.dlgs[] repository.
+
+    */
+    createDialog: function( cmd ){
+
+        var self = this,
+            dlg,
+            btn = self.btns[cmd],
+            factory = Function.from( self.dialogs[cmd] )(),
+            type = typeOf(factory);
+
+        //console.log('Commands.createDialog() '+cmd+' '+ ' btn='+btn +" "+type);
+
+        //expect factory to be [Dialog class,  {dialog options object}]
+        if( type != 'array' || factory.length != 2 ){
+
+            factory = ( type == 'element' ) ?
+                [Dialog, {dialog:factory}] : [Dialog.Selection, {body:factory}];
+        }
+
+        dlg = new factory[0]( Object.append( factory[1],{
+            //cssClass: 'dialog float',
+            autoClose: false, //fixme: suggestion dialog should not be autoclosed
+            relativeTo: btn   //button or textareaa
+            //draggable: true
+        }) );
+
+        //Make sure that this.dlgs[cmd] gets initialized prior to calling show()
+        return self.attach(cmd, dlg);
+    },
+
+    /*
+    Function: openDialog
+        Opens a dialog. If already another dialog was open, that one will first be closed.
+        When a toolbar button exists, it will get the css class '.active'.
+
+        Note: make sure that this.dlgs[cmd] is initialized prior to calling show() !
+
+    Argument:
+        command - dialog to be opened
+        preOpen - ...
+    */
+    openDialog: function(command, dialog){
+
+        var self = this, 
+            current = self.activeCmd, 
+            tmp;
+
+        //console.log('Commands.openDialog() ' + command + ' ' + self.activeCmd );
+
+        if( ( current!=command ) && ( tmp = self.dlgs[current] ) ){ tmp.hide(); }
+        //toobar button will be deactivated by closeDialog()
+
+        self.activeCmd = command;
+        if( tmp = self.btns[command] ){ $(tmp).addClass('active'); }
+
+        self.fireEvent('open', command, dialog);
+    },
+
+    /*
+    Function: closeDialog
+
+    Arguments:
+        cmd - (mandatory) dialog to be closed
+    */
+    closeDialog: function(cmd, dialog){
+
+        var self = this, 
+            btn = self.btns[cmd];
+
+        //console.log('Commands.closeDialog() ' + cmd + ' ' + self.activeCmd )
+
+        if( cmd == self.activeCmd ){ self.activeCmd = null; }
+        if( btn ){ $(btn).removeClass('active'); }
+
+        self.fireEvent('close', cmd, dialog);
+    },
+
+    /*
+    Function: close
+        Close the active dialog, if any.
+    */
+    close: function(){
+
+        var activeCmd = this.activeCmd;
+        if( activeCmd ){ this.dlgs[activeCmd].hide(); }
+
+    }
+
+});
+
+

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.js?rev=1573337&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.js Sun Mar  2 18:27:50 2014
@@ -0,0 +1,199 @@
+/*
+Class: SnipEditor.Sections
+    This dialog displays the list of page sections.
+    A page section includes the header
+
+    (all) - allows to select all sections (auto generated)
+    start-of-page - only present when first section starts on an offset > 0
+    section1..n - section titles, with indentation level depending on their weight
+
+    The set of sections is generated by the parseSections() callback handler.
+    This parser returns an array of section 'descriptors':
+>    [ {title:text, start:char-offset, indent:indentation-level}, ... ]
+
+    Clicking an entry triggers the updateSections() callback handler.
+    FIXME: why not fire an onAction event (similar to other dialogs)
+
+Depends:
+    Snipe
+
+*/
+
+Snipe.Sections = new Class({
+
+    Implements: [Events],
+    Binds: ['show','update','action'],
+    
+    options: {
+        //snipe:snip-editor
+        //parser: function
+        all: "( all )".localize(),
+        startOfPage: "Start of Page".localize()
+    },
+
+    initialize: function(element, options){
+
+        var self = this;
+
+        self.element = element  //dropdown menu
+            .onHover( self.container = element.get('data-sections'), self.show )
+            .addEvent( 'click:relay(a)', self.action );
+        self.container =  element.getParent( element.get('data-sections') );
+        
+        self.parser = options.parser;
+        self.main = options.snipe.get('mainarea');
+        self.work = options.snipe.toElement().addEvents({ 
+            keyup: self.update, 
+            change: self.update 
+        });
+
+        self.parse();
+        self.action( location.search );  //url?section=0..n 
+        self.show();
+    },
+
+    /*
+    Function: parse
+        Invoke the external parser on the contents of the main textarea.
+        This external parser should return an array with an entry for each section:
+        [ {title:text, start:char-offset, depth:nesting level}, ... ]
+
+        >        0 : start-of-page (if applicable) => title=s-1 => cursor=-1
+        >        1..n : page sections              => title=s0..sn => cursor=0..n
+    */
+    parse: function(){
+
+        this.sections = this.parser( this.main.value );
+
+    },
+
+    /*
+    Function: onOpen
+        UPDATE/RFEFRESH the textarea section dialog.
+        Build the DOM list-items 
+    (start code)
+        ul.dropdown-menu
+            li
+                a.indent-0.section-2 (all)
+            li
+                a.indent-0.section-1 Start Of Page
+            li.divider
+            li
+                a.indent-0.section0 Title-Section-0
+            li
+                a.indent-0.section1 Title-Section-1
+            ...
+            li
+                a.indent-0.section99 Title-Section-2                
+    (end)        
+    */
+    //onOpen: function( dialog ){
+    show: function( ){
+
+        var options = this.options,
+            data = [],
+            sections = this.sections,
+            
+            addItem = function(indent,name,offset){
+                data.push('li',['a.indent-'+indent+'.section'+offset,{ html:name }]);
+            }
+
+        addItem(0, options.all ,-2);
+        
+        if( sections[0] ){
+        
+            if( sections[0].start > 0 ){ addItem(0, options.startOfPage, -1); }
+
+            data.push('li.divider');
+            
+            sections.each( function(item, idx){ 
+                addItem( item.depth, item.title.trunc(36), idx );
+            });
+
+        }
+        
+        this.element.empty().adopt( data.slick() );
+
+    },
+
+    /*
+    Function: update
+        Make sure that changes to the work textarea are propagated to the main textarea.
+        This functions handles the correct insertion of the changed section into the main
+        textarea.
+    */
+    update: function(){
+
+        //console.log("Sections: update");
+        var self = this,
+            main = self.main,
+            work = self.work.value,
+            sections = self.sections,
+            s = main.value,
+            //insert \n to ensure the next section always starts on a new line.
+            linefeed = (work.slice(-1) != '\n')  ? '\n' : '';
+
+        //console.log('change txta: from='+sections.begin+ ' end='+sections.end);
+        main.value = s.slice(0, self.begin) + work + linefeed + s.slice(self.end);
+        self.end = self.begin + work.length;
+
+        self.parse();
+    },
+
+    /*
+    Function: onAction
+        This function copies the selected section from the main to the work textarea.
+        It is invoked at initialization and through the dialog onAction click handler.
+
+    Arguments:
+        item - index of selected section: all, -1, 0..n
+    */
+    //onAction:function( item ){
+
+    /*
+    setValue: function(value){
+    },
+    action: function(item){
+        var value = item.get('title');
+        this.setValue(value).parent(value);
+    },
+    */
+    action:function( item ){
+
+        var self = this,
+            main = self.main.value,
+            sections = self.sections,
+            begin = 0,
+            end = main.length;
+
+        if( item ){
+        
+            //item.target => event.target; this is an onclick invocation
+            if( item.target ) item = item.target.className;
+            
+            //section-2=All, section-1=StartOfPage, section0..section99=rest
+            item = ( item.match( /section=?(-?\d+)/ )||[,-2])[1].toInt();
+            
+            if( item == -1 ){
+
+                //show the Start Of Page, prior to the first real section
+                end = sections[0].start;
+
+            } else if(item >= 0  && sections[item] ){
+
+                begin = sections[item].start;
+                //if( item+1 < sections.length ){ end = sections[item+1].start; }
+                if( sections[item+1] ){ end = sections[item+1].start; }
+
+            }
+        }
+
+        self.work.value = main.slice(begin, end);
+        self.begin = begin;
+        self.end = end;
+
+        //now close the hover menu and focus the text-area...
+        self.container.removeClass('open');
+        self.container.ifClass( item >= -1, 'section-selected');
+    }
+});

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.old.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.old.js?rev=1573337&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.old.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.old.js Sun Mar  2 18:27:50 2014
@@ -0,0 +1,202 @@
+/*
+Class: SnipEditor.Sections
+    This dialog displays the list of page sections.
+    A page section includes the header
+
+    (all) - allows to select all sections (auto generated)
+    start-of-page - only present when first section starts on an offset > 0
+    section1..n - section titles, with indentation level depending on their weight
+
+    The set of sections is generated by the parseSections() callback handler.
+    This parser returns an array of section 'descriptors':
+>    [ {title:text, start:char-offset, indent:indentation-level}, ... ]
+
+    Clicking an entry triggers the updateSections() callback handler.
+    FIXME: why not fire an onAction event (similar to other dialogs)
+
+Depends:
+    Dialog.Selection
+
+
+TODO
+Convert to Bootstrap DropDown, 
+Wiki.Sections.js
+
+wiki.add('[data-sections]',  Snipe.Sections); 
+
+section = container.getElement('.section');
+if(section) new Snip.Sections( snipe, selected string, parser);
+    
+});
+//need snipe object
+//need "selected" string -- create yourself ...
+
+    this.snipe = options.snipe;
+    this.parser = options.parser;
+    new Wiki.Sections( snipe );
+    
+snipe.addEvent('change', this.change.bind(this))
+snipe.addEvent('keyup', this.change.bind(this))
+
+dropdown.addEvent('mouseenter', this.show.bind(this))
+dropdown.onHover(...); //hover effect
+//dropdown.addEvent('mouseleave')
+
+);
+
+*/
+
+Snipe.Sections = new Class({
+
+    Extends:Dialog.Selection,
+
+    options: {
+        //main:textarea
+        //work:textarea
+        //selected: selected item: all,s-1,s0..sn
+        //parser: function
+        all: "( all )".localize(),
+        startOfPage: "Start of Page".localize()
+    },
+
+    initialize: function(options){
+
+        var self = this,
+            onChange = self.onChange.bind(self);
+
+        this.setClass('.sections',options);
+        self.parent(options);
+
+        self.parse();
+        self.action();
+
+        //can be hooked up by the SnipEditor.Commands
+        /*self.dialogDefinition = [Dialog.Selection, {
+            selected: self.options.selected,
+            onOpen: self.onOpen,
+            onAction: self.onAction
+        }];*/
+
+        //FIXME !! keyup
+        self.options.work.addEvents({ change:onChange, keyup:onChange });
+
+    },
+
+    /*
+    Function: parse
+        Invoke the external parser on the contents of the main textarea.
+        This external parser should return an array with an entry for each section:
+        [ {title:text, start:char-offset, depth:nesting level}, ... ]
+
+        >        0 : ( all )                       => title=All => cursor=NaN
+        >        1 : start-of-page (if applicable) => title=s-1 => cursor=-1
+        >        2..n : page sections              => title=s0..sn => cursor=0..n
+
+    */
+    parse: function(){
+        this.sections = this.options.parser( this.options.main.value );
+    },
+
+    /*
+    Function: onOpen
+        UPDATE/RFEFRESH the textarea section dialog.
+    */
+    //onOpen: function( dialog ){
+    show: function( ){
+
+        //console.log("Sections: show");
+        var options = this.options,
+            data = { all: options.all },
+            sections = this.sections;
+
+        if( sections[0] /*.length > 0*/ ){
+            if( sections[0].start>0 ){ data['s-1'] = options.startOfPage }
+            sections.each( function(item, idx){ data['s'+idx] = item.title.trunc(36); });
+        }
+
+        //dialog.setBody( data ).getItems().each(function(el){
+        this.setBody( data ).getItems().each(function(el){
+            var t = el.title.slice(1).toInt();
+            if( t>=0 ){ el.setStyle('padding-left',(.5+sections[t].depth)+'em'); }
+        });
+
+        this.parent(); //invoke parent's show
+    },
+
+    /*
+    Function: onChange
+        Make sure that changes to the work textarea are propagated to the main textarea.
+        This functions handles the correct insertion of the changed section into the main
+        textarea.
+    */
+    onChange: function(){
+
+        //console.log("Sections: onChange");
+        var self = this,
+            main = self.options.main,
+            work = self.options.work.value,
+            sections = self.sections,
+            s = main.value,
+            //insert \n to ensure the next section always starts on a new line.
+            linefeed = (work.slice(-1) != '\n')  ? '\n' : '';
+
+        //console.log('change txta: from='+sections.begin+ ' end='+sections.end);
+        main.value = s.slice(0, self.begin) + work + linefeed + s.slice(self.end);
+        self.end = self.begin + work.length;
+
+        self.parse();
+    },
+
+    /*
+    Function: onAction
+        This function copies the selected section from the main to the work textarea.
+        It is invoked at initialization and through the dialog onAction click handler.
+
+    Arguments:
+        cursor - index of selected section: all, -1, 0..n
+    */
+    //onAction:function( item ){
+
+    /*
+    setValue: function(value){
+    },
+    action: function(item){
+        var value = item.get('title');
+        this.setValue(value).parent(value);
+    },
+    */
+    action:function( item ){
+
+        var self = this,
+            main = self.options.main.value,
+            sections = self.sections,
+            begin = 0,
+            end = main.length;
+
+        if( item ){
+
+            item = item.replace(/^s/,'').toInt();
+
+            if( item == -1 ){
+
+                //show the Start Of Page, prior to the first real section
+                end = sections[0].start;
+
+            } else if(item >= 0  && sections[item] /*item < sections.length*/ ){
+
+                begin = sections[item].start;
+                //if( item+1 < sections.length ){ end = sections[item+1].start; }
+                if( sections[item+1] ){ end = sections[item+1].start; }
+
+            }
+        }
+
+        self.options.work.value = main.slice(begin, end);
+        self.begin = begin;
+        self.end = end;
+        //console.log("Section: onAction " + item + " "+self.begin+" "+self.end);
+
+        //checkme
+        if( item ) self.parent(item);
+    }
+});



Mime
View raw message