]> git.wh0rd.org - tt-rss.git/blob - lib/dijit/_editor/selection.js.uncompressed.js
modify dojo rebuild script to remove uncompressed files
[tt-rss.git] / lib / dijit / _editor / selection.js.uncompressed.js
1 define("dijit/_editor/selection", [
2 "dojo/dom", // dom.byId
3 "dojo/_base/lang",
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){
8
9 // module:
10 // dijit/_editor/selection
11 // summary:
12 // Text selection API
13
14 // FIXME:
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.
18
19 var selection = {
20 getType: function(){
21 // summary:
22 // Get the selection type (like win.doc.select.type in IE).
23 if(win.doc.getSelection){
24 // W3C path
25 var stype = "text";
26
27 // Check if the actual selection is a CONTROL (IMG, TABLE, HR, etc...).
28 var oSel;
29 try{
30 oSel = win.global.getSelection();
31 }catch(e){ /*squelch*/ }
32
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*/)
38 ){
39 stype = "control";
40 }
41 }
42 return stype; //String
43 }else{
44 // IE6-8
45 return win.doc.selection.type.toLowerCase();
46 }
47 },
48
49 getSelectedText: function(){
50 // summary:
51 // Return the text (no html tags) included in the current selection or null if no text is selected
52 if(win.doc.getSelection){
53 // W3C path
54 var selection = win.global.getSelection();
55 return selection ? selection.toString() : ""; //String
56 }else{
57 // IE6-8
58 if(dijit._editor.selection.getType() == 'control'){
59 return null;
60 }
61 return win.doc.selection.createRange().text;
62 }
63 },
64
65 getSelectedHtml: function(){
66 // summary:
67 // Return the html text of the current selection or null if unavailable
68 if(win.doc.getSelection){
69 // W3C path
70 var selection = win.global.getSelection();
71 if(selection && selection.rangeCount){
72 var i;
73 var html = "";
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;
80 }
81 return html; //String
82 }
83 return null;
84 }else{
85 // IE6-8
86 if(dijit._editor.selection.getType() == 'control'){
87 return null;
88 }
89 return win.doc.selection.createRange().htmlText;
90 }
91 },
92
93 getSelectedElement: function(){
94 // summary:
95 // Retrieves the selected element (if any), just in the case that
96 // a single element (object like and image or a table) is
97 // selected.
98 if(dijit._editor.selection.getType() == "control"){
99 if(win.doc.getSelection){
100 // W3C path
101 var selection = win.global.getSelection();
102 return selection.anchorNode.childNodes[ selection.anchorOffset ];
103 }else{
104 // IE6-8
105 var range = win.doc.selection.createRange();
106 if(range && range.item){
107 return win.doc.selection.createRange().item(0);
108 }
109 }
110 }
111 return null;
112 },
113
114 getParentElement: function(){
115 // summary:
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; }
120 }else{
121 if(win.doc.getSelection){
122 var selection = win.global.getSelection();
123 if(selection){
124 var node = selection.anchorNode;
125 while(node && (node.nodeType != 1)){ // not an element
126 node = node.parentNode;
127 }
128 return node;
129 }
130 }else{
131 var r = win.doc.selection.createRange();
132 r.collapse(true);
133 return r.parentElement();
134 }
135 }
136 return null;
137 },
138
139 hasAncestorElement: function(/*String*/ tagName /* ... */){
140 // summary:
141 // Check whether current selection has a parent element which is
142 // of type tagName (or one of the other specified tagName)
143 // tagName: String
144 // The tag name to determine if it has an ancestor of.
145 return this.getAncestorElement.apply(this, arguments) != null; //Boolean
146 },
147
148 getAncestorElement: function(/*String*/ tagName /* ... */){
149 // summary:
150 // Return the parent element of the current selection which is of
151 // type tagName (or one of the other specified tagName)
152 // tagName: String
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
156 },
157
158 isTag: function(/*DomNode*/ node, /*String[]*/ tags){
159 // summary:
160 // Function to determine if a node is one of an array of tags.
161 // node:
162 // The node to inspect.
163 // tags:
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();
169 if(_nlc == _tlc){
170 return _tlc; // String
171 }
172 }
173 }
174 return "";
175 },
176
177 getParentOfType: function(/*DomNode*/ node, /*String[]*/ tags){
178 // summary:
179 // Function to locate a parent node that matches one of a set of tags
180 // node:
181 // The node to inspect.
182 // tags:
183 // An array of tag name strings to check to see if the node matches.
184 while(node){
185 if(this.isTag(node, tags).length){
186 return node; // DOMNode
187 }
188 node = node.parentNode;
189 }
190 return null;
191 },
192
193 collapse: function(/*Boolean*/ beginning){
194 // summary:
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){
199 // W3C path
200 var selection = win.global.getSelection();
201 if(selection.removeAllRanges){ // Mozilla
202 if(beginning){
203 selection.collapseToStart();
204 }else{
205 selection.collapseToEnd();
206 }
207 }else{ // Safari
208 // pulled from WebCore/ecma/kjs_window.cpp, line 2536
209 selection.collapse(beginning);
210 }
211 }else{
212 // IE6-8
213 var range = win.doc.selection.createRange();
214 range.collapse(beginning);
215 range.select();
216 }
217 },
218
219 remove: function(){
220 // summary:
221 // Function to delete the currently selected content from the document.
222 var sel = win.doc.selection;
223 if(win.doc.getSelection){
224 // W3C path
225 sel = win.global.getSelection();
226 sel.deleteFromDocument();
227 return sel; //Selection
228 }else{
229 // IE6-8
230 if(sel.type.toLowerCase() != "none"){
231 sel.clear();
232 }
233 return sel; //Selection
234 }
235 },
236
237 selectElementChildren: function(/*DomNode*/ element, /*Boolean?*/ nochangefocus){
238 // summary:
239 // clear previous selection and select the content of the node
240 // (excluding the node itself)
241 // element: DOMNode
242 // The element you wish to select the children content of.
243 // nochangefocus: Boolean
244 // Indicates if the focus should change or not.
245 var doc = win.doc;
246 var range;
247 element = dom.byId(element);
248 if(win.doc.getSelection){
249 // W3C
250 var selection = win.global.getSelection();
251 if(has("opera")){
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);
257 }else{
258 range = doc.createRange();
259 }
260 range.setStart(element, 0);
261 range.setEnd(element,(element.nodeType == 3) ? element.length : element.childNodes.length);
262 selection.addRange(range);
263 }else{
264 selection.selectAllChildren(element);
265 }
266 }else{
267 // IE6-8
268 range = element.ownerDocument.body.createTextRange();
269 range.moveToElementText(element);
270 if(!nochangefocus){
271 try{
272 range.select(); // IE throws an exception here if the widget is hidden. See #5439
273 }catch(e){ /* squelch */}
274 }
275 }
276 },
277
278 selectElement: function(/*DomNode*/ element, /*Boolean?*/ nochangefocus){
279 // summary:
280 // clear previous selection and select element (including all its children)
281 // element: DOMNode
282 // The element to select.
283 // nochangefocus: Boolean
284 // Boolean indicating if the focus should be changed. IE only.
285 var range;
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){
290 // W3C path
291 var selection = global.getSelection();
292 range = doc.createRange();
293 if(selection.removeAllRanges){ // Mozilla
294 // FIXME: does this work on Safari?
295 if(has("opera")){
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);
300 }
301 }
302 range.selectNode(element);
303 selection.removeAllRanges();
304 selection.addRange(range);
305 }
306 }else{
307 // IE6-8
308 try{
309 var tg = element.tagName ? element.tagName.toLowerCase() : "";
310 if(tg === "img" || tg === "table"){
311 range = win.body(doc).createControlRange();
312 }else{
313 range = win.body(doc).createRange();
314 }
315 range.addElement(element);
316 if(!nochangefocus){
317 range.select();
318 }
319 }catch(e){
320 this.selectElementChildren(element, nochangefocus);
321 }
322 }
323 },
324
325 inSelection: function(node){
326 // summary:
327 // This function determines if 'node' is
328 // in the current selection.
329 // tags:
330 // public
331 if(node){
332 var newRange;
333 var doc = win.doc;
334 var range;
335
336 if(win.doc.getSelection){
337 // WC3
338 var sel = win.global.getSelection();
339 if(sel && sel.rangeCount > 0){
340 range = sel.getRangeAt(0);
341 }
342 if(range && range.compareBoundaryPoints && doc.createRange){
343 try{
344 newRange = doc.createRange();
345 newRange.setStart(node, 0);
346 if(range.compareBoundaryPoints(range.START_TO_END, newRange) === 1){
347 return true;
348 }
349 }catch(e){ /* squelch */}
350 }
351 }else{
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();
356 try{
357 newRange = node.ownerDocument.body.createControlRange();
358 if(newRange){
359 newRange.addElement(node);
360 }
361 }catch(e1){
362 try{
363 newRange = node.ownerDocument.body.createTextRange();
364 newRange.moveToElementText(node);
365 }catch(e2){/* squelch */}
366 }
367 if(range && newRange){
368 // We can finally compare similar to W3C
369 if(range.compareEndPoints("EndToStart", newRange) === 1){
370 return true;
371 }
372 }
373 }
374 }
375 return false; // Boolean
376 }
377 };
378
379
380 lang.setObject("dijit._editor.selection", selection);
381
382 return selection;
383 });