summaryrefslogtreecommitdiff
path: root/lib/dijit/_editor/plugins/EnterKeyHandling.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dijit/_editor/plugins/EnterKeyHandling.js')
-rw-r--r--lib/dijit/_editor/plugins/EnterKeyHandling.js1007
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|&nbsp;|\xA0|<span\b[^>]*\bclass=['"]Apple-style-span['"][^>]*>(\s|&nbsp;|\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="&nbsp;";
-}
-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>&nbsp;</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: '&nbsp;',
+
+ // 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|&nbsp;|\xA0|<span\b[^>]*\bclass=['"]Apple-style-span['"][^>]*>(\s|&nbsp;|\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?"":"&nbsp;";
-}
-_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=="&nbsp;");
-};
-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;
-}});
+
}