| author | Simon Descarpentries <sid@sopinspace.com> |
| Thu, 31 Oct 2013 11:49:30 +0100 | |
| changeset 558 | 5ba711a2bd06 |
| parent 556 | 69503659fe8f |
| child 600 | fda73ac53450 |
| permissions | -rw-r--r-- |
| 0 | 1 |
getWrapperAncestor = function(elt) { |
| 341 | 2 |
var parent = elt ; |
3 |
while (parent != null) { |
|
4 |
if (CY.DOM.hasClass(parent, 'c-s')) |
|
5 |
return parent ; |
|
6 |
parent = parent.parentNode ; |
|
7 |
} |
|
8 |
return null ; |
|
| 0 | 9 |
} |
10 |
||
11 |
hasWrapperAncestor = function(elt) { |
|
| 341 | 12 |
return (getWrapperAncestor(elt) != null) ; |
13 |
/* var parent = elt ; |
|
14 |
while (parent != null) { |
|
15 |
if (CY.DOM.hasClass(parent, 'c-s')) |
|
16 |
return true ; |
|
17 |
parent = parent.parentNode ; |
|
18 |
} |
|
19 |
return false ;*/ |
|
| 0 | 20 |
} |
21 |
||
22 |
// returns null or : |
|
23 |
// {'text' : textcontent, 'start': {'elt':startNode, 'nbChar':startOffset(==number of characters to selection start in the start node}, |
|
24 |
// 'end': ....} |
|
25 |
// the text attribute is informational having it empty doesn't mean selection is empty !! |
|
26 |
||
27 |
// when selection starts/ends in/on a non textual element (<hr/> for example) we very often have anchorNode/focusNode == body elt |
|
28 |
// TODO adapt this body case by considering offset ( cf. http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html) |
|
|
556
69503659fe8f
[c_selection.js] If safari_mobile, get current selection from a previously created global variable
Simon Descarpentries <sid@sopinspace.com>
parents:
532
diff
changeset
|
29 |
|
| 0 | 30 |
getSelectionInfo = function () { |
| 341 | 31 |
var startNode = null, endNode = null, startOffset = 0, endOffset = 0, text = '' ; |
32 |
|
|
33 |
if (window.getSelection) { // everything else than IE |
|
|
558
5ba711a2bd06
Add comments, fix missing compressed js
Simon Descarpentries <sid@sopinspace.com>
parents:
556
diff
changeset
|
34 |
// SID: if on safari_mobile get the previous meaningfull selection from a global variable set in text_view_comments.html |
|
556
69503659fe8f
[c_selection.js] If safari_mobile, get current selection from a previously created global variable
Simon Descarpentries <sid@sopinspace.com>
parents:
532
diff
changeset
|
35 |
var userSelection = safari_mobile ? storedSelection : window.getSelection (); |
| 0 | 36 |
|
| 341 | 37 |
if (userSelection.rangeCount > 0) { |
38 |
var range = userSelection.getRangeAt(0) ; |
|
39 |
text = range.toString() ; |
|
40 |
if (text != "") { |
|
41 |
|
|
42 |
// selection occured from right to left ? : |
|
43 |
var r1 = document.createRange() ;r1.setStart(userSelection.anchorNode, userSelection.anchorOffset) ;r1.collapse(true) ; |
|
44 |
var r2 = document.createRange() ;r2.setEnd(userSelection.focusNode, userSelection.focusOffset) ;r2.collapse(false) ; |
|
45 |
var leftToRight = (r2.compareBoundaryPoints(2, r1) == 1) ; // 2 is for END_TO_END |
|
46 |
// CY.log("leftToRight : " + leftToRight) ; |
|
47 |
startNode = (leftToRight) ? userSelection.anchorNode.parentNode : userSelection.focusNode.parentNode ; |
|
| 397 | 48 |
// GIB: when selecting amath, we should go up in the dom to find the accurate start/end Nodes |
49 |
if (startNode.nodeName == 'mi' || startNode.nodeName == 'mo') { |
|
50 |
startNode = startNode.parentElement.parentElement.parentElement.parentElement; |
|
51 |
} |
|
| 341 | 52 |
innerStartNode = (leftToRight) ? userSelection.anchorNode : userSelection.focusNode ; |
53 |
endNode = (leftToRight) ? userSelection.focusNode.parentNode : userSelection.anchorNode.parentNode; |
|
| 397 | 54 |
// GIB: when selecting amath, we should go up in the dom to find the accurate start/end Nodes |
55 |
if (endNode.nodeName == 'mi' || endNode.nodeName == 'mo') { |
|
56 |
endNode = endNode.parentElement.parentElement.parentElement.parentElement; |
|
57 |
} |
|
| 341 | 58 |
innerEndNode = (leftToRight) ? userSelection.focusNode : userSelection.anchorNode; |
59 |
|
|
60 |
startOffset = (leftToRight) ? userSelection.anchorOffset : userSelection.focusOffset; |
|
61 |
endOffset = (leftToRight) ? userSelection.focusOffset : userSelection.anchorOffset ; |
|
| 0 | 62 |
|
| 341 | 63 |
if (!hasWrapperAncestor(endNode) && hasWrapperAncestor(startNode)){ |
64 |
var r3 = document.createRange() ; |
|
65 |
r3.setStart(innerStartNode, startOffset) ; |
|
| 0 | 66 |
|
| 341 | 67 |
var csStartAncestor = getWrapperAncestor(startNode) ; |
68 |
var next = csStartAncestor ; |
|
69 |
r3.setEndAfter(next) ; |
|
70 |
|
|
71 |
var ind = parseInt(csStartAncestor.id.substring('sv_'.length)) ; |
|
72 |
while(r3.toString().length < range.toString().length) { |
|
73 |
ind++ ; |
|
|
532
0bad3613f59d
Reverse to YUI 3.0.0 since with YUI.3.10.3, comment content including words 'paragraph' or 'section' do not show up on Firefox, this is weird and has to be investigated.
gibus
parents:
525
diff
changeset
|
74 |
var node = CY.get("#sv_"+ind) ; |
| 341 | 75 |
if (node) { |
76 |
next = CY.Node.getDOMNode(node) ; |
|
77 |
r3.setEndAfter(next) ; |
|
78 |
} |
|
79 |
else |
|
80 |
break ; |
|
81 |
} |
|
82 |
endNode = next.lastChild ; |
|
83 |
endOffset = CY.DOM.getText(endNode).length ; |
|
84 |
} |
|
85 |
else if (!hasWrapperAncestor(startNode) && hasWrapperAncestor(endNode)){ |
|
86 |
var r3 = document.createRange() ; |
|
87 |
r3.setEnd(innerEndNode, endOffset) ; |
|
| 0 | 88 |
|
| 341 | 89 |
var csEndAncestor = getWrapperAncestor(endNode) ; |
90 |
var prev = csEndAncestor ; |
|
91 |
r3.setStartBefore(prev) ; |
|
92 |
|
|
93 |
var ind = parseInt(csEndAncestor.id.substring('sv_'.length)) ; |
|
94 |
while(r3.toString().length < range.toString().length) { |
|
95 |
ind-- ; |
|
|
532
0bad3613f59d
Reverse to YUI 3.0.0 since with YUI.3.10.3, comment content including words 'paragraph' or 'section' do not show up on Firefox, this is weird and has to be investigated.
gibus
parents:
525
diff
changeset
|
96 |
var node = CY.get("#sv_"+ind) ; |
| 341 | 97 |
if (node) { |
98 |
prev = CY.Node.getDOMNode(node) ; |
|
99 |
r3.setStartBefore(prev) ; |
|
100 |
} |
|
101 |
else |
|
102 |
break ; |
|
103 |
} |
|
104 |
startNode = prev.firstChild ; |
|
105 |
startOffset = 0 ; |
|
106 |
} |
|
107 |
else if (!hasWrapperAncestor(startNode) && !hasWrapperAncestor(endNode)){ |
|
108 |
var textLength = text.length ; |
|
109 |
|
|
110 |
// gather nodes with id sv_xxxx as candidates for start ancestor |
|
111 |
var startNodeInds = [] ; |
|
112 |
for (var ind = 0 ; ; ind++) { |
|
|
532
0bad3613f59d
Reverse to YUI 3.0.0 since with YUI.3.10.3, comment content including words 'paragraph' or 'section' do not show up on Firefox, this is weird and has to be investigated.
gibus
parents:
525
diff
changeset
|
113 |
var svNode = CY.get("#sv_"+ind) ; |
| 341 | 114 |
if (svNode == null) { |
115 |
break; |
|
116 |
} |
|
117 |
else { |
|
118 |
var svText = svNode.get("text") ; |
|
119 |
if (text.indexOf(svText) == 0) { |
|
120 |
startNodeInds.push(ind) ; |
|
121 |
} |
|
122 |
} |
|
123 |
} |
|
124 |
|
|
125 |
// gather nodes with id sv_xxxx as candidates for end ancestor |
|
126 |
var endNodeInds = [] ; |
|
127 |
for (var ind = 0 ; ; ind++) { |
|
|
532
0bad3613f59d
Reverse to YUI 3.0.0 since with YUI.3.10.3, comment content including words 'paragraph' or 'section' do not show up on Firefox, this is weird and has to be investigated.
gibus
parents:
525
diff
changeset
|
128 |
var svNode = CY.get("#sv_"+ind) ; |
| 341 | 129 |
if (svNode == null) { |
130 |
break; |
|
131 |
} |
|
132 |
else { |
|
133 |
var svText = svNode.get("text") ; |
|
134 |
if (text.indexOf(svText) == (textLength - svText.length)) { // i.e. the selection exactly ends with svText |
|
135 |
endNodeInds.push(ind) ; |
|
136 |
} |
|
137 |
} |
|
138 |
} |
|
| 0 | 139 |
|
| 341 | 140 |
var stop = false ; |
141 |
for (var i = 0 ; i < startNodeInds.length ; i++) { |
|
142 |
for (var j = 0 ; j < endNodeInds.length ; j++) { |
|
143 |
var r4 = document.createRange() ; |
|
144 |
|
|
|
532
0bad3613f59d
Reverse to YUI 3.0.0 since with YUI.3.10.3, comment content including words 'paragraph' or 'section' do not show up on Firefox, this is weird and has to be investigated.
gibus
parents:
525
diff
changeset
|
145 |
var s = CY.Node.getDOMNode(CY.get("#sv_"+startNodeInds[i])) ; var e = CY.Node.getDOMNode(CY.get("#sv_"+endNodeInds[j])) ; |
| 341 | 146 |
|
147 |
r4.setStartBefore(s) ; r4.setEndAfter(CY.Node.getDOMNode(e)) ; |
|
148 |
|
|
149 |
// does r4 starts after range start and r4 ends before range end ? |
|
150 |
if ((-1 < r4.compareBoundaryPoints(0, range)) && (1 > r4.compareBoundaryPoints(2, range))) { |
|
151 |
startNode = s.firstChild ; |
|
152 |
startOffset = 0 ; |
|
153 |
endNode = e.lastChild ; |
|
154 |
endOffset = CY.DOM.getText(e).length ; |
|
155 |
|
|
156 |
stop = true ; |
|
157 |
break ; |
|
158 |
} |
|
159 |
} |
|
160 |
if (stop) |
|
161 |
break ; |
|
162 |
} |
|
163 |
} |
|
164 |
|
|
165 |
r1.detach() ; |
|
166 |
r2.detach() ; |
|
167 |
} |
|
168 |
else |
|
169 |
return null ; |
|
170 |
} |
|
|
556
69503659fe8f
[c_selection.js] If safari_mobile, get current selection from a previously created global variable
Simon Descarpentries <sid@sopinspace.com>
parents:
532
diff
changeset
|
171 |
else |
| 341 | 172 |
return null ; |
173 |
|
|
174 |
} |
|
175 |
else if (document.selection) { // IE case |
|
176 |
var rng = document.selection.createRange(); |
|
177 |
if (rng.text.length == 0) |
|
178 |
return null ; |
|
179 |
var el = rng.parentElement(); |
|
| 0 | 180 |
|
| 341 | 181 |
// duplicate the range and collapse it to its start, to ask IE the parent element of the start textNode. |
182 |
var rngStart = rng.duplicate(); |
|
183 |
var rngEnd = rng.duplicate(); |
|
| 0 | 184 |
|
| 341 | 185 |
rngStart.collapse(true); // collapse to start |
186 |
rngEnd.collapse(false); // collapse to end |
|
187 |
|
|
188 |
startNode = rngStart.parentElement() ; |
|
189 |
while(rngStart.moveStart('character', -1) != 0) { |
|
190 |
if (rngStart.parentElement() != startNode) |
|
191 |
break ; |
|
192 |
startOffset++ ; |
|
193 |
} |
|
194 |
endNode = rngEnd.parentElement() ; |
|
195 |
while(rngEnd.moveEnd('character', -1) != 0) { |
|
196 |
if (rngEnd.parentElement() != endNode) |
|
197 |
break ; |
|
198 |
endOffset++ ; |
|
199 |
} |
|
200 |
|
|
201 |
text = rng.text ; |
|
202 |
} |
|
203 |
|
|
204 |
if (!hasWrapperAncestor(startNode) || !hasWrapperAncestor(endNode)){ |
|
205 |
// CY.log('no wrapper on one end') ; |
|
206 |
return null ; |
|
207 |
} |
|
208 |
return {'text' : text, 'start' : {'elt':startNode, 'offset':startOffset}, 'end' : {'elt':endNode, 'offset':endOffset}} ; |
|
209 |
} |