Changeset 693
- Timestamp:
- 01/23/07 13:56:06 (6 years ago)
- Location:
- branches/688-fixup
- Files:
-
- 2 added
- 15 modified
-
XinhaCore.js (modified) (10 diffs)
-
modules/CreateLink/link.html (modified) (1 diff)
-
modules/CreateLink/link.js (modified) (3 diffs)
-
modules/Dialogs/dialog.js (modified) (1 diff)
-
modules/Dialogs/inline-dialog.js (modified) (1 diff)
-
modules/Gecko/Gecko.js (modified) (4 diffs)
-
modules/Gecko/paraHandlerBest.js (modified) (15 diffs)
-
modules/Gecko/paraHandlerDirty.js (added)
-
modules/GetHtml/DOMwalk.js (modified) (1 diff)
-
modules/GetHtml/TransformInnerHTML.js (modified) (2 diffs)
-
modules/InsertImage/insert_image.html (modified) (2 diffs)
-
modules/InsertImage/insert_image.js (modified) (3 diffs)
-
modules/InsertTable/insert_table.html (modified) (2 diffs)
-
modules/InsertTable/insert_table.js (added)
-
modules/InternetExplorer/InternetExplorer.js (modified) (1 diff)
-
plugins/GetHtml/get-html.js (modified) (2 diffs)
-
plugins/TableOperations/table-operations.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/688-fixup/XinhaCore.js
r689 r693 279 279 // plugin from "hipikat", rolled in to be part of the core code 280 280 281 282 // possible values 283 // 'DOMwalk' (the "original") 284 // 'TransformInnerHTML' (this used to be the GetHtml plugin) 285 this.getHtmlMethod = 'DOMwalk'; 286 281 287 // maximum size of the undo queue 282 288 this.undoSteps = 20; … … 459 465 { 460 466 "blank": "popups/blank.html", 461 "link": "link.html",462 "insert_image": "insert_image.html",463 "insert_table": "insert_table.html",467 "link": _editor_url + "modules/CreateLink/link.html", 468 "insert_image": _editor_url + "modules/InsertImage/insert_image.html", 469 "insert_table": _editor_url + "modules/InsertTable/insert_table.html", 464 470 "select_color": "select_color.html", 465 471 "about": "about.html", … … 1445 1451 { 1446 1452 var i; 1447 var editor = this; // we'll need "this" in some nested functions1453 var editor = this; // we'll need "this" in some nested functions 1448 1454 1449 1455 // Now load a specific browser plugin which will implement the above for us. … … 1452 1458 if ( typeof InternetExplorer == 'undefined' ) 1453 1459 { 1454 Xinha.loadPlugin("InternetExplorer", function() { editor.generate(); }, _editor_url + ' functionsIE.js' );1460 Xinha.loadPlugin("InternetExplorer", function() { editor.generate(); }, _editor_url + 'modules/InternetExplorer/InternetExplorer.js' ); 1455 1461 return false; 1456 1462 } … … 1461 1467 if ( typeof Gecko == 'undefined' ) 1462 1468 { 1463 Xinha.loadPlugin("Gecko", function() { editor.generate(); }, _editor_url + ' functionsMozilla.js' );1469 Xinha.loadPlugin("Gecko", function() { editor.generate(); }, _editor_url + 'modules/Gecko/Gecko.js' ); 1464 1470 return false; 1465 1471 } … … 1471 1477 if ( typeof Dialog == 'undefined' ) 1472 1478 { 1473 Xinha._loadback(_editor_url + ' dialog.js', this.generate, this );1479 Xinha._loadback(_editor_url + 'modules/Dialogs/dialog.js', this.generate, this ); 1474 1480 return false; 1475 1481 } … … 1477 1483 if ( typeof Xinha.Dialog == 'undefined' ) 1478 1484 { 1479 Xinha._loadback(_editor_url + ' inline-dialog.js', this.generate, this );1485 Xinha._loadback(_editor_url + 'modules/Dialogs/inline-dialog.js', this.generate, this ); 1480 1486 return false; 1481 1487 } 1482 1488 1483 if ( typeof PopupWin == 'undefined' ) 1484 { 1485 Xinha._loadback(_editor_url + 'popupwin.js', this.generate, this ); 1486 return false; 1487 } 1489 var toolbar = editor.config.toolbar; 1490 for ( i = toolbar.length; --i >= 0; ) 1491 { 1492 for ( var j = toolbar[i].length; --j >= 0; ) 1493 { 1494 switch (toolbar[i][j]) 1495 { 1496 case "popupeditor": 1497 if ( typeof FullScreen == "undefined" ) 1498 { 1499 Xinha.loadPlugin("FullScreen", function() { editor.generate(); }, _editor_url + 'modules/FullScreen/full-screen.js' ); 1500 return false; 1501 } 1502 editor.registerPlugin('FullScreen'); 1503 break; 1504 case "insertimage": 1505 if ( typeof InsertImage == 'undefined' && typeof Xinha.prototype._insertImage == 'undefined' ) 1506 { 1507 Xinha.loadPlugin("InsertImage", function() { editor.generate(); } , _editor_url + 'modules/InsertImage/insert_image.js'); 1508 return false; 1509 } 1510 else if ( typeof InsertImage != 'undefined') editor.registerPlugin('InsertImage'); 1511 break; 1512 case "createlink": 1513 if ( typeof CreateLink == 'undefined' && typeof Xinha.prototype._createLink == 'undefined' && typeof Linker == 'undefined' ) 1514 { 1515 Xinha.loadPlugin("CreateLink", function() { editor.generate(); } , _editor_url + 'modules/CreateLink/link.js'); 1516 return false; 1517 } 1518 else if ( typeof CreateLink != 'undefined') editor.registerPlugin('CreateLink'); 1519 break; 1520 case "inserttable": 1521 if ( typeof InsertTable == 'undefined' && typeof Xinha.prototype._insertTable == 'undefined' ) 1522 { 1523 Xinha.loadPlugin("InsertTable", function() { editor.generate(); } , _editor_url + 'modules/InsertTable/insert_table.js'); 1524 return false; 1525 } 1526 else if ( typeof InsertTable != 'undefined') editor.registerPlugin('InsertTable'); 1527 break; 1528 } 1529 } 1530 } 1531 1532 // If this is gecko, set up the paragraph handling now 1533 if ( Xinha.is_gecko && ( editor.config.mozParaHandler == 'best' || editor.config.mozParaHandler == 'dirty' ) ) 1534 { 1535 switch (this.config.mozParaHandler) 1536 { 1537 case 'dirty': 1538 var ParaHandlerPlugin = _editor_url + 'modules/Gecko/paraHandlerDirty.js'; 1539 break; 1540 default: 1541 var ParaHandlerPlugin = _editor_url + 'modules/Gecko/paraHandlerBest.js'; 1542 break; 1543 } 1544 if ( typeof EnterParagraphs == 'undefined' ) 1545 { 1546 Xinha.loadPlugin("EnterParagraphs", function() { editor.generate(); }, ParaHandlerPlugin ); 1547 return false; 1548 } 1549 editor.registerPlugin('EnterParagraphs'); 1550 } 1551 1552 switch (this.config.getHtmlMethod) 1553 { 1554 case 'TransformInnerHTML': 1555 var getHtmlMethodPlugin = _editor_url + 'modules/GetHtml/TransformInnerHTML.js'; 1556 break; 1557 default: 1558 var getHtmlMethodPlugin = _editor_url + 'modules/GetHtml/DOMwalk.js'; 1559 break; 1560 } 1561 1562 if (typeof GetHtmlImplementation == 'undefined') 1563 { 1564 Xinha.loadPlugin("GetHtmlImplementation", function() { editor.generate(); } , getHtmlMethodPlugin); 1565 return false; 1566 } 1567 else editor.registerPlugin('GetHtmlImplementation'); 1568 1488 1569 1489 1570 if ( _editor_skin !== "" ) … … 1508 1589 } 1509 1590 } 1510 1511 //backwards-compatibility: load FullScreen-Plugin if we find a "popupeditor"-button in the toolbar1512 // @todo: remove the backward compatibility in release 2.01513 var toolbar = editor.config.toolbar;1514 for ( i = toolbar.length; --i >= 0; )1515 {1516 for ( var j = toolbar[i].length; --j >= 0; )1517 {1518 if ( toolbar[i][j]=="popupeditor" )1519 {1520 if ( typeof FullScreen == "undefined" )1521 {1522 // why can't we use the following line instead ?1523 // Xinha.loadPlugin("FullScreen", this.generate );1524 Xinha.loadPlugin("FullScreen", function() { editor.generate(); } );1525 return false;1526 }1527 editor.registerPlugin('FullScreen');1528 }1529 }1530 }1531 1532 // If this is gecko, set up the paragraph handling now1533 if ( Xinha.is_gecko && editor.config.mozParaHandler == 'best' )1534 {1535 if ( typeof EnterParagraphs == 'undefined' )1536 {1537 // why can't we use the following line instead ?1538 // Xinha.loadPlugin("EnterParagraphs", this.generate );1539 Xinha.loadPlugin("EnterParagraphs", function() { editor.generate(); } );1540 return false;1541 }1542 editor.registerPlugin('EnterParagraphs');1543 }1544 1545 if ( typeof Xinha.getHTML == 'undefined' )1546 {1547 Xinha._loadback(_editor_url + "getHTML.js", function() { editor.generate(); } );1548 return false;1549 }1550 1591 1551 if ( typeof Xinha.prototype._insertImage == 'undefined' )1552 {1553 Xinha._loadback(_editor_url + "popups/insert_image.js", function() { editor.generate(); } );1554 return false;1555 }1556 1557 if ( typeof Xinha.prototype._createLink == 'undefined' && typeof Linker == 'undefined' )1558 {1559 Xinha._loadback(_editor_url + "popups/link.js", function() { editor.generate(); } );1560 return false;1561 }1562 1563 1592 // create the editor framework, yah, table layout I know, but much easier 1564 1593 // to get it working correctly this way, sorry about that, patches welcome. … … 3599 3628 3600 3629 // Called when the user clicks the Insert Table button 3601 Xinha.prototype._insertTable = function() 3602 { 3603 var sel = this.getSelection(); 3604 var range = this.createRange(sel); 3605 var editor = this; // for nested functions 3606 this._popupDialog( 3607 editor.config.URIs.insert_table, 3608 function(param) 3609 { 3610 // user must have pressed Cancel 3611 if ( !param ) 3612 { 3613 return false; 3614 } 3615 var doc = editor._doc; 3616 // create the table element 3617 var table = doc.createElement("table"); 3618 // assign the given arguments 3619 3620 for ( var field in param ) 3621 { 3622 var value = param[field]; 3623 if ( !value ) 3624 { 3625 continue; 3626 } 3627 switch (field) 3628 { 3629 case "f_width": 3630 table.style.width = value + param.f_unit; 3631 break; 3632 case "f_align": 3633 table.align = value; 3634 break; 3635 case "f_border": 3636 table.border = parseInt(value, 10); 3637 break; 3638 case "f_spacing": 3639 table.cellSpacing = parseInt(value, 10); 3640 break; 3641 case "f_padding": 3642 table.cellPadding = parseInt(value, 10); 3643 break; 3644 } 3645 } 3646 var cellwidth = 0; 3647 if ( param.f_fixed ) 3648 { 3649 cellwidth = Math.floor(100 / parseInt(param.f_cols, 10)); 3650 } 3651 var tbody = doc.createElement("tbody"); 3652 table.appendChild(tbody); 3653 for ( var i = 0; i < param.f_rows; ++i ) 3654 { 3655 var tr = doc.createElement("tr"); 3656 tbody.appendChild(tr); 3657 for ( var j = 0; j < param.f_cols; ++j ) 3658 { 3659 var td = doc.createElement("td"); 3660 // @todo : check if this line doesnt stop us to use pixel width in cells 3661 if (cellwidth) 3662 { 3663 td.style.width = cellwidth + "%"; 3664 } 3665 tr.appendChild(td); 3666 // Browsers like to see something inside the cell ( ). 3667 td.appendChild(doc.createTextNode('\u00a0')); 3668 } 3669 } 3670 if ( Xinha.is_ie ) 3671 { 3672 range.pasteHTML(table.outerHTML); 3673 } 3674 else 3675 { 3676 // insert the table 3677 editor.insertNodeAtSelection(table); 3678 } 3679 return true; 3680 }, 3681 null 3682 ); 3683 }; 3630 3684 3631 3685 3632 /*************************************************** … … 3739 3686 if ( typeof colorPicker == 'undefined' ) 3740 3687 { 3741 Xinha._loadback(_editor_url + ' popups/color_picker.js', function () {editor._colorSelector(cmdID)});3688 Xinha._loadback(_editor_url + 'modules/ColorPicker/ColorPicker.js', function () {editor._colorSelector(cmdID)}); 3742 3689 return false; 3743 3690 } -
branches/688-fixup/modules/CreateLink/link.html
r690 r693 3 3 <head> 4 4 <title>Insert/Modify Link</title> 5 <script type="text/javascript" src=" popup.js"></script>6 <link rel="stylesheet" type="text/css" href=" popup.css" />5 <script type="text/javascript" src="../../popups/popup.js"></script> 6 <link rel="stylesheet" type="text/css" href="../../popups/popup.css" /> 7 7 8 8 <script type="text/javascript"> -
branches/688-fixup/modules/CreateLink/link.js
r690 r693 14 14 -- which provides the functionality to insert a hyperlink in the editor. 15 15 -- 16 -- The file is loadedby the Xinha Core when no alternative method (plugin) is loaded.16 -- he file is loaded as a special plugin by the Xinha Core when no alternative method (plugin) is loaded. 17 17 -- 18 18 -- … … 22 22 -- $LastChangedBy$ 23 23 --------------------------------------------------------------------------*/ 24 24 CreateLink._pluginInfo = { 25 name : "CreateLink", 26 origin : "Xinha Core", 27 version : "$LastChangedRevision$".replace(/^[^:]*: (.*) \$$/, '$1'), 28 developer : "The Xinha Core Developer Team", 29 developer_url : "$HeadURL$".replace(/^[^:]*: (.*) \$$/, '$1'), 30 sponsor : "", 31 sponsor_url : "", 32 license : "htmlArea" 33 }; 34 35 function CreateLink(editor) { 36 } 25 37 26 38 Xinha.prototype._createLink = function(link) … … 82 94 }; 83 95 } 84 this._popupDialog(96 Dialog( 85 97 editor.config.URIs.link, 86 98 function(param) -
branches/688-fixup/modules/Dialogs/dialog.js
r690 r693 1 // htmlArea v3.0 - Copyright (c) 2003-2004 interactivetools.com, inc.2 // This copyright notice MUST stay intact for use (see license.txt).3 //4 // Portions (c) dynarch.com, 2003-20045 //6 // A free WYSIWYG editor replacement for <textarea> fields.7 // For full source code and docs, visit http://www.interactivetools.com/8 //9 // Version 3.0 developed by Mihai Bazon.10 // http://dynarch.com/mishoo11 //12 // $Id$13 1 14 // Though "Dialog" looks like an object, it isn't really an object. Instead 15 // it's just namespace for protecting global symbols. 2 /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:-- 3 -- Xinha (is not htmlArea) - http://xinha.gogo.co.nz/ 4 -- 5 -- Use of Xinha is granted by the terms of the htmlArea License (based on 6 -- BSD license) please read license.txt in this package for details. 7 -- 8 -- Xinha was originally based on work by Mihai Bazon which is: 9 -- Copyright (c) 2003-2004 dynarch.com. 10 -- Copyright (c) 2002-2003 interactivetools.com, inc. 11 -- This copyright notice MUST stay intact for use. 12 -- 13 -- This is the implementation of the standard popup dialog 14 -- 15 -- Though "Dialog" looks like an object, it isn't really an object. Instead 16 -- it's just namespace for protecting global symbols. 17 -- 18 -- 19 -- $HeadURL$ 20 -- $LastChangedDate$ 21 -- $LastChangedRevision$ 22 -- $LastChangedBy$ 23 --------------------------------------------------------------------------*/ 24 16 25 17 26 function Dialog(url, action, init) { -
branches/688-fixup/modules/Dialogs/inline-dialog.js
r690 r693 1 1 2 /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:-- 3 -- Xinha (is not htmlArea) - http://xinha.gogo.co.nz/ 4 -- 5 -- Use of Xinha is granted by the terms of the htmlArea License (based on 6 -- BSD license) please read license.txt in this package for details. 7 -- 8 -- Xinha was originally based on work by Mihai Bazon which is: 9 -- Copyright (c) 2003-2004 dynarch.com. 10 -- Copyright (c) 2002-2003 interactivetools.com, inc. 11 -- This copyright notice MUST stay intact for use. 12 -- 13 -- This is the implementation of the inline dialog (as use by the Linker plugin) 14 -- 15 -- 16 -- 17 -- 18 -- $HeadURL$ 19 -- $LastChangedDate$ 20 -- $LastChangedRevision$ 21 -- $LastChangedBy$ 22 --------------------------------------------------------------------------*/ 2 23 Xinha.Dialog = function(editor, html, localizer) 3 24 { -
branches/688-fixup/modules/Gecko/Gecko.js
r690 r693 38 38 developer : "The Xinha Core Developer Team", 39 39 developer_url : "$HeadURL$".replace(/^[^:]*: (.*) \$$/, '$1'), 40 sponsor : "", 41 sponsor_url : "", 40 42 license : "htmlArea" 41 43 }; … … 184 186 switch ( ev.keyCode ) 185 187 { 188 /* This is now handled by a plugin 186 189 case 13: // ENTER 187 190 if( !ev.shiftKey && editor.config.mozParaHandler == 'dirty' ) … … 190 193 Xinha._stopEvent(ev); 191 194 } 192 break; 195 break;*/ 193 196 194 197 case 27: // ESCAPE … … 323 326 10); 324 327 }; 325 /** The idea here is326 * 1. See if we are in a block element327 * 2. If we are not, then wrap the current "block" of text into a paragraph328 * 3. Now that we have a block element, select all the text between the insertion point329 * and just AFTER the end of the block330 * eg <p>The quick |brown fox jumped over the lazy dog.</p>|331 * ---------------------------------------332 * 4. Extract that from the document, making333 * <p>The quick </p>334 * and a document fragment with335 * <p>brown fox jumped over the lazy dog.</p>336 * 5. Reinsert it just after the block element337 * <p>The quick </p><p>brown fox jumped over the lazy dog.</p>338 *339 * Along the way, allow inserting blank paragraphs, which will look like <p><br/></p>340 */341 342 Gecko.prototype.dom_checkInsertP = function()343 {344 var editor = this.editor;345 var p, body;346 // Get the insertion point, we'll scrub any highlighted text the user wants rid of while we are there.347 var sel = editor.getSelection();348 var range = editor.createRange(sel);349 if ( !range.collapsed )350 {351 range.deleteContents();352 }353 editor.deactivateEditor();354 //sel.removeAllRanges();355 //sel.addRange(range);356 357 var SC = range.startContainer;358 var SO = range.startOffset;359 var EC = range.endContainer;360 var EO = range.endOffset;361 362 // If the insertion point is character 0 of the363 // document, then insert a space character that we will wrap into a paragraph364 // in a bit.365 if ( SC == EC && SC == body && !SO && !EO )366 {367 p = editor._doc.createTextNode(" ");368 body.insertBefore(p, body.firstChild);369 range.selectNodeContents(p);370 SC = range.startContainer;371 SO = range.startOffset;372 EC = range.endContainer;373 EO = range.endOffset;374 }375 376 // See if we are in a block element, if so, great.377 p = editor.getAllAncestors();378 379 var block = null;380 body = editor._doc.body;381 for ( var i = 0; i < p.length; ++i )382 {383 if ( Xinha.isParaContainer(p[i]) )384 {385 break;386 }387 else if ( Xinha.isBlockElement(p[i]) && ! ( /body|html/i.test(p[i].tagName) ) )388 {389 block = p[i];390 break;391 }392 }393 394 // If not in a block element, we'll have to turn some stuff into a paragraph395 if ( !block )396 {397 // We want to wrap as much stuff as possible into the paragraph in both directions398 // from the insertion point. We start with the start container and walk back up to the399 // node just before any of the paragraph containers.400 var wrap = range.startContainer;401 while ( wrap.parentNode && !Xinha.isParaContainer(wrap.parentNode) )402 {403 wrap = wrap.parentNode;404 }405 var start = wrap;406 var end = wrap;407 408 // Now we walk up the sibling list until we hit the top of the document409 // or an element that we shouldn't put in a p (eg other p, div, ul, ol, table)410 while ( start.previousSibling )411 {412 if ( start.previousSibling.tagName )413 {414 if ( !Xinha.isBlockElement(start.previousSibling) )415 {416 start = start.previousSibling;417 }418 else419 {420 break;421 }422 }423 else424 {425 start = start.previousSibling;426 }427 }428 429 // Same down the list430 while ( end.nextSibling )431 {432 if ( end.nextSibling.tagName )433 {434 if ( !Xinha.isBlockElement(end.nextSibling) )435 {436 end = end.nextSibling;437 }438 else439 {440 break;441 }442 }443 else444 {445 end = end.nextSibling;446 }447 }448 449 // Select the entire block450 range.setStartBefore(start);451 range.setEndAfter(end);452 453 // Make it a paragraph454 range.surroundContents(editor._doc.createElement('p'));455 456 // Which becomes the block element457 block = range.startContainer.firstChild;458 459 // And finally reset the insertion point to where it was originally460 range.setStart(SC, SO);461 }462 463 // The start point is the insertion point, so just move the end point to immediatly464 // after the block465 range.setEndAfter(block);466 467 // Extract the range, to split the block468 // If we just did range.extractContents() then Mozilla does wierd stuff469 // with selections, but if we clone, then remove the original range and extract470 // the clone, it's quite happy.471 var r2 = range.cloneRange();472 sel.removeRange(range);473 var df = r2.extractContents();474 475 if ( df.childNodes.length === 0 )476 {477 df.appendChild(editor._doc.createElement('p'));478 df.firstChild.appendChild(editor._doc.createElement('br'));479 }480 481 if ( df.childNodes.length > 1 )482 {483 var nb = editor._doc.createElement('p');484 while ( df.firstChild )485 {486 var s = df.firstChild;487 df.removeChild(s);488 nb.appendChild(s);489 }490 df.appendChild(nb);491 }492 493 // If the original block is empty, put a &nsbp; in it.494 // @fixme: why using a regex instead of : if (block.innerHTML.trim() == '') ?495 if ( ! ( /\S/.test(block.innerHTML) ) )496 {497 block.innerHTML = " ";498 }499 500 p = df.firstChild;501 // @fixme: why using a regex instead of : if (p.innerHTML.trim() == '') ?502 if ( ! ( /\S/.test(p.innerHTML) ) )503 {504 p.innerHTML = "<br />";505 }506 507 // If the new block is empty and it's a heading, make it a paragraph508 // note, the new block is empty when you are hitting enter at the end of the existing block509 if ( ( /^\s*<br\s*\/?>\s*$/.test(p.innerHTML) ) && ( /^h[1-6]$/i.test(p.tagName) ) )510 {511 df.appendChild(editor.convertNode(p, "p"));512 df.removeChild(p);513 }514 515 var newblock = block.parentNode.insertBefore(df.firstChild, block.nextSibling);516 517 // Select the range (to set the insertion)518 // collapse to the start of the new block519 // (remember the block might be <p><br/></p>, so if we collapsed to the end the <br/> would be noticable)520 521 //range.selectNode(newblock.firstChild);522 //range.collapse(true);523 524 editor.activateEditor();525 526 sel = editor.getSelection();527 sel.removeAllRanges();528 sel.collapse(newblock,0);529 530 // scroll into view531 editor.scrollToElement(newblock);532 533 //editor.forceRedraw();534 535 };536 328 537 329 Gecko.prototype.inwardHtml = function(html) -
branches/688-fixup/modules/Gecko/paraHandlerBest.js
r690 r693 16 16 17 17 EnterParagraphs._pluginInfo = 18 {18 { 19 19 name : "EnterParagraphs", 20 20 version : "1.0", … … 24 24 sponsor_url : "http://www.uwa.edu.au/", 25 25 license : "htmlArea" 26 };26 }; 27 27 28 28 // ------------------------------------------------------------------ … … 86 86 87 87 function EnterParagraphs(editor) 88 {89 88 { 89 90 90 this.editor = editor; 91 92 // [STRIP 93 // create a ddt debug trace object. There may be multiple editors on 94 // the page each EnterParagraphs .. to distinguish which instance 95 // is generating the message we tack on the name of the textarea. 96 97 //this.ddt = new DDT( editor._textArea + ":EnterParagraphs Plugin" ); 98 99 // uncomment to turn on debugging messages. 100 101 //this.ddt._ddtOn(); 102 103 //this.ddt._ddt( "enter-paragraphs.js","23", "EnterParagraphs(): constructor" ); 104 105 // STRIP] 106 91 107 92 // hook into the event handler to intercept key presses if we are using 108 // gecko (Mozilla/FireFox) 109 93 // gecko (Mozilla/FireFox) 110 94 if (Xinha.is_gecko) 111 { 112 //this.ddt._ddt( "enter-paragraphs.js","23", "EnterParagraphs(): we are gecko. Setting event handler." ); 95 { 113 96 this.onKeyPress = this.__onKeyPress; 114 }115 116 } // end of constructor.97 } 98 99 } // end of constructor. 117 100 118 101 // ------------------------------------------------------------------ … … 124 107 * messages. 125 108 */ 126 127 109 EnterParagraphs.prototype.name = "EnterParagraphs"; 128 110 … … 130 112 * Gecko's a bit lacking in some odd ways... 131 113 */ 132 133 114 EnterParagraphs.prototype.insertAdjacentElement = function(ref,pos,el) 134 { 135 136 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "122", "insertAdjacentElement(): top with pos '" + pos + "' ref:", ref ); 137 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "122", "insertAdjacentElement(): top with el:", el ); 138 115 { 139 116 if ( pos == 'BeforeBegin' ) 140 {141 ref.parentNode.insertBefore(el,ref);142 }117 { 118 ref.parentNode.insertBefore(el,ref); 119 } 143 120 else if ( pos == 'AfterEnd' ) 144 {145 ref.nextSibling ? ref.parentNode.insertBefore(el,ref.nextSibling) : ref.parentNode.appendChild(el);146 }121 { 122 ref.nextSibling ? ref.parentNode.insertBefore(el,ref.nextSibling) : ref.parentNode.appendChild(el); 123 } 147 124 else if ( pos == 'AfterBegin' && ref.firstChild ) 148 {149 ref.insertBefore(el,ref.firstChild);150 }125 { 126 ref.insertBefore(el,ref.firstChild); 127 } 151 128 else if ( pos == 'BeforeEnd' || pos == 'AfterBegin' ) 152 { 153 ref.appendChild(el); 154 } 155 156 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "122", "insertAdjacentElement(): bottom with ref:", ref ); 157 158 }; // end of insertAdjacentElement() 129 { 130 ref.appendChild(el); 131 } 132 133 }; // end of insertAdjacentElement() 159 134 160 135 // ---------------------------------------------------------------- … … 170 145 171 146 EnterParagraphs.prototype.forEachNodeUnder = function ( root, mode, direction, init ) 172 { 173 174 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): top mode is '" + mode + "' direction is '" + direction + "' starting with root node:", root ); 175 147 { 148 176 149 // Identify the first and last nodes to deal with 177 178 150 var start, end; 179 180 // nodeType 11 is DOCUMENT_FRAGMENT_NODE which is a container. 181 151 152 // nodeType 11 is DOCUMENT_FRAGMENT_NODE which is a container. 182 153 if ( root.nodeType == 11 && root.firstChild ) 183 {154 { 184 155 start = root.firstChild; 185 156 end = root.lastChild; 186 } 187 else 188 { 189 start = end = root; 190 } 191 192 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): start node is:", start ); 193 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): initial end node is:", end ); 194 195 // traverse down the right hand side of the tree getting the last child of the last 196 // child in each level until we reach bottom. 157 } 158 else 159 { 160 start = end = root; 161 } 162 // traverse down the right hand side of the tree getting the last child of the last 163 // child in each level until we reach bottom. 197 164 while ( end.lastChild ) 198 end = end.lastChild; 199 200 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): end node after descent is:", end ); 201 165 { 166 end = end.lastChild; 167 } 168 202 169 return this.forEachNode( start, end, mode, direction, init); 203 204 }; // end of forEachNodeUnder()170 171 }; // end of forEachNodeUnder() 205 172 206 173 // ----------------------------------------------------------------------- … … 217 184 218 185 EnterParagraphs.prototype.forEachNode = function (left_node, right_node, mode, direction, init) 186 { 187 188 // returns "Brother" node either left or right. 189 var getSibling = function(elem, direction) 219 190 { 220 221 //this.ddt._ddt( "enter-paragraphs.js", "175", "forEachNode(): top - mode is:" + mode + "' direction '" + direction + "'" ); 222 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): top - left node is:", left_node ); 223 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): top - right node is:", right_node ); 224 225 // returns "Brother" node either left or right. 226 227 var getSibling = function(elem, direction) 228 { 229 return ( direction == "ltr" ? elem.nextSibling : elem.previousSibling ); 230 }; 231 191 return ( direction == "ltr" ? elem.nextSibling : elem.previousSibling ); 192 }; 193 232 194 var getChild = function(elem, direction) 233 {234 return ( direction == "ltr" ? elem.firstChild : elem.lastChild );235 };236 195 { 196 return ( direction == "ltr" ? elem.firstChild : elem.lastChild ); 197 }; 198 237 199 var walk, lookup, fnReturnVal; 238 239 // FIXME: init is a boolean in the emptyset case and an object in240 // the cullids case. Used inconsistently.241 242 var next_node = init;243 244 // used to flag having reached the last node.245 246 var done_flag = false;247 200 201 // FIXME: init is a boolean in the emptyset case and an object in 202 // the cullids case. Used inconsistently. 203 204 var next_node = init; 205 206 // used to flag having reached the last node. 207 208 var done_flag = false; 209 248 210 // loop ntil we've hit the last node in the given direction. 249 // if we're going left to right that's the right_node and visa-versa.250 211 // if we're going left to right that's the right_node and visa-versa. 212 251 213 while ( walk != direction == "ltr" ? right_node : left_node ) 252 {253 214 { 215 254 216 // on first entry, walk here is null. So this is how 255 // we prime the loop with the first node.256 217 // we prime the loop with the first node. 218 257 219 if ( !walk ) 258 { 259 walk = direction == "ltr" ? left_node : right_node; 260 261 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): !walk - current node is:", walk ); 262 } 220 { 221 walk = direction == "ltr" ? left_node : right_node; 222 } 263 223 else 264 {265 266 // is there a child node?267 224 { 225 226 // is there a child node? 227 268 228 if ( getChild(walk,direction) ) 269 { 270 271 // descend down into the child. 272 273 walk = getChild(walk,direction); 274 275 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode():descending to child node:", walk ); 276 277 } 229 { 230 231 // descend down into the child. 232 233 walk = getChild(walk,direction); 234 235 } 278 236 else 279 {280 281 // is there a sibling node on this level?282 237 { 238 239 // is there a sibling node on this level? 240 283 241 if ( getSibling(walk,direction) ) 284 { 285 286 // move to the sibling. 287 288 walk = getSibling(walk,direction); 289 290 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): moving to sibling node:", walk ); 291 292 } 242 { 243 // move to the sibling. 244 walk = getSibling(walk,direction); 245 } 293 246 else 294 {247 { 295 248 lookup = walk; 296 297 // climb back up the tree until we find a level where we are not the end298 // node on the level (i.e. that we have a sibling in the direction299 // we are searching) or until we reach the end.300 249 250 // climb back up the tree until we find a level where we are not the end 251 // node on the level (i.e. that we have a sibling in the direction 252 // we are searching) or until we reach the end. 253 301 254 while ( !getSibling(lookup,direction) && lookup != (direction == "ltr" ? right_node : left_node) ) 302 {303 lookup = lookup.parentNode;304 }305 306 // did we find a level with a sibling?307 255 { 256 lookup = lookup.parentNode; 257 } 258 259 // did we find a level with a sibling? 260 308 261 // walk = ( lookup.nextSibling ? lookup.nextSibling : lookup ) ; 309 262 310 263 walk = ( getSibling(lookup,direction) ? getSibling(lookup,direction) : lookup ) ; 311 312 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): climbed back up (or found right node):", walk ); 313 314 } 315 } 316 317 } // end of else walk. 318 319 // have we reached the end? either as a result of the top while loop or climbing 320 // back out above. 321 322 done_flag = (walk==( direction == "ltr" ? right_node : left_node)); 323 324 // call the requested function on the current node. Functions 325 // return an array. 326 // 327 // Possible functions are _fenCullIds, _fenEmptySet 328 // 329 // The situation is complicated by the fact that sometimes we want to 330 // return the base node and sometimes we do not. 331 // 332 // next_node can be an object (this.takenIds), a node (text, el, etc) or false. 333 334 //this.ddt._ddt( "enter-paragraphs.js", "175", "forEachNode(): calling function" ); 335 336 switch( mode ) 337 { 338 339 case "cullids": 340 341 fnReturnVal = this._fenCullIds(walk, next_node ); 342 break; 343 344 case "find_fill": 345 346 fnReturnVal = this._fenEmptySet(walk, next_node, mode, done_flag); 347 break; 348 349 case "find_cursorpoint": 350 351 fnReturnVal = this._fenEmptySet(walk, next_node, mode, done_flag); 352 break; 353 354 } 355 356 // If this node wants us to return, return next_node 357 264 265 } 266 } 267 268 } // end of else walk. 269 270 // have we reached the end? either as a result of the top while loop or climbing 271 // back out above. 272 273 done_flag = (walk==( direction == "ltr" ? right_node : left_node)); 274 275 // call the requested function on the current node. Functions 276 // return an array. 277 // 278 // Possible functions are _fenCullIds, _fenEmptySet 279 // 280 // The situation is complicated by the fact that sometimes we want to 281 // return the base node and sometimes we do not. 282 // 283 // next_node can be an object (this.takenIds), a node (text, el, etc) or false. 284 285 switch( mode ) 286 { 287 288 case "cullids": 289 290 fnReturnVal = this._fenCullIds(walk, next_node ); 291 break; 292 293 case "find_fill": 294 295 fnReturnVal = this._fenEmptySet(walk, next_node, mode, done_flag); 296 break; 297 298 case "find_cursorpoint": 299 300 fnReturnVal = this._fenEmptySet(walk, next_node, mode, done_flag); 301 break; 302 303 } 304 305 // If this node wants us to return, return next_node 306 358 307 if ( fnReturnVal[0] ) 359 { 360 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): returning node:", fnReturnVal[1] ); 361 362 return fnReturnVal[1]; 363 } 364 365 // are we done with the loop? 366 367 if ( done_flag ) 368 { 369 break; 370 } 371 372 // Otherwise, pass to the next node 373 308 { 309 return fnReturnVal[1]; 310 } 311 312 // are we done with the loop? 313 314 if ( done_flag ) 315 { 316 break; 317 } 318 319 // Otherwise, pass to the next node 320 374 321 if ( fnReturnVal[1] ) 375 { 376 next_node = fnReturnVal[1]; 377 } 378 379 } // end of while loop 380 381 //this.ddt._ddt( "enter-paragraphs.js", "175", "forEachNode(): returning false." ); 382 322 { 323 next_node = fnReturnVal[1]; 324 } 325 326 } // end of while loop 327 383 328 return false; 384 385 }; // end of forEachNode()329 330 }; // end of forEachNode() 386 331 387 332 // ------------------------------------------------------------------- … … 397 342 398 343 EnterParagraphs.prototype._fenEmptySet = function( node, next_node, mode, last_flag) 399 { 400 401 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : top with mode '" + mode + "' and last_flag '" + last_flag + "' and node:", node ); 402 344 { 345 403 346 // Mark this if it's the first base 404 347 405 348 if ( !next_node && !node.firstChild ) 406 {407 next_node = node;408 }409 349 { 350 next_node = node; 351 } 352 410 353 // Is it an element node and is it considered content? (br, hr, etc) 411 // or is it a text node that is not just whitespace?412 // or is it not an element node and not a text node?413 354 // or is it a text node that is not just whitespace? 355 // or is it not an element node and not a text node? 356 414 357 if ( (node.nodeType == 1 && this._elemSolid.test(node.nodeName)) || 415 358 (node.nodeType == 3 && !this._whiteSpace.test(node.nodeValue)) || 416 (node.nodeType != 1 && node.nodeType != 3) ) 417 { 418 419 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : found content in node:", node ); 420 421 switch( mode ) 422 { 423 424 case "find_fill": 425 426 // does not return content. 427 428 return new Array(true, false ); 429 break; 430 431 case "find_cursorpoint": 432 433 // returns content 434 435 return new Array(true, node ); 436 break; 437 438 } 439 440 } 441 359 (node.nodeType != 1 && node.nodeType != 3) ) 360 { 361 362 switch( mode ) 363 { 364 365 case "find_fill": 366 367 // does not return content. 368 369 return new Array(true, false ); 370 break; 371 372 case "find_cursorpoint": 373 374 // returns content 375 376 return new Array(true, node ); 377 break; 378 379 } 380 381 } 382 442 383 // In either case (fill or findcursor) we return the base node. The avoids 443 // problems in terminal cases (beginning or end of document or container tags)444 384 // problems in terminal cases (beginning or end of document or container tags) 385 445 386 if ( last_flag ) 446 { 447 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : return 'base' node:", next_node ); 448 449 return new Array( true, next_node ); 450 } 451 452 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : bottom returning false and :", next_node ); 453 387 { 388 return new Array( true, next_node ); 389 } 390 454 391 return new Array( false, next_node ); 455 456 }; // end of _fenEmptySet()392 393 }; // end of _fenEmptySet() 457 394 458 395 // ------------------------------------------------------------------------------ … … 465 402 466 403 EnterParagraphs.prototype._fenCullIds = function ( ep_ref, node, pong ) 467 { 468 469 //this.ddt._ddt( "enter-paragraphs.js", "299", "_fenCullIds(): top" ); 470 404 { 405 471 406 // Check for an id, blast it if it's in the store, otherwise add it 472 407 473 408 if ( node.id ) 474 { 475 476 //this.ddt._ddt( "enter-paragraphs.js", "299", "_fenCullIds(): node '" + node.nodeName + "' has an id '" + node.id + "'" ); 477 478 pong[node.id] ? node.id = '' : pong[node.id] = true; 479 } 480 409 { 410 411 pong[node.id] ? node.id = '' : pong[node.id] = true; 412 } 413 481 414 return new Array(false,pong); 482 483 };415 416 }; 484 417 485 418 // --------------------------------------------------------------------------------- … … 495 428 496 429 EnterParagraphs.prototype.processSide = function( rng, search_direction) 430 { 431 432 var next = function(element, search_direction) 497 433 { 498 499 //this.ddt._ddt( "enter-paragraphs.js", "329", "processSide(): top search_direction == '" + search_direction + "'" ); 500 501 var next = function(element, search_direction) 502 { 503 return ( search_direction == "left" ? element.previousSibling : element.nextSibling ); 504 }; 505 434 return ( search_direction == "left" ? element.previousSibling : element.nextSibling ); 435 }; 436 506 437 var node = search_direction == "left" ? rng.startContainer : rng.endContainer; 507 438 var offset = search_direction == "left" ? rng.startOffset : rng.endOffset; 508 439 var roam, start = node; 509 510 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "337", "processSide(): starting with node:", node ); 511 440 512 441 // Never start with an element, because then the first roaming node might 513 442 // be on the exclusion list and we wouldn't know until it was too late 514 443 515 444 while ( start.nodeType == 1 && !this._permEmpty.test(start.nodeName) ) 516 {517 start = ( offset ? start.lastChild : start.firstChild );518 }519 445 { 446 start = ( offset ? start.lastChild : start.firstChild ); 447 } 448 520 449 // Climb the tree, left or right, until our course of action presents itself 521 //522 // if roam is NULL try start.523 // if roam is NOT NULL, try next node in our search_direction524 // If that node is NULL, get our parent node.525 //526 // If all the above turns out NULL end the loop.527 //528 // FIXME: gecko (firefox 1.0.3) - enter "test" into an empty document and press enter.529 // sometimes this loop finds a blank text node, sometimes it doesn't.530 450 // 451 // if roam is NULL try start. 452 // if roam is NOT NULL, try next node in our search_direction 453 // If that node is NULL, get our parent node. 454 // 455 // If all the above turns out NULL end the loop. 456 // 457 // FIXME: gecko (firefox 1.0.3) - enter "test" into an empty document and press enter. 458 // sometimes this loop finds a blank text node, sometimes it doesn't. 459 531 460 while ( roam = roam ? ( next(roam,search_direction) ? next(roam,search_direction) : roam.parentNode ) : start ) 532 { 533 534 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "357", "processSide(): roaming loop, search_direction is '" + search_direction + "' current node is: ", roam ); 535 536 // next() is an inline function defined above that returns the next node depending 537 // on the direction we're searching. 538 461 { 462 463 // next() is an inline function defined above that returns the next node depending 464 // on the direction we're searching. 465 539 466 if ( next(roam,search_direction) ) 540 { 541 542 //this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Checking next node '" + next(roam,search_direction).NodeName + "' for _pExclusions list." ); 543 467 { 468 544 469 // If the next sibling's on the exclusion list, stop before it 545 470 546 471 if ( this._pExclusions.test(next(roam,search_direction).nodeName) ) 547 { 548 549 //this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Node '" + next(roam,search_direction).NodeName + "' is on the _pExclusions list. Stopping before it." ); 550 472 { 473 551 474 return this.processRng(rng, search_direction, roam, next(roam,search_direction), (search_direction == "left"?'AfterEnd':'BeforeBegin'), true, false); 552 } 553 } 554 else 555 { 556 557 //this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): No next node, examing parent node '" + roam.parentNode.nodeName + "' for containers or exclusions." ); 558 475 } 476 } 477 else 478 { 479 559 480 // If our parent's on the container list, stop inside it 560 481 561 482 if (this._pContainers.test(roam.parentNode.nodeName)) 562 { 563 564 //this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is on the _pContainer list. Stopping inside it." ); 565 483 { 484 566 485 return this.processRng(rng, search_direction, roam, roam.parentNode, (search_direction == "left"?'AfterBegin':'BeforeEnd'), true, false); 567 }486 } 568 487 else if (this._pExclusions.test(roam.parentNode.nodeName)) 569 { 570 571 //this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is on the _pExclusion list." ); 572 573 // chop without wrapping 574 488 { 489 490 // chop without wrapping 491 575 492 if (this._pBreak.test(roam.parentNode.nodeName)) 576 { 577 578 //this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is on the _pBreak list." ); 579 493 { 494 580 495 return this.processRng(rng, search_direction, roam, roam.parentNode, 581 (search_direction == "left"?'AfterBegin':'BeforeEnd'), false, (search_direction == "left" ?true:false)); 582 } 583 else 584 { 585 586 //this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is not on the _pBreak list." ); 587 588 // the next(roam,search_direction) in this call is redundant since we know it's false 589 // because of the "if next(roam,search_direction)" above. 590 // 591 // the final false prevents this range from being wrapped in <p>'s most likely 592 // because it's already wrapped. 593 496 (search_direction == "left"?'AfterBegin':'BeforeEnd'), false, (search_direction == "left" ?true:false)); 497 } 498 else 499 { 500 501 // the next(roam,search_direction) in this call is redundant since we know it's false 502 // because of the "if next(roam,search_direction)" above. 503 // 504 // the final false prevents this range from being wrapped in <p>'s most likely 505 // because it's already wrapped. 506 594 507 return this.processRng(rng, 595 search_direction, 596 (roam = roam.parentNode), 597 (next(roam,search_direction) ? next(roam,search_direction) : roam.parentNode), 598 (next(roam,search_direction) ? (search_direction == "left"?'AfterEnd':'BeforeBegin') : (search_direction == "left"?'AfterBegin':'BeforeEnd')), 599 false, 600 false); 601 } 602 } 603 } 604 } 605 606 //this.ddt._ddt( "enter-paragraphs.js", "424", "processSide(): bottom" ); 607 608 }; // end of processSide() 508 search_direction, 509 (roam = roam.parentNode), 510 (next(roam,search_direction) ? next(roam,search_direction) : roam.parentNode), 511 (next(roam,search_direction) ? (search_direction == "left"?'AfterEnd':'BeforeBegin') : (search_direction == "left"?'AfterBegin':'BeforeEnd')), 512 false, 513 false); 514 } 515 } 516 } 517 } 518 519 }; // end of processSide() 609 520 610 521 // ------------------------------------------------------------------------------ … … 624 535 625 536 EnterParagraphs.prototype.processRng = function(rng, search_direction, roam, neighbour, insertion, pWrap, preBr) 626 { 627 628 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "398", "processRng(): top - roam arg is:", roam ); 629 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "398", "processRng(): top - neighbor arg is:", neighbour ); 630 631 //this.ddt._ddt( "enter-paragraphs.js", "398", "processRng(): top - insertion arg is: '" + insertion + "'" ); 632 537 { 633 538 var node = search_direction == "left" ? rng.startContainer : rng.endContainer; 634 539 var offset = search_direction == "left" ? rng.startOffset : rng.endOffset; 635 636 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "447", "processRng(): range start (or end) is at offset '" + offset + "' is node :", node ); 637 540 638 541 // Define the range to cut, and extend the selection range to the same boundary 639 542 640 543 var editor = this.editor; 641 544 var newRng = editor._doc.createRange(); 642 545 643 546 newRng.selectNode(roam); 644 645 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): selecting newRng is:", newRng ); 646 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): selecting original rng is:", rng ); 647 648 // extend the range in the given direction. 649 547 // extend the range in the given direction. 548 650 549 if ( search_direction == "left") 651 {550 { 652 551 newRng.setEnd(node, offset); 653 552 rng.setStart(newRng.startContainer, newRng.startOffset); 654 655 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): extending direction left - newRng is:", newRng ); 656 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): extending direction left - rng is:", rng ); 657 658 } 659 else if ( search_direction == "right" ) 660 { 661 553 } 554 else if ( search_direction == "right" ) 555 { 556 662 557 newRng.setStart(node, offset); 663 rng.setEnd(newRng.endContainer, newRng.endOffset); 664 665 //this.ddt._ddt( "enter-paragraphs.js", "522", "processRng(): right - new range start is '" + offset + "' end offset is '" + newRng.endOffset + "'" ); 666 } 667 668 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): rng is:", rng ); 669 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): newRng is:", newRng ); 670 558 rng.setEnd(newRng.endContainer, newRng.endOffset); 559 } 671 560 // Clone the range and remove duplicate ids it would otherwise produce 672 561 673 562 var cnt = newRng.cloneContents(); 674 675 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "509", "processRng(): culling duplicate ids from:", cnt ); 676 677 // in this case "init" is an object not a boolen. 678 563 564 // in this case "init" is an object not a boolen. 565 679 566 this.forEachNodeUnder( cnt, "cullids", "ltr", this.takenIds, false, false); 680 567 681 568 // Special case, for inserting paragraphs before some blocks when caret is at 682 // their zero offset.683 //684 // Used to "open up space" in front of a list, table. Usefull if the list is at685 // the top of the document. (otherwise you'd have no way of "moving it down").686 569 // their zero offset. 570 // 571 // Used to "open up space" in front of a list, table. Usefull if the list is at 572 // the top of the document. (otherwise you'd have no way of "moving it down"). 573 687 574 var pify, pifyOffset, fill; 688 575 pify = search_direction == "left" ? (newRng.endContainer.nodeType == 3 ? true:false) : (newRng.startContainer.nodeType == 3 ? false:true); 689 576 pifyOffset = pify ? newRng.startOffset : newRng.endOffset; 690 577 pify = pify ? newRng.startContainer : newRng.endContainer; 691 692 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "521", "processRng(): pify is '" + pify.nodeName + "' pifyOffset is '" + pifyOffset + "':", pify ); 693 578 694 579 if ( this._pifyParent.test(pify.nodeName) && pify.parentNode.childNodes.item(0) == pify ) 695 {580 { 696 581 while ( !this._pifySibling.test(pify.nodeName) ) 697 {698 pify = pify.parentNode;699 }700 }701 702 // NODE TYPE 11 is DOCUMENT_FRAGMENT NODE582 { 583 pify = pify.parentNode; 584 } 585 } 586 587 // NODE TYPE 11 is DOCUMENT_FRAGMENT NODE 703 588 // I do not profess to understand any of this, simply applying a patch that others say is good - ticket:446 704 589 if ( cnt.nodeType == 11 && !cnt.firstChild) … … 710 595 } 711 596 712 // YmL: Added additional last parameter for fill case to work around logic 713 // error in forEachNode() 714 715 //this.ddt._ddt( "enter-paragraphs.js", "612", "processRng(): find_fill in cnt." ); 716 597 // YmL: Added additional last parameter for fill case to work around logic 598 // error in forEachNode() 599 717 600 fill = this.forEachNodeUnder(cnt, "find_fill", "ltr", false ); 718 719 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "612", "processRng(): fill node:" , fill ); 720 601 721 602 if ( fill && 722 this._pifySibling.test(pify.nodeName) && 723 ( (pifyOffset == 0) || ( pifyOffset == 1 && this._pifyForced.test(pify.nodeName) ) ) ) 724 { 725 726 //this.ddt._ddt( "enter-paragraphs.js", "544", "processRng(): pify handling. Creating p tag followed by nbsp tag" ); 727 728 roam = editor._doc.createElement( 'p' ); 729 roam.innerHTML = " "; 730 603 this._pifySibling.test(pify.nodeName) && 604 ( (pifyOffset == 0) || ( pifyOffset == 1 && this._pifyForced.test(pify.nodeName) ) ) ) 605 { 606 607 roam = editor._doc.createElement( 'p' ); 608 roam.innerHTML = " "; 609 731 610 // roam = editor._doc.createElement('p'); 732 611 // roam.appendChild(editor._doc.createElement('br')); 733 734 // for these cases, if we are processing the left hand side we want it to halt 735 // processing instead of doing the right hand side. (Avoids adding another <p> </p> 736 // after the list etc. 737 738 if ((search_direction == "left" ) && pify.previousSibling) 739 { 740 741 //this.ddt._ddt( "enter-paragraphs.js", "682", "processRng(): returning created roam AfterEnd" ); 742 743 return new Array(pify.previousSibling, 'AfterEnd', roam); 744 } 745 else if (( search_direction == "right") && pify.nextSibling) 746 { 747 748 //this.ddt._ddt( "enter-paragraphs.js", "682", "processRng(): returning created roam BeforeBegin" ); 749 750 return new Array(pify.nextSibling, 'BeforeBegin', roam); 751 } 612 613 // for these cases, if we are processing the left hand side we want it to halt 614 // processing instead of doing the right hand side. (Avoids adding another <p> </p> 615 // after the list etc. 616 617 if ((search_direction == "left" ) && pify.previousSibling) 618 { 619 620 return new Array(pify.previousSibling, 'AfterEnd', roam); 621 } 622 else if (( search_direction == "right") && pify.nextSibling) 623 { 624 625 return new Array(pify.nextSibling, 'BeforeBegin', roam); 626 } 627 else 628 { 629 630 return new Array(pify.parentNode, (search_direction == "left"?'AfterBegin':'BeforeEnd'), roam); 631 } 632 633 } 634 635 // If our cloned contents are 'content'-less, shove a break in them 636 637 if ( fill ) 638 { 639 640 // Ill-concieved? 641 // 642 // 3 is a TEXT node and it should be empty. 643 // 644 645 if ( fill.nodeType == 3 ) 646 { 647 // fill = fill.parentNode; 648 649 fill = editor._doc.createDocumentFragment(); 650 } 651 652 if ( (fill.nodeType == 1 && !this._elemSolid.test()) || fill.nodeType == 11 ) 653 { 654 655 // FIXME:/CHECKME: When Xinha is switched from WYSIWYG to text mode 656 // Xinha.getHTMLWrapper() will strip out the trailing br. Not sure why. 657 658 // fill.appendChild(editor._doc.createElement('br')); 659 660 var pterminator = editor._doc.createElement( 'p' ); 661 pterminator.innerHTML = " "; 662 663 fill.appendChild( pterminator ); 664 665 } 752 666 else 753 { 754 755 //this.ddt._ddt( "enter-paragraphs.js", "682", "processRng(): returning created roam for direction '" + search_direction + "'" ); 756 757 return new Array(pify.parentNode, (search_direction == "left"?'AfterBegin':'BeforeEnd'), roam); 758 } 759 760 } 761 762 // If our cloned contents are 'content'-less, shove a break in them 763 764 if ( fill ) 765 { 766 767 // Ill-concieved? 768 // 769 // 3 is a TEXT node and it should be empty. 770 // 771 772 if ( fill.nodeType == 3 ) 773 { 774 // fill = fill.parentNode; 775 776 fill = editor._doc.createDocumentFragment(); 777 778 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "575", "processRng(): fill.nodeType is 3. Moving up to parent:", fill ); 779 } 780 781 if ( (fill.nodeType == 1 && !this._elemSolid.test()) || fill.nodeType == 11 ) 782 { 783 784 // FIXME:/CHECKME: When Xinha is switched from WYSIWYG to text mode 785 // Xinha.getHTMLWrapper() will strip out the trailing br. Not sure why. 786 787 // fill.appendChild(editor._doc.createElement('br')); 788 789 var pterminator = editor._doc.createElement( 'p' ); 790 pterminator.innerHTML = " "; 791 792 fill.appendChild( pterminator ); 793 794 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "583", "processRng(): fill type is 1 and !elemsolid or it's type 11. Appending an nbsp tag:", fill ); 795 796 } 667 { 668 669 // fill.parentNode.insertBefore(editor._doc.createElement('br'),fill); 670 671 var pterminator = editor._doc.createElement( 'p' ); 672 pterminator.innerHTML = " "; 673 674 fill.parentNode.insertBefore(parentNode,fill); 675 676 } 677 } 678 679 // YmL: If there was no content replace with fill 680 // (previous code did not use fill and we ended up with the 681 // <p>test</p><p></p> because Gecko was finding two empty text nodes 682 // when traversing on the right hand side of an empty document. 683 684 if ( fill ) 685 { 686 687 roam = fill; 688 } 797 689 else 798 { 799 800 //this.ddt._ddt( "enter-paragraphs.js", "583", "processRng(): inserting a br tag before." ); 801 802 // fill.parentNode.insertBefore(editor._doc.createElement('br'),fill); 803 804 var pterminator = editor._doc.createElement( 'p' ); 805 pterminator.innerHTML = " "; 806 807 fill.parentNode.insertBefore(parentNode,fill); 808 809 } 810 } 811 812 // YmL: If there was no content replace with fill 813 // (previous code did not use fill and we ended up with the 814 // <p>test</p><p></p> because Gecko was finding two empty text nodes 815 // when traversing on the right hand side of an empty document. 816 817 if ( fill ) 818 { 819 820 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "606", "processRng(): no content. Using fill.", fill ); 821 822 roam = fill; 823 } 824 else 825 { 826 // And stuff a shiny new object with whatever contents we have 827 828 //this.ddt._ddt( "enter-paragraphs.js", "606", "processRng(): creating p tag or document fragment - pWrap is '" + pWrap + "' " ); 829 830 roam = (pWrap || (cnt.nodeType == 11 && !cnt.firstChild)) ? editor._doc.createElement('p') : editor._doc.createDocumentFragment(); 831 roam.appendChild(cnt); 832 } 833 834 if (preBr) 835 { 836 //this.ddt._ddt( "enter-paragraphs.js", "767", "processRng(): appending a br based on preBr flag" ); 837 838 roam.appendChild(editor._doc.createElement('br')); 839 } 840 841 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "606", "processRng(): bottom with roam:", roam ); 842 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "606", "processRng(): bottom with neighbour:", neighbour ); 843 844 // Return the nearest relative, relative insertion point and fragment to insert 845 846 return new Array(neighbour, insertion, roam); 847 848 }; // end of processRng() 690 { 691 // And stuff a shiny new object with whatever contents we have 692 693 roam = (pWrap || (cnt.nodeType == 11 && !cnt.firstChild)) ? editor._doc.createElement('p') : editor._doc.createDocumentFragment(); 694 roam.appendChild(cnt); 695 } 696 697 if (preBr) 698 { 699 roam.appendChild(editor._doc.createElement('br')); 700 } 701 // Return the nearest relative, relative insertion point and fragment to insert 702 703 return new Array(neighbour, insertion, roam); 704 705 }; // end of processRng() 849 706 850 707 // ---------------------------------------------------------------------------------- … … 865 722 866 723 EnterParagraphs.prototype.isNormalListItem = function(rng) 867 { 868 869 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "863", "isNormaListItem(): checking rng for list end:", rng ); 870 871 var node, listNode; 872 873 node = rng.startContainer; 874 875 if (( typeof node.nodeName != 'undefined') && 876 ( node.nodeName.toLowerCase() == 'li' )) 877 { 878 879 //this.ddt._ddt( "enter-paragraphs.js", "863", "isNormaListItem(): node is a list item"); 880 881 // are we a list item? 882 883 listNode = node; 884 } 885 else if (( typeof node.parentNode != 'undefined' ) && 886 ( typeof node.parentNode.nodeName != 'undefined' ) && 887 ( node.parentNode.nodeName.toLowerCase() == 'li' )) 888 { 889 890 //this.ddt._ddt( "enter-paragraphs.js", "863", "isNormaListItem(): parent is a list item"); 891 892 // our parent is a list item. 893 894 listNode = node.parentNode; 895 896 } 897 else 898 { 899 //this.ddt._ddt( "enter-paragraphs.js", "863", "isNormaListItem(): not list item"); 900 901 // neither we nor our parent are a list item. this is not a normal 902 // li case. 903 904 return false; 905 } 906 907 // at this point we have a listNode. Is it the first list item? 908 909 if ( ! listNode.previousSibling ) 910 { 911 //this.ddt._ddt( "enter-paragraphs.js", "839", "isNormaListItem(): we are the first li." ); 912 913 // are we on the first character of the first li? 914 915 if ( rng.startOffset == 0 ) 916 { 917 //this.ddt._ddt( "enter-paragraphs.js", "839", "isNormaListItem(): we are on the first character." ); 918 919 return false; 920 } 921 } 922 923 //this.ddt._ddt( "enter-paragraphs.js", "839", "isNormaListItem(): this is a normal list item case." ); 924 return true; 925 926 }; // end of isNormalListItem() 724 { 725 726 var node, listNode; 727 728 node = rng.startContainer; 729 730 if (( typeof node.nodeName != 'undefined') && 731 ( node.nodeName.toLowerCase() == 'li' )) 732 { 733 734 // are we a list item? 735 736 listNode = node; 737 } 738 else if (( typeof node.parentNode != 'undefined' ) && 739 ( typeof node.parentNode.nodeName != 'undefined' ) && 740 ( node.parentNode.nodeName.toLowerCase() == 'li' )) 741 { 742 743 // our parent is a list item. 744 745 listNode = node.parentNode; 746 747 } 748 else 749 { 750 // neither we nor our parent are a list item. this is not a normal 751 // li case. 752 753 return false; 754 } 755 756 // at this point we have a listNode. Is it the first list item? 757 758 if ( ! listNode.previousSibling ) 759 { 760 // are we on the first character of the first li? 761 762 if ( rng.startOffset == 0 ) 763 { 764 return false; 765 } 766 } 767 return true; 768 769 }; // end of isNormalListItem() 927 770 928 771 // ---------------------------------------------------------------------------------- … … 932 775 933 776 EnterParagraphs.prototype.__onKeyPress = function(ev) 934 { 935 936 //this.ddt._ddt( "enter-paragraphs.js", "517", "__onKeyPress(): top with keyCode '" + ev.keyCode + "'" ); 937 777 { 778 938 779 // If they've hit enter and shift is not pressed, handle it 939 780 940 781 if (ev.keyCode == 13 && !ev.shiftKey && this.editor._iframe.contentWindow.getSelection) 941 { 942 //this.ddt._ddt( "enter-paragraphs.js", "517", "__onKeyPress(): calling handleEnter" ); 943 782 { 944 783 return this.handleEnter(ev); 945 } 946 947 //this.ddt._ddt( "enter-paragraphs.js", "517", "__onKeyPress(): bottom" ); 948 949 }; // end of _onKeyPress() 784 } 785 786 }; // end of _onKeyPress() 950 787 951 788 // ----------------------------------------------------------------------------------- … … 956 793 957 794 EnterParagraphs.prototype.handleEnter = function(ev) 958 { 959 960 //this.ddt._ddt( "enter-paragraphs.js", "537", "handleEnter(): top" ); 961 962 var cursorNode; 963 795 { 796 797 var cursorNode; 798 964 799 // Grab the selection and associated range 965 800 966 801 var sel = this.editor.getSelection(); 967 802 var rng = this.editor.createRange(sel); 968 969 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "757", "handleEnter(): initial range is: ", rng ); 970 971 // if we are at the end of a list and the node is empty let the browser handle 972 // it to get us out of the list. 973 974 if ( this.isNormalListItem(rng) ) 975 { 976 //this.ddt._ddt( "enter-paragraphs.js", "757", "handleEnter(): we are at the end of a list with a blank item. Letting the browser handle it." ); 977 return true; 978 } 979 980 // as far as I can tell this isn't actually used. 981 803 804 // if we are at the end of a list and the node is empty let the browser handle 805 // it to get us out of the list. 806 807 if ( this.isNormalListItem(rng) ) 808 { 809 810 return true; 811 } 812 813 // as far as I can tell this isn't actually used. 814 982 815 this.takenIds = new Object(); 983 816 984 817 // Grab ranges for document re-stuffing, if appropriate 985 // 986 // pStart and pEnd are arrays consisting of 987 // [0] neighbor node 988 // [1] insertion type 989 // [2] roam 990 991 //this.ddt._ddt( "enter-paragraphs.js", "537", "handleEnter(): calling processSide on left side." ); 992 818 // 819 // pStart and pEnd are arrays consisting of 820 // [0] neighbor node 821 // [1] insertion type 822 // [2] roam 823 993 824 var pStart = this.processSide(rng, "left"); 994 995 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "757", "handleEnter(): after processing left side range is: ", rng ); 996 997 //this.ddt._ddt( "enter-paragraphs.js", "537", "handleEnter(): calling processSide on right side." ); 998 999 var pEnd = this.processSide(rng, "right"); 1000 1001 // used to position the cursor after insertion. 1002 1003 cursorNode = pEnd[2]; 1004 825 826 var pEnd = this.processSide(rng, "right"); 827 828 // used to position the cursor after insertion. 829 830 cursorNode = pEnd[2]; 831 1005 832 // Get rid of everything local to the selection 1006 833 1007 834 sel.removeAllRanges(); 1008 835 rng.deleteContents(); 1009 1010 // Grab a node we'll have after insertion, since fragments will be lost 1011 // 1012 // we'll use this to position the cursor. 1013 1014 //this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): looking for cursor position" ); 1015 836 837 // Grab a node we'll have after insertion, since fragments will be lost 838 // 839 // we'll use this to position the cursor. 840 1016 841 var holdEnd = this.forEachNodeUnder( cursorNode, "find_cursorpoint", "ltr", false, true); 1017 1018 if ( ! holdEnd )1019 {1020 alert( "INTERNAL ERROR - could not find place to put cursor after ENTER" );1021 }1022 842 843 if ( ! holdEnd ) 844 { 845 alert( "INTERNAL ERROR - could not find place to put cursor after ENTER" ); 846 } 847 1023 848 // Insert our carefully chosen document fragments 1024 849 1025 850 if ( pStart ) 1026 { 1027 1028 //this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): inserting pEnd" ); 1029 1030 this.insertAdjacentElement(pStart[0], pStart[1], pStart[2]); 1031 } 1032 851 { 852 853 this.insertAdjacentElement(pStart[0], pStart[1], pStart[2]); 854 } 855 1033 856 if ( pEnd && pEnd.nodeType != 1) 1034 { 1035 1036 //this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): inserting pEnd" ); 1037 1038 this.insertAdjacentElement(pEnd[0], pEnd[1], pEnd[2]); 1039 } 1040 857 { 858 859 this.insertAdjacentElement(pEnd[0], pEnd[1], pEnd[2]); 860 } 861 1041 862 // Move the caret in front of the first good text element 1042 863 1043 864 if ((holdEnd) && (this._permEmpty.test(holdEnd.nodeName) )) 1044 { 1045 1046 //this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): looping to find cursor element." ); 1047 865 { 866 1048 867 var prodigal = 0; 1049 868 while ( holdEnd.parentNode.childNodes.item(prodigal) != holdEnd ) 1050 {1051 prodigal++;1052 }1053 869 { 870 prodigal++; 871 } 872 1054 873 sel.collapse( holdEnd.parentNode, prodigal); 1055 }874 } 1056 875 else 1057 { 1058 1059 // holdEnd might be false. 1060 1061 try 1062 { 1063 sel.collapse(holdEnd, 0); 1064 1065 //this.ddt._ddtDumpNode( "enter-paragraphs.js", "1057", "handleEnter(): scrolling to element:", holdEnd ); 1066 1067 // interestingly, scrollToElement() scroll so the top if holdEnd is a text node. 1068 1069 if ( holdEnd.nodeType == 3 ) 1070 { 1071 holdEnd = holdEnd.parentNode; 1072 } 1073 1074 this.editor.scrollToElement(holdEnd); 1075 } 1076 catch (e) 1077 { 1078 // we could try to place the cursor at the end of the document. 1079 } 1080 } 1081 876 { 877 878 // holdEnd might be false. 879 880 try 881 { 882 sel.collapse(holdEnd, 0); 883 884 // interestingly, scrollToElement() scroll so the top if holdEnd is a text node. 885 886 if ( holdEnd.nodeType == 3 ) 887 { 888 holdEnd = holdEnd.parentNode; 889 } 890 891 this.editor.scrollToElement(holdEnd); 892 } 893 catch (e) 894 { 895 // we could try to place the cursor at the end of the document. 896 } 897 } 898 1082 899 this.editor.updateToolbar(); 1083 1084 Xinha._stopEvent(ev);1085 1086 return true;1087 1088 }; // end of handleEnter()900 901 Xinha._stopEvent(ev); 902 903 return true; 904 905 }; // end of handleEnter() 1089 906 1090 907 // END -
branches/688-fixup/modules/GetHtml/DOMwalk.js
r690 r693 21 21 -- $LastChangedBy$ 22 22 --------------------------------------------------------------------------*/ 23 function GetHtmlImplementation(editor) { 24 this.editor = editor; 25 } 26 27 GetHtmlImplementation._pluginInfo = { 28 name : "GetHtmlImplementation DOMwalk", 29 origin : "Xinha Core", 30 version : "$LastChangedRevision$".replace(/^[^:]*: (.*) \$$/, '$1'), 31 developer : "The Xinha Core Developer Team", 32 developer_url : "$HeadURL$".replace(/^[^:]*: (.*) \$$/, '$1'), 33 sponsor : "", 34 sponsor_url : "", 35 license : "htmlArea" 36 }; 23 37 24 38 // Retrieves the HTML code from the given node. This is a replacement for -
branches/688-fixup/modules/GetHtml/TransformInnerHTML.js
r690 r693 19 19 */ 20 20 21 function GetHtml (editor) {21 function GetHtmlImplementation(editor) { 22 22 this.editor = editor; 23 23 } 24 24 25 GetHtml ._pluginInfo = {26 name : "GetHtml ",25 GetHtmlImplementation._pluginInfo = { 26 name : "GetHtmlImplementation TransformInnerHTML", 27 27 version : "1.0", 28 28 developer : "Nelson Bright", 29 29 developer_url : "http://www.brightworkweb.com/", 30 sponsor : "", 31 sponsor_url : "", 30 32 license : "htmlArea" 31 33 }; … … 206 208 return html; 207 209 }; 208 209 //overload outwardHtml() to handle onclick suppression210 HTMLArea.prototype._origOutwardHtml = HTMLArea.prototype.outwardHtml;211 HTMLArea.prototype.outwardHtml = function(html) {212 html = html.replace("onclick=\"try{if(document.designMode && document.designMode == 'on') return false;}catch(e){} window.open(", "onclick=\"window.open(");213 html = this._origOutwardHtml(html);214 return html;215 }; -
branches/688-fixup/modules/InsertImage/insert_image.html
r690 r693 4 4 <title>Insert Image</title> 5 5 6 <script type="text/javascript" src=" popup.js"></script>7 <link rel="stylesheet" type="text/css" href=" popup.css" />6 <script type="text/javascript" src="../../popups/popup.js"></script> 7 <link rel="stylesheet" type="text/css" href="../../popups/popup.css" /> 8 8 9 9 <script type="text/javascript"> … … 161 161 <div class="fr">Image Preview:</div> 162 162 <iframe name="ipreview" id="ipreview" frameborder="0" style="border : 1px solid gray;" 163 height="200" width="300" src=" blank.html"></iframe>163 height="200" width="300" src="../../popups/blank.html"></iframe> 164 164 </td> 165 165 <td valign="bottom" style="text-align: right"> -
branches/688-fixup/modules/InsertImage/insert_image.js
r690 r693 14 14 -- which provides the functionality to insert an image in the editor. 15 15 -- 16 -- The file is loadedby the Xinha Core when no alternative method (plugin) is loaded.16 -- he file is loaded as a special plugin by the Xinha Core when no alternative method (plugin) is loaded. 17 17 -- 18 18 -- … … 22 22 -- $LastChangedBy$ 23 23 --------------------------------------------------------------------------*/ 24 InsertImage._pluginInfo = { 25 name : "InsertImage", 26 origin : "Xinha Core", 27 version : "$LastChangedRevision$".replace(/^[^:]*: (.*) \$$/, '$1'), 28 developer : "The Xinha Core Developer Team", 29 developer_url : "$HeadURL$".replace(/^[^:]*: (.*) \$$/, '$1'), 30 sponsor : "", 31 sponsor_url : "", 32 license : "htmlArea" 33 }; 34 35 function InsertImage(editor) { 36 } 24 37 25 38 // Called when the user clicks on "InsertImage" button. If an image is already … … 52 65 }; 53 66 } 54 this._popupDialog(67 Dialog( 55 68 editor.config.URIs.insert_image, 56 69 function(param) -
branches/688-fixup/modules/InsertTable/insert_table.html
r690 r693 4 4 <title>Insert Table</title> 5 5 6 <script type="text/javascript" src=" popup.js"></script>7 <link rel="stylesheet" type="text/css" href=" popup.css" />6 <script type="text/javascript" src="../../popups/popup.js"></script> 7 <link rel="stylesheet" type="text/css" href="../../popups/popup.css" /> 8 8 9 9 <script type="text/javascript"> 10 10 11 window.resizeTo(4 10, 250);11 window.resizeTo(425, 250); 12 12 13 13 Xinha = window.opener.Xinha; … … 19 19 Xinha = window.opener.Xinha; // load the Xinha plugin and lang file 20 20 __dlg_translate('Xinha'); 21 __dlg_init(null, Xinha.is_ie ? null : {width:4 10,height:250});21 __dlg_init(null, Xinha.is_ie ? null : {width:425,height:250}); 22 22 // Make sure the translated string appears in the drop down. (for gecko) 23 23 document.getElementById("f_unit").selectedIndex = 1; -
branches/688-fixup/modules/InternetExplorer/InternetExplorer.js
r690 r693 38 38 developer : "The Xinha Core Developer Team", 39 39 developer_url : "$HeadURL$".replace(/^[^:]*: (.*) \$$/, '$1'), 40 sponsor : "", 41 sponsor_url : "", 40 42 license : "htmlArea" 41 43 }; -
branches/688-fixup/plugins/GetHtml/get-html.js
r689 r693 1 1 /** 2 * Based on XML_Utility functions submitted by troels_kn. 3 * credit also to adios, who helped with reg exps: 4 * http://www.sitepoint.com/forums/showthread.php?t=201052 5 * 6 * A replacement for HTMLArea.getHTML 7 * 8 * Features: 9 * - Generates XHTML code 10 * - Much faster than HTMLArea.getHTML 11 * - Eliminates the hacks to accomodate browser quirks 12 * - Returns correct code for Flash objects and scripts 13 * - Formats html in an indented, readable format in html mode 14 * - Preserves script and pre formatting 15 * - Preserves formatting in comments 16 * - Removes contenteditable from body tag in full-page mode 17 * - Supports only7BitPrintablesInURLs config option 18 * - Supports htmlRemoveTags config option 2 Implemented now as GetHtmlImplementation plugin in modules/GetHtml/TransformInnerHTML.js 19 3 */ 20 4 21 5 function GetHtml(editor) { 22 this.editor = editor;6 editor.config.getHtmlMethod = "TransformInnerHTML"; 23 7 } 24 8 … … 28 12 developer : "Nelson Bright", 29 13 developer_url : "http://www.brightworkweb.com/", 14 sponsor : "", 15 sponsor_url : "", 30 16 license : "htmlArea" 31 17 }; 32 33 HTMLArea.RegExpCache = [34 /*00*/ new RegExp().compile(/<\s*\/?([^\s\/>]+)[\s*\/>]/gi),//lowercase tags35 /*01*/ new RegExp().compile(/(\s+)_moz[^=>]*=[^\s>]*/gi),//strip _moz attributes36 /*02*/ new RegExp().compile(/\s*=\s*(([^'"][^>\s]*)([>\s])|"([^"]+)"|'([^']+)')/g),// find attributes37 /*03*/ new RegExp().compile(/\/>/g),//strip singlet terminators38 /*04*/ new RegExp().compile(/<(br|hr|img|input|link|meta|param|embed|area)((\s*\S*="[^"]*")*)>/g),//terminate singlet tags39 /*05*/ new RegExp().compile(/(checked|compact|declare|defer|disabled|ismap|multiple|no(href|resize|shade|wrap)|readonly|selected)([\s>])/gi),//expand singlet attributes40 /*06*/ new RegExp().compile(/(="[^']*)'([^'"]*")/),//check quote nesting41 /*07*/ new RegExp().compile(/&(?=[^<]*>)/g),//expand query ampersands42 /*08*/ new RegExp().compile(/<\s+/g),//strip tagstart whitespace43 /*09*/ new RegExp().compile(/\s+(\/)?>/g),//trim whitespace44 /*10*/ new RegExp().compile(/\s{2,}/g),//trim extra whitespace45 /*11*/ new RegExp().compile(/\s+([^=\s]+)((="[^"]+")|([\s>]))/g),// lowercase attribute names46 /*12*/ new RegExp().compile(/\s+contenteditable(=[^>\s\/]*)?/gi),//strip contenteditable47 /*13*/ new RegExp().compile(/((href|src)=")([^\s]*)"/g), //find href and src for stripBaseHref()48 /*14*/ new RegExp().compile(/<\/?(div|p|h[1-6]|table|tr|td|th|ul|ol|li|blockquote|object|br|hr|img|embed|param|pre|script|html|head|body|meta|link|title|area|input|form|textarea|select|option)[^>]*>/g),49 /*15*/ new RegExp().compile(/<\/(div|p|h[1-6]|table|tr|ul|ol|blockquote|object|html|head|body|script|form|select)( [^>]*)?>/g),//blocklevel closing tag50 /*16*/ new RegExp().compile(/<(div|p|h[1-6]|table|tr|ul|ol|blockquote|object|html|head|body|script|form|select)( [^>]*)?>/g),//blocklevel opening tag51 /*17*/ new RegExp().compile(/<(td|th|li|option|br|hr|embed|param|pre|meta|link|title|area|input|textarea)[^>]*>/g),//singlet tag or output on 1 line52 /*18*/ new RegExp().compile(/(^|<\/(pre|script)>)(\s|[^\s])*?(<(pre|script)[^>]*>|$)/g),//find content NOT inside pre and script tags53 /*19*/ new RegExp().compile(/(<pre[^>]*>)([\s\S])*?(<\/pre>)/g),//find content inside pre tags54 /*20*/ new RegExp().compile(/(^|<!--[\s\S]*?-->)([\s\S]*?)(?=<!--[\s\S]*?-->|$)/g),//find content NOT inside comments55 /*21*/ new RegExp().compile(/\S*=""/g), //find empty attributes56 /*22*/ new RegExp().compile(/<!--[\s\S]*?-->|<\?[\s\S]*?\?>|<\/?\w[^>]*>/g), //find all tags, including comments and php57 /*23*/ new RegExp().compile(/(^|<\/script>)[\s\S]*?(<script[^>]*>|$)/g) //find content NOT inside script tags58 ];59 60 /**61 * Cleans HTML into wellformed xhtml62 */63 HTMLArea.prototype.cleanHTML = function(sHtml) {64 var c = HTMLArea.RegExpCache;65 sHtml = sHtml.66 replace(c[0], function(str) { return str.toLowerCase(); } ).//lowercase tags/attribute names67 replace(c[1], ' ').//strip _moz attributes68 replace(c[12], ' ').//strip contenteditable69 replace(c[2], '="$2$4$5"$3').//add attribute quotes70 replace(c[21], ' ').//strip empty attributes71 replace(c[11], function(str, p1, p2) { return ' '+p1.toLowerCase()+p2; }).//lowercase attribute names72 replace(c[3], '>').//strip singlet terminators73 replace(c[9], '$1>').//trim whitespace74 replace(c[5], '$1="$1"$3').//expand singlet attributes75 replace(c[4], '<$1$2 />').//terminate singlet tags76 replace(c[6], '$1$2').//check quote nesting77 // replace(c[7], '&').//expand query ampersands78 replace(c[8], '<').//strip tagstart whitespace79 replace(c[10], ' ');//trim extra whitespace80 if(HTMLArea.is_ie && c[13].test(sHtml)) {81 sHtml = sHtml.replace(c[13],'$1'+this.stripBaseURL(RegExp.$3)+'"');82 }83 if(this.config.only7BitPrintablesInURLs) {84 if (HTMLArea.is_ie) c[13].test(sHtml); // oddly the test below only triggers when we call this once before (IE6), in Moz it fails if tested twice85 if ( c[13].test(sHtml)) {86 try { //Mozilla returns an incorrectly encoded value with innerHTML87 sHtml = sHtml.replace(c[13], '$1'+decodeURIComponent(RegExp.$3).replace(/([^!-~]+)/g,function(chr){return escape(chr);})+'"');88 } catch (e) { // once the URL is escape()ed, you can't decodeURIComponent() it anymore89 sHtml = sHtml.replace(c[13], '$1'+RegExp.$3.replace(/([^!-~]+)/g,function(chr){return escape(chr);})+'"');90 }91 }92 }93 return sHtml;94 };95 96 /**97 * Prettyfies html by inserting linebreaks before tags, and indenting blocklevel tags98 */99 HTMLArea.indent = function(s, sindentChar) {100 HTMLArea.__nindent = 0;101 HTMLArea.__sindent = "";102 HTMLArea.__sindentChar = (typeof sindentChar == "undefined") ? " " : sindentChar;103 var c = HTMLArea.RegExpCache;104 if(HTMLArea.is_gecko) { //moz changes returns into <br> inside <pre> tags105 s = s.replace(c[19], function(str){return str.replace(/<br \/>/g,"\n")});106 }107 s = s.replace(c[18], function(strn) { //skip pre and script tags108 strn = strn.replace(c[20], function(st,$1,$2) { //exclude comments109 string = $2.replace(/[\n\r]/gi, " ").replace(/\s+/gi," ").replace(c[14], function(str) {110 if (str.match(c[16])) {111 var s = "\n" + HTMLArea.__sindent + str;112 // blocklevel openingtag - increase indent113 HTMLArea.__sindent += HTMLArea.__sindentChar;114 ++HTMLArea.__nindent;115 return s;116 } else if (str.match(c[15])) {117 // blocklevel closingtag - decrease indent118 --HTMLArea.__nindent;119 HTMLArea.__sindent = "";120 for (var i=HTMLArea.__nindent;i>0;--i) {121 HTMLArea.__sindent += HTMLArea.__sindentChar;122 }123 return "\n" + HTMLArea.__sindent + str;124 } else if (str.match(c[17])) {125 // singlet tag126 return "\n" + HTMLArea.__sindent + str;127 }128 return str; // this won't actually happen129 });130 return $1 + string;131 });return strn;132 });133 //final cleanup134 s = s.replace(/^\s*/,'').//strip leading whitespace135 replace(/ +\n/g,'\n').//strip spaces at end of lines136 replace(/[\r\n]+<\/script>/g,'\n</script>');//strip returns added into scripts137 return s;138 };139 140 HTMLArea.getHTML = function(root, outputRoot, editor) {141 var html = "";142 var c = HTMLArea.RegExpCache;143 144 if(root.nodeType == 11) {//document fragment145 //we can't get innerHTML from the root (type 11) node, so we146 //copy all the child nodes into a new div and get innerHTML from the div147 var div = document.createElement("div");148 var temp = root.insertBefore(div,root.firstChild);149 for (j = temp.nextSibling; j; j = j.nextSibling) {150 temp.appendChild(j.cloneNode(true));151 }152 html += temp.innerHTML.replace(c[23], function(strn) { //skip content inside script tags153 strn = strn.replace(c[22], function(tag){154 if(/^<[!\?]/.test(tag)) return tag; //skip comments and php tags155 else return editor.cleanHTML(tag)});156 return strn;157 });158 159 } else {160 161 var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';162 if (outputRoot) { //only happens with <html> tag in fullpage mode163 html += "<" + root_tag;164 var attrs = root.attributes; // strangely, this doesn't work in moz165 for (i = 0; i < attrs.length; ++i) {166 var a = attrs.item(i);167 if (!a.specified) {168 continue;169 }170 var name = a.nodeName.toLowerCase();171 var value = a.nodeValue;172 html += " " + name + '="' + value + '"';173 }174 html += ">";175 }176 if(root_tag == "html") {177 innerhtml = editor._doc.documentElement.innerHTML;178 } else {179 innerhtml = root.innerHTML;180 }181 //pass tags to cleanHTML() one at a time182 //includes support for htmlRemoveTags config option183 html += innerhtml.replace(c[23], function(strn) { //skip content inside script tags184 strn = strn.replace(c[22], function(tag){185 if(/^<[!\?]/.test(tag)) return tag; //skip comments and php tags186 else if(!(editor.config.htmlRemoveTags && editor.config.htmlRemoveTags.test(tag.replace(/<([^\s>\/]+)/,'$1'))))187 return editor.cleanHTML(tag);188 else return ''});189 return strn;190 });191 //IE drops all </li> tags in a list except the last one192 if(HTMLArea.is_ie) {193 html = html.replace(/<li( [^>]*)?>/g,'</li><li$1>').194 replace(/(<(ul|ol)[^>]*>)[\s\n]*<\/li>/g, '$1').195 replace(/<\/li>([\s\n]*<\/li>)+/g, '<\/li>');196 }197 if(HTMLArea.is_gecko)198 html = html.replace(/<br \/>\n$/, ''); //strip trailing <br> added by moz199 if (outputRoot) {200 html += "</" + root_tag + ">";201 }202 html = HTMLArea.indent(html);203 };204 // html = HTMLArea.htmlEncode(html);205 206 return html;207 };208 209 //overload outwardHtml() to handle onclick suppression210 HTMLArea.prototype._origOutwardHtml = HTMLArea.prototype.outwardHtml;211 HTMLArea.prototype.outwardHtml = function(html) {212 html = html.replace("onclick=\"try{if(document.designMode && document.designMode == 'on') return false;}catch(e){} window.open(", "onclick=\"window.open(");213 html = this._origOutwardHtml(html);214 return html;215 }; -
branches/688-fixup/plugins/TableOperations/table-operations.js
r689 r693 46 46 // add a new line in the toolbar 47 47 cfg.toolbar.push(toolbar); 48 49 if ( typeof PopupWin == 'undefined' ) 50 { 51 Xinha._loadback(_editor_url + 'modules/Dialogs/popupwin.js'); 52 } 48 53 } 49 54
