r59364 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r59363‎ | r59364 | r59365 >
Date:19:25, 23 November 2009
Author:catrope
Status:deferred
Tags:
Comment:
UsabilityInitiative: Make the TOC work nicely with the iframe. Mostly works now except for moving the cursor
Modified paths:
  • /trunk/extensions/UsabilityInitiative/UsabilityInitiative.hooks.php (modified) (history)
  • /trunk/extensions/UsabilityInitiative/js/plugins.combined.js (modified) (history)
  • /trunk/extensions/UsabilityInitiative/js/plugins.combined.min.js (modified) (history)
  • /trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.js (modified) (history)
  • /trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toc.js (modified) (history)

Diff [purge]

Index: trunk/extensions/UsabilityInitiative/UsabilityInitiative.hooks.php
@@ -70,18 +70,18 @@
7171 array( 'src' => 'js/plugins/jquery.namespaceSelect.js', 'version' => 1 ),
7272 array( 'src' => 'js/plugins/jquery.suggestions.js', 'version' => 6 ),
7373 array( 'src' => 'js/plugins/jquery.textSelection.js', 'version' => 20 ),
74 - array( 'src' => 'js/plugins/jquery.wikiEditor.js', 'version' => 18 ),
 74+ array( 'src' => 'js/plugins/jquery.wikiEditor.js', 'version' => 19 ),
7575 array( 'src' => 'js/plugins/jquery.wikiEditor.highlight.js', 'version' => 1 ),
7676 array( 'src' => 'js/plugins/jquery.wikiEditor.toolbar.js', 'version' => 32 ),
7777 array( 'src' => 'js/plugins/jquery.wikiEditor.dialogs.js', 'version' => 9 ),
78 - array( 'src' => 'js/plugins/jquery.wikiEditor.toc.js', 'version' => 39 ),
 78+ array( 'src' => 'js/plugins/jquery.wikiEditor.toc.js', 'version' => 40 ),
7979 array( 'src' => 'js/plugins/jquery.wikiEditor.preview.js', 'version' => 3 ),
8080 ),
8181 'combined' => array(
82 - array( 'src' => 'js/plugins.combined.js', 'version' => 85 ),
 82+ array( 'src' => 'js/plugins.combined.js', 'version' => 86 ),
8383 ),
8484 'minified' => array(
85 - array( 'src' => 'js/plugins.combined.min.js', 'version' => 85 ),
 85+ array( 'src' => 'js/plugins.combined.min.js', 'version' => 86 ),
8686 ),
8787 ),
8888 );
Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toc.js
@@ -55,11 +55,9 @@
5656
5757 // Add the TOC to the document
5858 $.wikiEditor.modules.toc.fn.build( context, config );
59 - context.$textarea
60 - // FIXME: magic iframe integration
61 - .delayedBind( 250, 'mouseup scrollToPosition focus keyup encapsulateSelection change',
62 - function( event ) {
63 - var context = $(this).data( 'wikiEditor-context' );
 59+ context.$content.parent()
 60+ .delayedBind( 250, 'mouseup scrollToTop keyup change',
 61+ function() {
6462 $(this).eachAsync( {
6563 bulk: 0,
6664 loop: function() {
@@ -69,12 +67,12 @@
7068 } );
7169 }
7270 )
73 - .blur( function() {
74 - var context = $(this).data( 'wikiEditor-context' );
75 - context.$textarea.delayedBindCancel( 250,
76 - 'mouseup scrollToPosition focus keyup encapsulateSelection change' );
 71+ .blur( function( event ) {
 72+ var context = event.data.context;
 73+ context.$textarea.delayedBindCancel( 250, 'mouseup scrollToTop keyup change' );
7774 $.wikiEditor.modules.toc.fn.unhighlight( context );
7875 });
 76+
7977 },
8078
8179 unhighlight: function( context ) {
@@ -211,7 +209,6 @@
212210 .data( 'wrapper', structure[i].wrapper )
213211 .mousedown( function( event ) {
214212 context.fn.scrollToTop( $(this).data( 'wrapper' ) );
215 - // TODO: Move cursor
216213 if ( typeof $.trackAction != 'undefined' )
217214 $.trackAction( 'ntoc.heading' );
218215 event.preventDefault();
@@ -228,6 +225,7 @@
229226 return list;
230227 }
231228 function buildCollapseControls() {
 229+ // FIXME: Coding style
232230 var $collapseControl = $( '<div />' ), $expandControl = $( '<div />' );
233231 $collapseControl
234232 .addClass( 'tab' )
@@ -253,6 +251,7 @@
254252 context.$ui.find( '.wikiEditor-ui-left .wikiEditor-ui-top' ).append( $expandControl );
255253 }
256254 function buildResizeControls() {
 255+ // FIXME: Coding style
257256 context.$ui.find( '.ui-resizable-e' )
258257 .removeClass( 'ui-resizable-e' )
259258 .addClass( 'ui-resizable-w' )
@@ -288,27 +287,35 @@
289288
290289 // Build outline from wikitext
291290 var outline = [];
 291+
292292 // Traverse all text nodes in context.$content
293293 var h = 0;
294 - context.$content.contents().each( function() {
295 - if ( this.nodeName != '#text' )
 294+ context.$content.contents().add( context.$content.find( '.wikiEditor-toc-header' ) ).each( function() {
 295+ if ( this.nodeName != '#text' && !$(this).is( '.wikiEditor-toc-header' ) )
296296 return;
297 - var text = this.textContent;
 297+ var text = this.nodeValue;
 298+ if ( $(this).is( '.wikiEditor-toc-header' ) )
 299+ text = $(this).html();
 300+
298301 var match = text.match( /^(={1,6})(.*?)\1\s*$/ );
299 - if ( !match )
 302+ if ( !match ) {
 303+ if ( $(this).is( '.wikiEditor-toc-header' ) )
 304+ // Header has become invalid
 305+ // Remove the class but keep the <div> intact
 306+ // to prevent issues with Firefox
 307+ $(this).removeClass( 'wikiEditor-toc-header' );
300308 return;
 309+ }
301310 // Wrap the header in a <div>, unless it's already wrapped
302311 var div;
303 - if ( $(this).parent().is( 'div' ) && $(this).parent().children().size() == 1 )
304 - div = $(this)
305 - .parent()
306 - .addClass( 'wikiEditor-toc-header' );
 312+ if ( $(this).is( '.wikiEditor-toc-header' ) )
 313+ div = $(this);
307314 else {
308315 div = $j( '<div />' )
309316 .text( text )
310317 .css( 'display', 'inline' )
311318 .addClass( 'wikiEditor-toc-header' );
312 - this.parentNode.replaceChild( div.get( 0 ), this );
 319+ $(this).replaceWith( div );
313320 }
314321 outline[h] = { 'text': match[2], 'wrapper': div, 'level': match[1].length, 'index': h + 1 };
315322 h++;
@@ -336,18 +343,16 @@
337344 // section 0, if needed
338345 var structure = buildStructure( outline );
339346 if ( $( 'input[name=wpSection]' ).val() == '' ) {
340 - // Add a <div> at the beginning
341 - // FIXME: The user can remove this div, use the <body> tag for anchor
342 - var div = $j( '<div />' )
343 - .addClass( 'wikiEditor-toc-start' )
344 - .hide()
345 - .prependTo( context.$content );
346347 structure.unshift( { 'text': wgPageName.replace(/_/g, ' '), 'level': 1, 'index': 0,
347 - 'wrapper': div } );
 348+ 'wrapper': context.$content } );
348349 }
349350 context.modules.$toc.html( buildList( structure ) );
350 - if(wgNavigableTOCResizable) {
351 - context.$ui.find( '.wikiEditor-ui-right' )
 351+
 352+ // FIXME: Coding style
 353+ if ( wgNavigableTOCResizable && !context.$ui.data( 'resizableDone' ) ) {
 354+ context.$ui
 355+ .data( 'resizableDone', true )
 356+ .find( '.wikiEditor-ui-right' )
352357 .data( 'wikiEditor-ui-left', context.$ui.find( '.wikiEditor-ui-left' ))
353358 .resizable( {handles: 'w,e', dontScrewWithLeft: true, minWidth: 50,
354359 start: function( e, ui ) {
Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.js
@@ -261,6 +261,7 @@
262262 context.evt = {
263263 'change': function( event ) {
264264 // BTW: context is in event.data.context
 265+
265266 switch ( event.type ) {
266267 case 'keypress':
267268 if ( /* something interesting was deleted */ false ) {
@@ -269,7 +270,7 @@
270271 //console.log( 'MINOR CHANGE' );
271272 }
272273 break;
273 - case 'mousedown':
 274+ case 'mousedown': // FIXME: mouseup?
274275 if ( /* text was dragged and dropped */ false ) {
275276 //console.log( 'MAJOR CHANGE' );
276277 } else {
@@ -287,21 +288,21 @@
288289 * DO NOT CALL THESE DIRECTLY, use .textSelection( 'functionname', options ) instead
289290 */
290291 context.fn = {
291 - /*
292 - * When finishing these functions, take a look at jquery.textSelection.js because this is designed to be API
293 - * compatible with those functions. The key difference is that these perform actions on a designMode iframe
 292+ /**
 293+ * Set up the magic iframe
294294 */
295295 'setup': function() {
296296 // Setup the iframe with a basic document
297297 context.$iframe[0].contentWindow.document.open();
298298 context.$iframe[0].contentWindow.document.write(
299 - '<html><head><title>wikiEditor</title><script>var context = window.parent.jQuery.wikiEditor.instances[' + context.instance + '].data( "wikiEditor-context" ); window.parent.jQuery( document ).bind( "keypress mouseup cut paste", { "context": context }, context.evt.change );</script></head><body style="margin:0;padding:0;width:100%;height:100%;white-space:pre-wrap;font-family:monospace"></body></html>'
 299+ '<html><head><title>wikiEditor</title><script>var context = window.parent.jQuery.wikiEditor.instances[' + context.instance + '].data( "wikiEditor-context" ); window.parent.jQuery( document ).bind( "keydown keypress keyup mousedown mouseup cut paste", { "context": context }, context.evt.change );</script></head><body style="margin:0;padding:0;width:100%;height:100%;white-space:pre-wrap;font-family:monospace"></body></html>'
300300 );
301301 context.$iframe[0].contentWindow.document.close();
302302 // Turn the document's design mode on
303303 context.$iframe[0].contentWindow.document.designMode = 'on';
 304+
304305 // Get a reference to the content area of the iframe
305 - context.$content = context.$iframe.contents().find( 'body' );
 306+ context.$content = $( context.$iframe[0].contentWindow.document.body );
306307 if ( $( 'body' ).is( '.rtl' ) )
307308 context.$content.addClass( 'rtl' ).attr( 'dir', 'rtl' );
308309
@@ -316,6 +317,12 @@
317318 context.$iframe.show();
318319 },
319320 /**
 321+ * Checks whether the magic iframe is properly set up
 322+ */
 323+ 'isSetup': function() {
 324+ return context.$content != undefined && context.$content[0].innerHTML != undefined;
 325+ },
 326+ /**
320327 * Gets the complete contents of the iframe
321328 */
322329 'getContents': function() {
@@ -394,11 +401,8 @@
395402 if ( lastNode )
396403 context.fn.scrollToTop( lastNode );
397404
398 - // ...
399 - // Scroll the textarea to the inserted text
400 - //?.scrollToCaretPosition();
401405 // Trigger the encapsulateSelection event (this might need to get named something else/done differently)
402 - //context.$textarea.trigger( 'encapsulateSelection', [ pre, peri, post, ownline, replace ] );
 406+ context.$content.trigger( 'encapsulateSelection', [ pre, peri, post, ownline, replace ] );
403407 return context.$textarea;
404408 },
405409 /**
@@ -436,6 +440,7 @@
437441 var y = $element.offset().top - context.$content.offset().top;
438442 if ( force || y < body.scrollTop() || y > body.scrollTop() + body.height() )
439443 body.scrollTop( y );
 444+ $element.trigger( 'scrollToTop' );
440445 }
441446 };
442447 }
@@ -444,13 +449,13 @@
445450 // API call
446451 if ( arguments.length > 0 && typeof arguments[0] == 'object' ) {
447452 // If the iframe construction isn't ready yet, defer the call
448 - if ( context.$content )
 453+ if ( context.fn.isSetup() )
449454 context.api.addModule( context, arguments[0] );
450455 else {
451456 var args = arguments;
452457 setTimeout( function() {
453458 context.api.addModule( context, args[0] );
454 - }, 2 );
 459+ }, 2 );
455460 }
456461 } else {
457462 // Since javascript gives arguments as an object, we need to convert them
@@ -461,7 +466,7 @@
462467 var call = arguments.shift();
463468 if ( call in context.api ) {
464469 // If the iframe construction isn't ready yet, defer the call
465 - if ( context.$content )
 470+ if ( context.fn.isSetup() )
466471 context.api[call]( context, arguments[0] == undefined ? {} : arguments[0] );
467472 else {
468473 var args = arguments;
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.js
@@ -1559,6 +1559,7 @@
15601560 context.evt = {
15611561 'change': function( event ) {
15621562 // BTW: context is in event.data.context
 1563+
15631564 switch ( event.type ) {
15641565 case 'keypress':
15651566 if ( /* something interesting was deleted */ false ) {
@@ -1567,7 +1568,7 @@
15681569 //console.log( 'MINOR CHANGE' );
15691570 }
15701571 break;
1571 - case 'mousedown':
 1572+ case 'mousedown': // FIXME: mouseup?
15721573 if ( /* text was dragged and dropped */ false ) {
15731574 //console.log( 'MAJOR CHANGE' );
15741575 } else {
@@ -1585,21 +1586,21 @@
15861587 * DO NOT CALL THESE DIRECTLY, use .textSelection( 'functionname', options ) instead
15871588 */
15881589 context.fn = {
1589 - /*
1590 - * When finishing these functions, take a look at jquery.textSelection.js because this is designed to be API
1591 - * compatible with those functions. The key difference is that these perform actions on a designMode iframe
 1590+ /**
 1591+ * Set up the magic iframe
15921592 */
15931593 'setup': function() {
15941594 // Setup the iframe with a basic document
15951595 context.$iframe[0].contentWindow.document.open();
15961596 context.$iframe[0].contentWindow.document.write(
1597 - '<html><head><title>wikiEditor</title><script>var context = window.parent.jQuery.wikiEditor.instances[' + context.instance + '].data( "wikiEditor-context" ); window.parent.jQuery( document ).bind( "keypress mouseup cut paste", { "context": context }, context.evt.change );</script></head><body style="margin:0;padding:0;width:100%;height:100%;white-space:pre-wrap;font-family:monospace"></body></html>'
 1597+ '<html><head><title>wikiEditor</title><script>var context = window.parent.jQuery.wikiEditor.instances[' + context.instance + '].data( "wikiEditor-context" ); window.parent.jQuery( document ).bind( "keydown keypress keyup mousedown mouseup cut paste", { "context": context }, context.evt.change );</script></head><body style="margin:0;padding:0;width:100%;height:100%;white-space:pre-wrap;font-family:monospace"></body></html>'
15981598 );
15991599 context.$iframe[0].contentWindow.document.close();
16001600 // Turn the document's design mode on
16011601 context.$iframe[0].contentWindow.document.designMode = 'on';
 1602+
16021603 // Get a reference to the content area of the iframe
1603 - context.$content = context.$iframe.contents().find( 'body' );
 1604+ context.$content = $( context.$iframe[0].contentWindow.document.body );
16041605 if ( $( 'body' ).is( '.rtl' ) )
16051606 context.$content.addClass( 'rtl' ).attr( 'dir', 'rtl' );
16061607
@@ -1614,6 +1615,12 @@
16151616 context.$iframe.show();
16161617 },
16171618 /**
 1619+ * Checks whether the magic iframe is properly set up
 1620+ */
 1621+ 'isSetup': function() {
 1622+ return context.$content != undefined && context.$content[0].innerHTML != undefined;
 1623+ },
 1624+ /**
16181625 * Gets the complete contents of the iframe
16191626 */
16201627 'getContents': function() {
@@ -1692,11 +1699,8 @@
16931700 if ( lastNode )
16941701 context.fn.scrollToTop( lastNode );
16951702
1696 - // ...
1697 - // Scroll the textarea to the inserted text
1698 - //?.scrollToCaretPosition();
16991703 // Trigger the encapsulateSelection event (this might need to get named something else/done differently)
1700 - //context.$textarea.trigger( 'encapsulateSelection', [ pre, peri, post, ownline, replace ] );
 1704+ context.$content.trigger( 'encapsulateSelection', [ pre, peri, post, ownline, replace ] );
17011705 return context.$textarea;
17021706 },
17031707 /**
@@ -1734,6 +1738,7 @@
17351739 var y = $element.offset().top - context.$content.offset().top;
17361740 if ( force || y < body.scrollTop() || y > body.scrollTop() + body.height() )
17371741 body.scrollTop( y );
 1742+ $element.trigger( 'scrollToTop' );
17381743 }
17391744 };
17401745 }
@@ -1742,13 +1747,13 @@
17431748 // API call
17441749 if ( arguments.length > 0 && typeof arguments[0] == 'object' ) {
17451750 // If the iframe construction isn't ready yet, defer the call
1746 - if ( context.$content )
 1751+ if ( context.fn.isSetup() )
17471752 context.api.addModule( context, arguments[0] );
17481753 else {
17491754 var args = arguments;
17501755 setTimeout( function() {
17511756 context.api.addModule( context, args[0] );
1752 - }, 2 );
 1757+ }, 2 );
17531758 }
17541759 } else {
17551760 // Since javascript gives arguments as an object, we need to convert them
@@ -1759,7 +1764,7 @@
17601765 var call = arguments.shift();
17611766 if ( call in context.api ) {
17621767 // If the iframe construction isn't ready yet, defer the call
1763 - if ( context.$content )
 1768+ if ( context.fn.isSetup() )
17641769 context.api[call]( context, arguments[0] == undefined ? {} : arguments[0] );
17651770 else {
17661771 var args = arguments;
@@ -2599,11 +2604,9 @@
26002605
26012606 // Add the TOC to the document
26022607 $.wikiEditor.modules.toc.fn.build( context, config );
2603 - context.$textarea
2604 - // FIXME: magic iframe integration
2605 - .delayedBind( 250, 'mouseup scrollToPosition focus keyup encapsulateSelection change',
2606 - function( event ) {
2607 - var context = $(this).data( 'wikiEditor-context' );
 2608+ context.$content.parent()
 2609+ .delayedBind( 250, 'mouseup scrollToTop keyup change',
 2610+ function() {
26082611 $(this).eachAsync( {
26092612 bulk: 0,
26102613 loop: function() {
@@ -2613,12 +2616,12 @@
26142617 } );
26152618 }
26162619 )
2617 - .blur( function() {
2618 - var context = $(this).data( 'wikiEditor-context' );
2619 - context.$textarea.delayedBindCancel( 250,
2620 - 'mouseup scrollToPosition focus keyup encapsulateSelection change' );
 2620+ .blur( function( event ) {
 2621+ var context = event.data.context;
 2622+ context.$textarea.delayedBindCancel( 250, 'mouseup scrollToTop keyup change' );
26212623 $.wikiEditor.modules.toc.fn.unhighlight( context );
26222624 });
 2625+
26232626 },
26242627
26252628 unhighlight: function( context ) {
@@ -2755,7 +2758,6 @@
27562759 .data( 'wrapper', structure[i].wrapper )
27572760 .mousedown( function( event ) {
27582761 context.fn.scrollToTop( $(this).data( 'wrapper' ) );
2759 - // TODO: Move cursor
27602762 if ( typeof $.trackAction != 'undefined' )
27612763 $.trackAction( 'ntoc.heading' );
27622764 event.preventDefault();
@@ -2772,6 +2774,7 @@
27732775 return list;
27742776 }
27752777 function buildCollapseControls() {
 2778+ // FIXME: Coding style
27762779 var $collapseControl = $( '<div />' ), $expandControl = $( '<div />' );
27772780 $collapseControl
27782781 .addClass( 'tab' )
@@ -2797,6 +2800,7 @@
27982801 context.$ui.find( '.wikiEditor-ui-left .wikiEditor-ui-top' ).append( $expandControl );
27992802 }
28002803 function buildResizeControls() {
 2804+ // FIXME: Coding style
28012805 context.$ui.find( '.ui-resizable-e' )
28022806 .removeClass( 'ui-resizable-e' )
28032807 .addClass( 'ui-resizable-w' )
@@ -2832,27 +2836,35 @@
28332837
28342838 // Build outline from wikitext
28352839 var outline = [];
 2840+
28362841 // Traverse all text nodes in context.$content
28372842 var h = 0;
2838 - context.$content.contents().each( function() {
2839 - if ( this.nodeName != '#text' )
 2843+ context.$content.contents().add( context.$content.find( '.wikiEditor-toc-header' ) ).each( function() {
 2844+ if ( this.nodeName != '#text' && !$(this).is( '.wikiEditor-toc-header' ) )
28402845 return;
2841 - var text = this.textContent;
 2846+ var text = this.nodeValue;
 2847+ if ( $(this).is( '.wikiEditor-toc-header' ) )
 2848+ text = $(this).html();
 2849+
28422850 var match = text.match( /^(={1,6})(.*?)\1\s*$/ );
2843 - if ( !match )
 2851+ if ( !match ) {
 2852+ if ( $(this).is( '.wikiEditor-toc-header' ) )
 2853+ // Header has become invalid
 2854+ // Remove the class but keep the <div> intact
 2855+ // to prevent issues with Firefox
 2856+ $(this).removeClass( 'wikiEditor-toc-header' );
28442857 return;
 2858+ }
28452859 // Wrap the header in a <div>, unless it's already wrapped
28462860 var div;
2847 - if ( $(this).parent().is( 'div' ) && $(this).parent().children().size() == 1 )
2848 - div = $(this)
2849 - .parent()
2850 - .addClass( 'wikiEditor-toc-header' );
 2861+ if ( $(this).is( '.wikiEditor-toc-header' ) )
 2862+ div = $(this);
28512863 else {
28522864 div = $j( '<div />' )
28532865 .text( text )
28542866 .css( 'display', 'inline' )
28552867 .addClass( 'wikiEditor-toc-header' );
2856 - this.parentNode.replaceChild( div.get( 0 ), this );
 2868+ $(this).replaceWith( div );
28572869 }
28582870 outline[h] = { 'text': match[2], 'wrapper': div, 'level': match[1].length, 'index': h + 1 };
28592871 h++;
@@ -2880,18 +2892,16 @@
28812893 // section 0, if needed
28822894 var structure = buildStructure( outline );
28832895 if ( $( 'input[name=wpSection]' ).val() == '' ) {
2884 - // Add a <div> at the beginning
2885 - // FIXME: The user can remove this div, use the <body> tag for anchor
2886 - var div = $j( '<div />' )
2887 - .addClass( 'wikiEditor-toc-start' )
2888 - .hide()
2889 - .prependTo( context.$content );
28902896 structure.unshift( { 'text': wgPageName.replace(/_/g, ' '), 'level': 1, 'index': 0,
2891 - 'wrapper': div } );
 2897+ 'wrapper': context.$content } );
28922898 }
28932899 context.modules.$toc.html( buildList( structure ) );
2894 - if(wgNavigableTOCResizable) {
2895 - context.$ui.find( '.wikiEditor-ui-right' )
 2900+
 2901+ // FIXME: Coding style
 2902+ if ( wgNavigableTOCResizable && !context.$ui.data( 'resizableDone' ) ) {
 2903+ context.$ui
 2904+ .data( 'resizableDone', true )
 2905+ .find( '.wikiEditor-ui-right' )
28962906 .data( 'wikiEditor-ui-left', context.$ui.find( '.wikiEditor-ui-left' ))
28972907 .resizable( {handles: 'w,e', dontScrewWithLeft: true, minWidth: 50,
28982908 start: function( e, ui ) {
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.min.js
@@ -88,8 +88,8 @@
8989 if(typeof data=='string'){callModuleApi(data,'create',{});}else if(typeof data=='object'){for(module in data){if(typeof module=='string'){callModuleApi(module,'create',data[module]);}}}}};for(module in $.wikiEditor.modules){if('api'in $.wikiEditor.modules[module]){for(call in $.wikiEditor.modules[module].api){if(!(call in context.api)){context.api[call]=$.wikiEditor.modules[module].api[call];}}}}
9090 context.evt={'change':function(event){switch(event.type){case'keypress':if(false){}else{}
9191 break;case'mousedown':if(false){}else{}
92 -break;default:break;}}};context.fn={'setup':function(){context.$iframe[0].contentWindow.document.open();context.$iframe[0].contentWindow.document.write('<html><head><title>wikiEditor</title><script>var context = window.parent.jQuery.wikiEditor.instances['+context.instance+'].data( "wikiEditor-context" ); window.parent.jQuery( document ).bind( "keypress mouseup cut paste", { "context": context }, context.evt.change );</script></head><body style="margin:0;padding:0;width:100%;height:100%;white-space:pre-wrap;font-family:monospace"></body></html>');context.$iframe[0].contentWindow.document.close();context.$iframe[0].contentWindow.document.designMode='on';context.$content=context.$iframe.contents().find('body');if($('body').is('.rtl'))
93 -context.$content.addClass('rtl').attr('dir','rtl');context.$textarea.attr('disabled',true);context.$content.text(context.$textarea.val());context.$textarea.hide();context.$iframe.show();},'getContents':function(){return $('<div />').html(context.$content.html().replace(/\<br\>/g,"\n")).text();},'setContents':function(options){context.$content.text(options.contents);return context.$textarea;},'getSelection':function(){var retval;if(context.$iframe[0].contentWindow.getSelection){retval=context.$iframe[0].contentWindow.getSelection();}else if(context.$iframe[0].contentWindow.selection){retval=context.$iframe[0].contentWindow.selection.createRange();}
 92+break;default:break;}}};context.fn={'setup':function(){context.$iframe[0].contentWindow.document.open();context.$iframe[0].contentWindow.document.write('<html><head><title>wikiEditor</title><script>var context = window.parent.jQuery.wikiEditor.instances['+context.instance+'].data( "wikiEditor-context" ); window.parent.jQuery( document ).bind( "keydown keypress keyup mousedown mouseup cut paste", { "context": context }, context.evt.change );</script></head><body style="margin:0;padding:0;width:100%;height:100%;white-space:pre-wrap;font-family:monospace"></body></html>');context.$iframe[0].contentWindow.document.close();context.$iframe[0].contentWindow.document.designMode='on';context.$content=$(context.$iframe[0].contentWindow.document.body);if($('body').is('.rtl'))
 93+context.$content.addClass('rtl').attr('dir','rtl');context.$textarea.attr('disabled',true);context.$content.text(context.$textarea.val());context.$textarea.hide();context.$iframe.show();},'isSetup':function(){return context.$content!=undefined&&context.$content[0].innerHTML!=undefined;},'getContents':function(){return $('<div />').html(context.$content.html().replace(/\<br\>/g,"\n")).text();},'setContents':function(options){context.$content.text(options.contents);return context.$textarea;},'getSelection':function(){var retval;if(context.$iframe[0].contentWindow.getSelection){retval=context.$iframe[0].contentWindow.getSelection();}else if(context.$iframe[0].contentWindow.selection){retval=context.$iframe[0].contentWindow.selection.createRange();}
9494 if(retval.text){retval=retval.text;}else if(retval.toString){retval=retval.toString();}
9595 return retval;},'encapsulateSelection':function(options){var selText=$(this).textSelection('getSelection');var selectAfter=false;var pre=options.pre,post=options.post;if(!selText){selText=options.peri;selectAfter=true;}else if(options.replace){selText=options.peri;}else if(selText.charAt(selText.length-1)==' '){selText=selText.substring(0,selText.length-1);post+=' ';}
9696 var range=context.$iframe[0].contentWindow.getSelection().getRangeAt(0);if(options.ownline){if(range.startOffset!=0)
@@ -98,10 +98,10 @@
9999 var insertText=pre+selText+post;var insertLines=insertText.split("\n");range.extractContents();var lastNode;for(var i=insertLines.length-1;i>=0;i--){range.insertNode(document.createTextNode(insertLines[i]));if(i>0)
100100 lastNode=range.insertNode(document.createElement('br'));}
101101 if(lastNode)
102 -context.fn.scrollToTop(lastNode);return context.$textarea;},'getCaretPosition':function(options){},'setSelection':function(options){},'scrollToCaretPosition':function(options){},'scrollToTop':function($element,force){var body=context.$content.closest('body');var y=$element.offset().top-context.$content.offset().top;if(force||y<body.scrollTop()||y>body.scrollTop()+body.height())
103 -body.scrollTop(y);}};}
104 -if(arguments.length>0&&typeof arguments[0]=='object'){if(context.$content)
105 -context.api.addModule(context,arguments[0]);else{var args=arguments;setTimeout(function(){context.api.addModule(context,args[0]);},2);}}else{arguments=$.makeArray(arguments);if(arguments.length>0){var call=arguments.shift();if(call in context.api){if(context.$content)
 102+context.fn.scrollToTop(lastNode);context.$content.trigger('encapsulateSelection',[pre,peri,post,ownline,replace]);return context.$textarea;},'getCaretPosition':function(options){},'setSelection':function(options){},'scrollToCaretPosition':function(options){},'scrollToTop':function($element,force){var body=context.$content.closest('body');var y=$element.offset().top-context.$content.offset().top;if(force||y<body.scrollTop()||y>body.scrollTop()+body.height())
 103+body.scrollTop(y);$element.trigger('scrollToTop');}};}
 104+if(arguments.length>0&&typeof arguments[0]=='object'){if(context.fn.isSetup())
 105+context.api.addModule(context,arguments[0]);else{var args=arguments;setTimeout(function(){context.api.addModule(context,args[0]);},2);}}else{arguments=$.makeArray(arguments);if(arguments.length>0){var call=arguments.shift();if(call in context.api){if(context.fn.isSetup())
106106 context.api[call](context,arguments[0]==undefined?{}:arguments[0]);else{var args=arguments;setTimeout(function(){context.api[call](context,args[0]==undefined?{}:args[0]);},2);}}}}
107107 return $(this).data('wikiEditor-context',context);};})(jQuery);RegExp.escape=function(s){return s.replace(/([.*+?^${}()|\/\\[\]])/g,'\\$1');};(function($){$.wikiEditor.modules.dialogs={api:{addDialog:function(context,data){$.wikiEditor.modules.dialogs.fn.create(context,data)},openDialog:function(context,module){if(module in $.wikiEditor.modules.dialogs.modules){$('#'+$.wikiEditor.modules.dialogs.modules[module].id).dialog('open');}},closeDialog:function(context,data){if(module in $.wikiEditor.modules.dialogs.modules){$('#'+$.wikiEditor.modules.dialogs.modules[module].id).dialog('close');}}},fn:{create:function(context,config){for(module in config){$.wikiEditor.modules.dialogs.modules[module]=config[module];}
108108 mvJsLoader.doLoad(['$j.ui','$j.ui.dialog','$j.ui.draggable','$j.ui.resizable'],function(){for(module in $.wikiEditor.modules.dialogs.modules){var module=$.wikiEditor.modules.dialogs.modules[module];if($('#'+module.id).size()==0){var configuration=module.dialog;configuration.bgiframe=true;configuration.autoOpen=false;configuration.modal=true;configuration.title=$.wikiEditor.autoMsg(module,'title');configuration.newButtons={};for(msg in configuration.buttons)
@@ -158,7 +158,7 @@
159159 $pages.children().hide();$pages.find('*[rel='+selected+']').show();$index.children().removeClass('current');$selectedIndex.addClass('current');},build:function(context,config){var $tabs=$('<div />').addClass('tabs').appendTo(context.modules.$toolbar);var $sections=$('<div />').addClass('sections').appendTo(context.modules.$toolbar);context.modules.$toolbar.append($('<div />').css('clear','both'));var sectionQueue=[];for(section in config){if(section=='main'){context.modules.$toolbar.prepend($.wikiEditor.modules.toolbar.fn.buildSection(context,section,config[section]));}else{sectionQueue.push({'$sections':$sections,'context':context,'id':section,'config':config[section]});$tabs.append($.wikiEditor.modules.toolbar.fn.buildTab(context,section,config[section]));}}
160160 $.eachAsync(sectionQueue,{'bulk':0,'end':function(){$('body').css('position','static');$('body').css('position','relative');},'loop':function(i,s){s.$sections.append($.wikiEditor.modules.toolbar.fn.buildSection(s.context,s.id,s.config));var $section=s.$sections.find('.section:visible');if($section.size()){$sections.animate({'height':$section.outerHeight()},$section.outerHeight()*2,function(){context.modules.$toc.height(context.$ui.find('.wikiEditor-ui-left').outerHeight()-context.$ui.find('.tab-toc').outerHeight());});}}});}}};})(jQuery);(function($){$.wikiEditor.modules.toc={api:{},defaultWidth:'13em',fn:{create:function(context,config){if('$toc'in context.modules){return;}
161161 context.initialWidth=$.wikiEditor.modules.toc.defaultWidth;if(wgNavigableTOCResizable){if(!$.cookie('wikiEditor-'+context.instance+'-toc-width')){$.cookie('wikiEditor-'+context.instance+'-toc-width',$.wikiEditor.modules.toc.defaultWidth);}else{context.initialWidth=$.cookie('wikiEditor-'+context.instance+'-toc-width');}}
162 -var height=context.$ui.find('.wikiEditor-ui-left').height();context.modules.$toc=$('<div />').addClass('wikiEditor-ui-toc').data('context',context);context.$ui.find('.wikiEditor-ui-right').css('width',$.wikiEditor.modules.toc.defaultWidth).append(context.modules.$toc);context.modules.$toc.height(context.$ui.find('.wikiEditor-ui-left').height());context.$ui.find('.wikiEditor-ui-left').css('marginRight',"-"+$.wikiEditor.modules.toc.defaultWidth).children().css('marginRight',$.wikiEditor.modules.toc.defaultWidth);$.wikiEditor.modules.toc.fn.build(context,config);context.$textarea.delayedBind(250,'mouseup scrollToPosition focus keyup encapsulateSelection change',function(event){var context=$(this).data('wikiEditor-context');$(this).eachAsync({bulk:0,loop:function(){$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);}});}).blur(function(){var context=$(this).data('wikiEditor-context');context.$textarea.delayedBindCancel(250,'mouseup scrollToPosition focus keyup encapsulateSelection change');$.wikiEditor.modules.toc.fn.unhighlight(context);});},unhighlight:function(context){context.modules.$toc.find('div').removeClass('current');},update:function(context){$.wikiEditor.modules.toc.fn.unhighlight(context);var position=context.$textarea.textSelection('getCaretPosition');var section=0;if(context.data.outline.length>0){if(!(position<context.data.outline[0].position-1)){while(section<context.data.outline.length&&context.data.outline[section].position-1<position){section++;}
 162+var height=context.$ui.find('.wikiEditor-ui-left').height();context.modules.$toc=$('<div />').addClass('wikiEditor-ui-toc').data('context',context);context.$ui.find('.wikiEditor-ui-right').css('width',$.wikiEditor.modules.toc.defaultWidth).append(context.modules.$toc);context.modules.$toc.height(context.$ui.find('.wikiEditor-ui-left').height());context.$ui.find('.wikiEditor-ui-left').css('marginRight',"-"+$.wikiEditor.modules.toc.defaultWidth).children().css('marginRight',$.wikiEditor.modules.toc.defaultWidth);$.wikiEditor.modules.toc.fn.build(context,config);context.$content.parent().delayedBind(250,'mouseup scrollToTop keyup change',function(){$(this).eachAsync({bulk:0,loop:function(){$.wikiEditor.modules.toc.fn.build(context);$.wikiEditor.modules.toc.fn.update(context);}});}).blur(function(event){var context=event.data.context;context.$textarea.delayedBindCancel(250,'mouseup scrollToTop keyup change');$.wikiEditor.modules.toc.fn.unhighlight(context);});},unhighlight:function(context){context.modules.$toc.find('div').removeClass('current');},update:function(context){$.wikiEditor.modules.toc.fn.unhighlight(context);var position=context.$textarea.textSelection('getCaretPosition');var section=0;if(context.data.outline.length>0){if(!(position<context.data.outline[0].position-1)){while(section<context.data.outline.length&&context.data.outline[section].position-1<position){section++;}
163163 section=Math.max(0,section);}
164164 var sectionLink=context.modules.$toc.find('div.section-'+section);sectionLink.addClass('current');var relTop=sectionLink.offset().top-context.modules.$toc.offset().top;var scrollTop=context.modules.$toc.scrollTop();var divHeight=context.modules.$toc.height();var sectionHeight=sectionLink.height();if(relTop<0)
165165 context.modules.$toc.scrollTop(scrollTop+relTop);else if(relTop+sectionHeight>divHeight)
@@ -175,16 +175,18 @@
176176 if(!context.modules.$toc.data('openWidth')){context.modules.$toc.data('openWidth',context.initialWidth==1?$.wikiEditor.modules.toc.defaultWidth:context.initialWidth);}
177177 if(context.initialWidth==1)
178178 $.wikiEditor.modules.toc.fn.collapse({data:context});return"";}
179 -var outline=[];var h=0;context.$content.contents().each(function(){if(this.nodeName!='#text')
180 -return;var text=this.textContent;var match=text.match(/^(={1,6})(.*?)\1\s*$/);if(!match)
181 -return;var div;if($(this).parent().is('div')&&$(this).parent().children().size()==1)
182 -div=$(this).parent().addClass('wikiEditor-toc-header');else{div=$j('<div />').text(text).css('display','inline').addClass('wikiEditor-toc-header');this.parentNode.replaceChild(div.get(0),this);}
 179+var outline=[];var h=0;context.$content.contents().add(context.$content.find('.wikiEditor-toc-header')).each(function(){if(this.nodeName!='#text'&&!$(this).is('.wikiEditor-toc-header'))
 180+return;var text=this.nodeValue;if($(this).is('.wikiEditor-toc-header'))
 181+text=$(this).html();var match=text.match(/^(={1,6})(.*?)\1\s*$/);if(!match){if($(this).is('.wikiEditor-toc-header'))
 182+$(this).removeClass('wikiEditor-toc-header');return;}
 183+var div;if($(this).is('.wikiEditor-toc-header'))
 184+div=$(this);else{div=$j('<div />').text(text).css('display','inline').addClass('wikiEditor-toc-header');$(this).replaceWith(div);}
183185 outline[h]={'text':match[2],'wrapper':div,'level':match[1].length,'index':h+1};h++;});var lastLevel=0;var nLevel=0;for(var i=0;i<outline.length;i++){if(outline[i].level>lastLevel){nLevel++;}
184186 else if(outline[i].level<lastLevel){nLevel-=Math.max(1,lastLevel-outline[i].level);}
185187 if(nLevel<=0){nLevel=1;}
186188 outline[i].nLevel=nLevel;lastLevel=outline[i].level;}
187 -var structure=buildStructure(outline);if($('input[name=wpSection]').val()==''){var div=$j('<div />').addClass('wikiEditor-toc-start').hide().prependTo(context.$content);structure.unshift({'text':wgPageName.replace(/_/g,' '),'level':1,'index':0,'wrapper':div});}
188 -context.modules.$toc.html(buildList(structure));if(wgNavigableTOCResizable){context.$ui.find('.wikiEditor-ui-right').data('wikiEditor-ui-left',context.$ui.find('.wikiEditor-ui-left')).resizable({handles:'w,e',dontScrewWithLeft:true,minWidth:50,start:function(e,ui){$this=$(this);$('<div />').addClass('wikiEditor-ui-resize-mask').css('position','absolute').css('z-index',2).css('left',0).css('top',0).css('bottom',0).css('right',0).appendTo(context.$ui.find('.wikiEditor-ui-left'));$this.resizable('option','maxWidth',$this.parent().width()-450);},resize:function(e,ui){$(this).css({'width':ui.size.width,'top':'auto'}).data('wikiEditor-ui-left').css('marginRight',(-1*ui.size.width)).children().css('marginRight',ui.size.width);},stop:function(e,ui){context.$ui.find('.wikiEditor-ui-resize-mask').remove();if(ui.size.width<70){context.modules.$toc.trigger('collapse');}}});context.modules.$toc.append(buildResizeControls());buildCollapseControls();}
 189+var structure=buildStructure(outline);if($('input[name=wpSection]').val()==''){structure.unshift({'text':wgPageName.replace(/_/g,' '),'level':1,'index':0,'wrapper':context.$content});}
 190+context.modules.$toc.html(buildList(structure));if(wgNavigableTOCResizable&&!context.$ui.data('resizableDone')){context.$ui.data('resizableDone',true).find('.wikiEditor-ui-right').data('wikiEditor-ui-left',context.$ui.find('.wikiEditor-ui-left')).resizable({handles:'w,e',dontScrewWithLeft:true,minWidth:50,start:function(e,ui){$this=$(this);$('<div />').addClass('wikiEditor-ui-resize-mask').css('position','absolute').css('z-index',2).css('left',0).css('top',0).css('bottom',0).css('right',0).appendTo(context.$ui.find('.wikiEditor-ui-left'));$this.resizable('option','maxWidth',$this.parent().width()-450);},resize:function(e,ui){$(this).css({'width':ui.size.width,'top':'auto'}).data('wikiEditor-ui-left').css('marginRight',(-1*ui.size.width)).children().css('marginRight',ui.size.width);},stop:function(e,ui){context.$ui.find('.wikiEditor-ui-resize-mask').remove();if(ui.size.width<70){context.modules.$toc.trigger('collapse');}}});context.modules.$toc.append(buildResizeControls());buildCollapseControls();}
189191 context.modules.$toc.find('div').autoEllipse({'position':'right','tooltip':true});context.data.outline=outline;}}};$.ui.plugin.add("resizable","dontScrewWithLeft",{resize:function(event,ui){$(this).data("resizable").position.left=0;}});})(jQuery);(function($){$.wikiEditor.modules.preview={api:{},fn:{create:function(context,config){mvJsLoader.doLoad(['$j.ui','$j.ui.tabs'],function(){if('preview'in context.modules)
190192 return;var iframeHTML=context.$content.html();context.$ui.wrapInner($('<div />').addClass('wikiEditor-tab-edit').attr('id','wikiEditor-'+context.instance+'-tab-edit')).wrapInner($('<div />').addClass('wikiEditor-tabs'));var tabList=context.$ui.children();var editTab=tabList.children();var loadingMsg=gM('wikieditor-preview-loading');var previewTab=$('<div />').addClass('wikiEditor-tab-preview').attr('id','wikiEditor-'+context.instance+'-tab-preview').append($('<div />').addClass('wikiEditor-preview-spinner').append($('<img />').attr({'src':$.wikiEditor.imgPath+'dialogs/loading.gif','alt':loadingMsg,'title':loadingMsg}))).append($('<div />').addClass('wikiEditor-preview-contents')).insertAfter(editTab);var dialogID='wikiEditor-'+context.instance+'-savedialog';$.wikiEditor.modules.dialogs.fn.create(context,{previewsave:{id:dialogID,titleMsg:'wikieditor-preview-savedialog-title',html:'\
191193 <div class="wikiEditor-savedialog-copywarn"></div>\

Status & tagging log