diff options
author | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
commit | 81bea17aefb26859f825b9293c7c99192874806e (patch) | |
tree | fb244408ca271affa2899adb634788802c9a89d8 /lib/dijit/_editor/plugins/EnterKeyHandling.js | |
parent | 870a70e109ac9e80a88047044530de53d0404ec7 (diff) |
upgrade Dojo to 1.6.1
Diffstat (limited to 'lib/dijit/_editor/plugins/EnterKeyHandling.js')
-rw-r--r-- | lib/dijit/_editor/plugins/EnterKeyHandling.js | 1007 |
1 files changed, 594 insertions, 413 deletions
diff --git a/lib/dijit/_editor/plugins/EnterKeyHandling.js b/lib/dijit/_editor/plugins/EnterKeyHandling.js index 51a8fdde8..670d491ae 100644 --- a/lib/dijit/_editor/plugins/EnterKeyHandling.js +++ b/lib/dijit/_editor/plugins/EnterKeyHandling.js @@ -1,423 +1,604 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"]){ -dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"]=true; +if(!dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"] = true; dojo.provide("dijit._editor.plugins.EnterKeyHandling"); dojo.require("dojo.window"); -dojo.declare("dijit._editor.plugins.EnterKeyHandling",dijit._editor._Plugin,{blockNodeForEnter:"BR",constructor:function(_1){ -if(_1){ -dojo.mixin(this,_1); -} -},setEditor:function(_2){ -this.editor=_2; -if(this.blockNodeForEnter=="BR"){ -if(dojo.isIE){ -_2.contentDomPreFilters.push(dojo.hitch(this,"regularPsToSingleLinePs")); -_2.contentDomPostFilters.push(dojo.hitch(this,"singleLinePsToRegularPs")); -_2.onLoadDeferred.addCallback(dojo.hitch(this,"_fixNewLineBehaviorForIE")); -}else{ -_2.onLoadDeferred.addCallback(dojo.hitch(this,function(d){ -try{ -this.editor.document.execCommand("insertBrOnReturn",false,true); -} -catch(e){ -} -return d; -})); -} -}else{ -if(this.blockNodeForEnter){ -dojo["require"]("dijit._editor.range"); -var h=dojo.hitch(this,this.handleEnterKey); -_2.addKeyHandler(13,0,0,h); -_2.addKeyHandler(13,0,1,h); -this.connect(this.editor,"onKeyPressed","onKeyPressed"); -} -} -},onKeyPressed:function(e){ -if(this._checkListLater){ -if(dojo.withGlobal(this.editor.window,"isCollapsed",dijit)){ -var _3=dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,["LI"]); -if(!_3){ -dijit._editor.RichText.prototype.execCommand.call(this.editor,"formatblock",this.blockNodeForEnter); -var _4=dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,[this.blockNodeForEnter]); -if(_4){ -_4.innerHTML=this.bogusHtmlContent; -if(dojo.isIE){ -var r=this.editor.document.selection.createRange(); -r.move("character",-1); -r.select(); -} -}else{ -console.error("onKeyPressed: Cannot find the new block node"); -} -}else{ -if(dojo.isMoz){ -if(_3.parentNode.parentNode.nodeName=="LI"){ -_3=_3.parentNode.parentNode; -} -} -var fc=_3.firstChild; -if(fc&&fc.nodeType==1&&(fc.nodeName=="UL"||fc.nodeName=="OL")){ -_3.insertBefore(fc.ownerDocument.createTextNode(" "),fc); -var _5=dijit.range.create(this.editor.window); -_5.setStart(_3.firstChild,0); -var _6=dijit.range.getSelection(this.editor.window,true); -_6.removeAllRanges(); -_6.addRange(_5); -} -} -} -this._checkListLater=false; -} -if(this._pressedEnterInBlock){ -if(this._pressedEnterInBlock.previousSibling){ -this.removeTrailingBr(this._pressedEnterInBlock.previousSibling); -} -delete this._pressedEnterInBlock; -} -},bogusHtmlContent:" ",blockNodes:/^(?:P|H1|H2|H3|H4|H5|H6|LI)$/,handleEnterKey:function(e){ -var _7,_8,_9,_a=this.editor.document,br; -if(e.shiftKey){ -var _b=dojo.withGlobal(this.editor.window,"getParentElement",dijit._editor.selection); -var _c=dijit.range.getAncestor(_b,this.blockNodes); -if(_c){ -if(!e.shiftKey&&_c.tagName=="LI"){ -return true; -} -_7=dijit.range.getSelection(this.editor.window); -_8=_7.getRangeAt(0); -if(!_8.collapsed){ -_8.deleteContents(); -_7=dijit.range.getSelection(this.editor.window); -_8=_7.getRangeAt(0); -} -if(dijit.range.atBeginningOfContainer(_c,_8.startContainer,_8.startOffset)){ -if(e.shiftKey){ -br=_a.createElement("br"); -_9=dijit.range.create(this.editor.window); -_c.insertBefore(br,_c.firstChild); -_9.setStartBefore(br.nextSibling); -_7.removeAllRanges(); -_7.addRange(_9); -}else{ -dojo.place(br,_c,"before"); -} -}else{ -if(dijit.range.atEndOfContainer(_c,_8.startContainer,_8.startOffset)){ -_9=dijit.range.create(this.editor.window); -br=_a.createElement("br"); -if(e.shiftKey){ -_c.appendChild(br); -_c.appendChild(_a.createTextNode(" ")); -_9.setStart(_c.lastChild,0); -}else{ -dojo.place(br,_c,"after"); -_9.setStartAfter(_c); -} -_7.removeAllRanges(); -_7.addRange(_9); -}else{ -return true; -} -} -}else{ -dijit._editor.RichText.prototype.execCommand.call(this.editor,"inserthtml","<br>"); -} -return false; -} -var _d=true; -_7=dijit.range.getSelection(this.editor.window); -_8=_7.getRangeAt(0); -if(!_8.collapsed){ -_8.deleteContents(); -_7=dijit.range.getSelection(this.editor.window); -_8=_7.getRangeAt(0); -} -var _e=dijit.range.getBlockAncestor(_8.endContainer,null,this.editor.editNode); -var _f=_e.blockNode; -if((this._checkListLater=(_f&&(_f.nodeName=="LI"||_f.parentNode.nodeName=="LI")))){ -if(dojo.isMoz){ -this._pressedEnterInBlock=_f; -} -if(/^(\s| |\xA0|<span\b[^>]*\bclass=['"]Apple-style-span['"][^>]*>(\s| |\xA0)<\/span>)?(<br>)?$/.test(_f.innerHTML)){ -_f.innerHTML=""; -if(dojo.isWebKit){ -_9=dijit.range.create(this.editor.window); -_9.setStart(_f,0); -_7.removeAllRanges(); -_7.addRange(_9); -} -this._checkListLater=false; -} -return true; -} -if(!_e.blockNode||_e.blockNode===this.editor.editNode){ -try{ -dijit._editor.RichText.prototype.execCommand.call(this.editor,"formatblock",this.blockNodeForEnter); -} -catch(e2){ -} -_e={blockNode:dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,[this.blockNodeForEnter]),blockContainer:this.editor.editNode}; -if(_e.blockNode){ -if(_e.blockNode!=this.editor.editNode&&(!(_e.blockNode.textContent||_e.blockNode.innerHTML).replace(/^\s+|\s+$/g,"").length)){ -this.removeTrailingBr(_e.blockNode); -return false; -} -}else{ -_e.blockNode=this.editor.editNode; -} -_7=dijit.range.getSelection(this.editor.window); -_8=_7.getRangeAt(0); -} -var _10=_a.createElement(this.blockNodeForEnter); -_10.innerHTML=this.bogusHtmlContent; -this.removeTrailingBr(_e.blockNode); -if(dijit.range.atEndOfContainer(_e.blockNode,_8.endContainer,_8.endOffset)){ -if(_e.blockNode===_e.blockContainer){ -_e.blockNode.appendChild(_10); -}else{ -dojo.place(_10,_e.blockNode,"after"); -} -_d=false; -_9=dijit.range.create(this.editor.window); -_9.setStart(_10,0); -_7.removeAllRanges(); -_7.addRange(_9); -if(this.editor.height){ -dojo.window.scrollIntoView(_10); -} -}else{ -if(dijit.range.atBeginningOfContainer(_e.blockNode,_8.startContainer,_8.startOffset)){ -dojo.place(_10,_e.blockNode,_e.blockNode===_e.blockContainer?"first":"before"); -if(_10.nextSibling&&this.editor.height){ -_9=dijit.range.create(this.editor.window); -_9.setStart(_10.nextSibling,0); -_7.removeAllRanges(); -_7.addRange(_9); -dojo.window.scrollIntoView(_10.nextSibling); -} -_d=false; -}else{ -if(_e.blockNode===_e.blockContainer){ -_e.blockNode.appendChild(_10); -}else{ -dojo.place(_10,_e.blockNode,"after"); -} -_d=false; -if(_e.blockNode.style){ -if(_10.style){ -if(_e.blockNode.style.cssText){ -_10.style.cssText=_e.blockNode.style.cssText; -} -} -} -var rs=_8.startContainer; -if(rs&&rs.nodeType==3){ -var _11,_12; -var txt=rs.nodeValue; -var _13=_a.createTextNode(txt.substring(0,_8.startOffset)); -var _14=_a.createTextNode(txt.substring(_8.startOffset,txt.length)); -dojo.place(_13,rs,"before"); -dojo.place(_14,rs,"after"); -dojo.destroy(rs); -var _15=_13.parentNode; -while(_15!==_e.blockNode){ -var tg=_15.tagName; -var _16=_a.createElement(tg); -if(_15.style){ -if(_16.style){ -if(_15.style.cssText){ -_16.style.cssText=_15.style.cssText; -} -} -} -_11=_14; -while(_11){ -_12=_11.nextSibling; -_16.appendChild(_11); -_11=_12; -} -dojo.place(_16,_15,"after"); -_13=_15; -_14=_16; -_15=_15.parentNode; -} -_11=_14; -if(_11.nodeType==1||(_11.nodeType==3&&_11.nodeValue)){ -_10.innerHTML=""; -} -while(_11){ -_12=_11.nextSibling; -_10.appendChild(_11); -_11=_12; -} -} -_9=dijit.range.create(this.editor.window); -_9.setStart(_10,0); -_7.removeAllRanges(); -_7.addRange(_9); -if(this.editor.height){ -dijit.scrollIntoView(_10); -} -if(dojo.isMoz){ -this._pressedEnterInBlock=_e.blockNode; -} -} -} -return _d; -},removeTrailingBr:function(_17){ -var _18=/P|DIV|LI/i.test(_17.tagName)?_17:dijit._editor.selection.getParentOfType(_17,["P","DIV","LI"]); -if(!_18){ -return; -} -if(_18.lastChild){ -if((_18.childNodes.length>1&&_18.lastChild.nodeType==3&&/^[\s\xAD]*$/.test(_18.lastChild.nodeValue))||_18.lastChild.tagName=="BR"){ -dojo.destroy(_18.lastChild); -} -} -if(!_18.childNodes.length){ -_18.innerHTML=this.bogusHtmlContent; -} -},_fixNewLineBehaviorForIE:function(d){ -var doc=this.editor.document; -if(doc.__INSERTED_EDITIOR_NEWLINE_CSS===undefined){ -var _19=dojo.create("style",{type:"text/css"},doc.getElementsByTagName("head")[0]); -_19.styleSheet.cssText="p{margin:0;}"; -this.editor.document.__INSERTED_EDITIOR_NEWLINE_CSS=true; -} -return d; -},regularPsToSingleLinePs:function(_1a,_1b){ -function _1c(el){ -function _1d(_1e){ -var _1f=_1e[0].ownerDocument.createElement("p"); -_1e[0].parentNode.insertBefore(_1f,_1e[0]); -dojo.forEach(_1e,function(_20){ -_1f.appendChild(_20); -}); -}; -var _21=0; -var _22=[]; -var _23; -while(_21<el.childNodes.length){ -_23=el.childNodes[_21]; -if(_23.nodeType==3||(_23.nodeType==1&&_23.nodeName!="BR"&&dojo.style(_23,"display")!="block")){ -_22.push(_23); -}else{ -var _24=_23.nextSibling; -if(_22.length){ -_1d(_22); -_21=(_21+1)-_22.length; -if(_23.nodeName=="BR"){ -dojo.destroy(_23); -} -} -_22=[]; -} -_21++; -} -if(_22.length){ -_1d(_22); -} -}; -function _25(el){ -var _26=null; -var _27=[]; -var _28=el.childNodes.length-1; -for(var i=_28;i>=0;i--){ -_26=el.childNodes[i]; -if(_26.nodeName=="BR"){ -var _29=_26.ownerDocument.createElement("p"); -dojo.place(_29,el,"after"); -if(_27.length==0&&i!=_28){ -_29.innerHTML=" "; -} -dojo.forEach(_27,function(_2a){ -_29.appendChild(_2a); -}); -dojo.destroy(_26); -_27=[]; -}else{ -_27.unshift(_26); -} -} -}; -var _2b=[]; -var ps=_1a.getElementsByTagName("p"); -dojo.forEach(ps,function(p){ -_2b.push(p); +dojo.require("dijit._editor._Plugin"); +dojo.require("dijit._editor.range"); + + +dojo.declare("dijit._editor.plugins.EnterKeyHandling", dijit._editor._Plugin, { + // summary: + // This plugin tries to make all browsers behave consistently with regard to + // how ENTER behaves in the editor window. It traps the ENTER key and alters + // the way DOM is constructed in certain cases to try to commonize the generated + // DOM and behaviors across browsers. + // + // description: + // This plugin has three modes: + // + // * blockModeForEnter=BR + // * blockModeForEnter=DIV + // * blockModeForEnter=P + // + // In blockModeForEnter=P, the ENTER key starts a new + // paragraph, and shift-ENTER starts a new line in the current paragraph. + // For example, the input: + // + // | first paragraph <shift-ENTER> + // | second line of first paragraph <ENTER> + // | second paragraph + // + // will generate: + // + // | <p> + // | first paragraph + // | <br/> + // | second line of first paragraph + // | </p> + // | <p> + // | second paragraph + // | </p> + // + // In BR and DIV mode, the ENTER key conceptually goes to a new line in the + // current paragraph, and users conceptually create a new paragraph by pressing ENTER twice. + // For example, if the user enters text into an editor like this: + // + // | one <ENTER> + // | two <ENTER> + // | three <ENTER> + // | <ENTER> + // | four <ENTER> + // | five <ENTER> + // | six <ENTER> + // + // It will appear on the screen as two 'paragraphs' of three lines each. Markupwise, this generates: + // + // BR: + // | one<br/> + // | two<br/> + // | three<br/> + // | <br/> + // | four<br/> + // | five<br/> + // | six<br/> + // + // DIV: + // | <div>one</div> + // | <div>two</div> + // | <div>three</div> + // | <div> </div> + // | <div>four</div> + // | <div>five</div> + // | <div>six</div> + + // blockNodeForEnter: String + // This property decides the behavior of Enter key. It can be either P, + // DIV, BR, or empty (which means disable this feature). Anything else + // will trigger errors. The default is 'BR' + // + // See class description for more details. + blockNodeForEnter: 'BR', + + constructor: function(args){ + if(args){ + if("blockNodeForEnter" in args){ + args.blockNodeForEnter = args.blockNodeForEnter.toUpperCase(); + } + dojo.mixin(this,args); + } + }, + + setEditor: function(editor){ + // Overrides _Plugin.setEditor(). + if(this.editor === editor) { return; } + this.editor = editor; + if(this.blockNodeForEnter == 'BR'){ + // While Moz has a mode tht mostly works, it's still a little different, + // So, try to just have a common mode and be consistent. Which means + // we need to enable customUndo, if not already enabled. + this.editor.customUndo = true; + editor.onLoadDeferred.addCallback(dojo.hitch(this,function(d){ + this.connect(editor.document, "onkeypress", function(e){ + if(e.charOrCode == dojo.keys.ENTER){ + // Just do it manually. The handleEnterKey has a shift mode that + // Always acts like <br>, so just use it. + var ne = dojo.mixin({},e); + ne.shiftKey = true; + if(!this.handleEnterKey(ne)){ + dojo.stopEvent(e); + } + } + }); + return d; + })); + }else if(this.blockNodeForEnter){ + // add enter key handler + // FIXME: need to port to the new event code!! + var h = dojo.hitch(this,this.handleEnterKey); + editor.addKeyHandler(13, 0, 0, h); //enter + editor.addKeyHandler(13, 0, 1, h); //shift+enter + this.connect(this.editor,'onKeyPressed','onKeyPressed'); + } + }, + onKeyPressed: function(e){ + // summary: + // Handler for keypress events. + // tags: + // private + if(this._checkListLater){ + if(dojo.withGlobal(this.editor.window, 'isCollapsed', dijit)){ + var liparent=dojo.withGlobal(this.editor.window, 'getAncestorElement', dijit._editor.selection, ['LI']); + if(!liparent){ + // circulate the undo detection code by calling RichText::execCommand directly + dijit._editor.RichText.prototype.execCommand.call(this.editor, 'formatblock',this.blockNodeForEnter); + // set the innerHTML of the new block node + var block = dojo.withGlobal(this.editor.window, 'getAncestorElement', dijit._editor.selection, [this.blockNodeForEnter]); + if(block){ + block.innerHTML=this.bogusHtmlContent; + if(dojo.isIE){ + // move to the start by moving backwards one char + var r = this.editor.document.selection.createRange(); + r.move('character',-1); + r.select(); + } + }else{ + console.error('onKeyPressed: Cannot find the new block node'); // FIXME + } + }else{ + if(dojo.isMoz){ + if(liparent.parentNode.parentNode.nodeName == 'LI'){ + liparent=liparent.parentNode.parentNode; + } + } + var fc=liparent.firstChild; + if(fc && fc.nodeType == 1 && (fc.nodeName == 'UL' || fc.nodeName == 'OL')){ + liparent.insertBefore(fc.ownerDocument.createTextNode('\xA0'),fc); + var newrange = dijit.range.create(this.editor.window); + newrange.setStart(liparent.firstChild,0); + var selection = dijit.range.getSelection(this.editor.window, true); + selection.removeAllRanges(); + selection.addRange(newrange); + } + } + } + this._checkListLater = false; + } + if(this._pressedEnterInBlock){ + // the new created is the original current P, so we have previousSibling below + if(this._pressedEnterInBlock.previousSibling){ + this.removeTrailingBr(this._pressedEnterInBlock.previousSibling); + } + delete this._pressedEnterInBlock; + } + }, + + // bogusHtmlContent: [private] String + // HTML to stick into a new empty block + bogusHtmlContent: ' ', + + // blockNodes: [private] Regex + // Regex for testing if a given tag is a block level (display:block) tag + blockNodes: /^(?:P|H1|H2|H3|H4|H5|H6|LI)$/, + + handleEnterKey: function(e){ + // summary: + // Handler for enter key events when blockModeForEnter is DIV or P. + // description: + // Manually handle enter key event to make the behavior consistent across + // all supported browsers. See class description for details. + // tags: + // private + + var selection, range, newrange, startNode, endNode, brNode, doc=this.editor.document,br,rs,txt; + if(e.shiftKey){ // shift+enter always generates <br> + var parent = dojo.withGlobal(this.editor.window, "getParentElement", dijit._editor.selection); + var header = dijit.range.getAncestor(parent,this.blockNodes); + if(header){ + if(header.tagName == 'LI'){ + return true; // let browser handle + } + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + if(!range.collapsed){ + range.deleteContents(); + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + } + if(dijit.range.atBeginningOfContainer(header, range.startContainer, range.startOffset)){ + br=doc.createElement('br'); + newrange = dijit.range.create(this.editor.window); + header.insertBefore(br,header.firstChild); + newrange.setStartBefore(br.nextSibling); + selection.removeAllRanges(); + selection.addRange(newrange); + }else if(dijit.range.atEndOfContainer(header, range.startContainer, range.startOffset)){ + newrange = dijit.range.create(this.editor.window); + br=doc.createElement('br'); + header.appendChild(br); + header.appendChild(doc.createTextNode('\xA0')); + newrange.setStart(header.lastChild,0); + selection.removeAllRanges(); + selection.addRange(newrange); + }else{ + rs = range.startContainer; + if(rs && rs.nodeType == 3){ + // Text node, we have to split it. + txt = rs.nodeValue; + dojo.withGlobal(this.editor.window, function(){ + startNode = doc.createTextNode(txt.substring(0, range.startOffset)); + endNode = doc.createTextNode(txt.substring(range.startOffset)); + brNode = doc.createElement("br"); + + if(endNode.nodeValue == "" && dojo.isWebKit){ + endNode = doc.createTextNode('\xA0') + } + dojo.place(startNode, rs, "after"); + dojo.place(brNode, startNode, "after"); + dojo.place(endNode, brNode, "after"); + dojo.destroy(rs); + newrange = dijit.range.create(dojo.gobal); + newrange.setStart(endNode,0); + selection.removeAllRanges(); + selection.addRange(newrange); + }); + return false; + } + return true; // let browser handle + } + }else{ + selection = dijit.range.getSelection(this.editor.window); + if(selection.rangeCount){ + range = selection.getRangeAt(0); + if(range && range.startContainer){ + if(!range.collapsed){ + range.deleteContents(); + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + } + rs = range.startContainer; + if(rs && rs.nodeType == 3){ + // Text node, we have to split it. + dojo.withGlobal(this.editor.window, dojo.hitch(this, function(){ + var endEmpty = false; + + var offset = range.startOffset; + if(rs.length < offset){ + //We are not splitting the right node, try to locate the correct one + ret = this._adjustNodeAndOffset(rs, offset); + rs = ret.node; + offset = ret.offset; + } + txt = rs.nodeValue; + + startNode = doc.createTextNode(txt.substring(0, offset)); + endNode = doc.createTextNode(txt.substring(offset)); + brNode = doc.createElement("br"); + + if(!endNode.length){ + endNode = doc.createTextNode('\xA0'); + endEmpty = true; + } + + if(startNode.length){ + dojo.place(startNode, rs, "after"); + }else{ + startNode = rs; + } + dojo.place(brNode, startNode, "after"); + dojo.place(endNode, brNode, "after"); + dojo.destroy(rs); + newrange = dijit.range.create(dojo.gobal); + newrange.setStart(endNode,0); + newrange.setEnd(endNode, endNode.length); + selection.removeAllRanges(); + selection.addRange(newrange); + if(endEmpty && !dojo.isWebKit){ + dijit._editor.selection.remove(); + }else{ + dijit._editor.selection.collapse(true); + } + })); + }else{ + dojo.withGlobal(this.editor.window, dojo.hitch(this, function(){ + var brNode = doc.createElement("br"); + rs.appendChild(brNode); + var endNode = doc.createTextNode('\xA0'); + rs.appendChild(endNode); + newrange = dijit.range.create(dojo.global); + newrange.setStart(endNode,0); + newrange.setEnd(endNode, endNode.length); + selection.removeAllRanges(); + selection.addRange(newrange); + dijit._editor.selection.collapse(true); + })); + } + } + }else{ + // don't change this: do not call this.execCommand, as that may have other logic in subclass + dijit._editor.RichText.prototype.execCommand.call(this.editor, 'inserthtml', '<br>'); + } + } + return false; + } + var _letBrowserHandle = true; + + // first remove selection + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + if(!range.collapsed){ + range.deleteContents(); + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + } + + var block = dijit.range.getBlockAncestor(range.endContainer, null, this.editor.editNode); + var blockNode = block.blockNode; + + // if this is under a LI or the parent of the blockNode is LI, just let browser to handle it + if((this._checkListLater = (blockNode && (blockNode.nodeName == 'LI' || blockNode.parentNode.nodeName == 'LI')))){ + if(dojo.isMoz){ + // press enter in middle of P may leave a trailing <br/>, let's remove it later + this._pressedEnterInBlock = blockNode; + } + // if this li only contains spaces, set the content to empty so the browser will outdent this item + if(/^(\s| |\xA0|<span\b[^>]*\bclass=['"]Apple-style-span['"][^>]*>(\s| |\xA0)<\/span>)?(<br>)?$/.test(blockNode.innerHTML)){ + // empty LI node + blockNode.innerHTML = ''; + if(dojo.isWebKit){ // WebKit tosses the range when innerHTML is reset + newrange = dijit.range.create(this.editor.window); + newrange.setStart(blockNode, 0); + selection.removeAllRanges(); + selection.addRange(newrange); + } + this._checkListLater = false; // nothing to check since the browser handles outdent + } + return true; + } + + // text node directly under body, let's wrap them in a node + if(!block.blockNode || block.blockNode===this.editor.editNode){ + try{ + dijit._editor.RichText.prototype.execCommand.call(this.editor, 'formatblock',this.blockNodeForEnter); + }catch(e2){ /*squelch FF3 exception bug when editor content is a single BR*/ } + // get the newly created block node + // FIXME + block = {blockNode:dojo.withGlobal(this.editor.window, "getAncestorElement", dijit._editor.selection, [this.blockNodeForEnter]), + blockContainer: this.editor.editNode}; + if(block.blockNode){ + if(block.blockNode != this.editor.editNode && + (!(block.blockNode.textContent || block.blockNode.innerHTML).replace(/^\s+|\s+$/g, "").length)){ + this.removeTrailingBr(block.blockNode); + return false; + } + }else{ // we shouldn't be here if formatblock worked + block.blockNode = this.editor.editNode; + } + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + } + + var newblock = doc.createElement(this.blockNodeForEnter); + newblock.innerHTML=this.bogusHtmlContent; + this.removeTrailingBr(block.blockNode); + var endOffset = range.endOffset; + var node = range.endContainer; + if(node.length < endOffset){ + //We are not checking the right node, try to locate the correct one + var ret = this._adjustNodeAndOffset(node, endOffset); + node = ret.node; + endOffset = ret.offset; + } + if(dijit.range.atEndOfContainer(block.blockNode, node, endOffset)){ + if(block.blockNode === block.blockContainer){ + block.blockNode.appendChild(newblock); + }else{ + dojo.place(newblock, block.blockNode, "after"); + } + _letBrowserHandle = false; + // lets move caret to the newly created block + newrange = dijit.range.create(this.editor.window); + newrange.setStart(newblock, 0); + selection.removeAllRanges(); + selection.addRange(newrange); + if(this.editor.height){ + dojo.window.scrollIntoView(newblock); + } + }else if(dijit.range.atBeginningOfContainer(block.blockNode, + range.startContainer, range.startOffset)){ + dojo.place(newblock, block.blockNode, block.blockNode === block.blockContainer ? "first" : "before"); + if(newblock.nextSibling && this.editor.height){ + // position input caret - mostly WebKit needs this + newrange = dijit.range.create(this.editor.window); + newrange.setStart(newblock.nextSibling, 0); + selection.removeAllRanges(); + selection.addRange(newrange); + // browser does not scroll the caret position into view, do it manually + dojo.window.scrollIntoView(newblock.nextSibling); + } + _letBrowserHandle = false; + }else{ //press enter in the middle of P/DIV/Whatever/ + if(block.blockNode === block.blockContainer){ + block.blockNode.appendChild(newblock); + }else{ + dojo.place(newblock, block.blockNode, "after"); + } + _letBrowserHandle = false; + + // Clone any block level styles. + if(block.blockNode.style){ + if(newblock.style){ + if(block.blockNode.style.cssText){ + newblock.style.cssText = block.blockNode.style.cssText; + } + } + } + + // Okay, we probably have to split. + rs = range.startContainer; + var firstNodeMoved; + if(rs && rs.nodeType == 3){ + // Text node, we have to split it. + var nodeToMove, tNode; + endOffset = range.endOffset; + if(rs.length < endOffset){ + //We are not splitting the right node, try to locate the correct one + ret = this._adjustNodeAndOffset(rs, endOffset); + rs = ret.node; + endOffset = ret.offset; + } + + txt = rs.nodeValue; + startNode = doc.createTextNode(txt.substring(0, endOffset)); + endNode = doc.createTextNode(txt.substring(endOffset, txt.length)); + + // Place the split, then remove original nodes. + dojo.place(startNode, rs, "before"); + dojo.place(endNode, rs, "after"); + dojo.destroy(rs); + + // Okay, we split the text. Now we need to see if we're + // parented to the block element we're splitting and if + // not, we have to split all the way up. Ugh. + var parentC = startNode.parentNode; + while(parentC !== block.blockNode){ + var tg = parentC.tagName; + var newTg = doc.createElement(tg); + // Clone over any 'style' data. + if(parentC.style){ + if(newTg.style){ + if(parentC.style.cssText){ + newTg.style.cssText = parentC.style.cssText; + } + } + } + // If font also need to clone over any font data. + if(parentC.tagName === "FONT"){ + if(parentC.color){ + newTg.color = parentC.color; + } + if(parentC.face){ + newTg.face = parentC.face; + } + if(parentC.size){ // this check was necessary on IE + newTg.size = parentC.size; + } + } + + nodeToMove = endNode; + while(nodeToMove){ + tNode = nodeToMove.nextSibling; + newTg.appendChild(nodeToMove); + nodeToMove = tNode; + } + dojo.place(newTg, parentC, "after"); + startNode = parentC; + endNode = newTg; + parentC = parentC.parentNode; + } + + // Lastly, move the split out tags to the new block. + // as they should now be split properly. + nodeToMove = endNode; + if(nodeToMove.nodeType == 1 || (nodeToMove.nodeType == 3 && nodeToMove.nodeValue)){ + // Non-blank text and non-text nodes need to clear out that blank space + // before moving the contents. + newblock.innerHTML = ""; + } + firstNodeMoved = nodeToMove; + while(nodeToMove){ + tNode = nodeToMove.nextSibling; + newblock.appendChild(nodeToMove); + nodeToMove = tNode; + } + } + + //lets move caret to the newly created block + newrange = dijit.range.create(this.editor.window); + var nodeForCursor; + var innerMostFirstNodeMoved = firstNodeMoved; + if(this.blockNodeForEnter !== 'BR'){ + while(innerMostFirstNodeMoved){ + nodeForCursor = innerMostFirstNodeMoved; + tNode = innerMostFirstNodeMoved.firstChild; + innerMostFirstNodeMoved = tNode; + } + if(nodeForCursor && nodeForCursor.parentNode){ + newblock = nodeForCursor.parentNode; + newrange.setStart(newblock, 0); + selection.removeAllRanges(); + selection.addRange(newrange); + if(this.editor.height){ + dijit.scrollIntoView(newblock); + } + if(dojo.isMoz){ + // press enter in middle of P may leave a trailing <br/>, let's remove it later + this._pressedEnterInBlock = block.blockNode; + } + }else{ + _letBrowserHandle = true; + } + }else{ + newrange.setStart(newblock, 0); + selection.removeAllRanges(); + selection.addRange(newrange); + if(this.editor.height){ + dijit.scrollIntoView(newblock); + } + if(dojo.isMoz){ + // press enter in middle of P may leave a trailing <br/>, let's remove it later + this._pressedEnterInBlock = block.blockNode; + } + } + } + return _letBrowserHandle; + }, + + _adjustNodeAndOffset: function(/*DomNode*/node, /*Int*/offset){ + // summary: + // In the case there are multiple text nodes in a row the offset may not be within the node. If the offset is larger than the node length, it will attempt to find + // the next text sibling until it locates the text node in which the offset refers to + // node: + // The node to check. + // offset: + // The position to find within the text node + // tags: + // private. + while(node.length < offset && node.nextSibling && node.nextSibling.nodeType==3){ + //Adjust the offset and node in the case of multiple text nodes in a row + offset = offset - node.length; + node = node.nextSibling; + } + var ret = {"node": node, "offset": offset}; + return ret; + }, + + removeTrailingBr: function(container){ + // summary: + // If last child of container is a <br>, then remove it. + // tags: + // private + var para = /P|DIV|LI/i.test(container.tagName) ? + container : dijit._editor.selection.getParentOfType(container,['P','DIV','LI']); + + if(!para){ return; } + if(para.lastChild){ + if((para.childNodes.length > 1 && para.lastChild.nodeType == 3 && /^[\s\xAD]*$/.test(para.lastChild.nodeValue)) || + para.lastChild.tagName=='BR'){ + + dojo.destroy(para.lastChild); + } + } + if(!para.childNodes.length){ + para.innerHTML=this.bogusHtmlContent; + } + } }); -dojo.forEach(_2b,function(p){ -var _2c=p.previousSibling; -if((_2c)&&(_2c.nodeType==1)&&(_2c.nodeName=="P"||dojo.style(_2c,"display")!="block")){ -var _2d=p.parentNode.insertBefore(this.document.createElement("p"),p); -_2d.innerHTML=_1b?"":" "; -} -_25(p); -},this.editor); -_1c(_1a); -return _1a; -},singleLinePsToRegularPs:function(_2e){ -function _2f(_30){ -var ps=_30.getElementsByTagName("p"); -var _31=[]; -for(var i=0;i<ps.length;i++){ -var p=ps[i]; -var _32=false; -for(var k=0;k<_31.length;k++){ -if(_31[k]===p.parentNode){ -_32=true; -break; -} -} -if(!_32){ -_31.push(p.parentNode); -} -} -return _31; -}; -function _33(_34){ -return (!_34.childNodes.length||_34.innerHTML==" "); -}; -var _35=_2f(_2e); -for(var i=0;i<_35.length;i++){ -var _36=_35[i]; -var _37=null; -var _38=_36.firstChild; -var _39=null; -while(_38){ -if(_38.nodeType!=1||_38.tagName!="P"||(_38.getAttributeNode("style")||{}).specified){ -_37=null; -}else{ -if(_33(_38)){ -_39=_38; -_37=null; -}else{ -if(_37==null){ -_37=_38; -}else{ -if((!_37.lastChild||_37.lastChild.nodeName!="BR")&&(_38.firstChild)&&(_38.firstChild.nodeName!="BR")){ -_37.appendChild(this.editor.document.createElement("br")); -} -while(_38.firstChild){ -_37.appendChild(_38.firstChild); -} -_39=_38; -} -} -} -_38=_38.nextSibling; -if(_39){ -dojo.destroy(_39); -_39=null; -} -} -} -return _2e; -}}); + } |