Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.toc.js |
— | — | @@ -57,6 +57,9 @@ |
58 | 58 | ready: function( context, event ) { |
59 | 59 | // Add the TOC to the document |
60 | 60 | $.wikiEditor.modules.toc.fn.build( context ); |
| 61 | + if ( !context.$content ) { |
| 62 | + return; |
| 63 | + } |
61 | 64 | context.$content.parent() |
62 | 65 | .blur( function() { |
63 | 66 | var context = event.data.context; |
— | — | @@ -295,6 +298,9 @@ |
296 | 299 | * @param {Object} context |
297 | 300 | */ |
298 | 301 | update: function( context ) { |
| 302 | + //temporarily commenting this out because it is causing all kinds of cursor |
| 303 | + //and text jumping issues in IE. WIll get back to this --pdhanda |
| 304 | + /* |
299 | 305 | var div = context.fn.beforeSelection( 'wikiEditor-toc-header' ); |
300 | 306 | if ( div === null ) { |
301 | 307 | // beforeSelection couldn't figure it out, keep the old highlight state |
— | — | @@ -309,6 +315,7 @@ |
310 | 316 | |
311 | 317 | // Scroll the highlighted link into view if necessary |
312 | 318 | var relTop = sectionLink.offset().top - context.modules.toc.$toc.offset().top; |
| 319 | + |
313 | 320 | var scrollTop = context.modules.toc.$toc.scrollTop(); |
314 | 321 | var divHeight = context.modules.toc.$toc.height(); |
315 | 322 | var sectionHeight = sectionLink.height(); |
— | — | @@ -319,6 +326,7 @@ |
320 | 327 | // Scroll down |
321 | 328 | context.modules.toc.$toc.scrollTop( scrollTop + relTop + sectionHeight - divHeight ); |
322 | 329 | } |
| 330 | + */ |
323 | 331 | }, |
324 | 332 | |
325 | 333 | /** |
— | — | @@ -461,8 +469,11 @@ |
462 | 470 | // Bring user's eyes to the point we've now jumped to |
463 | 471 | context.fn.highlightLine( $( wrapper ) ); |
464 | 472 | // Highlight the clicked link |
465 | | - $.wikiEditor.modules.toc.fn.unhighlight( context ); |
| 473 | + //remove highlighting of toc after a second. Temporary hack till the highlight works --pdhanda |
| 474 | + //$.wikiEditor.modules.toc.fn.unhighlight( context ); |
466 | 475 | $( this ).addClass( 'current' ); |
| 476 | + //$( this ).removeClass( 'current' ); |
| 477 | + setTimeout( function() { $.wikiEditor.modules.toc.fn.unhighlight( context ) }, 1000 ); |
467 | 478 | |
468 | 479 | if ( typeof $.trackAction != 'undefined' ) |
469 | 480 | $.trackAction( 'ntoc.heading' ); |
Index: trunk/extensions/UsabilityInitiative/js/plugins/jquery.wikiEditor.js |
— | — | @@ -413,36 +413,50 @@ |
414 | 414 | 'paste': function( event ) { |
415 | 415 | // Save the cursor position to restore it after all this voodoo |
416 | 416 | var cursorPos = context.fn.getCaretPosition(); |
417 | | - var offset = 0; |
418 | 417 | var oldLength = context.fn.getContents().length; |
| 418 | + var positionFromEnd = oldLength - cursorPos[1]; |
419 | 419 | |
420 | 420 | //give everything the wikiEditor class so that we can easily pick out things without that class as pasted |
421 | 421 | context.$content.find( '*' ).addClass( 'wikiEditor' ); |
422 | 422 | if ( $.layout.name !== 'webkit' ) { |
423 | 423 | context.$content.addClass( 'pasting' ); |
424 | 424 | } |
| 425 | + |
425 | 426 | setTimeout( function() { |
426 | | - |
427 | 427 | // Kill stuff we know we don't want |
428 | 428 | context.$content.find( 'script,style,img,input,select,textarea,hr,button,link,meta' ).remove(); |
429 | | - |
430 | | - //anything without wikiEditor class was pasted. |
431 | | - var $selection = context.$content.find( ':not(.wikiEditor)' ); |
432 | 429 | var nodeToDelete = []; |
| 430 | + var pastedContent = []; |
433 | 431 | var firstDirtyNode; |
434 | | - if ( $selection.length == 0 ) { |
435 | | - firstDirtyNode = context.fn.getOffset( cursorPos[0] ).node; |
| 432 | + var $lastDirtyNode; |
| 433 | + var elementAtCursor; |
| 434 | + if ( $.browser.msie && !context.offsets ) { |
| 435 | + elementAtCursor = null; |
436 | 436 | } else { |
437 | | - firstDirtyNode = $selection.eq( 0 )[0]; |
| 437 | + elementAtCursor = context.fn.getOffset( cursorPos[0] ); |
438 | 438 | } |
| 439 | + if ( elementAtCursor == null || elementAtCursor.node == null ) { |
| 440 | + context.$content.prepend( '<p class = wikiEditor></p>' ); |
| 441 | + firstDirtyNode = context.$content.children()[0]; |
| 442 | + } else { |
| 443 | + firstDirtyNode = elementAtCursor.node; |
| 444 | + } |
| 445 | + |
| 446 | + //this is ugly but seems like the best way to handle the case where we select and replace all editor contents |
| 447 | + try { |
| 448 | + firstDirtyNode.parentNode; |
| 449 | + } catch ( err ) { |
| 450 | + context.$content.prepend( '<p class = wikiEditor></p>' ); |
| 451 | + firstDirtyNode = context.$content.children()[0]; |
| 452 | + } |
| 453 | + |
439 | 454 | while ( firstDirtyNode != null ) { |
440 | | - //go up till we find the top pasted node |
441 | | - while ( firstDirtyNode.parentNode.nodeName != 'BODY' |
442 | | - && ! $( firstDirtyNode.parentNode ).hasClass( 'wikiEditor' ) |
| 455 | + //we're going to replace the contents of the entire parent node. |
| 456 | + while ( firstDirtyNode.parentNode && firstDirtyNode.parentNode.nodeName != 'BODY' |
| 457 | + && ! $( firstDirtyNode ).hasClass( 'wikiEditor' ) |
443 | 458 | ) { |
444 | 459 | firstDirtyNode = firstDirtyNode.parentNode; |
445 | 460 | } |
446 | | - |
447 | 461 | //go back till we find the first pasted node |
448 | 462 | while ( firstDirtyNode.previousSibling != null |
449 | 463 | && ! $( firstDirtyNode.previousSibling ).hasClass( 'wikiEditor' ) |
— | — | @@ -455,36 +469,27 @@ |
456 | 470 | } |
457 | 471 | } |
458 | 472 | |
459 | | - var $lastDirtyNode = $( firstDirtyNode ); |
| 473 | + if ( firstDirtyNode.previousSibling != null ) { |
| 474 | + $lastDirtyNode = $( firstDirtyNode.previousSibling ); |
| 475 | + } else { |
| 476 | + $lastDirtyNode = $( firstDirtyNode ); |
| 477 | + } |
| 478 | + |
460 | 479 | var cc = makeContentCollector( $.browser, null ); |
461 | | - while ( firstDirtyNode != null && ! $( firstDirtyNode ).hasClass( 'wikiEditor' ) ) { |
| 480 | + while ( firstDirtyNode != null ) { |
462 | 481 | cc.collectContent(firstDirtyNode); |
| 482 | + cc.notifyNextNode(firstDirtyNode.nextSibling); |
463 | 483 | |
464 | | - cc.notifyNextNode(firstDirtyNode.nextSibling); |
465 | | - pastedContent = cc.getLines(); |
466 | | - if ((pastedContent.length <= 1 || pastedContent[pastedContent.length - 1] !== "") |
467 | | - && firstDirtyNode.nextSibling) { |
468 | | - nodeToDelete.push( firstDirtyNode ); |
469 | | - firstDirtyNode = firstDirtyNode.nextSibling; |
470 | | - cc.collectContent(firstDirtyNode); |
471 | | - cc.notifyNextNode(firstDirtyNode.nextSibling); |
472 | | - } |
473 | 484 | nodeToDelete.push( firstDirtyNode ); |
| 485 | + |
474 | 486 | firstDirtyNode = firstDirtyNode.nextSibling; |
| 487 | + if ( $( firstDirtyNode ).hasClass( 'wikiEditor' ) ) { |
| 488 | + break; |
| 489 | + } |
475 | 490 | } |
| 491 | + |
476 | 492 | var ccData = cc.finish(); |
477 | | - var pastedContent = ccData.lines; |
478 | | - if ( pastedContent.length == 0 && firstDirtyNode ) { |
479 | | - offset += $( firstDirtyNode ).text().length; |
480 | | - } |
481 | | - |
482 | | - if ( nodeToDelete.length > 0 ) { |
483 | | - $lastDirtyNode = $( nodeToDelete[nodeToDelete.length - 1] ); |
484 | | - } |
485 | | - |
486 | | - var testVal = ''; |
487 | | - testVal = $( nodeToDelete[0] ).text(); |
488 | | - |
| 493 | + pastedContent = ccData.lines; |
489 | 494 | var pastedPretty = ''; |
490 | 495 | for ( var i = 0; i < pastedContent.length; i++ ) { |
491 | 496 | //escape html |
— | — | @@ -497,45 +502,58 @@ |
498 | 503 | pastedPretty = leadingSpace + pastedPretty.substring(index, pastedPretty.length); |
499 | 504 | } |
500 | 505 | |
501 | | - $newElement = $( '<p class="wikiEditor" ></p>' ); |
| 506 | + |
| 507 | + if( !pastedPretty && $.browser.msie && i == 0 ) { |
| 508 | + continue; |
| 509 | + } |
| 510 | + $newElement = $( '<p class="wikiEditor pasted" ></p>' ); |
502 | 511 | if ( pastedPretty ) { |
503 | | - $newElement.html( '<span class = "wikiEditor">' + pastedPretty + '</span>' ); |
| 512 | + $newElement.html( pastedPretty ); |
504 | 513 | } else { |
505 | 514 | $newElement.html( '<br class="wikiEditor">' ); |
506 | 515 | } |
507 | 516 | $newElement.insertAfter( $lastDirtyNode ); |
508 | | - offset += pastedPretty.length; |
| 517 | + |
509 | 518 | $lastDirtyNode = $newElement; |
| 519 | + |
510 | 520 | } |
511 | 521 | |
| 522 | + //now delete all the original nodes that we prettified already |
512 | 523 | while ( nodeToDelete.length > 0 ) { |
513 | | - $( nodeToDelete.pop() ).remove(); |
| 524 | + $deleteNode = $( nodeToDelete.pop() ); |
| 525 | + $deleteNode.remove(); |
514 | 526 | } |
515 | 527 | |
516 | | - //find the next node that may not be the next sibling (in IE) |
| 528 | + //anything without wikiEditor class was pasted. |
517 | 529 | $selection = context.$content.find( ':not(.wikiEditor)' ); |
518 | 530 | if ( $selection.length == 0 ) { |
519 | | - firstDirtyNode = null; |
| 531 | + break; |
520 | 532 | } else { |
521 | 533 | firstDirtyNode = $selection.eq( 0 )[0]; |
522 | 534 | } |
523 | 535 | } |
524 | | - |
525 | 536 | context.$content.find( '.wikiEditor' ).removeClass( 'wikiEditor' ); |
526 | 537 | |
527 | | - //context.$content.find( '*' ).addClass( 'wikiEditor' ); |
528 | | - |
529 | 538 | //now place the cursor at the end of pasted content |
530 | | - var restoreTo = cursorPos[1] + offset; |
| 539 | + var newLength = context.fn.getContents().length; |
| 540 | + var newPos = newLength - positionFromEnd; |
531 | 541 | |
532 | | - context.fn.setSelection( { start: restoreTo, end: restoreTo } ); |
| 542 | + context.fn.purgeOffsets(); |
| 543 | + context.fn.setSelection( { start: newPos, end: newPos } ); |
| 544 | + |
| 545 | + context.fn.scrollToCaretPosition(); |
| 546 | + |
533 | 547 | |
534 | 548 | }, 0 ); |
535 | 549 | return true; |
536 | 550 | }, |
537 | 551 | 'ready': function( event ) { |
538 | 552 | // Initialize our history queue |
539 | | - context.history.push( { 'html': context.$content.html(), 'sel': context.fn.getCaretPosition() } ); |
| 553 | + if ( context.$content ) { |
| 554 | + context.history.push( { 'html': context.$content.html(), 'sel': context.fn.getCaretPosition() } ); |
| 555 | + } else { |
| 556 | + context.history.push( { 'html': '', 'sel': context.fn.getCaretPosition() } ); |
| 557 | + } |
540 | 558 | return true; |
541 | 559 | } |
542 | 560 | }; |
— | — | @@ -555,15 +573,16 @@ |
556 | 574 | if ( typeof event.data == 'undefined' ) { |
557 | 575 | event.data = {}; |
558 | 576 | } |
| 577 | + |
559 | 578 | // Allow filtering to occur |
560 | 579 | if ( name in context.evt ) { |
561 | 580 | if ( !context.evt[name]( event ) ) { |
562 | 581 | return false; |
563 | 582 | } |
564 | 583 | } |
565 | | - |
566 | 584 | var returnFromModules = null; //they return null by default |
567 | 585 | // Pass the event around to all modules activated on this context |
| 586 | + |
568 | 587 | for ( var module in context.modules ) { |
569 | 588 | if ( |
570 | 589 | module in $.wikiEditor.modules && |
— | — | @@ -734,6 +753,9 @@ |
735 | 754 | classname = ''; |
736 | 755 | } |
737 | 756 | var e = null, offset = null; |
| 757 | + if ( $.browser.msie && !context.$iframe[0].contentWindow.document.body ) { |
| 758 | + return null; |
| 759 | + } |
738 | 760 | if ( context.$iframe[0].contentWindow.getSelection ) { |
739 | 761 | // Firefox and Opera |
740 | 762 | var selection = context.$iframe[0].contentWindow.getSelection(); |
— | — | @@ -1231,6 +1253,9 @@ |
1232 | 1254 | 'getContents': function() { |
1233 | 1255 | // For <p></p>, .html() returns <p> </p> in IE |
1234 | 1256 | // This seems to convince IE while not affecting display |
| 1257 | + if ( !context.$content ) { |
| 1258 | + return ''; |
| 1259 | + } |
1235 | 1260 | var html; |
1236 | 1261 | if ( $.browser.msie ) { |
1237 | 1262 | // Don't manipulate the iframe DOM itself, causes cursor jumping issues |
— | — | @@ -1847,6 +1872,7 @@ |
1848 | 1873 | // Only allow modules which are supported (and thus actually being turned on) affect this decision |
1849 | 1874 | if ( module in $.wikiEditor.modules && $.wikiEditor.isSupported( $.wikiEditor.modules[module] ) && |
1850 | 1875 | $.wikiEditor.isRequired( $.wikiEditor.modules[module], 'iframe' ) ) { |
| 1876 | + |
1851 | 1877 | context.fn.setupIframe(); |
1852 | 1878 | break; |
1853 | 1879 | } |
Index: trunk/extensions/UsabilityInitiative/js/thirdparty/contentCollector.js |
— | — | @@ -35,8 +35,15 @@ |
36 | 36 | return n.tagName; |
37 | 37 | }, |
38 | 38 | nodeValue : function(n) { |
39 | | - return n.nodeValue; |
| 39 | + try { |
| 40 | + return n.nodeValue; |
| 41 | + } catch ( err ) { |
| 42 | + return ''; |
| 43 | + } |
40 | 44 | }, |
| 45 | + nodeName : function(n) { |
| 46 | + return n.nodeName; |
| 47 | + }, |
41 | 48 | nodeNumChildren : function(n) { |
42 | 49 | return n.childNodes.length; |
43 | 50 | }, |
— | — | @@ -264,6 +271,7 @@ |
265 | 272 | } |
266 | 273 | |
267 | 274 | } else { |
| 275 | + var cls = dom.nodeProp(node, "className"); |
268 | 276 | var tname = (dom.nodeTagName(node) || "").toLowerCase(); |
269 | 277 | if (tname == "br") { |
270 | 278 | _startNewLine(state); |
— | — | @@ -271,8 +279,7 @@ |
272 | 280 | // ignore |
273 | 281 | } else if (!isEmpty) { |
274 | 282 | var styl = dom.nodeAttr(node, "style"); |
275 | | - var cls = dom.nodeProp(node, "className"); |
276 | | - |
| 283 | + |
277 | 284 | var isPre = (tname == "pre"); |
278 | 285 | if ((!isPre) && browser.safari) { |
279 | 286 | isPre = (styl && /\bwhite-space:\s*pre\b/i.exec(styl)); |
— | — | @@ -284,6 +291,11 @@ |
285 | 292 | var nc = dom.nodeNumChildren(node); |
286 | 293 | for ( var i = 0; i < nc; i++) { |
287 | 294 | var c = dom.nodeChild(node, i); |
| 295 | + //very specific IE case where it inserts <span lang="en"> which we want to ginore. |
| 296 | + //to reproduce copy content from wordpad andpaste into the middle of a line in IE |
| 297 | + if ( browser.msie && cls.indexOf('wikiEditor') >= 0 && dom.nodeName(c) == 'SPAN' && dom.nodeAttr(c, 'lang') == "" ) { |
| 298 | + continue; |
| 299 | + } |
288 | 300 | cc.collectContent(c, state); |
289 | 301 | } |
290 | 302 | |
— | — | @@ -347,7 +359,9 @@ |
348 | 360 | lines.flush(); |
349 | 361 | var lineStrings = cc.getLines(); |
350 | 362 | |
351 | | - lineStrings.length--; |
| 363 | + if ( lineStrings.length > 0 && !lineStrings[lineStrings.length - 1] ) { |
| 364 | + lineStrings.length--; |
| 365 | + } |
352 | 366 | |
353 | 367 | var ss = getSelectionStart(); |
354 | 368 | var se = getSelectionEnd(); |