r61215 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r61214‎ | r61215 | r61216 >
Date:21:16, 18 January 2010
Author:tparscal
Status:ok
Tags:
Comment:
Added whitespace support for IE.
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.html (modified) (history)
  • /trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.js (modified) (history)

Diff [purge]

Index: trunk/extensions/UsabilityInitiative/UsabilityInitiative.hooks.php
@@ -153,7 +153,7 @@
154154 array(
155155 'src' => 'js/plugins/jquery.wikiEditor.js',
156156 'class' => 'j.wikiEditor',
157 - 'version' => 47
 157+ 'version' => 48
158158 ),
159159 array(
160160 'src' => 'js/plugins/jquery.wikiEditor.highlight.js',
@@ -191,10 +191,10 @@
192192 'version' => 1 ),
193193 ),
194194 'combined' => array(
195 - array( 'src' => 'js/plugins.combined.js', 'version' => 147 ),
 195+ array( 'src' => 'js/plugins.combined.js', 'version' => 148 ),
196196 ),
197197 'minified' => array(
198 - array( 'src' => 'js/plugins.combined.min.js', 'version' => 147 ),
 198+ array( 'src' => 'js/plugins.combined.min.js', 'version' => 148 ),
199199 ),
200200 ),
201201 );
Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.html
@@ -19,10 +19,17 @@
2020 white-space: -o-pre-wrap; /* Opera 7 */
2121 word-wrap: break-word; /* Internet Explorer 5.5+ */
2222 }
 23+ p {
 24+ margin: 0;
 25+ padding: 0;
 26+ }
2327 /* Wikitext that's folded away and shouldn't be displayed */
2428 .wikiEditor-nodisplay {
2529 display: none !important;
2630 }
 31+ .wikiEditor-tab {
 32+ padding-left: 4em;
 33+ }
2734 /* A collapsed template */
2835 .wikiEditor-template-collapsed {
2936 background-color:#DDEEFF;
Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.js
@@ -394,9 +394,16 @@
395395 // We use .html() instead of .text() so HTML entities are handled right - setting the HTML of the textarea
396396 // doesn't work on all browsers, use a dummy <div> instead
397397 // Get rid of the noincludes when getting text
398 -
399 - var $pre = $( '<pre>' + context.$content.html().replace( /\<br[^\>]*\>/gi, "\n" ) + '</pre>' );
 398+ var $pre = $( '<pre>' +
 399+ context.$content.html()
 400+ .replace( /\r?\n/g, "" )
 401+ .replace( /\<br[^\>]*\>/gi, "\n" )
 402+ .replace( /&nbsp;/g, " " )
 403+ .replace( /\<p[^\>]*\>/gi, "\n" )
 404+ .replace( /\<\/p[^\>]*\>/gi, "" )
 405+ + '</pre>' );
400406 $pre.find( ".wikiEditor-noinclude" ).each( function() { $( this ).remove(); } );
 407+ $pre.find( ".wikiEditor-tab" ).each( function() { $( this ).text( "\t" ) } );
401408 return $pre.text();
402409 },
403410 /**
@@ -676,12 +683,33 @@
677684 // Get a reference to the content area of the iframe
678685 context.$content = $( context.$iframe[0].contentWindow.document.body );
679686 // If we just do "context.$content.text( context.$textarea.val() )", Internet Explorer will strip out the
680 - // whitespace charcters, specifically "\n" - so we must manually encode the text and append it
681 - context.$content.append(
682 - context.$textarea.val().replace( /\</g, '&lt;' ).replace( /\>/g, '&gt;' ).replace( /\n/g, '<br />' )
683 - );
684 - //context.$content[0].innerText = context.$textarea.val().replace( /\n/g, '\n\n' );
685 - //context.$content.text( context.$textarea.val() );
 687+ // whitespace charcters, specifically "\n" - so we must manually encode the text and append it
 688+ var html = context.$textarea.val().replace( /\</g, '&lt;' ).replace( /\>/g, '&gt;' );
 689+ // We must do some extra processing on IE to avoid dirty diffs, specifically IE will collapse leading spaces
 690+ if ( $.browser.msie ) {
 691+ // Browser sniffing is not ideal, but executing this code on a non-broken browser doesn't cause harm
 692+ if ( $.browser.versionNumber <= 7 ) {
 693+ // Replace all spaces matching /(^|n) +/ with &nbsp; - IE <= 7 needs this because of its overzealous
 694+ // whitespace collapsing;
 695+ var prefix = '', suffix = html;
 696+ while ( suffix ) {
 697+ var match = suffix.match( /(^|\n) / );
 698+ if ( match ) {
 699+ prefix += suffix.substr( 0, match.index + match[0].length - 1 ) + '&nbsp;';
 700+ suffix = suffix.substr( match.index + match[0].length );
 701+ } else {
 702+ break;
 703+ }
 704+ }
 705+ html = prefix + suffix;
 706+ } else {
 707+ // IE8 is happy if we just convert the first leading space to &nbsp;
 708+ html = html.replace( /(^|\n) /g, "$1&nbsp;" );
 709+ }
 710+ html = html.replace( /\t/g, '<span class="wikiEditor-tab"></span>' );
 711+ }
 712+ // We must append, because IE will crash if we set html() - which is the same as empty() and append()
 713+ context.$content.append( html.replace( /\r?\n/g, '<br />' ) );
686714 // Reflect direction of parent frame into child
687715 if ( $( 'body' ).is( '.rtl' ) ) {
688716 context.$content.addClass( 'rtl' ).attr( 'dir', 'rtl' );
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.js
@@ -6756,9 +6756,16 @@
67576757 // We use .html() instead of .text() so HTML entities are handled right - setting the HTML of the textarea
67586758 // doesn't work on all browsers, use a dummy <div> instead
67596759 // Get rid of the noincludes when getting text
6760 -
6761 - var $pre = $( '<pre>' + context.$content.html().replace( /\<br[^\>]*\>/gi, "\n" ) + '</pre>' );
 6760+ var $pre = $( '<pre>' +
 6761+ context.$content.html()
 6762+ .replace( /\r?\n/g, "" )
 6763+ .replace( /\<br[^\>]*\>/gi, "\n" )
 6764+ .replace( /&nbsp;/g, " " )
 6765+ .replace( /\<p[^\>]*\>/gi, "\n" )
 6766+ .replace( /\<\/p[^\>]*\>/gi, "" )
 6767+ + '</pre>' );
67626768 $pre.find( ".wikiEditor-noinclude" ).each( function() { $( this ).remove(); } );
 6769+ $pre.find( ".wikiEditor-tab" ).each( function() { $( this ).text( "\t" ) } );
67636770 return $pre.text();
67646771 },
67656772 /**
@@ -7038,12 +7045,33 @@
70397046 // Get a reference to the content area of the iframe
70407047 context.$content = $( context.$iframe[0].contentWindow.document.body );
70417048 // If we just do "context.$content.text( context.$textarea.val() )", Internet Explorer will strip out the
7042 - // whitespace charcters, specifically "\n" - so we must manually encode the text and append it
7043 - context.$content.append(
7044 - context.$textarea.val().replace( /\</g, '&lt;' ).replace( /\>/g, '&gt;' ).replace( /\n/g, '<br />' )
7045 - );
7046 - //context.$content[0].innerText = context.$textarea.val().replace( /\n/g, '\n\n' );
7047 - //context.$content.text( context.$textarea.val() );
 7049+ // whitespace charcters, specifically "\n" - so we must manually encode the text and append it
 7050+ var html = context.$textarea.val().replace( /\</g, '&lt;' ).replace( /\>/g, '&gt;' );
 7051+ // We must do some extra processing on IE to avoid dirty diffs, specifically IE will collapse leading spaces
 7052+ if ( $.browser.msie ) {
 7053+ // Browser sniffing is not ideal, but executing this code on a non-broken browser doesn't cause harm
 7054+ if ( $.browser.versionNumber <= 7 ) {
 7055+ // Replace all spaces matching /(^|n) +/ with &nbsp; - IE <= 7 needs this because of its overzealous
 7056+ // whitespace collapsing;
 7057+ var prefix = '', suffix = html;
 7058+ while ( suffix ) {
 7059+ var match = suffix.match( /(^|\n) / );
 7060+ if ( match ) {
 7061+ prefix += suffix.substr( 0, match.index + match[0].length - 1 ) + '&nbsp;';
 7062+ suffix = suffix.substr( match.index + match[0].length );
 7063+ } else {
 7064+ break;
 7065+ }
 7066+ }
 7067+ html = prefix + suffix;
 7068+ } else {
 7069+ // IE8 is happy if we just convert the first leading space to &nbsp;
 7070+ html = html.replace( /(^|\n) /g, "$1&nbsp;" );
 7071+ }
 7072+ html = html.replace( /\t/g, '<span class="wikiEditor-tab"></span>' );
 7073+ }
 7074+ // We must append, because IE will crash if we set html() - which is the same as empty() and append()
 7075+ context.$content.append( html.replace( /\r?\n/g, '<br />' ) );
70487076 // Reflect direction of parent frame into child
70497077 if ( $( 'body' ).is( '.rtl' ) ) {
70507078 context.$content.addClass( 'rtl' ).attr( 'dir', 'rtl' );
@@ -8256,6 +8284,16 @@
82578285 sanatizedStr = sanatizedStr.substring( 0, endBraces.index ) + " " +
82588286 sanatizedStr.substring( endBraces.index + 2 );
82598287 }
 8288+
 8289+ //treat HTML comments like whitespace
 8290+ while ( sanatizedStr.indexOf( '<!' ) != -1 ) {
 8291+ startIndex = sanatizedStr.indexOf( '<!' );
 8292+ endIndex = sanatizedStr.indexOf('-->') + 3;
 8293+ sanatizedSegment = sanatizedStr.substring( startIndex,endIndex ).replace( /\S/g , ' ' );
 8294+ sanatizedStr =
 8295+ sanatizedStr.substring( 0, startIndex ) + sanatizedSegment + sanatizedStr.substring( endIndex );
 8296+ }
 8297+
82608298 // Match the open braces we just found with equivalent closing braces note, works for any level of braces
82618299 while ( sanatizedStr.indexOf( '{{' ) != -1 ) {
82628300 startIndex = sanatizedStr.indexOf( '{{' ) + 1;
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.min.js
@@ -443,7 +443,9 @@
444444 for(module in context.modules){if(module in $.wikiEditor.modules&&'evt'in $.wikiEditor.modules[module]&&name in $.wikiEditor.modules[module].evt){$.wikiEditor.modules[module].evt[name](context,event);}}},'addButton':function(options){context.$controls.show();context.$buttons.show();return $('<button />').text($.wikiEditor.autoMsg(options,'caption')).click(options.action).appendTo(context.$buttons);},'addView':function(options){function addTab(options){context.$controls.show();context.$tabs.show();return $('<div></div>').attr('rel','wikiEditor-ui-view-'+options.name).addClass(context.view==options.name?'current':null).append($('<a></a>').attr('href','#').click(function(event){context.$ui.find('.wikiEditor-ui-view').hide();context.$ui.find('.'+$(this).parent().attr('rel')).show();context.$tabs.find('div').removeClass('current');$(this).parent().addClass('current');$(this).blur();if('init'in options&&typeof options.init=='function'){options.init(context);}
445445 event.preventDefault();return false;}).text($.wikiEditor.autoMsg(options,'title'))).appendTo(context.$tabs);}
446446 if(!context.$tabs.children().size()){addTab({'name':'wikitext','titleMsg':'wikieditor-wikitext-tab'});}
447 -addTab(options);return $('<div></div>').addClass('wikiEditor-ui-view wikiEditor-ui-view-'+options.name).hide().appendTo(context.$ui);},'getContents':function(){var $pre=$('<pre>'+context.$content.html().replace(/\<br[^\>]*\>/gi,"\n")+'</pre>');$pre.find(".wikiEditor-noinclude").each(function(){$(this).remove();});return $pre.text();},'getSelection':function(){var retval;if(context.$iframe[0].contentWindow.getSelection){retval=context.$iframe[0].contentWindow.getSelection();}else if(context.$iframe[0].contentWindow.document.selection){retval=context.$iframe[0].contentWindow.document.selection.createRange();}
 447+addTab(options);return $('<div></div>').addClass('wikiEditor-ui-view wikiEditor-ui-view-'+options.name).hide().appendTo(context.$ui);},'getContents':function(){var $pre=$('<pre>'+
 448+context.$content.html().replace(/\r?\n/g,"").replace(/\<br[^\>]*\>/gi,"\n").replace(/&nbsp;/g," ").replace(/\<p[^\>]*\>/gi,"\n").replace(/\<\/p[^\>]*\>/gi,"")
 449++'</pre>');$pre.find(".wikiEditor-noinclude").each(function(){$(this).remove();});$pre.find(".wikiEditor-tab").each(function(){$(this).text("\t")});return $pre.text();},'getSelection':function(){var retval;if(context.$iframe[0].contentWindow.getSelection){retval=context.$iframe[0].contentWindow.getSelection();}else if(context.$iframe[0].contentWindow.document.selection){retval=context.$iframe[0].contentWindow.document.selection.createRange();}
448450 if(retval.text){retval=retval.text;}else if(retval.toString){retval=retval.toString();}
449451 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+=' ';}
450452 if(context.$iframe[0].contentWindow.getSelection){var range=context.$iframe[0].contentWindow.getSelection().getRangeAt(0);if(options.ownline){if(range.startOffset!=0){pre="\n"+options.pre;}
@@ -462,7 +464,10 @@
463465 return $(e);var next=e.previousSibling;while(next&&next.lastChild){next=next.lastChild;}
464466 e=next||e.parentNode;strict=false;}
465467 return $([]);}};context.$textarea.wrap($('<div></div>').addClass('wikiEditor-ui')).wrap($('<div></div>').addClass('wikiEditor-ui-view wikiEditor-ui-view-wikitext')).wrap($('<div></div>').addClass('wikiEditor-ui-left')).wrap($('<div></div>').addClass('wikiEditor-ui-bottom')).wrap($('<div></div>').addClass('wikiEditor-ui-text'));context.$ui=context.$textarea.parent().parent().parent().parent().parent();context.$wikitext=context.$textarea.parent().parent().parent().parent();context.$wikitext.before($('<div></div>').addClass('wikiEditor-ui-controls').append($('<div></div>').addClass('wikiEditor-ui-tabs').hide()).append($('<div></div>').addClass('wikiEditor-ui-buttons'))).before($('<div style="clear:both;"></div>'));context.$controls=context.$ui.find('.wikiEditor-ui-buttons').hide();context.$buttons=context.$ui.find('.wikiEditor-ui-buttons');context.$tabs=context.$ui.find('.wikiEditor-ui-tabs');context.$ui.after($('<div style="clear:both;"></div>'));context.$wikitext.append($('<div></div>').addClass('wikiEditor-ui-right'));context.$wikitext.find('.wikiEditor-ui-left').prepend($('<div></div>').addClass('wikiEditor-ui-top'));context.view='wikitext';$(window).resize(function(event){context.fn.trigger('resize',event)});context.$iframe=$('<iframe></iframe>').attr({'frameBorder':0,'border':0,'src':wgScriptPath+'/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.html?'+'instance='+context.instance+'&ts='+(new Date()).getTime(),'id':'wikiEditor-iframe-'+context.instance}).css({'backgroundColor':'white','width':'100%','height':context.$textarea.height(),'display':'none','overflow-y':'scroll','overflow-x':'hidden'}).insertAfter(context.$textarea).load(function(){if(!this.isSecondRun){context.$iframe[0].contentWindow.document.designMode='on';if($.browser.msie){this.isSecondRun=true;return;}}
466 -context.$content=$(context.$iframe[0].contentWindow.document.body);context.$content.append(context.$textarea.val().replace(/\</g,'&lt;').replace(/\>/g,'&gt;').replace(/\n/g,'<br />'));if($('body').is('.rtl')){context.$content.addClass('rtl').attr('dir','rtl');}
 468+context.$content=$(context.$iframe[0].contentWindow.document.body);var html=context.$textarea.val().replace(/\</g,'&lt;').replace(/\>/g,'&gt;');if($.browser.msie){if($.browser.versionNumber<=7){var prefix='',suffix=html;while(suffix){var match=suffix.match(/(^|\n) /);if(match){prefix+=suffix.substr(0,match.index+match[0].length-1)+'&nbsp;';suffix=suffix.substr(match.index+match[0].length);}else{break;}}
 469+html=prefix+suffix;}else{html=html.replace(/(^|\n) /g,"$1&nbsp;");}
 470+html=html.replace(/\t/g,'<span class="wikiEditor-tab"></span>');}
 471+context.$content.append(html.replace(/\r?\n/g,'<br />'));if($('body').is('.rtl')){context.$content.addClass('rtl').attr('dir','rtl');}
467472 context.$textarea.attr('disabled',true);context.$textarea.hide();context.$iframe.show();context.fn.trigger('ready');});context.$textarea.closest('form').submit(function(){context.$textarea.attr('disabled',false);context.$textarea.val(context.$textarea.textSelection('getContents'));});}
468473 arguments=$.makeArray(arguments);if(arguments.length>0){var call=arguments.shift();if(call in context.api){context.api[call](context,typeof arguments[0]=='undefined'?{}:arguments[0]);}}
469474 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];}
@@ -545,6 +550,7 @@
546551 ranges[i].end+=adjustment;}};if(wikitext.match(/\s*{{\s*\S*:/)){}
547552 var sanatizedStr=wikitext.replace(/{{/," ");endBraces=sanatizedStr.match(/}}\s*$/);if(endBraces){sanatizedStr=sanatizedStr.substring(0,endBraces.index)+" "+
548553 sanatizedStr.substring(endBraces.index+2);}
 554+while(sanatizedStr.indexOf('<!')!=-1){startIndex=sanatizedStr.indexOf('<!');endIndex=sanatizedStr.indexOf('-->')+3;sanatizedSegment=sanatizedStr.substring(startIndex,endIndex).replace(/\S/g,' ');sanatizedStr=sanatizedStr.substring(0,startIndex)+sanatizedSegment+sanatizedStr.substring(endIndex);}
549555 while(sanatizedStr.indexOf('{{')!=-1){startIndex=sanatizedStr.indexOf('{{')+1;openBraces=2;endIndex=startIndex;while((openBraces>0)&&(endIndex<sanatizedStr.length)){var brace=sanatizedStr[++endIndex];openBraces+=brace=='}'?-1:brace=='{'?1:0;}
550556 sanatizedSegment=sanatizedStr.substring(startIndex,endIndex).replace(/[{}|=]/g,'X');sanatizedStr=sanatizedStr.substring(0,startIndex)+sanatizedSegment+sanatizedStr.substring(endIndex);}
551557 while(sanatizedStr.indexOf('[[')!=-1){startIndex=sanatizedStr.indexOf('[[')+1;openBraces=2;endIndex=startIndex;while((openBraces>0)&&(endIndex<sanatizedStr.length)){var brace=sanatizedStr[++endIndex];openBraces+=brace==']'?-1:brace=='['?1:0;}

Follow-up revisions

RevisionCommit summaryAuthorDate
r61521UsabilityInitiative: Fix for r61215: IE7 collapses all whitespace, even non-l...catrope16:48, 26 January 2010

Status & tagging log