You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by br...@apache.org on 2009/09/26 15:23:59 UTC

svn commit: r819135 [2/4] - in /incubator/jspwiki/trunk/src/WebContent/scripts: dialog.js jspwiki-common.js jspwiki-commonstyles.js jspwiki-edit.js jspwiki-prefs.js mootools-core.js mootools-more.js mootools.js stripes-support.js

Modified: incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-edit.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-edit.js?rev=819135&r1=819134&r2=819135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-edit.js (original)
+++ incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-edit.js Sat Sep 26 13:23:58 2009
@@ -1,4 +1,4 @@
-/*! 
+/*!
     JSPWiki - a JSP-based WikiWiki clone.
 
     Licensed to the Apache Software Foundation (ASF) under one
@@ -16,21 +16,20 @@
     "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.
 */
 
 /*
-Function: toISODate
+Function: toISOString
 	Return the current date in ISO8601 format 'yyyy-mm-dd'.
-	(ref. EcmaScript 5)	
+	(ref. EcmaScript 5)
 
 Example:
-> alert( new Date().toISODate() ); // alerts 2009-05-21
-> alert( new Date().toISODate() ); // alerts 2009-05-21T16:06:05.000TZ
+> alert( new Date().toISOString() ); // alerts 2009-05-21
+> alert( new Date().toISOString() ); // alerts 2009-05-21T16:06:05.000TZ
 */
-$native(Date);
 Date.extend({
-	toISODate: function(){
+	toISOString: function(){
 		var d = this,
 			dd = d.getDate(),
 			mm = d.getMonth()+1;
@@ -45,17 +44,19 @@
 Class: WikiEditor
 	The WikiEditor class implement all JSPWiki's plain editor support functions.
 	It uses the [SnipEditor] class to enhance the textarea object.
-	
-	The WikiEditor contains all JSPWiki's specific snippets to ease the entry of 
-	the JSPWiki markup syntax.	
+
+	The WikiEditor contains all JSPWiki's specific snippets to ease the entry of
+	the JSPWiki markup syntax.
 */
-var WikiEdit = 
+
+
+var WikiEdit =
 {
 	initialize: function(){
 
 		//should always run first, but seems not guaranteed on ie so let's do this for sure
-		Wiki.initialize(); 
-		
+		Wiki.initialize();
+
 		var txta = $('editorarea'),
 			self = this,
 			snipe,
@@ -65,19 +66,38 @@
 			tileBtns, tileFn,
  			height = prefs.get('EditorSize');
 
+		/*
+			Install an onbeforeunload handler.
+
+			This handler is called ''before'' the page unloads.
+			If a string is returned, the user will be prompted with a warning
+			popup, to allow to cancel the page unload.
+			(eg. warning when moving to another page without first saving )
+
+			Remove the onsubmit handler on regular exit of the page.
+		*/
 		window.onbeforeunload = function(){
-			if( txta.value != txta.defaultValue ) return "edit.areyousure".localize();
+			if( txta.get('value') != txta.get('defaultValue')) return "edit.areyousure".localize();
 		};
 
+		$('editform').addEvent('submit',function(){
+			window.onbeforeunload = null;
+		});
+
+		/*
+			Initialize user-prefered height.
+		*/
 		if( height ) txta.setStyle('height',height);
 
-		// open the new snipEditor
+		/*
+			Initialize the snippet editor.
+		*/
 		snipe = self.snipEditor = new SnipEditor( txta, {
 
-			tabsnips: self.tabSnippets, 
+			tabsnips: self.tabSnippets,
 			// tabcompletion => set by this.configFn()
-			// directsnips => set by this.configFn() 
-			suggestsnips: self.suggestSnippets(), 
+			// directsnips => set by this.configFn()
+			suggestsnips: self.suggestSnippets(),
 
   			buttons: $$('a.tool'),
 
@@ -113,21 +133,23 @@
 
   			next: $('nextInput'),
 
-  			onresize:function(height){  
+  			onresize:function(height){
   				//save the height in the preference cookie
-  				prefs.set('EditorSize',height); 
+  				prefs.set('EditorSize',height);
   			}
 
   		});
 
-		//initialize the configuration dialog and link it to the buttons
+		/*
+			Initialize the configuration dialog and link it to the buttons
+		*/
 		configFn = function(){
 			snipe.set('directsnips', $('smartpairs').checked ? self.directSnippets : {})
 				.set('tabcompletion', $('tabcompletion').checked == true );
 		};
 		['smartpairs', 'tabcompletion'].each( function(id){
 			var element = $(id);
-			if( element ){ 
+			if( element ){
 				element.setProperty( 'checked', prefs.get(id) || false )
 					.addEvent( 'click', function(e){
 						configFn();
@@ -136,14 +158,16 @@
 			}
 		});
 		configFn();
-		
-		//initialize the preview layout buttons: tile-vert or tile-horz
+
+		/*
+			Initialize the preview layout buttons: tile-vert or tile-horz
+		*/
 		tileBtns = $$('.tHORZ','.tVERT');
 		tileFn = function(tile){
 
 			prefs.set('previewLayout',tile);
 			tileBtns.each(function(el){
-				el[( el.getText()==tile ) ? 'hide': 'show']();
+				el[( el.get('text')==tile ) ? 'hide': 'show']();
 			});
 
 			tile = (tile=='tile-vert') ? 'size1of1':'size1of2';
@@ -152,20 +176,21 @@
 			});
 		};
 		tileBtns.each( function(el){
-			el.addEvent( 'click',function(){ tileFn(this.getText()); });
+			el.addEvent( 'click',function(){ tileFn(this.get('text')); });
 		});
 		tileFn( prefs.get('previewLayout')||'tile-vert' );
 
 
 		//add a localized hover title to the resize drag-bar
-		$E('.editor-container .resize-bar').set({'title':'edit.resize'.localize()});
+		//CHECK !v1.2.3.
+		document.getElement('.editor-container .resize-bar').set('title', 'edit.resize'.localize());
 
 		// Select the right section of the page:  URL?section=0..n
 		// cursor = -2 (all) or 0..n (section# - first section is 0)
 		tocCursor = location.search.match(/[&?]section=(\d+)/);
 		snipe.selectTocItem( tocCursor ? tocCursor[1].toInt() : -2 );
 
-		self.initializePreview( snipe );		
+		self.initializePreview( snipe );
 	},
 
 	/*
@@ -173,7 +198,7 @@
 		DirectSnippet definitions for JSPWiki, aka ''smartpairs''.
 		These snippets are directly expanded on keypress.
 	*/
-	directSnippets: { 
+	directSnippets: {
 		'"' : '"',
 		'(' : ')',
 		'[' : ']',
@@ -185,7 +210,7 @@
 			}
 		}
 	},
-	
+
 	/*
 	Function: tabSnippets
 		TabSnippet definitions for JSPWiki.
@@ -196,8 +221,8 @@
 	Example:
 	Clicking following link(button) with text "br" inserts a "\\" followed by a nexline
 	>  <a href="#" class="tool" id="tbBR" title="key='editor.plain.tbBR.title'">br</a>
-	
-	The keystrokes {{nl<TAB>}} are converted to "\\" followed by a newline, 
+
+	The keystrokes {{nl<TAB>}} are converted to "\\" followed by a newline,
 	when the ''tabcompletion'' flag is on.
 	>	'nl':'\\\\\n'
 
@@ -224,12 +249,12 @@
 		"br": "\\\\\n",
 		"nl": { synonym: "br" },
 		"hr": "\n----\n",
-		"h1": "\n!!!{Heading 1 title}\n", 
+		"h1": "\n!!!{Heading 1 title}\n",
 		"h2": "\n!!{Heading 2 title}\n",
 		"h3": "\n!{Heading 3 title}\n",
 
 		"font": {
-			nScope: { 
+			nScope: {
 				"%%(":")",
 				"font-family:":";"
 			},
@@ -243,9 +268,9 @@
 			snippet: "{special}",
 			nScope: { "%%(":")" }
 		},
-		
-		
-		"dl": "\n;{term}:{definition-text} ", 
+
+
+		"dl": "\n;{term}:{definition-text} ",
 		"sub": "%%sub {subscript text}/% ",
 		"sup": "%%sup {superscript text}/% ",
 		"strike": "%%strike {strikethrough text}/% ",
@@ -258,20 +283,20 @@
 			snippet:"[{link text}|{pagename or url}|{attributes}] ",
 			attributes:"acceskey=X|title=description|target:_blank"
 		},
-/*		'accesskey', 'charset', 'class', 'hreflang', 'id', 'lang', 'dir', 
+/*		'accesskey', 'charset', 'class', 'hreflang', 'id', 'lang', 'dir',
 		'rel', 'rev', 'style', 'tabindex', 'target', 'title', 'type'
 		- link-text
 		- wiki-page or url
 		- description:title
-		
-		
-		
+
+
+
 		- target: _blank --new-- window yes or no
 */
 
 		"bold": "__{bold text}__ ",
 		"italic": "''{italic text}'' ",
-		
+
 		"acl": {
 			snippet: "\n[\{ALLOW {permission} {principal(,principal)} \}]\n",
 			permission: "view|edit|modify|comment|rename|upload|delete",
@@ -281,12 +306,12 @@
 			}
 		},
 		"allow": { synonym: "acl" },
-	
+
 		"img": {
 			snippet:"\n[\\{Image src='{img.jpg}' width='{400px}' height='{300px}' align='{text-align}' style='{css-style}' class='{css-class}' }]\n",
 			'text-align':'left|center|right'
 		},
-				
+
 		"plugin": {
 			snippet:"\n[\\{{plugin}}]\n",
 			plugin: {
@@ -305,7 +330,7 @@
 			}
 		},
 		"tab": {
-			nScope: { 
+			nScope: {
 				"%%(":")",
 				"%%tabbedSection":"/%"
 			},
@@ -321,21 +346,21 @@
 		},
 		"table": "\n||heading-1||heading-2\n| cell11   | cell12\n| cell21   | cell22\n",
 		"quote": "\n%%quote \n{quoted text}\n/%\n",
-	
+
 		"sign": function(){
 			var name = Wiki.UserName || 'UserName';
-			return "\\\\--" + name + ", "+ new Date().toISODate() + "\n";
+			return "\\\\--" + name + ", "+ new Date().toISOString() + "\n";
 		},
 
 		"date": function(k) {
-			return new Date().toISODate()+' ';
-			//return "[{Date value='" + d.toISODate() + "' }]"
-			//return "[{Date " + d.toISODate() + " }]"
+			return new Date().toISOString()+' ';
+			//return "[{Date value='" + d.toISOString() + "' }]"
+			//return "[{Date " + d.toISOString() + " }]"
 		},
 		"lorem" : "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n",
 		"Lorem" : { synonym: "lorem" }
-	}, 
-		
+	},
+
 	/*
 	Function: suggestSnippets
 		Suggest-Snippet definitions for JSPWiki.
@@ -384,7 +409,7 @@
 			},
 			dialog: [SelectionDialog, {
 				body:'',
-				caption:'Link Suggestion Dialog', 
+				caption:'Link Suggestion Dialog',
 				onShow:this.updateSuggest.bind(this),
 				onSelect:this.updateLink.bind(this)
 			}]
@@ -392,7 +417,7 @@
 
 		};
 	},
-	
+
 	/*
 	Function: suggestLink
 		Suggest list of page of page/attachement names based on the
@@ -402,9 +427,9 @@
 
 		var txta = this.snipEditor.get('textarea'),
 			caret = txta.getSelectionRange();
-		
+
 		//extend the selection till next ] or end of the line
-		if( caret.thin ){ 
+		if( caret.thin ){
 			var end = txta.getTillEnd().search( /[\n\r\]]/ );
 			if( end!=-1 ) txta.setSelectionRange( caret.start, caret.start + end );
 		}
@@ -421,45 +446,45 @@
 			fromStart = txta.getFromStart(),
 			//match '[' + 'any char except \n or ]' at end of the string
 			searchword = fromStart.match( /\[([^\n\r\]]*)$/ )[1];
-	
+
 		if(searchword.indexOf('|') != -1) searchword = searchword.split('|')[1];
 		this.suggestPrefix = searchword.length;
-		
+
 		//ifn o searchword, then get list of page attachments
 		if(searchword == "" ) searchword = Wiki.PageName + '/';
-		//alert(searchword);		
-		
+		//alert(searchword);
+
 		Wiki.jsonrpc('search.getSuggestions', [searchword,30], function(result,exception){
 			//offline testing:
 			//var result = {list:['result1', 'result longer 2', 'result very longereererere 3', 'results moremore']};
 			//var exception;
-		
-			if( exception ){ 
 
-				alert( exception.message ); 
+			if( exception ){
 
-			} else if( !result.list || ( result.list.length == 0 ) ){ 
+				alert( exception.message );
+
+			} else if( !result.list || ( result.list.length == 0 ) ){
 
 				dialog.hide();
 
 			} else {
-			
+
 				dialog.setBody( result.list );
 
 			}
 
 		});
-		
+
 	},
-	
+
 	/*
 	Function: jspwikiTOC
 		Convert a jspwiki-markup page to an array of page sections.
 		Each section starts with a JSPWiki header line. ( !, !! !!! )
-		This function is a callback function for the [SnipEditor]. 
+		This function is a callback function for the [SnipEditor].
 		It is called by [snipeditor.buildToc] every time the textarea of the
 		snipeditor is being changed.
-	
+
 	Returns:
 		This function returns a array of objects [{title, start, indent}]
 		title - (string) title of the section without markup characters
@@ -467,12 +492,12 @@
 	 	indent - (integer) indentation or nesting level of the section 0,1...n
 	*/
 	jspwikiTOC: function( text ){
-		
+
 		// mask any header line inside a {{{ ... }}} but keep length of the text unchanged!
 		text = text.replace(/\{\{\{([\s\S]*?)\}\}\}/g, function(match){
 			return match.replace( /^!/mg, ' ' );
 		});
-			
+
 		var result = [],
 			DELIM = '\u00a4',
 			// after the regexp and split text, you'll get an array:
@@ -480,7 +505,7 @@
 			// [1,odd] : header markup !, !! or !!!
 			// [2,even] : remainder of the section, starting with header title
 			tt = text.replace( /^([!]{1,3})/mg, DELIM+"$1"+DELIM ).split(DELIM),
-				
+
 			pos = tt.shift().length,  //get length of the first element, prior to first section
 			count = tt.length;
 
@@ -491,8 +516,8 @@
 				title = tt[i+1].split(/[\r\n]/)[0]
 					//remove unescaped(~) inline wiki markup __,'',{{,}}, %%(*), /%
 					.replace(/(^|[^~])(__|''|\{\{|\}\}|%%\([^\)]+\)|%%\S+\s|%%\([^\)]+\)|\/%)/g,'$1')
-				    //and remove wiki-markup escape chars ~ 			
-					.replace(/~([^~])/g, '$1'); 
+				    //and remove wiki-markup escape chars ~
+					.replace(/~([^~])/g, '$1');
 
 			//Indent: convert length of header markup (!!!,!!,!) into #indent-level:  3,2,1 => 0,1,2
 			result.push({'title':title, 'start':pos, 'indent':3-hlen})
@@ -501,33 +526,33 @@
 
 		return result;
 	},
-	
+
 	/*
 	Function: initializePreview
 		Initialize textarea preview functionality.
 		When #autopreview checkbox is checked, bind the
 		[refreshPreview] handler to the {{preview}} event
 		of the textarea.
-		
-		Finally, send periodically the preview event. 
+
+		Finally, send periodically the preview event.
 	*/
-	initializePreview : function( snipe ){
-	
+	initializePreview: function( snipe ){
+
 		var autopreview = 'autopreview',
 			self = this,
 			prefs = Wiki.prefs,
 			refreshFn = self.refreshPreview.bind(self);
 
 		$(autopreview)
-			.setProperty('checked', prefs.get(autopreview) || false)
+			.set('checked', prefs.get(autopreview) || false)
 			.addEvent('click', function(){
 				prefs.set(autopreview, this.checked);
 				refreshFn();
 			})
 			.fireEvent('click');
-		
-		self.refreshPreview.periodical(3000, self);
-		snipe.toElement().addEvent('change',refreshFn);
+
+		refreshFn.periodical(3000);
+		$(snipe).addEvent('change',refreshFn);
     },
 
 
@@ -535,8 +560,7 @@
 	Function: refreshPreview
 		Make AJAX call to the backend to convert the contents of the textarea
 		(wiki markup) to HTML.
-		
-		
+
 	*/
 	refreshPreview: function(){
 
@@ -548,7 +572,7 @@
     		spin = $('previewspin');
 
 
-		if( !$('autopreview').checked ){ 
+		if( !$('autopreview').checked ){
 
 			if( self.previewcache ){
 				preview.empty();
@@ -557,18 +581,19 @@
 
 		} else if( self.previewcache != text ){
 
-			self.previewcache = text;		
-    		
-			new Ajax( Wiki.TemplateUrl + "/AJAXPreview.jsp?page=" + page, { 
-				postBody: 'wikimarkup=' + encodeURIComponent( text ),
+			self.previewcache = text;
+
+			new Request.HTML({
+				url:Wiki.TemplateUrl + "/AJAXPreview.jsp?page=" + page,
+				data: 'wikimarkup=' + encodeURIComponent( text ),
 				update: preview,
 				onRequest: function(){ spin.show(); },
 				onComplete: function(){ spin.hide(); Wiki.renderPage(preview, page); }
-			}).request();
-		
+			}).send();
+
 		}
 	}
-	
+
 }
 
 /*
@@ -581,30 +606,30 @@
 
 /*
 Class: SnipEditor
-	The SnipEditor class enriches a TEXTAREA object with many capabilities, 
-	including tab-autocompletion, auto-indentation, smart typing pairs, suggestion 
+	The SnipEditor class enriches a TEXTAREA object with many capabilities,
+	including tab-autocompletion, auto-indentation, smart typing pairs, suggestion
 	popups, live-preview, textarea resizing, toggle buttons etc.
-	The configuration of the snip-editor is done through Snippet objects. 
+	The configuration of the snip-editor is done through Snippet objects.
 	See [getSnippet] for more info on how to define snippets.
 
 Credit:
-	The SnipEditor was inspired by postEditor (by Daniel Mota aka IceBeat, 
+	The SnipEditor was inspired by postEditor (by Daniel Mota aka IceBeat,
 	http://icebeat.bitacoras.com ) and ''textMate'' (http://macromates.com/).
 	It has been written to fit with needs of the JSPWIKI project.
-	The main changes and enhancements include support for suggestion-popups, toolbar 
-	driven toggle buttons, simplified the snippet definition, 
+	The main changes and enhancements include support for suggestion-popups, toolbar
+	driven toggle buttons, simplified the snippet definition,
 	and compatible with IE6/7. (ugh)
-	
+
 	Dirk Frederickx, Oct-Dec 2008
-	
+
 Arguments:
 	el - textarea element
 	options - optional, see options below
 
 Options:
-	tab - (string) number of spaces used to insert/remove a tab in the textarea; 
+	tab - (string) number of spaces used to insert/remove a tab in the textarea;
 		default is 4
-	tabcompletion - (boolean, default true) when set to true, 
+	tabcompletion - (boolean, default true) when set to true,
 	    the tabSnippet keywords will be expanded
 		when pressing the TAB key.  See also [tabSnippet]
 	tabsnips - (snippet-object) set of snippets, which will be expanded when
@@ -614,11 +639,11 @@
 	suggestsnips - (snippet-object) set of snippets which are triggered at
 		key-up or mouse click events. Typically suggestsnips are used to generate
 		help dialog popups.
-	buttons - (array of Elements), each button elemnet will bind its click-event 
+	buttons - (array of Elements), each button elemnet will bind its click-event
 	    with [onButtonClick}. When the click event fires, the {{rel}} attribute
 	    or the text of the element will be used as snippet keyword.
 	    See also [tabSnippet].
-	dialogs - set of dialogs, consisting of either a Dialog object, 
+	dialogs - set of dialogs, consisting of either a Dialog object,
 		or a set of {dialog-options} for the predefined
 		dialogs suchs as Font, Color and Special.
 		See property [initializeDialogs] and [openDialog]
@@ -626,7 +651,7 @@
 	next - (Element), when pressing Shift-Enter, the textarea will ''blur'' and
 		this ''next'' element will ge the focus.
 		This compensates the overwritting default TAB handling of the browser.
-	onresize - (function, optional), when present, a textarea resize bar 
+	onresize - (function, optional), when present, a textarea resize bar
 		with css class {{resize-bar}} is added after the textarea,
 		allowing to resize the heigth of the textarea.
 		This onresize callback function is called whenever
@@ -635,16 +660,16 @@
 Dependencies:
 	[Textarea]
 	[UndoRedo]
-	
+
 Example:
 	(start code)
 	<script>
 		new SnipEditor( "mainTextarea", {
-			tabsnips: { bold:"**{bold text}**", italic:"''{italice text}''" }, 
+			tabsnips: { bold:"**{bold text}**", italic:"''{italice text}''" },
 			tabcompletion:true,
-			directsnips: { '(':')', '[' : ']' }, 
+			directsnips: { '(':')', '[' : ']' },
 			buttons: $$('a.tool'),
-			next:'nextInputField' 
+			next:'nextInputField'
 	  	});
   	</script>
 	(end)
@@ -652,6 +677,7 @@
 */
 var SnipEditor = new Class({
 
+	Implements: Options,
 	options: {
 		tab: "    ", //default tab = 4 spaces
 		tabcompletion: true,
@@ -694,10 +720,10 @@
 				.removeProperty('id')
 				.removeProperty('name')
 				.injectBefore( main.hide() )
-				.addEvent('change', self.onChangeTXTA.bind( self ) ); 
-				// Make sure to catch ALL {{change}} events, and copy the 
-				// content of txta back to the main textarea. 
-				// This includes the ''last'' change event, just before firing 
+				.addEvent('change', self.onChangeTXTA.bind( self ) );
+				// Make sure to catch ALL {{change}} events, and copy the
+				// content of txta back to the main textarea.
+				// This includes the ''last'' change event, just before firing
 				// the submit event of the form.
 
 		self.textarea = new Textarea( txta );
@@ -708,7 +734,7 @@
 		self.initializeResizing( txta );
 
 		var keystroke = self.onKeystroke.bind( self ),
-			btns = options.buttons,
+			btns = $$(options.buttons),
 			find = options.findForm.submit,
 			suggest = self.suggestSnippet.bind( self );
 
@@ -725,14 +751,14 @@
 			.addEvent( 'keyup', suggest );
 
 	},
-	
-		
+
+
 	/*
 	Function: toElement
 		Retrieve textarea DOM element;
-		This allows the dollar function to return 
+		This allows the dollar function to return
 		the element when passed an instance of the class. (mootools 1.2.x)
-		
+
 	Example:
 	>	var snipe = new SnipEditor('textarea-element');
 	>	$('textarea-element') == snipe.toElement();
@@ -741,21 +767,21 @@
 	*/
 	toElement: function(){
 		return this.textarea.toElement();
-	},	
-	
+	},
+
 	/*
 	Function: get
-		Retrieve some of the public properties of the snip-editor: 
+		Retrieve some of the public properties of the snip-editor:
 		textarea, resize object.
 
 	Arguments:
 		item - 'resize' or 'textarea'
 	*/
 	get: function(item){
-		return( /textarea|dialogs|tabcompletion|tabsnips|directsnips|suggestsnips/.test(item) 
+		return( /textarea|dialogs|tabcompletion|tabsnips|directsnips|suggestsnips/.test(item)
 			? this[item] : null )
 	},
-	
+
 	/*
 	Function: set
 		Set/Reset some of the options of the snip-editor.
@@ -775,13 +801,13 @@
 
 	/*
 	Function: onKeystroke
-		This is a cross-browser keystroke handler for keyPress and keyDown 
+		This is a cross-browser keystroke handler for keyPress and keyDown
 		events on the textarea.
 
 	Note:
 		The KeyPress is used to accept regular character keys.
 		The KeyDown event captures all special keys, such as Enter, Del, Backspace, Esc, ...
-		To work around some browser incompatibilities, a hack with the {{event.which}} 
+		To work around some browser incompatibilities, a hack with the {{event.which}}
 		attribute is used to grab the actual special chars.
 		Ref. keyboard event paper by Jan Wolter, http://unixpapa.com/js/key.html
 		Todo: check on Opera
@@ -791,26 +817,27 @@
 	*/
 	onKeystroke: function(e){
 
-		e = new Event(e);
+		//e = new Event(e);
+		console.log("keystroke "+e.shift+" "+e.type );
 
 		if( e.type=='keydown' ){
 
 			//Only accept special keys via keydown event
-			if( !Event.keys[e.key] ) return;
+			if( !Event.Keys[e.key] ) return;
 
 		} else { // e.type=='keypress'
 
 			//Only accept regular character keys via keypress event
 			//Note: cross-browser hack with 'which' attribute for special chars
-			if( $chk(e.event.which) && (e.event.which==0) ) return; 
+			if( $chk(e.event.which) && (e.event.which==0) ) return;
 
 			//Reset faulty 'special char' treatment by mootools
-			e.key = String.fromCharCode(e.code).toLowerCase(); 
+			e.key = String.fromCharCode(e.code).toLowerCase();
 
 		}
 
 	    if( e.shift && e.key=='enter' ){
-	    
+
 	    	//Exit and jump to the next element
 	    	e.stop();
 	    	this.clearActiveSnip();
@@ -818,40 +845,40 @@
 	    	return;
 
 	    }
-	    
+
 	    var self = this,
 	    	txta = self.textarea,
 	    	el = txta.toElement(),
 	    	caret = txta.getSelectionRange(),
-			top = el.scrollTop, 
+			top = el.scrollTop,
 			left = el.scrollLeft;
-	    
+
 		if( this.directSnippet(e, txta, caret) ) return;
 
 		el.focus();
 
 		switch( e.key ){
 
-			case 'tab': 
+			case 'tab':
 
 				e.stop();
-	
+
 				if( self.activeSnip ){
 
 					return self.nextParameter(txta, caret);
 
 				} else {
-				
+
 					if( self.tabSnippet(e, txta, caret) ) return;
 
 					self.convertTabToSpaces(e, txta, caret);
 
 				}
-				
+
 				break;
 
 			case 'up' :
-			case 'down': 
+			case 'down':
 			case 'esc': self.clearActiveSnip(); return;
 
 			case 'enter': self.onEnter(e, txta, caret); break;
@@ -866,7 +893,7 @@
 		el.scrollLeft = left;
 
 	},
-	
+
 	/*
 	Function: onEnter
 		When the Enter key is pressed, the next line will be ''auto-indented''
@@ -878,7 +905,7 @@
 		caret - caret object, indicating the start/end of the textarea selection
 	*/
 	onEnter: function(e, txta, caret) {
-		
+
 		//if( this.activeSnip ){
 			//fixme
 			//how to 'continue previous snippet ??
@@ -888,7 +915,7 @@
 		//}
 
 		this.clearActiveSnip();
-		
+
 		if( caret.thin ){
 
 			var fromStart = txta.getFromStart(),
@@ -896,13 +923,13 @@
 				indent = prevline.match( /^\s+/gi );
 
 			if( indent ){
-				e.stop(); 
+				e.stop();
 				txta.insertAfter( '\n' + indent.join('') );
 			}
 
 		}
 	},
-	
+
 	/*
 	Function: onBackspace
 		Remove single-character directsnips such as {{ (), [], {} }}
@@ -916,7 +943,7 @@
 
 		if( caret.thin  && (caret.start > 0) ){
 
-			var key = txta.getValue().charAt(caret.start-1), 
+			var key = txta.getValue().charAt(caret.start-1),
 				snip = this.getSnippet( this.options.directsnips );
 
 			if( snip && (snip.snippet == txta.getValue().charAt(caret.start)) ){
@@ -949,7 +976,7 @@
 				.setSelection('');
 
 		}
-	},	
+	},
 
 
 	/*
@@ -967,19 +994,19 @@
 		var form = this.options.findForm,
 			dialog = form.findDialog,
 			showDialog = ( dialog.getStyle('display')=='none' );
-			
-		dialog.setStyle( 'display', showDialog ? '' : 'none' );	
+
+		dialog.setStyle( 'display', showDialog ? '' : 'none' );
 		showDialog ? form.findInput.focus() : this.toElement().focus();
-		
+
 	},
-	
+
 	/*
 	Function: onFindAndReplace
 		Perform the find and replace operation on either the full textarea
-		or the selection of the textarea. It supports 
+		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. 
+		find and replace dialog.
 
 	Arguments:
 		e - event
@@ -995,21 +1022,21 @@
 			isRegExp	= (fo.isRegExp) ? fo.isRegExp.checked : false,
 			reGlobal	= (fo.isReplaceGlobal && fo.isReplaceGlobal.checked) ? 'g' : '',
 			reMatchCase	= (fo.isMatchCase && fo.isMatchCase.checked) ? '' : 'i';
-			
+
 		if( findText == '' ) return;
 
 		var sel = txta.getSelection() || '',
 			data = (sel=='') ? txta.getValue() : sel;
-			
+
 		if( !isRegExp ) findText = findText.escapeRegExp();
-		
+
 		var re = new RegExp(findText, reGlobal + reMatchCase + 'm'); //multiline
 
 		if( data.match(re) ){
 
 			this.undoredo.onChange();
-			data = data.replace(re, replaceText);  
-			(sel=='') ? txta.toElement().value = data : txta.setSelection(data);			
+			data = data.replace(re, replaceText);
+			(sel=='') ? txta.toElement().value = data : txta.setSelection(data);
 
 		} else {
 
@@ -1021,8 +1048,8 @@
 
 	/*
 	Function: setActiveSnip
-		The activeSnip contains an array with ''{parameters}'' used to step through 
-		each parameter when pressing subsequent tabs. 
+		The activeSnip contains an array with ''{parameters}'' used to step through
+		each parameter when pressing subsequent tabs.
 		It also contains a ref to the related snippet and snippet key.
 		See also nextParameter(..)
 		As long the snippet is active, the textarea gets the css class {{activeSnip}}.
@@ -1048,7 +1075,7 @@
 	clearActiveSnip: function(){
 
 		var self = this;
-		
+
 	    self.activeSnip = null;
 		self.hideDialog();
 		self.toElement().removeClass('activeSnip').focus();
@@ -1060,10 +1087,10 @@
 		found or not in scope.
 
 	About snippets:
-	In the simplest case, you can use snippets to insert plain text that you do not 
-	want to type again and again. The snippet is expanded when hitting 
+	In the simplest case, you can use snippets to insert plain text that you do not
+	want to type again and again. The snippet is expanded when hitting
 	the Tab key: the ''snippet'' is replaced by ''snippet expansion text''.
-	
+
 	(start code)
 	var tabSnippets = {
 		<snippet1> : <snippet expansion text>,
@@ -1073,8 +1100,8 @@
 
 	See also [DirectSnippets].
 
-	For example, following snippet will expand the ''toc'' text into the 
-	TableOfContents wiki plugin call. Don't forget to escape '{' and '}'  
+	For example, following snippet will expand the ''toc'' text into the
+	TableOfContents wiki plugin call. Don't forget to escape '{' and '}'
 	with a backslash, because they have a special meaning. (see below)
 	Use the '\n' charater to define multi-line snippets. Start the snippet
 	with '\n' to make sure the snippet starts on a new line.
@@ -1083,17 +1110,17 @@
 	"toc": "\n[\{TableOfContents \}]\n"
 	(end)
 
-	After tab-completion, the caret is placed just after the expanded snippet. 
+	After tab-completion, the caret is placed just after the expanded snippet.
 
 	Snippet parameters:
 	If you want, you can put ''{parameters}'' inside the snippet. Pressing the tab
-	will jump to the next parameter. If you are ok with the default value, 
+	will jump to the next parameter. If you are ok with the default value,
 	just tab over it. If not, start typing to overwrite it.
-	
+
 	(start code)
 	"bold": "__{some bold text}__"
 	(end)
-   
+
 	You can have multiple ''{parameters}'' too. Pressing more tabs will get you there.
 
 	(start code)
@@ -1101,9 +1128,9 @@
 	(end)
 
 	Extended snippet syntax:
-	So far we discussed the simple snippet syntax. In order to unlock more advanced 
+	So far we discussed the simple snippet syntax. In order to unlock more advanced
 	snippet features, you'll need to use the extended snippet syntax.
-	
+
 	(start code)
 	"toc": {
 		snippet : "\n[\{TableOfContents \}]\n"
@@ -1119,20 +1146,20 @@
 	Snippet synonyms:
 	Instead of defining the snippet text, you can also refer to another snippet.
 	This allows you to create synonyms.
-	
+
 	(start code)
-	"allow": { 
-		synonym: "acl" 
+	"allow": {
+		synonym: "acl"
 	}
 	(end)
 
 	Dynamic snippets:
-	Next to static snippet texts, you can also dynamically generate 
+	Next to static snippet texts, you can also dynamically generate
 	the snippet text through a javascript function. For example, you could
 	use ajax calls to populate the snippet on the fly. The function should return
 	either the string (simple snippet syntax) or a snippet object.
 	(eg return {{ { snippet:"..." } }} )
-	
+
 	(start code)
 	"date": function(e, textarea){
 		return new Date().toLocaleString();
@@ -1154,9 +1181,9 @@
 	Parameter dialog boxes:
 	To help the entry of parameters, you can specify a predefined set of choices
 	for a ''{parameter}'', as a string (with | separator), js array or js object.
-	A parameter dialog box will be displayed to provide easy selection of 
+	A parameter dialog box will be displayed to provide easy selection of
 	one of the choices.  See [SelectionDialog].
-	
+
 	Example of parameter suggestion-list:
 
 	(start code)
@@ -1177,13 +1204,13 @@
 		}
 	}
 	(end)
-	
+
 	You can also define global dialog boxes via the ''dialogs'' option, which
-	can be re-used in any snippet.	
-	
+	can be re-used in any snippet.
+
 	(start code)
 	new SnipEditor( $('myTextarea'), {
-		...	
+		...
 		tabSnippet: {
 			acl: "[\{ALLOW {permission} \}]"
 		},
@@ -1197,7 +1224,7 @@
 
 	Arguments:
 		snips - snippet collection object for lookup of the key
-		key - (optional) snippet key. If not present, retreive the key from 
+		key - (optional) snippet key. If not present, retreive the key from
 		 	the textarea just to the left of the caret. (i.e. tab-completion)
 
 	Returns:
@@ -1216,7 +1243,7 @@
 		var txta = this.textarea,
 			fromStart = txta.getFromStart(),
 			snip = false;
-			
+
 		if( key ){
 
 			snip = snips[key];
@@ -1225,7 +1252,7 @@
 
 			//lookup key and snippet backwards from the text preceeding the caret
 			var len = fromStart.length;
-				
+
 			for( var sn in snips ){
 				if( (len >= sn.length) && (sn == fromStart.slice( - sn.length ) ) ){
 					snip = snips[sn];
@@ -1261,7 +1288,7 @@
 		if(last) parms.push( s.slice(s.lastIndexOf(last) + last.length) );
 
 		//collapse \n of previous line if the snippet starts with \n
-		if( (s.indexOf('\n')==0) 
+		if( (s.indexOf('\n')==0)
 		&& ( fromStart.slice(0, -key.length ).test( /(^|\n\s*)$/g ) ) ) {
 			s = s.substr(1);
 		}
@@ -1270,24 +1297,24 @@
 
 		//auto-indent the snippet's internal \n
 		var prevline = fromStart.split('\r?\n').pop(),
-			indent = prevline.match(/^\s+/gi); 
+			indent = prevline.match(/^\s+/gi);
 		if( indent ) s = s.replace( /\n/g, '\n' + indent.join('') );
 
 		//complete the snip object
 		snip.text = s;
 		snip.parms = parms;
 
-		return snip; 				
+		return snip;
 	},
-	
+
 	/*
 	Function: inScope
-		Sometimes it is useful to restrict the scope of a snippet, and only perform 
+		Sometimes it is useful to restrict the scope of a snippet, and only perform
 		the tab-completion in specifc parts of the text. The scope parameter allows
-		you to do that by defining start and end delimiting strings. 
+		you to do that by defining start and end delimiting strings.
 		For example, the following "fn" snippet will only expands when it appears
-		inside the scope of a script tag. 
-	
+		inside the scope of a script tag.
+
 		(start code)
 		"fn": {
 			snippet: "function( {args} )\{ \n    {body}\n\}\n",
@@ -1297,7 +1324,7 @@
 
 		The opposite is possible too. Use the 'nScope' or not-in-scope parameter
 		to make sure the snippet is only inserted when not in scope.
-	
+
 		(start code)
 		"special": {
 			snippet: "{special}",
@@ -1318,7 +1345,7 @@
 
 			if( $type( snip.scope )=='function' ){
 
-				return snip.scope( this.textarea ); 
+				return snip.scope( this.textarea );
 
 			} else {
 
@@ -1333,14 +1360,14 @@
 		}
 
 		if( snip.nScope ){
-		
+
 			for( var key in snip.nScope ){
 
 				var open = text.lastIndexOf(key);
 				if( (open > -1) && (text.indexOf( snip.nScope[key], open ) == -1) ) return false;
 
 			}
-		
+
 		}
 		return true;
 	},
@@ -1351,7 +1378,7 @@
 		Direct snippet are invoked immediately when the key is pressed
 		as opposed to a [tabSnippet] which are expanded after pressing the Tab key.
 
-		Direct snippets are typically used for smart typing pairs, 
+		Direct snippets are typically used for smart typing pairs,
 		such as {{ (), [] or {}. }}
 		Direct snippets can also be defined through javascript functions
 		or restricted to a certain scope. (ref. [getSnippet], [inScope] )
@@ -1369,7 +1396,7 @@
 
 	Example:
 	(start code)
-	directSnippets: { 
+	directSnippets: {
 		'"' : '"',
 		'(' : ')',
 		'{' : '}',
@@ -1384,13 +1411,13 @@
 		}
 	}
 	(end)
-	
+
 	*/
 	directSnippet: function(e, txta, caret){
 
 		var snip = this.getSnippet( this.options.directsnips, e.key );
 		if(!snip) return false;
-		
+
 		e.stop();
 
 		txta.setSelection( e.key, txta.getSelection(), snip.snippet )
@@ -1413,13 +1440,13 @@
 	*/
 	tabSnippet: function(e, txta, caret){
 
-		if( !this.options.tabcompletion ) return;	
-		            
+		if( !this.options.tabcompletion ) return;
+
 		if( caret.thin ){
 			var snip = this.getSnippet( this.options.tabsnips );
 		}
 		if( !snip ) return false;
-		
+
 		this.undoredo.onChange();
 
 		//replace the snippet key by the snippet text
@@ -1440,18 +1467,18 @@
 			this.nextParameter(txta, caret);
 
 		}
-		
+
 		return true;
 	},
 
 	/*
 	Function: onButtonClick
 		This function is a Click event handler.
-		It looks up the snippet based on the rel-attribute or the text value 
+		It looks up the snippet based on the rel-attribute or the text value
 		of the clicked element, and inserts its value in the textarea.
 
 		When text was selected prior to the click event, the selection will
-		be injects in one of the snippet {parameter}. 
+		be injects in one of the snippet {parameter}.
 
 		Additionally, when the snippet only contains one {parameter},
 		the snippet will toggle: i.e. remove the snippet when already present,
@@ -1471,28 +1498,28 @@
 
 		var self = this,
 			el = e.target,
-			key = el.getProperty('rel') || el.getText(); 
+			key = el.get('rel') || el.get('text');
 
 		//toggle previously activate dialog, if it is the same command !!fixme
 		if( self.activeDialog ) return self.hideDialog();
 
-		//catch predefined commands 
+		//catch predefined commands
 		if( key=='undo' ) return self.undoredo.onUndo();
 		if( key=='redo' ) return self.undoredo.onRedo();
 		if( key=='find' ) return self.toggleFindAndReplace();
 
 
 		var snip = self.getSnippet( self.options.tabsnips, key );
-		self.relativeTo = el; //this is a button event -- used to positon the dialog 
+		self.relativeTo = el; //this is a button event -- used to positon the dialog
 
 		if( !snip ){
 
 			//check if this is a button-only dialog command
-			if( self.dialogs[key] ) self.openDialog( key );	
+			if( self.dialogs[key] ) self.openDialog( key );
 			return;
 		}
-		
-		var txta = self.textarea, 
+
+		var txta = self.textarea,
 			caret = txta.getSelectionRange();
 
 		self.undoredo.onChange();
@@ -1504,7 +1531,7 @@
 		if( !caret.thin ){
 
 			//when text was selected, inject it the first undefined {parameter}
-			var dialogs = self.dialogs; 
+			var dialogs = self.dialogs;
 
 			snip.parms.slice(0,-1).some( function(parm,i){
 
@@ -1516,7 +1543,7 @@
 
 			});
 		}
- 
+
 		//now insert the snippet text
 		txta.setSelection( s );
 
@@ -1531,19 +1558,19 @@
 			//this snippet has one or more parameters
 			//store the active snip and process the first {parameter}
 			self.setActiveSnip( snip );
-			//alert(Json.toString(snip));
+			//alert(JSON.encode(snip));
 			caret = txta.getSelectionRange(); //update new caret
-			
+
 			self.nextParameter(txta, caret);
-	
+
 		}
 
 	},
 
 	/*
 	Function: toggleSnippet
-		This helper function toggles a snippet. 
-		The snippet should consists of exactly one parameter.		
+		This helper function toggles a snippet.
+		The snippet should consists of exactly one parameter.
 		It is called by the onButtonClick event handler.
 
 	Arguments:
@@ -1556,10 +1583,10 @@
 		var selection = txta.getSelection();
 
 		// First validate the toggle conditions:
-		// 1) check if some text was selected, 
+		// 1) check if some text was selected,
 		// 2) check whether there is exactly one {parameter} in the snippet
 		if( (selection=='') || (snip.parms.length!= 2) ) return false;
-				
+
 		var s = snip.text,
 			//get the first and last textual parts of the snippet
 			//the last marker already contains the final text part of the snippet
@@ -1582,7 +1609,7 @@
 		} else if( txta.getFromStart().test(fst+'$') && txta.getTillEnd().test('^'+lst) ){
 
 			txta.setSelectionRange(caret.start-fst.length, caret.end+lst.length);
-			
+
 		} else {
 
 			//insert snippet
@@ -1590,8 +1617,8 @@
 				.setSelectionRange( caret.start + fst.length );
 		}
 
-		txta.setSelection( selection );	
-		return true;	
+		txta.setSelection( selection );
+		return true;
 	},
 
 	/*
@@ -1599,13 +1626,13 @@
 		Suggestion snippets are dialog-boxes appearing as you type.
 		When clicking items in the suggest dialogs, content is inserted
 		in the textarea.
-		
-		
+
+
 	Example:
 	> FIXME!!
 	(start code)
 	suggestionSnippets: [
-		{ // 0 : page links  
+		{ // 0 : page links
 			scope:{ '[':']'	},
 			snippet: function(e, textarea){
 				ajax = <retrieve suggestion list>.join('|');
@@ -1613,7 +1640,7 @@
 			}
 		},
 		{ // 1 : color dialog
-			scope:{ 
+			scope:{
 				'%%(color:#':';',
 				'%%(background-color:#':';'
 			},
@@ -1624,10 +1651,10 @@
 		}
 	]
 	(end)
-	
+
 	*/
 	suggestSnippet: function(){
-	
+
 		var self = this,
 			txta = self.textarea,
 			fromStart = txta.getFromStart(),
@@ -1640,7 +1667,7 @@
 
 				var snip = snips[sn];
 				if( self.inScope(snip, fromStart) ){
-				
+
 					//alert('bingo '+sn);
 					//get dialog
 					if( !dialogs[sn] ){
@@ -1650,7 +1677,7 @@
 						//if( !dialog ) continue; //bad snippet def.
 						dialogs[sn] = snip.dialog;
 					}
-					self.openDialog( sn ); 
+					self.openDialog( sn );
 					return; //found
 				}
 			}
@@ -1678,12 +1705,12 @@
 
 			parameter = parms.shift();
 			pos = txta.getValue().indexOf(parameter, caret.start);
-				
+
 			if( pos > -1 ){
-			
+
 				//found the next {parameter} or possibly the end of the snippet
 				this.hideDialog();
-			
+
 				if( parms.length > 0 ){
 
 					// select the next {parameter}
@@ -1693,18 +1720,18 @@
 					this.undoredo.onChange();
 
 					// open a suggestion dialog, if any
-					this.openDialog( parameter );	
+					this.openDialog( parameter );
 
 					return; // and retain the activeSnip for subsequent {parameters}
-				
+
 				} else {
 
 					// no more {parameters}, move the caret after the end of the snippet
 					txta.setSelectionRange( pos + parameter.length );
-					
+
 				}
-			}		
-		}		
+			}
+		}
 
 		this.clearActiveSnip();
 
@@ -1716,9 +1743,9 @@
 		While dragging the textarea, also updates the size of the
 		''toc'' overlay menu. Notice the addtion of 10px (8+2)
 		to compensate for padding and borders. (CHECK)
-		
+
 		When done, call the onresize callback handler.
-		
+
 	Arguments:
 		txta - Textarea object
 	*/
@@ -1730,9 +1757,9 @@
 		if( resizeFn ){
 
 			txta.makeResizable({
-				handle: new Element('div',{'class': 'resize-bar' }).injectAfter(txta), 
-				modifiers: { x:false, y:'height' },
-				onDrag: function() { 
+				handle: new Element('div',{'class': 'resize-bar'}).injectAfter(txta),
+				modifiers: { x:null },
+				onDrag: function() {
 					var toc = self.toc.element;
 					if( toc ) toc.setStyle('height', 10+this.value.now.y ) ;
 				},
@@ -1740,34 +1767,34 @@
 			});
 
 		}
-	
+
 	},
 
 	/*
 	Function: initializeDialogs
 		Prepare the set of predefined parameter dialog for fonts, colors, special.
 		And mixin the parameters from the dialog options.
-		
-		The snipEditor dialog options contain entries xxx either 
-		- a pre-created Dialog object, 
+
+		The snipEditor dialog options contain entries xxx either
+		- a pre-created Dialog object,
 		- an array with ~[Dialog-object, {Dialog options}~]
 			This will be initialised during the first invocation of the dialog.
-		- a set of ''{dialog-options}'' which will overwrite some of the options of  
+		- a set of ''{dialog-options}'' which will overwrite some of the options of
 			the predefined dialogs suchs as Font, Color and Special.
 	*/
 	initializeDialogs: function(){
-	
+
 		var select = this.onSelectDialog.bind(this),
 			change = this.onChangeDialog.bind(this);
-			
+
 		this.dialogs = {
 				fonts: [FontDialog, {caption:'Fonts', autoClose:true, onSelect:select}],
 				colors: [ColorDialog, {colorImage:'../dialog/circle-256.png', onChange:change}],
 				special: [CharsDialog, {caption:'Special Chars', autoClose:true, onSelect:select}]
 		};
 
-		//process the snipeditor.options.dialogs		
-		var dlgs = this.options.dialogs, 
+		//process the snipeditor.options.dialogs
+		var dlgs = this.options.dialogs,
 			dialogs = this.dialogs;
 		for( var d in dlgs ){
 
@@ -1797,10 +1824,10 @@
 	onSelectDialog: function( newtext ){
 
 		var txta = this.textarea;
-		
+
 		txta.setSelection( newtext )
 			.setSelectionRange( txta.getSelectionRange().end );
-			
+
 		this.nextParameter(txta, txta.getSelectionRange() );
 
 	},
@@ -1819,7 +1846,7 @@
 		this.textarea.setSelection( newtext );
 
 	},
-	
+
 
 	/*
 	Function: openDialog
@@ -1847,9 +1874,9 @@
 			//suggestion defined inside the snippet takes precedences.
 			dialog = new SelectionDialog({
 				body: suggest,
-				caption: parm, 
+				caption: parm,
 				onSelect: self.onSelectDialog.bind(self)
-			});	
+			});
 
 		} else if( dialog ){
 
@@ -1873,7 +1900,7 @@
 		self.activeDialog = dialog.show();
 
 	},
-	
+
 	/*
 	Function: hideDialog
 		Clear the active dialog and hide it.
@@ -1881,21 +1908,21 @@
 	hideDialog: function(){
 
 		var active = this.activeDialog;
-		if( active ){ 
+		if( active ){
 			active.hide();
 			this.activeDialog = null;
 		}
 
 	},
-	
+
 	/*
 	Function: initializeToc
 		Initialize the Table-Of-Contents of the textarea.
 		This clickable TOC allows the user to quickly zoom-in or
 		swith between section of the textarea.
-		
+
 		The sections are delimitted by header lines.
-		
+
 		The textarea is cloned into a main and work area.
 		The workarea is used for actual editing.
 		The mainarea reflects at all times the whole document.
@@ -1903,14 +1930,14 @@
 		The TOC is injected in a #snipetoc element, with absolute position,
 		such that is mapped perfectly behind the visible textarea.
 		The #snipetoc is resized equally to the textarea.
-		
+
 	*/
 	initializeToc: function( txta ){
-		
+
 		var self = this,
 			onChangeTXTA = self.onChangeTXTA.bind(self),
 			buildToc = self.buildToc.bind(self);
-			
+
 		if( self.options.toc.tocParser ){
 
 			self.toc = { /*items:[], begin:0, end:0,*/ cursor:0 };
@@ -1924,31 +1951,31 @@
 					'height': 10+txta.getStyle('height').toInt()
 				},
 				'events':{
-					'mouseenter':function(){ 
+					'mouseenter':function(){
 						onChangeTXTA();
-						$('snipetoc').removeClass('hidden'); 
+						$('snipetoc').removeClass('hidden');
 					},
 					'mouseleave':function(){ $('snipetoc').addClass('hidden'); }
 				}
 			}).adopt( self.toc.elements = new Element('ul') )
 				.injectBefore( txta );
-				
+
 			buildToc(); /*CHECK*/
 
 		}
-	},	
-	
+	},
+
 	/*
 	Function: buildToc
 		UPDATE/RFEFRESH the textarea table-of-contents selection list
 		This function is called at startup, and everytime the section textarea changes.
-		
-	Postcondition: 
+
+	Postcondition:
 		The section-edit dropdown contains following entries
 		* 0: ( all )
 		* 1: start-of-page (if applicable)
 		* 2..n: page sections
-	 */  
+	 */
 	 buildToc: function(){
 
 		var self = this,
@@ -1962,10 +1989,10 @@
 						'styles': {	'padding-left':(item.indent+0.5)+'em' },
 						'title':item.title,
 						'events':{
-							'click':self.selectTocItem.pass([index], self) 
+							'click':self.selectTocItem.pass([index], self)
 						}
-					}).setHTML(item.title.trunc(30))
-				); 
+					}).set('html',item.title.trunc(30))
+				);
 			},
 
 			liArr = [ newItem({title: options.all, start:0, indent:0}, -2) ],
@@ -1980,8 +2007,8 @@
 				liArr.push( newItem({title: options.startOfPage, start:0, indent:0}, -1) );
 			}
 
-			items.each( function(item, index){ 
-				liArr.push( newItem( item, index ) ); 
+			items.each( function(item, index){
+				liArr.push( newItem( item, index ) );
 			},self);
 
 		}
@@ -1990,7 +2017,7 @@
 
 	},
 
-	/* 
+	/*
 	Function: tocCursor
 
 	Arguments:
@@ -2004,23 +2031,23 @@
 		var toc = this.toc,
 			els = toc.elements.getChildren(),
 			offset = ((toc.items.length==0) || (toc.items[0].start>0)) ? 2 : 1;
-			
+
 		if( cursor < -2 ) cursor = -2;
 		this.toc.cursor = cursor;
 
 		els.removeClass('cursor');
-		if( els[cursor+offset] ) els[cursor+offset].addClass('cursor'); 
+		if( els[cursor+offset] ) els[cursor+offset].addClass('cursor');
 
 		$('snipetoc').addClass('hidden');
 	},
 
-	/* 
+	/*
 	Function: selectTocItem
 		Copy the right section of the main textarea to the work
 		textarea.
 
-		This event handler is called when the user clicks one of the 
-		entries of the Table Of contents. 
+		This event handler is called when the user clicks one of the
+		entries of the Table Of contents.
 
 	Arguments:
 		cursor - index of the display table of contents item
@@ -2030,12 +2057,12 @@
 	*/
 	selectTocItem: function( cursor ){
 
-		var txta = this.toElement(), 
+		var txta = this.toElement(),
 			main = this.mainarea.value,
 			toc = this.toc,
 			items = toc.items;
-			
-		//FIXME : what if no toc undefined : eg wiki-comments.	
+
+		//FIXME : what if no toc undefined : eg wiki-comments.
 
 		//default : show all
 		toc.begin = 0;
@@ -2048,7 +2075,7 @@
 
 		} else if(cursor >= 0  && cursor < items.length){
 
-			toc.begin = items[cursor].start; 
+			toc.begin = items[cursor].start;
 			if( cursor+1 < items.length ) toc.end = items[cursor+1].start;
 
 		} else {
@@ -2056,7 +2083,7 @@
 			cursor = -2;
 
 		}
-		
+
 		this.tocCursor( cursor );
 
 		txta.value = main.slice( toc.begin, toc.end );
@@ -2068,20 +2095,20 @@
 	Function: onChangeTXTA
 		This event handler is invoked when text is changed in the textarea.
 		It's main duty is to copy the textarea back into the main textarea,
-		on the right location.  When done, the snip toc is refreshed.		
-		
-		This {{change}} event fires when: 
+		on the right location.  When done, the snip toc is refreshed.
+
+		This {{change}} event fires when:
 		# {{change}} event on the textarea
-		  This event also fires just before the form is submitted. 
+		  This event also fires just before the form is submitted.
 		# user clicks a toolbar-button
 
 		This handler is also invoked when the {{mouseover}} event fires
 		to make the toc menu visible.
 
 	*/
-	onChangeTXTA: function(){	
+	onChangeTXTA: function(){
 
-		var	txta = this.toElement(),	
+		var	txta = this.toElement(),
 			main = this.mainarea,
 			toc = this.toc;
 
@@ -2092,7 +2119,7 @@
 			var	s = main.value,
 				//insert \n to ensure the next section always starts on a new line.
 				linefeed = (txta.value.slice(-1) != '\n')  ? '\n' : '';
-			
+
 			main.value = s.slice(0, toc.begin) + txta.value + linefeed + s.slice(toc.end);
 			toc.end = toc.begin + txta.value.length;
 
@@ -2104,7 +2131,7 @@
 	Function: convertTabToSpaces
 		Convert tabs to spaces. When no snippets are detected, the default
 		treatment of the TAB key is to insert a number of spaces.
-		Indentation is applied in case of multi-line selections. 
+		Indentation is applied in case of multi-line selections.
 
 	Arguments:
 		e - event
@@ -2165,33 +2192,33 @@
 	Function: getState
 		Get the current state of the SnipEditor which consist of
 		the content and selection of the textarea.
-		It implements the ''Undoable'' interface called from the 
+		It implements the ''Undoable'' interface called from the
 		[UndoRedo] class.
 	*/
 	getState: function(){
 
 		var txta = this.textarea,
-			el = txta.toElement(); 
+			el = txta.toElement();
 
-		return { 
+		return {
 			main: this.mainarea.value,
-			value: el.getValue(), 
-			cursor: txta.getSelectionRange(), 
-			scrollTop: el.scrollTop, 
+			value: el.get('value'),
+			cursor: txta.getSelectionRange(),
+			scrollTop: el.scrollTop,
 			scrollLeft: el.scrollLeft
 		};
 	},
 
 	/*
 	Function: putState
-		Set a state of the SnipEditor. 
+		Set a state of the SnipEditor.
 		This works in conjunction with the [UndoRedo] class.
 	*/
 	putState: function(o){
 
 		var self = this,
 			txta = self.textarea,
-			el = txta.toElement(); 
+			el = txta.toElement();
 
 		self.clearActiveSnip();
 		self.mainarea.value = o.main;
@@ -2203,7 +2230,6 @@
 	}
 
 });
-SnipEditor.implement(/*new Events,*/ new Options);
 
 
 /*
@@ -2232,9 +2258,9 @@
 	/*
 	Function: toElement
 		Return the DOM textarea element.
-		This allows the dollar function to return 
+		This allows the dollar function to return
 		the element when passed an instance of the class. (mootools 1.2.x)
-		
+
 	Example:
 	>	var txta = new Textarea('textarea-element');
 	>	$('textarea-element') == txta.toElement();
@@ -2267,24 +2293,24 @@
 	getTillEnd: function(){
 		return this.ta.value.slice( this.getSelectionRange().end );
 	},
-	
+
 	/*
 	Function: getSelection
 		Returns the selected text as a string
-	
+
 	Note:
-		IE fixme: this may return any selection, not only selected text in this textarea 
-			//if(window.ie) return document.selection.createRange().text;
+		IE fixme: this may return any selection, not only selected text in this textarea
+			//if(Browser.Engine.trident) return document.selection.createRange().text;
 	*/
 	getSelection: function(){
 
 		var cur = this.getSelectionRange();
-		return this.ta.getValue().slice(cur.start, cur.end);
+		return this.ta.get('value').slice(cur.start, cur.end);
 
 	},
-	
+
 	/*
-	Function: setSelectionRange 
+	Function: setSelectionRange
 		Selects the selection range of the textarea from start to end
 
 	Arguments:
@@ -2309,7 +2335,7 @@
             	diff = value.substr(start, end - start).replace(/\r/g, '').length;
 
             start = value.substr(0, start).replace(/\r/g, '').length;
-           
+
 			var range = txta.createTextRange();
 			range.collapse(true);
 			range.moveEnd('character', start + diff);
@@ -2324,7 +2350,7 @@
 
 	/*
 	Function: getSelectionRange
-		Returns an object describing the textarea selection range. 
+		Returns an object describing the textarea selection range.
 
 	Returns:
 		{{ { 'start':number, 'end':number, 'thin':boolean } }}
@@ -2340,7 +2366,7 @@
 			range = document.selection.createRange(),
 			re = this.createTextRange(),
 			dupe = re.duplicate();
-		re.moveToBookmark(range.getBookmark());	
+		re.moveToBookmark(range.getBookmark());
 		dupe.setEndPoint('EndToStart', re);
 		return { start: dupe.text.length, end: dupe.text.length + range.text.length, length: range.text.length, text: range.text };
 	},
@@ -2355,7 +2381,7 @@
 			pos = { start: txta.selectionStart, end: txta.selectionEnd };
 
 		} else {
-		
+
 	  		var range = document.selection.createRange();
 			if (!range || range.parentElement() != txta) return pos;
 	 		var dup = range.duplicate(),
@@ -2375,7 +2401,7 @@
 	},
 
 	/*
-	Function: setSelection 
+	Function: setSelection
 		Replaces the selection with a new value (concatenation of arguments).
 		On return, the selection is set to the replaced text string.
 
@@ -2394,28 +2420,28 @@
 		var value = $A(arguments).join('').replace(/\r/g, ''),
 			txta = this.ta,
 			scrollTop = txta.scrollTop; //cache top
-		 
+
 		if( $defined(txta.selectionStart) ){
 
-			var start = txta.selectionStart, 
+			var start = txta.selectionStart,
 				end = txta.selectionEnd,
 				v = txta.value;
 			txta.value = v.substr(0, start) + value + v.substr(end);
 			txta.selectionStart = start;
 			txta.selectionEnd = start + value.length;
 
-		} else { 
+		} else {
 
 			txta.focus();
 			var range = document.selection.createRange();
-			range.text = value;			
+			range.text = value;
 			range.collapse(true);
 			range.moveStart("character", -value.length);
 			range.select();
 
 		}
 		txta.focus();
-		txta.scrollTop = scrollTop;		
+		txta.scrollTop = scrollTop;
 		txta.fireEvent('change');
 		return this;
 
@@ -2432,14 +2458,14 @@
 		Textarea object
 	*/
 	insertAfter: function(){
-	
+
 		var value = $A(arguments).join('');
 
 		return this.setSelection( value )
-			.setSelectionRange( this.getSelectionRange().start + value.length );				
+			.setSelectionRange( this.getSelectionRange().start + value.length );
 
 	},
-	
+
 	/*
 	Function: isCaretAtStartOfLine
 		Returns boolean indicating whether caret is at the start of newline
@@ -2450,7 +2476,7 @@
 	    return( (i<=0) || ( this.ta.value.charAt( i-1 ).test( /[\n\r]/ ) ) );
 
 	}
-	
+
 });
 Textarea.implement(new Events);
 
@@ -2476,8 +2502,8 @@
 	(start code)
 	<script>
 		var undoredo = new UndoRedo(this, {
-			redoElement:'redoID', 
-			undoElement:'undoID' 
+			redoElement:'redoID',
+			undoElement:'undoID'
 		});
 
 		//when a change occurs on the calling object which needs to be persisted
@@ -2487,13 +2513,15 @@
 */
 var UndoRedo = new Class({
 
+	Implements: Options,
+
 	options: {
 		maxundo:40
 	},
 	initialize: function(obj, options){
 
 		this.setOptions(options);
-		this.obj = obj; 
+		this.obj = obj;
 		this.redo = [];
 		this.undo = [];
 
@@ -2510,7 +2538,7 @@
 	Function: onChange
 		Call the onChange function to persist the current state of the undo-able object.
 		The UndoRedo class will call the {{obj.getState()}} to retrieve the state info.
-		
+
 	Arguments:
 		state - (optional) state object to be persisted. If not present,
 			the state will be retrieved via a call to the {{obj.getState()}} function.
@@ -2539,7 +2567,7 @@
 		}
 
 		this.buttonCSS();
-	},	
+	},
 
 	/*
 	Function: onRedo
@@ -2557,17 +2585,16 @@
 
 		this.buttonCSS();
 	},
-	
+
 	/*
 	Function: buttonCSS
 		Helper function to change the css style of the undo/redo buttons.
 	*/
 	buttonCSS: function(){
-		
+
 		if(this.undoEL) this.undoEL[ (this.undo.length == 0) ? 'addClass' : 'removeClass' ]('disabled');
 		if(this.redoEL) this.redoEL[ (this.redo.length == 0) ? 'addClass' : 'removeClass' ]('disabled');
 
 	}
 
 });
-UndoRedo.implement(new Options);

Modified: incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-prefs.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-prefs.js?rev=819135&r1=819134&r2=819135&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-prefs.js (original)
+++ incubator/jspwiki/trunk/src/WebContent/scripts/jspwiki-prefs.js Sat Sep 26 13:23:58 2009
@@ -1,4 +1,4 @@
-/* 
+/*!
     JSPWiki - a JSP-based WikiWiki clone.
 
     Licensed to the Apache Software Foundation (ASF) under one
@@ -16,70 +16,87 @@
     "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.
  */
- 
+
 /**
  ** Javascript routines to support JSPWiki UserPreferences
  ** since v.2.6.0
- ** uses mootools v1.1
  **/
 
 var WikiPreferences =
 {
 	/*
-	Function: onPageLoad()
-		Register a onbeforeunload handler to show a popup when the user leaves
-		the Preferences page without saving.
+	Function: initialize()
+		Initialze submit and onberforeunload handlers to support the
+		UserPreferences page.
+
+		Register a onbeforeunload handler to show a warning popup
+		when the user leaves the Preferences page without saving.
+
+		Register a submit handler on the main preferences form,
+		in order to save the settings to the UserPref cookies.
+		Note: this could be done server side, but some of the prefs are only
+		known client-side, only persisted through cookies.
 	*/
-	onPageLoad: function(){
+	initialize: function(){
+
+		var self = this,
+			wikiprefs = Wiki.prefs,
+			p;
 
-		window.onbeforeunload = (function(){
+		window.onbeforeunload = function(){
+
+			if( $('prefs').getElements('input, select').some(function(el){
+
+				return ((el.type != "submit") && (el.get('value') != el.getDefaultValue()));
 
-			if( $('prefs').getFormElements().some(function(el){
-				return (el.getValue() != el.getDefaultValue());  
 			}) ) return "prefs.areyousure".localize();
 
-		}).bind(this);
+		};
+
+
+		$('setCookie').addEvent('submit', function(){
+
+ 			window.onbeforeunload = null;
+
+ 			/* see org.apache.wiki.preferences.Preferences.java */
+			var prefs = {
+				skin:'Skin',
+				timeZone:'TimeZone',
+				timeFormat:'DateFormat',
+				orientation:'Orientation',
+				editor:'Editor',
+				locale:'Locale',
+				sectionEditing:'SectionEditing'
+			};
+
+			for( var el in prefs ){
+				if( p = $(el) ) wikiprefs.set( prefs[el], p.get('value') );
+			};
+
+			//CHECK: covered by stripes ?
+			//Wiki.submitOnce(this);
+
+		});
 
 		/*
-		Make an immedieate change to the position of the Favorites block 
+		Make an immediate change to the position of the Favorites block
 		(aka left-menu) according to the setting prefOrientation dropdown.
 		The setting is persisted only when submitting the form. (savePrefs)
+
+		FIXME: value of selection is now LEFT or RIGHT iso fav-left/fav-right
 		*/
-		$('prefOrientation').addEvent('click',function(){
+		$('orientation').addEvent('change',function(){
 			$('wikibody')
 				.removeClass('fav-left|fav-right')
-				.addClass(this.getValue());
+				.addClass( 'fav-'+this.get('value').toLowerCase() );
 		});
 
- 	},
+ 	}
 
-	/*
-	Function: savePrefs()
-		Save all user preferences to the Wiki UserPrefs cookie.
-		This function is called as form onsubmit handler of the UserPref page.
-
-		FIXME: could this be done server side -- no since some prefs are only 
-		known client-side, only persisted through cookies.
-	*/
-	savePrefs: function(){
-		var prefs = {
-			'prefSkin':'SkinName',
-			'prefTimeZone':'TimeZone',
-			'prefTimeFormat':'DateFormat',
-			'prefOrientation':'Orientation',
-			'editor':'editor',
-			'prefLanguage':'Language',
-			'prefSectionEditing':'SectionEditing'
-		};
-		for(var el in prefs){
-			if($(el)) Wiki.prefs.set(prefs[el],$(el).getValue());
-		};
-	}
 }
-
-window.addEvent('load', WikiPreferences.onPageLoad.bind(WikiPreferences) );
+window.addEvent('domready', WikiPreferences.initialize );
 
 // refactor me
 var WikiGroup =
@@ -101,7 +118,7 @@
 		this.groups[group] = { members: members, groupInfo: groupInfo };
 
 		var g = $("grouptemplate");
-			gg = g.clone().removeProperty('id').setHTML(group).inject(g.getParent()).show();
+			gg = g.clone().removeProperty('id').set('html',group).inject(g.getParent()).show();
 
 		if(isSelected || !this.cursor) this.onMouseOverGroup(gg);
 	} ,