Index: trunk/extensions/UsabilityInitiative/UsabilityInitiative.hooks.php |
— | — | @@ -70,18 +70,18 @@ |
71 | 71 | array( 'src' => 'js/plugins/jquery.namespaceSelect.js', 'version' => 1 ), |
72 | 72 | array( 'src' => 'js/plugins/jquery.suggestions.js', 'version' => 6 ), |
73 | 73 | 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 ), |
75 | 75 | array( 'src' => 'js/plugins/jquery.wikiEditor.highlight.js', 'version' => 1 ), |
76 | 76 | array( 'src' => 'js/plugins/jquery.wikiEditor.toolbar.js', 'version' => 32 ), |
77 | 77 | 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 ), |
79 | 79 | array( 'src' => 'js/plugins/jquery.wikiEditor.preview.js', 'version' => 3 ), |
80 | 80 | ), |
81 | 81 | 'combined' => array( |
82 | | - array( 'src' => 'js/plugins.combined.js', 'version' => 85 ), |
| 82 | + array( 'src' => 'js/plugins.combined.js', 'version' => 86 ), |
83 | 83 | ), |
84 | 84 | 'minified' => array( |
85 | | - array( 'src' => 'js/plugins.combined.min.js', 'version' => 85 ), |
| 85 | + array( 'src' => 'js/plugins.combined.min.js', 'version' => 86 ), |
86 | 86 | ), |
87 | 87 | ), |
88 | 88 | ); |
Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toc.js |
— | — | @@ -55,11 +55,9 @@ |
56 | 56 | |
57 | 57 | // Add the TOC to the document |
58 | 58 | $.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() { |
64 | 62 | $(this).eachAsync( { |
65 | 63 | bulk: 0, |
66 | 64 | loop: function() { |
— | — | @@ -69,12 +67,12 @@ |
70 | 68 | } ); |
71 | 69 | } |
72 | 70 | ) |
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' ); |
77 | 74 | $.wikiEditor.modules.toc.fn.unhighlight( context ); |
78 | 75 | }); |
| 76 | + |
79 | 77 | }, |
80 | 78 | |
81 | 79 | unhighlight: function( context ) { |
— | — | @@ -211,7 +209,6 @@ |
212 | 210 | .data( 'wrapper', structure[i].wrapper ) |
213 | 211 | .mousedown( function( event ) { |
214 | 212 | context.fn.scrollToTop( $(this).data( 'wrapper' ) ); |
215 | | - // TODO: Move cursor |
216 | 213 | if ( typeof $.trackAction != 'undefined' ) |
217 | 214 | $.trackAction( 'ntoc.heading' ); |
218 | 215 | event.preventDefault(); |
— | — | @@ -228,6 +225,7 @@ |
229 | 226 | return list; |
230 | 227 | } |
231 | 228 | function buildCollapseControls() { |
| 229 | + // FIXME: Coding style |
232 | 230 | var $collapseControl = $( '<div />' ), $expandControl = $( '<div />' ); |
233 | 231 | $collapseControl |
234 | 232 | .addClass( 'tab' ) |
— | — | @@ -253,6 +251,7 @@ |
254 | 252 | context.$ui.find( '.wikiEditor-ui-left .wikiEditor-ui-top' ).append( $expandControl ); |
255 | 253 | } |
256 | 254 | function buildResizeControls() { |
| 255 | + // FIXME: Coding style |
257 | 256 | context.$ui.find( '.ui-resizable-e' ) |
258 | 257 | .removeClass( 'ui-resizable-e' ) |
259 | 258 | .addClass( 'ui-resizable-w' ) |
— | — | @@ -288,27 +287,35 @@ |
289 | 288 | |
290 | 289 | // Build outline from wikitext |
291 | 290 | var outline = []; |
| 291 | + |
292 | 292 | // Traverse all text nodes in context.$content |
293 | 293 | 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' ) ) |
296 | 296 | return; |
297 | | - var text = this.textContent; |
| 297 | + var text = this.nodeValue; |
| 298 | + if ( $(this).is( '.wikiEditor-toc-header' ) ) |
| 299 | + text = $(this).html(); |
| 300 | + |
298 | 301 | 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' ); |
300 | 308 | return; |
| 309 | + } |
301 | 310 | // Wrap the header in a <div>, unless it's already wrapped |
302 | 311 | 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); |
307 | 314 | else { |
308 | 315 | div = $j( '<div />' ) |
309 | 316 | .text( text ) |
310 | 317 | .css( 'display', 'inline' ) |
311 | 318 | .addClass( 'wikiEditor-toc-header' ); |
312 | | - this.parentNode.replaceChild( div.get( 0 ), this ); |
| 319 | + $(this).replaceWith( div ); |
313 | 320 | } |
314 | 321 | outline[h] = { 'text': match[2], 'wrapper': div, 'level': match[1].length, 'index': h + 1 }; |
315 | 322 | h++; |
— | — | @@ -336,18 +343,16 @@ |
337 | 344 | // section 0, if needed |
338 | 345 | var structure = buildStructure( outline ); |
339 | 346 | 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 ); |
346 | 347 | structure.unshift( { 'text': wgPageName.replace(/_/g, ' '), 'level': 1, 'index': 0, |
347 | | - 'wrapper': div } ); |
| 348 | + 'wrapper': context.$content } ); |
348 | 349 | } |
349 | 350 | 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' ) |
352 | 357 | .data( 'wikiEditor-ui-left', context.$ui.find( '.wikiEditor-ui-left' )) |
353 | 358 | .resizable( {handles: 'w,e', dontScrewWithLeft: true, minWidth: 50, |
354 | 359 | start: function( e, ui ) { |
Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.js |
— | — | @@ -261,6 +261,7 @@ |
262 | 262 | context.evt = { |
263 | 263 | 'change': function( event ) { |
264 | 264 | // BTW: context is in event.data.context |
| 265 | + |
265 | 266 | switch ( event.type ) { |
266 | 267 | case 'keypress': |
267 | 268 | if ( /* something interesting was deleted */ false ) { |
— | — | @@ -269,7 +270,7 @@ |
270 | 271 | //console.log( 'MINOR CHANGE' ); |
271 | 272 | } |
272 | 273 | break; |
273 | | - case 'mousedown': |
| 274 | + case 'mousedown': // FIXME: mouseup? |
274 | 275 | if ( /* text was dragged and dropped */ false ) { |
275 | 276 | //console.log( 'MAJOR CHANGE' ); |
276 | 277 | } else { |
— | — | @@ -287,21 +288,21 @@ |
288 | 289 | * DO NOT CALL THESE DIRECTLY, use .textSelection( 'functionname', options ) instead |
289 | 290 | */ |
290 | 291 | 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 |
294 | 294 | */ |
295 | 295 | 'setup': function() { |
296 | 296 | // Setup the iframe with a basic document |
297 | 297 | context.$iframe[0].contentWindow.document.open(); |
298 | 298 | 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>' |
300 | 300 | ); |
301 | 301 | context.$iframe[0].contentWindow.document.close(); |
302 | 302 | // Turn the document's design mode on |
303 | 303 | context.$iframe[0].contentWindow.document.designMode = 'on'; |
| 304 | + |
304 | 305 | // 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 ); |
306 | 307 | if ( $( 'body' ).is( '.rtl' ) ) |
307 | 308 | context.$content.addClass( 'rtl' ).attr( 'dir', 'rtl' ); |
308 | 309 | |
— | — | @@ -316,6 +317,12 @@ |
317 | 318 | context.$iframe.show(); |
318 | 319 | }, |
319 | 320 | /** |
| 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 | + /** |
320 | 327 | * Gets the complete contents of the iframe |
321 | 328 | */ |
322 | 329 | 'getContents': function() { |
— | — | @@ -394,11 +401,8 @@ |
395 | 402 | if ( lastNode ) |
396 | 403 | context.fn.scrollToTop( lastNode ); |
397 | 404 | |
398 | | - // ... |
399 | | - // Scroll the textarea to the inserted text |
400 | | - //?.scrollToCaretPosition(); |
401 | 405 | // 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 ] ); |
403 | 407 | return context.$textarea; |
404 | 408 | }, |
405 | 409 | /** |
— | — | @@ -436,6 +440,7 @@ |
437 | 441 | var y = $element.offset().top - context.$content.offset().top; |
438 | 442 | if ( force || y < body.scrollTop() || y > body.scrollTop() + body.height() ) |
439 | 443 | body.scrollTop( y ); |
| 444 | + $element.trigger( 'scrollToTop' ); |
440 | 445 | } |
441 | 446 | }; |
442 | 447 | } |
— | — | @@ -444,13 +449,13 @@ |
445 | 450 | // API call |
446 | 451 | if ( arguments.length > 0 && typeof arguments[0] == 'object' ) { |
447 | 452 | // If the iframe construction isn't ready yet, defer the call |
448 | | - if ( context.$content ) |
| 453 | + if ( context.fn.isSetup() ) |
449 | 454 | context.api.addModule( context, arguments[0] ); |
450 | 455 | else { |
451 | 456 | var args = arguments; |
452 | 457 | setTimeout( function() { |
453 | 458 | context.api.addModule( context, args[0] ); |
454 | | - }, 2 ); |
| 459 | + }, 2 ); |
455 | 460 | } |
456 | 461 | } else { |
457 | 462 | // Since javascript gives arguments as an object, we need to convert them |
— | — | @@ -461,7 +466,7 @@ |
462 | 467 | var call = arguments.shift(); |
463 | 468 | if ( call in context.api ) { |
464 | 469 | // If the iframe construction isn't ready yet, defer the call |
465 | | - if ( context.$content ) |
| 470 | + if ( context.fn.isSetup() ) |
466 | 471 | context.api[call]( context, arguments[0] == undefined ? {} : arguments[0] ); |
467 | 472 | else { |
468 | 473 | var args = arguments; |
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.js |
— | — | @@ -1559,6 +1559,7 @@ |
1560 | 1560 | context.evt = { |
1561 | 1561 | 'change': function( event ) { |
1562 | 1562 | // BTW: context is in event.data.context |
| 1563 | + |
1563 | 1564 | switch ( event.type ) { |
1564 | 1565 | case 'keypress': |
1565 | 1566 | if ( /* something interesting was deleted */ false ) { |
— | — | @@ -1567,7 +1568,7 @@ |
1568 | 1569 | //console.log( 'MINOR CHANGE' ); |
1569 | 1570 | } |
1570 | 1571 | break; |
1571 | | - case 'mousedown': |
| 1572 | + case 'mousedown': // FIXME: mouseup? |
1572 | 1573 | if ( /* text was dragged and dropped */ false ) { |
1573 | 1574 | //console.log( 'MAJOR CHANGE' ); |
1574 | 1575 | } else { |
— | — | @@ -1585,21 +1586,21 @@ |
1586 | 1587 | * DO NOT CALL THESE DIRECTLY, use .textSelection( 'functionname', options ) instead |
1587 | 1588 | */ |
1588 | 1589 | 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 |
1592 | 1592 | */ |
1593 | 1593 | 'setup': function() { |
1594 | 1594 | // Setup the iframe with a basic document |
1595 | 1595 | context.$iframe[0].contentWindow.document.open(); |
1596 | 1596 | 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>' |
1598 | 1598 | ); |
1599 | 1599 | context.$iframe[0].contentWindow.document.close(); |
1600 | 1600 | // Turn the document's design mode on |
1601 | 1601 | context.$iframe[0].contentWindow.document.designMode = 'on'; |
| 1602 | + |
1602 | 1603 | // 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 ); |
1604 | 1605 | if ( $( 'body' ).is( '.rtl' ) ) |
1605 | 1606 | context.$content.addClass( 'rtl' ).attr( 'dir', 'rtl' ); |
1606 | 1607 | |
— | — | @@ -1614,6 +1615,12 @@ |
1615 | 1616 | context.$iframe.show(); |
1616 | 1617 | }, |
1617 | 1618 | /** |
| 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 | + /** |
1618 | 1625 | * Gets the complete contents of the iframe |
1619 | 1626 | */ |
1620 | 1627 | 'getContents': function() { |
— | — | @@ -1692,11 +1699,8 @@ |
1693 | 1700 | if ( lastNode ) |
1694 | 1701 | context.fn.scrollToTop( lastNode ); |
1695 | 1702 | |
1696 | | - // ... |
1697 | | - // Scroll the textarea to the inserted text |
1698 | | - //?.scrollToCaretPosition(); |
1699 | 1703 | // 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 ] ); |
1701 | 1705 | return context.$textarea; |
1702 | 1706 | }, |
1703 | 1707 | /** |
— | — | @@ -1734,6 +1738,7 @@ |
1735 | 1739 | var y = $element.offset().top - context.$content.offset().top; |
1736 | 1740 | if ( force || y < body.scrollTop() || y > body.scrollTop() + body.height() ) |
1737 | 1741 | body.scrollTop( y ); |
| 1742 | + $element.trigger( 'scrollToTop' ); |
1738 | 1743 | } |
1739 | 1744 | }; |
1740 | 1745 | } |
— | — | @@ -1742,13 +1747,13 @@ |
1743 | 1748 | // API call |
1744 | 1749 | if ( arguments.length > 0 && typeof arguments[0] == 'object' ) { |
1745 | 1750 | // If the iframe construction isn't ready yet, defer the call |
1746 | | - if ( context.$content ) |
| 1751 | + if ( context.fn.isSetup() ) |
1747 | 1752 | context.api.addModule( context, arguments[0] ); |
1748 | 1753 | else { |
1749 | 1754 | var args = arguments; |
1750 | 1755 | setTimeout( function() { |
1751 | 1756 | context.api.addModule( context, args[0] ); |
1752 | | - }, 2 ); |
| 1757 | + }, 2 ); |
1753 | 1758 | } |
1754 | 1759 | } else { |
1755 | 1760 | // Since javascript gives arguments as an object, we need to convert them |
— | — | @@ -1759,7 +1764,7 @@ |
1760 | 1765 | var call = arguments.shift(); |
1761 | 1766 | if ( call in context.api ) { |
1762 | 1767 | // If the iframe construction isn't ready yet, defer the call |
1763 | | - if ( context.$content ) |
| 1768 | + if ( context.fn.isSetup() ) |
1764 | 1769 | context.api[call]( context, arguments[0] == undefined ? {} : arguments[0] ); |
1765 | 1770 | else { |
1766 | 1771 | var args = arguments; |
— | — | @@ -2599,11 +2604,9 @@ |
2600 | 2605 | |
2601 | 2606 | // Add the TOC to the document |
2602 | 2607 | $.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() { |
2608 | 2611 | $(this).eachAsync( { |
2609 | 2612 | bulk: 0, |
2610 | 2613 | loop: function() { |
— | — | @@ -2613,12 +2616,12 @@ |
2614 | 2617 | } ); |
2615 | 2618 | } |
2616 | 2619 | ) |
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' ); |
2621 | 2623 | $.wikiEditor.modules.toc.fn.unhighlight( context ); |
2622 | 2624 | }); |
| 2625 | + |
2623 | 2626 | }, |
2624 | 2627 | |
2625 | 2628 | unhighlight: function( context ) { |
— | — | @@ -2755,7 +2758,6 @@ |
2756 | 2759 | .data( 'wrapper', structure[i].wrapper ) |
2757 | 2760 | .mousedown( function( event ) { |
2758 | 2761 | context.fn.scrollToTop( $(this).data( 'wrapper' ) ); |
2759 | | - // TODO: Move cursor |
2760 | 2762 | if ( typeof $.trackAction != 'undefined' ) |
2761 | 2763 | $.trackAction( 'ntoc.heading' ); |
2762 | 2764 | event.preventDefault(); |
— | — | @@ -2772,6 +2774,7 @@ |
2773 | 2775 | return list; |
2774 | 2776 | } |
2775 | 2777 | function buildCollapseControls() { |
| 2778 | + // FIXME: Coding style |
2776 | 2779 | var $collapseControl = $( '<div />' ), $expandControl = $( '<div />' ); |
2777 | 2780 | $collapseControl |
2778 | 2781 | .addClass( 'tab' ) |
— | — | @@ -2797,6 +2800,7 @@ |
2798 | 2801 | context.$ui.find( '.wikiEditor-ui-left .wikiEditor-ui-top' ).append( $expandControl ); |
2799 | 2802 | } |
2800 | 2803 | function buildResizeControls() { |
| 2804 | + // FIXME: Coding style |
2801 | 2805 | context.$ui.find( '.ui-resizable-e' ) |
2802 | 2806 | .removeClass( 'ui-resizable-e' ) |
2803 | 2807 | .addClass( 'ui-resizable-w' ) |
— | — | @@ -2832,27 +2836,35 @@ |
2833 | 2837 | |
2834 | 2838 | // Build outline from wikitext |
2835 | 2839 | var outline = []; |
| 2840 | + |
2836 | 2841 | // Traverse all text nodes in context.$content |
2837 | 2842 | 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' ) ) |
2840 | 2845 | return; |
2841 | | - var text = this.textContent; |
| 2846 | + var text = this.nodeValue; |
| 2847 | + if ( $(this).is( '.wikiEditor-toc-header' ) ) |
| 2848 | + text = $(this).html(); |
| 2849 | + |
2842 | 2850 | 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' ); |
2844 | 2857 | return; |
| 2858 | + } |
2845 | 2859 | // Wrap the header in a <div>, unless it's already wrapped |
2846 | 2860 | 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); |
2851 | 2863 | else { |
2852 | 2864 | div = $j( '<div />' ) |
2853 | 2865 | .text( text ) |
2854 | 2866 | .css( 'display', 'inline' ) |
2855 | 2867 | .addClass( 'wikiEditor-toc-header' ); |
2856 | | - this.parentNode.replaceChild( div.get( 0 ), this ); |
| 2868 | + $(this).replaceWith( div ); |
2857 | 2869 | } |
2858 | 2870 | outline[h] = { 'text': match[2], 'wrapper': div, 'level': match[1].length, 'index': h + 1 }; |
2859 | 2871 | h++; |
— | — | @@ -2880,18 +2892,16 @@ |
2881 | 2893 | // section 0, if needed |
2882 | 2894 | var structure = buildStructure( outline ); |
2883 | 2895 | 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 ); |
2890 | 2896 | structure.unshift( { 'text': wgPageName.replace(/_/g, ' '), 'level': 1, 'index': 0, |
2891 | | - 'wrapper': div } ); |
| 2897 | + 'wrapper': context.$content } ); |
2892 | 2898 | } |
2893 | 2899 | 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' ) |
2896 | 2906 | .data( 'wikiEditor-ui-left', context.$ui.find( '.wikiEditor-ui-left' )) |
2897 | 2907 | .resizable( {handles: 'w,e', dontScrewWithLeft: true, minWidth: 50, |
2898 | 2908 | start: function( e, ui ) { |
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.min.js |
— | — | @@ -88,8 +88,8 @@ |
89 | 89 | 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];}}}} |
90 | 90 | context.evt={'change':function(event){switch(event.type){case'keypress':if(false){}else{} |
91 | 91 | 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();} |
94 | 94 | if(retval.text){retval=retval.text;}else if(retval.toString){retval=retval.toString();} |
95 | 95 | 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+=' ';} |
96 | 96 | var range=context.$iframe[0].contentWindow.getSelection().getRangeAt(0);if(options.ownline){if(range.startOffset!=0) |
— | — | @@ -98,10 +98,10 @@ |
99 | 99 | 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) |
100 | 100 | lastNode=range.insertNode(document.createElement('br'));} |
101 | 101 | 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()) |
106 | 106 | 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);}}}} |
107 | 107 | 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];} |
108 | 108 | 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 @@ |
159 | 159 | $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]));}} |
160 | 160 | $.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;} |
161 | 161 | 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++;} |
163 | 163 | section=Math.max(0,section);} |
164 | 164 | 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) |
165 | 165 | context.modules.$toc.scrollTop(scrollTop+relTop);else if(relTop+sectionHeight>divHeight) |
— | — | @@ -175,16 +175,18 @@ |
176 | 176 | if(!context.modules.$toc.data('openWidth')){context.modules.$toc.data('openWidth',context.initialWidth==1?$.wikiEditor.modules.toc.defaultWidth:context.initialWidth);} |
177 | 177 | if(context.initialWidth==1) |
178 | 178 | $.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);} |
183 | 185 | 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++;} |
184 | 186 | else if(outline[i].level<lastLevel){nLevel-=Math.max(1,lastLevel-outline[i].level);} |
185 | 187 | if(nLevel<=0){nLevel=1;} |
186 | 188 | 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();} |
189 | 191 | 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) |
190 | 192 | 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:'\ |
191 | 193 | <div class="wikiEditor-savedialog-copywarn"></div>\ |