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/selection.js | |
parent | 870a70e109ac9e80a88047044530de53d0404ec7 (diff) |
upgrade Dojo to 1.6.1
Diffstat (limited to 'lib/dijit/_editor/selection.js')
-rw-r--r-- | lib/dijit/_editor/selection.js | 620 |
1 files changed, 361 insertions, 259 deletions
diff --git a/lib/dijit/_editor/selection.js b/lib/dijit/_editor/selection.js index 3c99c0610..6fed82770 100644 --- a/lib/dijit/_editor/selection.js +++ b/lib/dijit/_editor/selection.js @@ -1,267 +1,369 @@ /* - 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.selection"]){ -dojo._hasResource["dijit._editor.selection"]=true; +if(!dojo._hasResource["dijit._editor.selection"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._editor.selection"] = true; dojo.provide("dijit._editor.selection"); -dojo.mixin(dijit._editor.selection,{getType:function(){ -if(dojo.isIE){ -return dojo.doc.selection.type.toLowerCase(); -}else{ -var _1="text"; -var _2; -try{ -_2=dojo.global.getSelection(); -} -catch(e){ -} -if(_2&&_2.rangeCount==1){ -var _3=_2.getRangeAt(0); -if((_3.startContainer==_3.endContainer)&&((_3.endOffset-_3.startOffset)==1)&&(_3.startContainer.nodeType!=3)){ -_1="control"; -} -} -return _1; -} -},getSelectedText:function(){ -if(dojo.isIE){ -if(dijit._editor.selection.getType()=="control"){ -return null; -} -return dojo.doc.selection.createRange().text; -}else{ -var _4=dojo.global.getSelection(); -if(_4){ -return _4.toString(); -} -} -return ""; -},getSelectedHtml:function(){ -if(dojo.isIE){ -if(dijit._editor.selection.getType()=="control"){ -return null; -} -return dojo.doc.selection.createRange().htmlText; -}else{ -var _5=dojo.global.getSelection(); -if(_5&&_5.rangeCount){ -var i; -var _6=""; -for(i=0;i<_5.rangeCount;i++){ -var _7=_5.getRangeAt(i).cloneContents(); -var _8=dojo.doc.createElement("div"); -_8.appendChild(_7); -_6+=_8.innerHTML; -} -return _6; -} -return null; -} -},getSelectedElement:function(){ -if(dijit._editor.selection.getType()=="control"){ -if(dojo.isIE){ -var _9=dojo.doc.selection.createRange(); -if(_9&&_9.item){ -return dojo.doc.selection.createRange().item(0); -} -}else{ -var _a=dojo.global.getSelection(); -return _a.anchorNode.childNodes[_a.anchorOffset]; -} -} -return null; -},getParentElement:function(){ -if(dijit._editor.selection.getType()=="control"){ -var p=this.getSelectedElement(); -if(p){ -return p.parentNode; -} -}else{ -if(dojo.isIE){ -var r=dojo.doc.selection.createRange(); -r.collapse(true); -return r.parentElement(); -}else{ -var _b=dojo.global.getSelection(); -if(_b){ -var _c=_b.anchorNode; -while(_c&&(_c.nodeType!=1)){ -_c=_c.parentNode; -} -return _c; -} -} -} -return null; -},hasAncestorElement:function(_d){ -return this.getAncestorElement.apply(this,arguments)!=null; -},getAncestorElement:function(_e){ -var _f=this.getSelectedElement()||this.getParentElement(); -return this.getParentOfType(_f,arguments); -},isTag:function(_10,_11){ -if(_10&&_10.tagName){ -var _12=_10.tagName.toLowerCase(); -for(var i=0;i<_11.length;i++){ -var _13=String(_11[i]).toLowerCase(); -if(_12==_13){ -return _13; -} -} -} -return ""; -},getParentOfType:function(_14,_15){ -while(_14){ -if(this.isTag(_14,_15).length){ -return _14; -} -_14=_14.parentNode; -} -return null; -},collapse:function(_16){ -if(window.getSelection){ -var _17=dojo.global.getSelection(); -if(_17.removeAllRanges){ -if(_16){ -_17.collapseToStart(); -}else{ -_17.collapseToEnd(); -} -}else{ -_17.collapse(_16); -} -}else{ -if(dojo.isIE){ -var _18=dojo.doc.selection.createRange(); -_18.collapse(_16); -_18.select(); -} -} -},remove:function(){ -var sel=dojo.doc.selection; -if(dojo.isIE){ -if(sel.type.toLowerCase()!="none"){ -sel.clear(); -} -return sel; -}else{ -sel=dojo.global.getSelection(); -sel.deleteFromDocument(); -return sel; -} -},selectElementChildren:function(_19,_1a){ -var win=dojo.global; -var doc=dojo.doc; -var _1b; -_19=dojo.byId(_19); -if(doc.selection&&dojo.isIE&&dojo.body().createTextRange){ -_1b=_19.ownerDocument.body.createTextRange(); -_1b.moveToElementText(_19); -if(!_1a){ -try{ -_1b.select(); -} -catch(e){ -} -} -}else{ -if(win.getSelection){ -var _1c=dojo.global.getSelection(); -if(dojo.isOpera){ -if(_1c.rangeCount){ -_1b=_1c.getRangeAt(0); -}else{ -_1b=doc.createRange(); -} -_1b.setStart(_19,0); -_1b.setEnd(_19,(_19.nodeType==3)?_19.length:_19.childNodes.length); -_1c.addRange(_1b); -}else{ -_1c.selectAllChildren(_19); -} -} -} -},selectElement:function(_1d,_1e){ -var _1f; -var doc=dojo.doc; -var win=dojo.global; -_1d=dojo.byId(_1d); -if(dojo.isIE&&dojo.body().createTextRange){ -try{ -_1f=dojo.body().createControlRange(); -_1f.addElement(_1d); -if(!_1e){ -_1f.select(); -} -} -catch(e){ -this.selectElementChildren(_1d,_1e); -} -}else{ -if(dojo.global.getSelection){ -var _20=win.getSelection(); -_1f=doc.createRange(); -if(_20.removeAllRanges){ -if(dojo.isOpera){ -if(_20.getRangeAt(0)){ -_1f=_20.getRangeAt(0); -} -} -_1f.selectNode(_1d); -_20.removeAllRanges(); -_20.addRange(_1f); -} -} -} -},inSelection:function(_21){ -if(_21){ -var _22; -var doc=dojo.doc; -var _23; -if(dojo.global.getSelection){ -var sel=dojo.global.getSelection(); -if(sel&&sel.rangeCount>0){ -_23=sel.getRangeAt(0); -} -if(_23&&_23.compareBoundaryPoints&&doc.createRange){ -try{ -_22=doc.createRange(); -_22.setStart(_21,0); -if(_23.compareBoundaryPoints(_23.START_TO_END,_22)===1){ -return true; -} -} -catch(e){ -} -} -}else{ -if(doc.selection){ -_23=doc.selection.createRange(); -try{ -_22=_21.ownerDocument.body.createControlRange(); -if(_22){ -_22.addElement(_21); -} -} -catch(e1){ -try{ -_22=_21.ownerDocument.body.createTextRange(); -_22.moveToElementText(_21); -} -catch(e2){ -} -} -if(_23&&_22){ -if(_23.compareEndPoints("EndToStart",_22)===1){ -return true; -} -} -} -} -} -return false; -}}); + + +dojo.getObject("_editor.selection", true, dijit); + +// FIXME: +// all of these methods branch internally for IE. This is probably +// sub-optimal in terms of runtime performance. We should investigate the +// size difference for differentiating at definition time. + +dojo.mixin(dijit._editor.selection, { + getType: function(){ + // summary: + // Get the selection type (like dojo.doc.select.type in IE). + if(dojo.isIE < 9){ + return dojo.doc.selection.type.toLowerCase(); + }else{ + var stype = "text"; + + // Check if the actual selection is a CONTROL (IMG, TABLE, HR, etc...). + var oSel; + try{ + oSel = dojo.global.getSelection(); + }catch(e){ /*squelch*/ } + + if(oSel && oSel.rangeCount == 1){ + var oRange = oSel.getRangeAt(0); + if( (oRange.startContainer == oRange.endContainer) && + ((oRange.endOffset - oRange.startOffset) == 1) && + (oRange.startContainer.nodeType != 3 /* text node*/) + ){ + stype = "control"; + } + } + return stype; //String + } + }, + + getSelectedText: function(){ + // summary: + // Return the text (no html tags) included in the current selection or null if no text is selected + if(dojo.isIE < 9){ + if(dijit._editor.selection.getType() == 'control'){ + return null; + } + return dojo.doc.selection.createRange().text; + }else{ + var selection = dojo.global.getSelection(); + if(selection){ + return selection.toString(); //String + } + } + return ''; + }, + + getSelectedHtml: function(){ + // summary: + // Return the html text of the current selection or null if unavailable + if(dojo.isIE < 9){ + if(dijit._editor.selection.getType() == 'control'){ + return null; + } + return dojo.doc.selection.createRange().htmlText; + }else{ + var selection = dojo.global.getSelection(); + if(selection && selection.rangeCount){ + var i; + var html = ""; + for(i = 0; i < selection.rangeCount; i++){ + //Handle selections spanning ranges, such as Opera + var frag = selection.getRangeAt(i).cloneContents(); + var div = dojo.doc.createElement("div"); + div.appendChild(frag); + html += div.innerHTML; + } + return html; //String + } + return null; + } + }, + + getSelectedElement: function(){ + // summary: + // Retrieves the selected element (if any), just in the case that + // a single element (object like and image or a table) is + // selected. + if(dijit._editor.selection.getType() == "control"){ + if(dojo.isIE < 9){ + var range = dojo.doc.selection.createRange(); + if(range && range.item){ + return dojo.doc.selection.createRange().item(0); + } + }else{ + var selection = dojo.global.getSelection(); + return selection.anchorNode.childNodes[ selection.anchorOffset ]; + } + } + return null; + }, + + getParentElement: function(){ + // summary: + // Get the parent element of the current selection + if(dijit._editor.selection.getType() == "control"){ + var p = this.getSelectedElement(); + if(p){ return p.parentNode; } + }else{ + if(dojo.isIE < 9){ + var r = dojo.doc.selection.createRange(); + r.collapse(true); + return r.parentElement(); + }else{ + var selection = dojo.global.getSelection(); + if(selection){ + var node = selection.anchorNode; + while(node && (node.nodeType != 1)){ // not an element + node = node.parentNode; + } + return node; + } + } + } + return null; + }, + + hasAncestorElement: function(/*String*/tagName /* ... */){ + // summary: + // Check whether current selection has a parent element which is + // of type tagName (or one of the other specified tagName) + // tagName: String + // The tag name to determine if it has an ancestor of. + return this.getAncestorElement.apply(this, arguments) != null; //Boolean + }, + + getAncestorElement: function(/*String*/tagName /* ... */){ + // summary: + // Return the parent element of the current selection which is of + // type tagName (or one of the other specified tagName) + // tagName: String + // The tag name to determine if it has an ancestor of. + var node = this.getSelectedElement() || this.getParentElement(); + return this.getParentOfType(node, arguments); //DOMNode + }, + + isTag: function(/*DomNode*/ node, /*String[]*/ tags){ + // summary: + // Function to determine if a node is one of an array of tags. + // node: + // The node to inspect. + // tags: + // An array of tag name strings to check to see if the node matches. + if(node && node.tagName){ + var _nlc = node.tagName.toLowerCase(); + for(var i=0; i<tags.length; i++){ + var _tlc = String(tags[i]).toLowerCase(); + if(_nlc == _tlc){ + return _tlc; // String + } + } + } + return ""; + }, + + getParentOfType: function(/*DomNode*/ node, /*String[]*/ tags){ + // summary: + // Function to locate a parent node that matches one of a set of tags + // node: + // The node to inspect. + // tags: + // An array of tag name strings to check to see if the node matches. + while(node){ + if(this.isTag(node, tags).length){ + return node; // DOMNode + } + node = node.parentNode; + } + return null; + }, + + collapse: function(/*Boolean*/beginning){ + // summary: + // Function to collapse (clear), the current selection + // beginning: Boolean + // Boolean to indicate whether to collapse the cursor to the beginning of the selection or end. + if(window.getSelection){ + var selection = dojo.global.getSelection(); + if(selection.removeAllRanges){ // Mozilla + if(beginning){ + selection.collapseToStart(); + }else{ + selection.collapseToEnd(); + } + }else{ // Safari + // pulled from WebCore/ecma/kjs_window.cpp, line 2536 + selection.collapse(beginning); + } + }else if(dojo.isIE){ // IE + var range = dojo.doc.selection.createRange(); + range.collapse(beginning); + range.select(); + } + }, + + remove: function(){ + // summary: + // Function to delete the currently selected content from the document. + var sel = dojo.doc.selection; + if(dojo.isIE < 9){ + if(sel.type.toLowerCase() != "none"){ + sel.clear(); + } + return sel; //Selection + }else{ + sel = dojo.global.getSelection(); + sel.deleteFromDocument(); + return sel; //Selection + } + }, + + selectElementChildren: function(/*DomNode*/element,/*Boolean?*/nochangefocus){ + // summary: + // clear previous selection and select the content of the node + // (excluding the node itself) + // element: DOMNode + // The element you wish to select the children content of. + // nochangefocus: Boolean + // Boolean to indicate if the foxus should change or not. + var win = dojo.global; + var doc = dojo.doc; + var range; + element = dojo.byId(element); + if(doc.selection && dojo.isIE < 9 && dojo.body().createTextRange){ // IE + range = element.ownerDocument.body.createTextRange(); + range.moveToElementText(element); + if(!nochangefocus){ + try{ + range.select(); // IE throws an exception here if the widget is hidden. See #5439 + }catch(e){ /* squelch */} + } + }else if(win.getSelection){ + var selection = dojo.global.getSelection(); + if(dojo.isOpera){ + //Opera's selectAllChildren doesn't seem to work right + //against <body> nodes and possibly others ... so + //we use the W3C range API + if(selection.rangeCount){ + range = selection.getRangeAt(0); + }else{ + range = doc.createRange(); + } + range.setStart(element, 0); + range.setEnd(element,(element.nodeType == 3)?element.length:element.childNodes.length); + selection.addRange(range); + }else{ + selection.selectAllChildren(element); + } + } + }, + + selectElement: function(/*DomNode*/element,/*Boolean?*/nochangefocus){ + // summary: + // clear previous selection and select element (including all its children) + // element: DOMNode + // The element to select. + // nochangefocus: Boolean + // Boolean indicating if the focus should be changed. IE only. + var range; + var doc = dojo.doc; + var win = dojo.global; + element = dojo.byId(element); + if(dojo.isIE < 9 && dojo.body().createTextRange){ + try{ + var tg = element.tagName ? element.tagName.toLowerCase() : ""; + if(tg === "img" || tg === "table"){ + range = dojo.body().createControlRange(); + }else{ + range = dojo.body().createRange(); + } + range.addElement(element); + if(!nochangefocus){ + range.select(); + } + }catch(e){ + this.selectElementChildren(element,nochangefocus); + } + }else if(dojo.global.getSelection){ + var selection = win.getSelection(); + range = doc.createRange(); + if(selection.removeAllRanges){ // Mozilla + // FIXME: does this work on Safari? + if(dojo.isOpera){ + //Opera works if you use the current range on + //the selection if present. + if(selection.getRangeAt(0)){ + range = selection.getRangeAt(0); + } + } + range.selectNode(element); + selection.removeAllRanges(); + selection.addRange(range); + } + } + }, + + inSelection: function(node){ + // summary: + // This function determines if 'node' is + // in the current selection. + // tags: + // public + if(node){ + var newRange; + var doc = dojo.doc; + var range; + + if(dojo.global.getSelection){ + //WC3 + var sel = dojo.global.getSelection(); + if(sel && sel.rangeCount > 0){ + range = sel.getRangeAt(0); + } + if(range && range.compareBoundaryPoints && doc.createRange){ + try{ + newRange = doc.createRange(); + newRange.setStart(node, 0); + if(range.compareBoundaryPoints(range.START_TO_END, newRange) === 1){ + return true; + } + }catch(e){ /* squelch */} + } + }else if(doc.selection){ + // Probably IE, so we can't use the range object as the pseudo + // range doesn't implement the boundry checking, we have to + // use IE specific crud. + range = doc.selection.createRange(); + try{ + newRange = node.ownerDocument.body.createControlRange(); + if(newRange){ + newRange.addElement(node); + } + }catch(e1){ + try{ + newRange = node.ownerDocument.body.createTextRange(); + newRange.moveToElementText(node); + }catch(e2){/* squelch */} + } + if(range && newRange){ + // We can finally compare similar to W3C + if(range.compareEndPoints("EndToStart", newRange) === 1){ + return true; + } + } + } + } + return false; // boolean + } + +}); + } |