r66661 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r66660‎ | r66661 | r66662 >
Date:22:08, 19 May 2010
Author:pdhanda
Status:ok (Comments)
Tags:
Comment:
Paste working on Firefox, Chrome and IE. Now I need to fix cursor positioning and write up a test case
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)

Diff [purge]

Index: trunk/extensions/UsabilityInitiative/UsabilityInitiative.hooks.php
@@ -74,7 +74,7 @@
7575 array( 'src' => 'js/plugins/jquery.expandableField.js', 'version' => 15 ),
7676 array( 'src' => 'js/plugins/jquery.suggestions.js', 'version' => 19 ),
7777 array( 'src' => 'js/plugins/jquery.textSelection.js', 'version' => 33 ),
78 - array( 'src' => 'js/plugins/jquery.wikiEditor.js', 'version' => 187 ),
 78+ array( 'src' => 'js/plugins/jquery.wikiEditor.js', 'version' => 188 ),
7979 array( 'src' => 'js/plugins/jquery.wikiEditor.highlight.js', 'version' => 53 ),
8080 array( 'src' => 'js/plugins/jquery.wikiEditor.toolbar.js', 'version' => 62 ),
8181 array( 'src' => 'js/plugins/jquery.wikiEditor.dialogs.js', 'version' => 24 ),
@@ -85,10 +85,10 @@
8686 array( 'src' => 'js/plugins/jquery.wikiEditor.publish.js', 'version' => 5 ),
8787 ),
8888 'combined' => array(
89 - array( 'src' => 'js/plugins.combined.js', 'version' => 403 ),
 89+ array( 'src' => 'js/plugins.combined.js', 'version' => 404 ),
9090 ),
9191 'minified' => array(
92 - array( 'src' => 'js/plugins.combined.min.js', 'version' => 403 ),
 92+ array( 'src' => 'js/plugins.combined.min.js', 'version' => 404 ),
9393 ),
9494 ),
9595 );
Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.js
@@ -397,7 +397,7 @@
398398 // Surround by <p> if it does not already have it
399399 var cursorPos = context.fn.getCaretPosition();
400400 var t = context.fn.getOffset( cursorPos[0] );
401 - if ( t && t.node.nodeName == '#text' && t.node.parentNode.nodeName.toLowerCase() == 'body' ) {
 401+ if ( ! $.browser.msie && t && t.node.nodeName == '#text' && t.node.parentNode.nodeName.toLowerCase() == 'body' ) {
402402 $( t.node ).wrap( "<p></p>" );
403403 context.fn.purgeOffsets();
404404 context.fn.setSelection( { start: cursorPos[0], end: cursorPos[1] } );
@@ -453,10 +453,11 @@
454454 }
455455
456456 var $selection = context.$content.find( ':not(.wikiEditor)' );
457 - var $previousElement;
 457+ var newElementHTML = '' ;
 458+ var $markElement = null;
458459 while ( $selection.length && $selection.length > 0 ) {
459460 var $currentElement = $selection.eq( 0 );
460 -
 461+
461462 //go up till we find the first pasted element
462463 while ( !$currentElement.parent().is( 'body' ) && !$currentElement.parent().is( '.wikiEditor' ) ) {
463464 $currentElement = $currentElement.parent();
@@ -468,63 +469,50 @@
469470 $currentElement = $( $currentElement[0].previousSibling );
470471 }
471472
472 - //each pasted element is always wrapped in a <p>
473 - var $newElement;
474 - var textNode = false;
475 - if ( $currentElement[0].nodeName == '#text' ) {
476 - $newElement = $( '<p></p>' );
477 - textNode = true;
478 - } else if ( $currentElement.is( 'p' ) || $currentElement.is( 'pre' ) || $currentElement.is( 'br' ) ) {
479 - $newElement = $( '<p></p>' );
480 - } else {
481 - $newElement = $( '<span></span>' );
482 - }
483 - var newElementHTML = '';
 473+ // we're going to collect and sanitize all the pasted content and then insert it at $markElement
484474 var currentHTML = '';
485 -
486 -
487 - if ( $currentElement[0].nodeName == '#text' ) {
 475+ if ( $currentElement[0].nodeName == '#text' ) {
488476 //if it is a text node then just append it
489477 currentHTML = $currentElement[0].nodeValue;
490478 } else {
491479 currentHTML = $currentElement.html();
 480+ // First remove all new lines
 481+ currentHTML = currentHTML.replace( /\r?\n/g, '');
492482 //replace all forms of <p> tags with a \n. All other tags get removed.
493483 currentHTML = currentHTML.replace(/(<[\s]*p[^>]*>)|(<[\s]*\/p[^>]*>)|(<[\s]*p[^\/>]*\/>)/gi, '\n');
 484+ // Replace all forms of html tags that should end up in their own <p>
 485+ currentHTML = currentHTML.replace(/(<[\s]*p[^>]*>)|(<[\s]*\/p[^>]*>)|(<[\s]*p[^\/>]*\/>)|(<[\s]*h[\d][^>]*>)|(<[\s]*h[\d][^\/>]*\/>)/gi, '\n');
494486 currentHTML = currentHTML.replace(/(<[^>]*>)|(<[^\>]*\>)/gi, '');
495 -
 487+ currentHTML += '\n';
496488 }
 489+ newElementHTML += currentHTML;
497490
498 - //wrap each piece in a <p> with a <br> in between.
499 - var pieces = currentHTML.split( '\n' );
500 - for ( var i = 0; i < pieces.length; i++ ) {
501 - if ( pieces[i] ) {
502 - if ( textNode || ! $newElement.is( 'p' ) ) {
503 - newElementHTML += '<p class="wikiEditor">' + pieces[i] + '</p>';
504 - } else {
505 - newElementHTML += pieces[i];
506 - }
507 - } else if ( textNode || ! $newElement.is( 'p' ) ) {
508 - newElementHTML += '<br class="wikiEditor" >';
509 - }
510 -
511 - if ( !textNode ) {
512 - newElementHTML += '<br class="wikiEditor" >';
513 - }
 491+ if ( $markElement == null ) {
 492+ $markElement = $( '<div></div>' ).addClass( 'wikiEditor' ).insertAfter( $currentElement );
 493+ }
 494+ $currentElement.remove();
 495+ $selection = context.$content.find( ':not(.wikiEditor)' );
 496+ }
 497+
 498+ //now put a <p> around each line of pasted content
 499+ var pieces = newElementHTML.split( '\n' );
 500+ var $newElement;
 501+ for ( var i = 0; i < pieces.length; i++ ) {
 502+ $newElement = $( '<p></p>' );
 503+ if ( pieces[i] ) {
 504+ $newElement.text( pieces[i] );
 505+ } else {
 506+ $newElement.html( '<br>' );
514507 }
515 -
516 - $newElement.html( newElementHTML ).addClass( 'wikiEditor' );
517508
518 - //remove extra <br>s
519 - if ( $newElement.is( 'p' ) && $currentElement[0].nextSibling != null && $( $currentElement[0].nextSibling ).is( 'br' ) ) {
520 - $( $currentElement[0].nextSibling ).remove();
 509+ $newElement.insertAfter( $markElement );
 510+ if (i == 0 ) {
 511+ $markElement.remove();
521512 }
522 - //swap out the original content with with newly sanitized one
523 - $newElement.insertAfter( $currentElement );
524 - $currentElement.remove();
525 -
526 - $selection = context.$content.find( ':not(.wikiEditor)' );
 513+ $markElement = $newElement;
527514 }
528515
 516+
529517 context.$content.find( '.wikiEditor' ).removeClass( 'wikiEditor' );
530518 if ( $.layout.name !== 'webkit' ) {
531519 context.$content.removeClass( 'pasting' );
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.js
@@ -7069,7 +7069,7 @@
70707070 // Surround by <p> if it does not already have it
70717071 var cursorPos = context.fn.getCaretPosition();
70727072 var t = context.fn.getOffset( cursorPos[0] );
7073 - if ( t && t.node.nodeName == '#text' && t.node.parentNode.nodeName.toLowerCase() == 'body' ) {
 7073+ if ( ! $.browser.msie && t && t.node.nodeName == '#text' && t.node.parentNode.nodeName.toLowerCase() == 'body' ) {
70747074 $( t.node ).wrap( "<p></p>" );
70757075 context.fn.purgeOffsets();
70767076 context.fn.setSelection( { start: cursorPos[0], end: cursorPos[1] } );
@@ -7125,10 +7125,11 @@
71267126 }
71277127
71287128 var $selection = context.$content.find( ':not(.wikiEditor)' );
7129 - var $previousElement;
 7129+ var newElementHTML = '' ;
 7130+ var $markElement = null;
71307131 while ( $selection.length && $selection.length > 0 ) {
71317132 var $currentElement = $selection.eq( 0 );
7132 -
 7133+
71337134 //go up till we find the first pasted element
71347135 while ( !$currentElement.parent().is( 'body' ) && !$currentElement.parent().is( '.wikiEditor' ) ) {
71357136 $currentElement = $currentElement.parent();
@@ -7140,63 +7141,50 @@
71417142 $currentElement = $( $currentElement[0].previousSibling );
71427143 }
71437144
7144 - //each pasted element is always wrapped in a <p>
7145 - var $newElement;
7146 - var textNode = false;
7147 - if ( $currentElement[0].nodeName == '#text' ) {
7148 - $newElement = $( '<p></p>' );
7149 - textNode = true;
7150 - } else if ( $currentElement.is( 'p' ) || $currentElement.is( 'pre' ) || $currentElement.is( 'br' ) ) {
7151 - $newElement = $( '<p></p>' );
7152 - } else {
7153 - $newElement = $( '<span></span>' );
7154 - }
7155 - var newElementHTML = '';
 7145+ // we're going to collect and sanitize all the pasted content and then insert it at $markElement
71567146 var currentHTML = '';
7157 -
7158 -
7159 - if ( $currentElement[0].nodeName == '#text' ) {
 7147+ if ( $currentElement[0].nodeName == '#text' ) {
71607148 //if it is a text node then just append it
71617149 currentHTML = $currentElement[0].nodeValue;
71627150 } else {
71637151 currentHTML = $currentElement.html();
 7152+ // First remove all new lines
 7153+ currentHTML = currentHTML.replace( /\r?\n/g, '');
71647154 //replace all forms of <p> tags with a \n. All other tags get removed.
71657155 currentHTML = currentHTML.replace(/(<[\s]*p[^>]*>)|(<[\s]*\/p[^>]*>)|(<[\s]*p[^\/>]*\/>)/gi, '\n');
 7156+ // Replace all forms of html tags that should end up in their own <p>
 7157+ currentHTML = currentHTML.replace(/(<[\s]*p[^>]*>)|(<[\s]*\/p[^>]*>)|(<[\s]*p[^\/>]*\/>)|(<[\s]*h[\d][^>]*>)|(<[\s]*h[\d][^\/>]*\/>)/gi, '\n');
71667158 currentHTML = currentHTML.replace(/(<[^>]*>)|(<[^\>]*\>)/gi, '');
7167 -
 7159+ currentHTML += '\n';
71687160 }
 7161+ newElementHTML += currentHTML;
71697162
7170 - //wrap each piece in a <p> with a <br> in between.
7171 - var pieces = currentHTML.split( '\n' );
7172 - for ( var i = 0; i < pieces.length; i++ ) {
7173 - if ( pieces[i] ) {
7174 - if ( textNode || ! $newElement.is( 'p' ) ) {
7175 - newElementHTML += '<p class="wikiEditor">' + pieces[i] + '</p>';
7176 - } else {
7177 - newElementHTML += pieces[i];
7178 - }
7179 - } else if ( textNode || ! $newElement.is( 'p' ) ) {
7180 - newElementHTML += '<br class="wikiEditor" >';
7181 - }
7182 -
7183 - if ( !textNode ) {
7184 - newElementHTML += '<br class="wikiEditor" >';
7185 - }
 7163+ if ( $markElement == null ) {
 7164+ $markElement = $( '<div></div>' ).addClass( 'wikiEditor' ).insertAfter( $currentElement );
 7165+ }
 7166+ $currentElement.remove();
 7167+ $selection = context.$content.find( ':not(.wikiEditor)' );
 7168+ }
 7169+
 7170+ //now put a <p> around each line of pasted content
 7171+ var pieces = newElementHTML.split( '\n' );
 7172+ var $newElement;
 7173+ for ( var i = 0; i < pieces.length; i++ ) {
 7174+ $newElement = $( '<p></p>' );
 7175+ if ( pieces[i] ) {
 7176+ $newElement.text( pieces[i] );
 7177+ } else {
 7178+ $newElement.html( '<br>' );
71867179 }
7187 -
7188 - $newElement.html( newElementHTML ).addClass( 'wikiEditor' );
71897180
7190 - //remove extra <br>s
7191 - if ( $newElement.is( 'p' ) && $currentElement[0].nextSibling != null && $( $currentElement[0].nextSibling ).is( 'br' ) ) {
7192 - $( $currentElement[0].nextSibling ).remove();
 7181+ $newElement.insertAfter( $markElement );
 7182+ if (i == 0 ) {
 7183+ $markElement.remove();
71937184 }
7194 - //swap out the original content with with newly sanitized one
7195 - $newElement.insertAfter( $currentElement );
7196 - $currentElement.remove();
7197 -
7198 - $selection = context.$content.find( ':not(.wikiEditor)' );
 7185+ $markElement = $newElement;
71997186 }
72007187
 7188+
72017189 context.$content.find( '.wikiEditor' ).removeClass( 'wikiEditor' );
72027190 if ( $.layout.name !== 'webkit' ) {
72037191 context.$content.removeClass( 'pasting' );
Index: trunk/extensions/UsabilityInitiative/js/plugins.combined.min.js
@@ -475,18 +475,18 @@
476476 break;}
477477 return true;},'change':function(event){event.data.scope='division';var newHTML=context.$content.html();if(context.oldHTML!=newHTML){context.fn.purgeOffsets();context.oldHTML=newHTML;event.data.scope='realchange';}
478478 if(context.$content.children().length==0){context.$content.append('<p></p>');}
479 -return true;},'delayedChange':function(event){event.data.scope='division';var newHTML=context.$content.html();if(context.oldDelayedHTML!=newHTML){context.oldDelayedHTML=newHTML;event.data.scope='realchange';var cursorPos=context.fn.getCaretPosition();var t=context.fn.getOffset(cursorPos[0]);if(t&&t.node.nodeName=='#text'&&t.node.parentNode.nodeName.toLowerCase()=='body'){$(t.node).wrap("<p></p>");context.fn.purgeOffsets();context.fn.setSelection({start:cursorPos[0],end:cursorPos[1]});}}
 479+return true;},'delayedChange':function(event){event.data.scope='division';var newHTML=context.$content.html();if(context.oldDelayedHTML!=newHTML){context.oldDelayedHTML=newHTML;event.data.scope='realchange';var cursorPos=context.fn.getCaretPosition();var t=context.fn.getOffset(cursorPos[0]);if(!$.browser.msie&&t&&t.node.nodeName=='#text'&&t.node.parentNode.nodeName.toLowerCase()=='body'){$(t.node).wrap("<p></p>");context.fn.purgeOffsets();context.fn.setSelection({start:cursorPos[0],end:cursorPos[1]});}}
480480 context.fn.updateHistory(event.data.scope=='realchange');return true;},'cut':function(event){setTimeout(function(){context.$content.find('br').each(function(){if($(this).parent().is('body')){$(this).wrap($('<p></p>'));}});},100);return true;},'paste':function(event){var cursorPos=context.fn.getCaretPosition();if(!context.$content.text()){context.$content.empty();}
481481 var oldLength=context.fn.getContents().length;context.$content.find('*').addClass('wikiEditor');if($.layout.name!=='webkit'){context.$content.addClass('pasting');}
482482 setTimeout(function(){context.$content.find('script,style,img,input,select,textarea,hr,button,link,meta').remove();context.$content.find('*').each(function(){if($(this).children().length==0&&this.childNodes.length>0){$(this).text($(this).text());}});context.$content.find('p:not(.wikiEditor) p:not(.wikiEditor)').each(function(){var outerParent=$(this).parent();outerParent.replaceWith(outerParent.childNodes);});if(!$.browser.msie){context.$content.find('span.Apple-style-span').each(function(){$(this).replaceWith(this.childNodes);});}
483 -var $selection=context.$content.find(':not(.wikiEditor)');var $previousElement;while($selection.length&&$selection.length>0){var $currentElement=$selection.eq(0);while(!$currentElement.parent().is('body')&&!$currentElement.parent().is('.wikiEditor')){$currentElement=$currentElement.parent();}
 483+var $selection=context.$content.find(':not(.wikiEditor)');var newElementHTML='';var $markElement=null;while($selection.length&&$selection.length>0){var $currentElement=$selection.eq(0);while(!$currentElement.parent().is('body')&&!$currentElement.parent().is('.wikiEditor')){$currentElement=$currentElement.parent();}
484484 while($currentElement[0]!=null&&$currentElement[0].previousSibling!=null&&!$($currentElement[0].previousSibling).hasClass('wikiEditor')){$currentElement=$($currentElement[0].previousSibling);}
485 -var $newElement;var textNode=false;if($currentElement[0].nodeName=='#text'){$newElement=$('<p></p>');textNode=true;}else if($currentElement.is('p')||$currentElement.is('pre')||$currentElement.is('br')){$newElement=$('<p></p>');}else{$newElement=$('<span></span>');}
486 -var newElementHTML='';var currentHTML='';if($currentElement[0].nodeName=='#text'){currentHTML=$currentElement[0].nodeValue;}else{currentHTML=$currentElement.html();currentHTML=currentHTML.replace(/(<[\s]*p[^>]*>)|(<[\s]*\/p[^>]*>)|(<[\s]*p[^\/>]*\/>)/gi,'\n');currentHTML=currentHTML.replace(/(<[^>]*>)|(<[^\>]*\>)/gi,'');}
487 -var pieces=currentHTML.split('\n');for(var i=0;i<pieces.length;i++){if(pieces[i]){if(textNode||!$newElement.is('p')){newElementHTML+='<p class="wikiEditor">'+pieces[i]+'</p>';}else{newElementHTML+=pieces[i];}}else if(textNode||!$newElement.is('p')){newElementHTML+='<br class="wikiEditor" >';}
488 -if(!textNode){newElementHTML+='<br class="wikiEditor" >';}}
489 -$newElement.html(newElementHTML).addClass('wikiEditor');if($newElement.is('p')&&$currentElement[0].nextSibling!=null&&$($currentElement[0].nextSibling).is('br')){$($currentElement[0].nextSibling).remove();}
490 -$newElement.insertAfter($currentElement);$currentElement.remove();$selection=context.$content.find(':not(.wikiEditor)');}
 485+var currentHTML='';if($currentElement[0].nodeName=='#text'){currentHTML=$currentElement[0].nodeValue;}else{currentHTML=$currentElement.html();currentHTML=currentHTML.replace(/\r?\n/g,'');currentHTML=currentHTML.replace(/(<[\s]*p[^>]*>)|(<[\s]*\/p[^>]*>)|(<[\s]*p[^\/>]*\/>)/gi,'\n');currentHTML=currentHTML.replace(/(<[\s]*p[^>]*>)|(<[\s]*\/p[^>]*>)|(<[\s]*p[^\/>]*\/>)|(<[\s]*h[\d][^>]*>)|(<[\s]*h[\d][^\/>]*\/>)/gi,'\n');currentHTML=currentHTML.replace(/(<[^>]*>)|(<[^\>]*\>)/gi,'');currentHTML+='\n';}
 486+newElementHTML+=currentHTML;if($markElement==null){$markElement=$('<div></div>').addClass('wikiEditor').insertAfter($currentElement);}
 487+$currentElement.remove();$selection=context.$content.find(':not(.wikiEditor)');}
 488+var pieces=newElementHTML.split('\n');var $newElement;for(var i=0;i<pieces.length;i++){$newElement=$('<p></p>');if(pieces[i]){$newElement.text(pieces[i]);}else{$newElement.html('<br>');}
 489+$newElement.insertAfter($markElement);if(i==0){$markElement.remove();}
 490+$markElement=$newElement;}
491491 context.$content.find('.wikiEditor').removeClass('wikiEditor');if($.layout.name!=='webkit'){context.$content.removeClass('pasting');}
492492 context.fn.purgeOffsets();var newLength=context.fn.getContents().length;var restoreTo=cursorPos[0]+newLength-oldLength;if(restoreTo>newLength){restoreTo=newLength;}
493493 context.fn.setSelection({start:restoreTo,end:restoreTo});},0);return true;},'ready':function(event){context.history.push({'html':context.$content.html(),'sel':context.fn.getCaretPosition()});return true;}};context.fn={'trigger':function(name,event){if(typeof event=='undefined'){event={'type':'custom'};}

Comments

#Comment by Catrope (talk | contribs)   19:55, 3 June 2010
+						currentHTML = currentHTML.replace(/(<[\s]*p[^>]*>)|(<[\s]*\/p[^>]*>)|(<[\s]*p[^\/>]*\/>)|(<[\s]*h[\d][^>]*>)|(<[\s]*h[\d][^\/>]*\/>)/gi, '\n');

Again, this regex contains brackets around \s and \d and includes cases that can be collapsed.

+						$markElement = $( '<div></div>' ).addClass( 'wikiEditor' ).insertAfter( $currentElement );
+                    }

You positioned this brace using spaces instead of tab, making it look out of place in any editor that doesn't use your exact tab size.

Status & tagging log