]> git.wh0rd.org Git - tt-rss.git/blob - lib/dijit/_editor/selection.js.uncompressed.js
upgrade dojo to 1.8.3 (refs #570)
[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 });