247 lines
6.9 KiB
JavaScript
247 lines
6.9 KiB
JavaScript
|
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");
|
||
|
|
||
|
// 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.doc.selection){ //IE
|
||
|
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;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
getSelectedText: function(){
|
||
|
// summary:
|
||
|
// Return the text (no html tags) included in the current selection or null if no text is selected
|
||
|
if(dojo.doc.selection){ //IE
|
||
|
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();
|
||
|
}
|
||
|
}
|
||
|
return ''
|
||
|
},
|
||
|
|
||
|
getSelectedHtml: function(){
|
||
|
// summary:
|
||
|
// Return the html of the current selection or null if unavailable
|
||
|
if(dojo.doc.selection){ //IE
|
||
|
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 frag = selection.getRangeAt(0).cloneContents();
|
||
|
var div = dojo.doc.createElement("div");
|
||
|
div.appendChild(frag);
|
||
|
return div.innerHTML;
|
||
|
}
|
||
|
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(this.getType() == "control"){
|
||
|
if(dojo.doc.selection){ //IE
|
||
|
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(this.getType() == "control"){
|
||
|
var p = this.getSelectedElement();
|
||
|
if(p){ return p.parentNode; }
|
||
|
}else{
|
||
|
if(dojo.doc.selection){ //IE
|
||
|
return dojo.doc.selection.createRange().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)
|
||
|
return this.getAncestorElement.apply(this, arguments) != null;
|
||
|
},
|
||
|
|
||
|
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)
|
||
|
|
||
|
var node = this.getSelectedElement() || this.getParentElement();
|
||
|
return this.getParentOfType(node, arguments);
|
||
|
},
|
||
|
|
||
|
isTag: function(/*DomNode*/node, /*Array*/tags){
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return "";
|
||
|
},
|
||
|
|
||
|
getParentOfType: function(/*DomNode*/node, /*Array*/tags){
|
||
|
while(node){
|
||
|
if(this.isTag(node, tags).length){
|
||
|
return node;
|
||
|
}
|
||
|
node = node.parentNode;
|
||
|
}
|
||
|
return null;
|
||
|
},
|
||
|
|
||
|
collapse: function(/*Boolean*/beginning) {
|
||
|
// summary: clear current selection
|
||
|
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.doc.selection){ // IE
|
||
|
var range = dojo.doc.selection.createRange();
|
||
|
range.collapse(beginning);
|
||
|
range.select();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
remove: function(){
|
||
|
// summary: delete current selection
|
||
|
var _s = dojo.doc.selection;
|
||
|
if(_s){ //IE
|
||
|
if(_s.type.toLowerCase() != "none"){
|
||
|
_s.clear();
|
||
|
}
|
||
|
return _s;
|
||
|
}else{
|
||
|
_s = dojo.global.getSelection();
|
||
|
_s.deleteFromDocument();
|
||
|
return _s;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
selectElementChildren: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
|
||
|
// summary:
|
||
|
// clear previous selection and select the content of the node
|
||
|
// (excluding the node itself)
|
||
|
var _window = dojo.global;
|
||
|
var _document = dojo.doc;
|
||
|
element = dojo.byId(element);
|
||
|
if(_document.selection && dojo.body().createTextRange){ // IE
|
||
|
var 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(_window.getSelection){
|
||
|
var selection = _window.getSelection();
|
||
|
if(selection.setBaseAndExtent){ // Safari
|
||
|
selection.setBaseAndExtent(element, 0, element, element.innerText.length - 1);
|
||
|
}else if(selection.selectAllChildren){ // Mozilla
|
||
|
selection.selectAllChildren(element);
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
selectElement: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
|
||
|
// summary:
|
||
|
// clear previous selection and select element (including all its children)
|
||
|
var range, _document = dojo.doc;
|
||
|
element = dojo.byId(element);
|
||
|
if(_document.selection && dojo.body().createTextRange){ // IE
|
||
|
try{
|
||
|
range = dojo.body().createControlRange();
|
||
|
range.addElement(element);
|
||
|
if(!nochangefocus){
|
||
|
range.select();
|
||
|
}
|
||
|
}catch(e){
|
||
|
this.selectElementChildren(element,nochangefocus);
|
||
|
}
|
||
|
}else if(dojo.global.getSelection){
|
||
|
var selection = dojo.global.getSelection();
|
||
|
// FIXME: does this work on Safari?
|
||
|
if(selection.removeAllRanges){ // Mozilla
|
||
|
range = _document.createRange();
|
||
|
range.selectNode(element);
|
||
|
selection.removeAllRanges();
|
||
|
selection.addRange(range);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
}
|