]>
git.wh0rd.org - tt-rss.git/blob - lib/dijit/_editor/selection.js.uncompressed.js
1 define("dijit/_editor/selection", [
2 "dojo/dom", // dom.byId
4 "dojo/sniff", // has("ie") has("opera")
5 "dojo/_base/window", // win.body win.doc win.doc.createElement win.doc.selection win.doc.selection.createRange win.doc.selection.type.toLowerCase win.global win.global.getSelection
6 "../main" // for exporting symbols to dijit._editor.selection (TODO: remove in 2.0)
7 ], function(dom
, lang
, has
, win
, dijit
){
10 // dijit/_editor/selection
15 // all of these methods branch internally for IE. This is probably
16 // sub-optimal in terms of runtime performance. We should investigate the
17 // size difference for differentiating at definition time.
22 // Get the selection type (like win.doc.select.type in IE).
23 if(win
.doc
.getSelection
){
27 // Check if the actual selection is a CONTROL (IMG, TABLE, HR, etc...).
30 oSel
= win
.global
.getSelection();
31 }catch(e
){ /*squelch*/ }
33 if(oSel
&& oSel
.rangeCount
== 1){
34 var oRange
= oSel
.getRangeAt(0);
35 if( (oRange
.startContainer
== oRange
.endContainer
) &&
36 ((oRange
.endOffset
- oRange
.startOffset
) == 1) &&
37 (oRange
.startContainer
.nodeType
!= 3 /* text node*/)
42 return stype
; //String
45 return win
.doc
.selection
.type
.toLowerCase();
49 getSelectedText: function(){
51 // Return the text (no html tags) included in the current selection or null if no text is selected
52 if(win
.doc
.getSelection
){
54 var selection
= win
.global
.getSelection();
55 return selection
? selection
.toString() : ""; //String
58 if(dijit
._editor
.selection
.getType() == 'control'){
61 return win
.doc
.selection
.createRange().text
;
65 getSelectedHtml: function(){
67 // Return the html text of the current selection or null if unavailable
68 if(win
.doc
.getSelection
){
70 var selection
= win
.global
.getSelection();
71 if(selection
&& selection
.rangeCount
){
74 for(i
= 0; i
< selection
.rangeCount
; i
++){
75 //Handle selections spanning ranges, such as Opera
76 var frag
= selection
.getRangeAt(i
).cloneContents();
77 var div
= win
.doc
.createElement("div");
78 div
.appendChild(frag
);
79 html
+= div
.innerHTML
;
86 if(dijit
._editor
.selection
.getType() == 'control'){
89 return win
.doc
.selection
.createRange().htmlText
;
93 getSelectedElement: function(){
95 // Retrieves the selected element (if any), just in the case that
96 // a single element (object like and image or a table) is
98 if(dijit
._editor
.selection
.getType() == "control"){
99 if(win
.doc
.getSelection
){
101 var selection
= win
.global
.getSelection();
102 return selection
.anchorNode
.childNodes
[ selection
.anchorOffset
];
105 var range
= win
.doc
.selection
.createRange();
106 if(range
&& range
.item
){
107 return win
.doc
.selection
.createRange().item(0);
114 getParentElement: function(){
116 // Get the parent element of the current selection
117 if(dijit
._editor
.selection
.getType() == "control"){
118 var p
= this.getSelectedElement();
119 if(p
){ return p
.parentNode
; }
121 if(win
.doc
.getSelection
){
122 var selection
= win
.global
.getSelection();
124 var node
= selection
.anchorNode
;
125 while(node
&& (node
.nodeType
!= 1)){ // not an element
126 node
= node
.parentNode
;
131 var r
= win
.doc
.selection
.createRange();
133 return r
.parentElement();
139 hasAncestorElement: function(/*String*/ tagName
/* ... */){
141 // Check whether current selection has a parent element which is
142 // of type tagName (or one of the other specified tagName)
144 // The tag name to determine if it has an ancestor of.
145 return this.getAncestorElement
.apply(this, arguments
) != null; //Boolean
148 getAncestorElement: function(/*String*/ tagName
/* ... */){
150 // Return the parent element of the current selection which is of
151 // type tagName (or one of the other specified tagName)
153 // The tag name to determine if it has an ancestor of.
154 var node
= this.getSelectedElement() || this.getParentElement();
155 return this.getParentOfType(node
, arguments
); //DOMNode
158 isTag: function(/*DomNode*/ node
, /*String[]*/ tags
){
160 // Function to determine if a node is one of an array of tags.
162 // The node to inspect.
164 // An array of tag name strings to check to see if the node matches.
165 if(node
&& node
.tagName
){
166 var _nlc
= node
.tagName
.toLowerCase();
167 for(var i
=0; i
<tags
.length
; i
++){
168 var _tlc
= String(tags
[i
]).toLowerCase();
170 return _tlc
; // String
177 getParentOfType: function(/*DomNode*/ node
, /*String[]*/ tags
){
179 // Function to locate a parent node that matches one of a set of tags
181 // The node to inspect.
183 // An array of tag name strings to check to see if the node matches.
185 if(this.isTag(node
, tags
).length
){
186 return node
; // DOMNode
188 node
= node
.parentNode
;
193 collapse: function(/*Boolean*/ beginning
){
195 // Function to collapse (clear), the current selection
196 // beginning: Boolean
197 // Indicates whether to collapse the cursor to the beginning of the selection or end.
198 if(win
.doc
.getSelection
){
200 var selection
= win
.global
.getSelection();
201 if(selection
.removeAllRanges
){ // Mozilla
203 selection
.collapseToStart();
205 selection
.collapseToEnd();
208 // pulled from WebCore/ecma/kjs_window.cpp, line 2536
209 selection
.collapse(beginning
);
213 var range
= win
.doc
.selection
.createRange();
214 range
.collapse(beginning
);
221 // Function to delete the currently selected content from the document.
222 var sel
= win
.doc
.selection
;
223 if(win
.doc
.getSelection
){
225 sel
= win
.global
.getSelection();
226 sel
.deleteFromDocument();
227 return sel
; //Selection
230 if(sel
.type
.toLowerCase() != "none"){
233 return sel
; //Selection
237 selectElementChildren: function(/*DomNode*/ element
, /*Boolean?*/ nochangefocus
){
239 // clear previous selection and select the content of the node
240 // (excluding the node itself)
242 // The element you wish to select the children content of.
243 // nochangefocus: Boolean
244 // Indicates if the focus should change or not.
247 element
= dom
.byId(element
);
248 if(win
.doc
.getSelection
){
250 var selection
= win
.global
.getSelection();
252 //Opera's selectAllChildren doesn't seem to work right
253 //against <body> nodes and possibly others ... so
254 //we use the W3C range API
255 if(selection
.rangeCount
){
256 range
= selection
.getRangeAt(0);
258 range
= doc
.createRange();
260 range
.setStart(element
, 0);
261 range
.setEnd(element
,(element
.nodeType
== 3) ? element
.length
: element
.childNodes
.length
);
262 selection
.addRange(range
);
264 selection
.selectAllChildren(element
);
268 range
= element
.ownerDocument
.body
.createTextRange();
269 range
.moveToElementText(element
);
272 range
.select(); // IE throws an exception here if the widget is hidden. See #5439
273 }catch(e
){ /* squelch */}
278 selectElement: function(/*DomNode*/ element
, /*Boolean?*/ nochangefocus
){
280 // clear previous selection and select element (including all its children)
282 // The element to select.
283 // nochangefocus: Boolean
284 // Boolean indicating if the focus should be changed. IE only.
286 element
= dom
.byId(element
); // TODO: remove for 2.0 or sooner, spec listed above doesn't allow for string
287 var doc
= element
.ownerDocument
;
288 var global
= win
.global
; // TODO: use winUtils.get(doc)?
289 if(doc
.getSelection
){
291 var selection
= global
.getSelection();
292 range
= doc
.createRange();
293 if(selection
.removeAllRanges
){ // Mozilla
294 // FIXME: does this work on Safari?
296 //Opera works if you use the current range on
297 //the selection if present.
298 if(selection
.getRangeAt(0)){
299 range
= selection
.getRangeAt(0);
302 range
.selectNode(element
);
303 selection
.removeAllRanges();
304 selection
.addRange(range
);
309 var tg
= element
.tagName
? element
.tagName
.toLowerCase() : "";
310 if(tg
=== "img" || tg
=== "table"){
311 range
= win
.body(doc
).createControlRange();
313 range
= win
.body(doc
).createRange();
315 range
.addElement(element
);
320 this.selectElementChildren(element
, nochangefocus
);
325 inSelection: function(node
){
327 // This function determines if 'node' is
328 // in the current selection.
336 if(win
.doc
.getSelection
){
338 var sel
= win
.global
.getSelection();
339 if(sel
&& sel
.rangeCount
> 0){
340 range
= sel
.getRangeAt(0);
342 if(range
&& range
.compareBoundaryPoints
&& doc
.createRange
){
344 newRange
= doc
.createRange();
345 newRange
.setStart(node
, 0);
346 if(range
.compareBoundaryPoints(range
.START_TO_END
, newRange
) === 1){
349 }catch(e
){ /* squelch */}
352 // IE6-8, so we can't use the range object as the pseudo
353 // range doesn't implement the boundary checking, we have to
354 // use IE specific crud.
355 range
= doc
.selection
.createRange();
357 newRange
= node
.ownerDocument
.body
.createControlRange();
359 newRange
.addElement(node
);
363 newRange
= node
.ownerDocument
.body
.createTextRange();
364 newRange
.moveToElementText(node
);
365 }catch(e2
){/* squelch */}
367 if(range
&& newRange
){
368 // We can finally compare similar to W3C
369 if(range
.compareEndPoints("EndToStart", newRange
) === 1){
375 return false; // Boolean
380 lang
.setObject("dijit._editor.selection", selection
);