aboutsummaryrefslogtreecommitdiff
path: root/sources/plugins/magicline
diff options
context:
space:
mode:
Diffstat (limited to 'sources/plugins/magicline')
-rw-r--r--sources/plugins/magicline/dev/magicline.html594
-rw-r--r--sources/plugins/magicline/images/hidpi/icon-rtl.pngbin0 -> 176 bytes
-rw-r--r--sources/plugins/magicline/images/hidpi/icon.pngbin0 -> 199 bytes
-rw-r--r--sources/plugins/magicline/images/icon-rtl.pngbin0 -> 138 bytes
-rw-r--r--sources/plugins/magicline/images/icon.pngbin0 -> 133 bytes
-rw-r--r--sources/plugins/magicline/lang/af.js8
-rw-r--r--sources/plugins/magicline/lang/ar.js8
-rw-r--r--sources/plugins/magicline/lang/az.js8
-rw-r--r--sources/plugins/magicline/lang/bg.js8
-rw-r--r--sources/plugins/magicline/lang/ca.js8
-rw-r--r--sources/plugins/magicline/lang/cs.js8
-rw-r--r--sources/plugins/magicline/lang/cy.js8
-rw-r--r--sources/plugins/magicline/lang/da.js8
-rw-r--r--sources/plugins/magicline/lang/de-ch.js8
-rw-r--r--sources/plugins/magicline/lang/de.js8
-rw-r--r--sources/plugins/magicline/lang/el.js8
-rw-r--r--sources/plugins/magicline/lang/en-gb.js8
-rw-r--r--sources/plugins/magicline/lang/en.js8
-rw-r--r--sources/plugins/magicline/lang/eo.js8
-rw-r--r--sources/plugins/magicline/lang/es.js8
-rw-r--r--sources/plugins/magicline/lang/et.js8
-rw-r--r--sources/plugins/magicline/lang/eu.js8
-rw-r--r--sources/plugins/magicline/lang/fa.js8
-rw-r--r--sources/plugins/magicline/lang/fi.js8
-rw-r--r--sources/plugins/magicline/lang/fr-ca.js8
-rw-r--r--sources/plugins/magicline/lang/fr.js8
-rw-r--r--sources/plugins/magicline/lang/gl.js8
-rw-r--r--sources/plugins/magicline/lang/he.js8
-rw-r--r--sources/plugins/magicline/lang/hr.js8
-rw-r--r--sources/plugins/magicline/lang/hu.js8
-rw-r--r--sources/plugins/magicline/lang/id.js8
-rw-r--r--sources/plugins/magicline/lang/it.js8
-rw-r--r--sources/plugins/magicline/lang/ja.js8
-rw-r--r--sources/plugins/magicline/lang/km.js8
-rw-r--r--sources/plugins/magicline/lang/ko.js8
-rw-r--r--sources/plugins/magicline/lang/ku.js8
-rw-r--r--sources/plugins/magicline/lang/lv.js8
-rw-r--r--sources/plugins/magicline/lang/nb.js8
-rw-r--r--sources/plugins/magicline/lang/nl.js8
-rw-r--r--sources/plugins/magicline/lang/no.js8
-rw-r--r--sources/plugins/magicline/lang/oc.js8
-rw-r--r--sources/plugins/magicline/lang/pl.js8
-rw-r--r--sources/plugins/magicline/lang/pt-br.js8
-rw-r--r--sources/plugins/magicline/lang/pt.js8
-rw-r--r--sources/plugins/magicline/lang/ru.js8
-rw-r--r--sources/plugins/magicline/lang/si.js8
-rw-r--r--sources/plugins/magicline/lang/sk.js8
-rw-r--r--sources/plugins/magicline/lang/sl.js8
-rw-r--r--sources/plugins/magicline/lang/sq.js8
-rw-r--r--sources/plugins/magicline/lang/sv.js8
-rw-r--r--sources/plugins/magicline/lang/tr.js8
-rw-r--r--sources/plugins/magicline/lang/tt.js8
-rw-r--r--sources/plugins/magicline/lang/ug.js8
-rw-r--r--sources/plugins/magicline/lang/uk.js8
-rw-r--r--sources/plugins/magicline/lang/vi.js8
-rw-r--r--sources/plugins/magicline/lang/zh-cn.js8
-rw-r--r--sources/plugins/magicline/lang/zh.js8
-rw-r--r--sources/plugins/magicline/plugin.js1874
-rw-r--r--sources/plugins/magicline/samples/magicline.html209
59 files changed, 3093 insertions, 0 deletions
diff --git a/sources/plugins/magicline/dev/magicline.html b/sources/plugins/magicline/dev/magicline.html
new file mode 100644
index 0000000..077b670
--- /dev/null
+++ b/sources/plugins/magicline/dev/magicline.html
@@ -0,0 +1,594 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Magicline muddy trenches &ndash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <link href="../../../samples/old/sample.css" rel="stylesheet">
12 <style>
13 body {
14 margin: 0 0 130px;
15 }
16 #dev {
17 border-top: 1px solid #555;
18 position: fixed;
19 bottom: 0px;
20 left: 0px;
21 right: 0px;
22 height: 110px;
23 background: #B5E5EE;
24 font-size: 15px;
25 }
26 #dev .hl {
27 color: red;
28 }
29 #tr_upper, #tr_lower {
30 padding: 3px 6px;
31 }
32 #tr_upper {
33 background: rgba(255,0,0,.3);
34 }
35 #tr_lower {
36 background: rgba(0,255,0,.3);
37 }
38
39 #dev p {
40 margin: 0;
41 padding: 0;
42 }
43
44 #timeData,
45 #triggerData,
46 #mouseData,
47 #hiddenData {
48 position: absolute;
49 }
50 #timeData {
51 right: 10px;
52 top: 10px;
53 }
54 #hiddenData {
55 right: 10px;
56 top: 40px;
57 }
58 #mouseData {
59 left: 10px;
60 top: 10px;
61 }
62 #dev h2 {
63 top: 10px;
64 left: 10px;
65 }
66 #triggerData {
67 bottom: 10px;
68 left: 10px;
69 }
70 </style>
71</head>
72<body>
73 <h1 class="samples">
74 CKEditor Sample &mdash; magicline muddy trenches
75 </h1>
76
77 <h2>Various cases</h2>
78 <textarea cols="80" id="editor1" name="editor1" rows="10">
79 <div style="padding: 20px; background: gray; width: 300px" class="1">Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies. Curabitur et ligula. Ut molestie a, ultricies porta urna. Vestibulum commodo volutpat a, convallis ac, laoreet enim.</div>
80 <div style="background: violet; padding: 30px" class="static">Position static</div>
81 <dl class="2">
82 <dt>Key</dt><dd>Value</dd>
83 </dl>
84 <div>Whatever</div>
85 <hr id="hr">
86 <div style="
87 display: block;
88 cursor: pointer;
89 background: green;
90 height: 50px; width: 50px;" >aasd
91 </div>
92 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
93 <hr>
94 <hr>
95 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
96 <table border="1" class="first">
97 <tbody><tr>
98 <td>
99 Table Cell 1
100 </td>
101 </tr>
102 <tr>
103 <td>
104 Table Cell 2<br>
105 Table Cell 2<br>
106 </td>
107 </tr>
108 </tbody>
109 </table>
110 <div style="border: 1px solid red; padding: 50px">
111 Parent
112 <div style="border: 10px solid green; padding: 10px">Child</div>
113 </div>
114 I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body.
115 I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body. I'm in a body.
116 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
117 <table border="1" style="margin: 15px 0 100px" class="outer">
118 <tbody>
119 <tr>
120 <td>Table Cell 1</td>
121 <td>Table Cell 1</td>
122 </tr>
123 <tr>
124 <td>
125 <table border="10" class="inner">
126 <tbody>
127 <tr>
128 <td>Table Cell 1</td>
129 </tr>
130 <tr>
131 <td>Table Cell 2<br> Table Cell 2<br></td>
132 </tr>
133 </tbody>
134 </table>
135 </td>
136 </tr>
137 </tbody>
138 </table>
139 <table border="1" style="margin: 15px" class="third">
140 <tbody><tr>
141 <td>
142 Table Cell 1
143 </td>
144 <td>
145 Table Cell 1
146 </td>
147 <td>
148 Table Cell 1
149 </td>
150 <td>
151 Table Cell 1
152 </td>
153 </tr>
154 <tr>
155 <td>
156 Table Cell 2
157 </td>
158 </tr>
159 </tbody>
160 </table>
161 <table border="1" style="margin: 15px" class="fourth">
162 <tbody><tr>
163 <td>
164 Table Cell 1
165 </td>
166 <td>
167 Table Cell 1
168 </td>
169 <td>
170 Table Cell 1
171 </td>
172 <td>
173 Table Cell 1
174 </td>
175 </tr>
176 <tr>
177 <td>
178 Table Cell 2
179 </td>
180 </tr>
181 </tbody>
182 </table>
183 <ul style="" class="fifth">
184 <li name="ul_first">List item</li>
185 <li name="ul_second">
186 <ol style="">
187 <li name="ol_first">Nested item</li>
188 <li>Nested item</li>
189 <li>Nested item</li>
190 </ol>
191 </li>
192 <li>List item</li>
193 </ul>
194 <table border="1" class="table#123">
195 <tbody>
196 <tr>
197 <td>Table Cell 1</td>
198 </tr>
199 <tr>
200 <td>Table Cell 2<br> Table Cell 2<br></td>
201 </tr>
202 </tbody>
203 </table>
204 <table border="1" align="right" class="aligned">
205 <tbody>
206 <tr>
207 <td>Table Cell 1</td>
208 </tr>
209 <tr>
210 <td>Table Cell 2<br> Table Cell 2<br></td>
211 </tr>
212 </tbody>
213 </table>
214 <table border="1" style="float: right" class="floated">
215 <tbody>
216 <tr>
217 <td>Table Cell 1</td>
218 </tr>
219 <tr>
220 <td>Table Cell 2<br> Table Cell 2<br></td>
221 </tr>
222 </tbody>
223 </table>
224 <table border="1" align=""class="table#124">
225 <tbody>
226 <tr>
227 <td>Table Cell 1</td>
228 </tr>
229 <tr>
230 <td>Table Cell 2<br> Table Cell 2<br></td>
231 </tr>
232 </tbody>
233 </table>
234 <table border="1"class="table#125">
235 <tbody>
236 <tr>
237 <td>Table Cell 1</td>
238 </tr>
239 <tr>
240 <td>Table Cell 2<br> Table Cell 2<br></td>
241 </tr>
242 </tbody>
243 </table>
244 <p> enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas male</p>
245 <table border="1"class="table#126">
246 <tbody>
247 <tr>
248 <td>Table Cell 1</td>
249 </tr>
250 <tr>
251 <td>Table Cell 2<br> Table Cell 2<br></td>
252 </tr>
253 </tbody>
254 </table>
255 <div style="background: orange; margin: 20px">Upper div</div>
256 <table style="background: blue; margin: 20px"><tr><td>Lower table</td></tr></table>
257 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
258 <div><strong>I'm a div. Let me stay here.</strong></div><dl>
259 <dt>Key</dt>
260 <dd>pendisse a pellentesque dui, non felis</dd>
261 <dt>Key</dt>
262 <dd>pendisse a pellentesque dui, non felis</dd>
263 </dl>
264 <div class="11" style="padding: 20px; background: pink; width: 400px">
265 Parent
266 <div class="12" style="padding: 20px; background: orange">
267 <!-- comment -->
268 <!-- another comment -->
269 <div class="13" style="padding: 20px; background: green">
270 Child#2
271 </div>
272 </div>
273 </div>
274 </textarea>
275
276 <h2>Odd case: first (last) element at the very beginning, short editable</h2>
277 <textarea cols="80" id="editor2" name="editor1a" rows="10">
278 <table border="1" style="width: 300px">
279 <tbody>
280 <tr>
281 <td>
282 Test</td>
283 </tr>
284 </tbody>
285 </table>
286 </textarea>
287
288 <h2>Large document, put everywhere</h2>
289 <textarea id="editor3">
290 <p><div class="navbar" align="center" style="color: rgb(0, 0, 0);font-family: sans-serif;font-size: medium;"><a accesskey="p" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">previous</a>   <a accesskey="n" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/idl-definitions.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">next</a>   <a accesskey="c" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/Overview.html#contents" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">contents</a>   <a accesskey="i" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/def-index.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">index</a><hr title="Navigation area separator"></div><div class="noprint" style="color: rgb(0, 0, 0);font-family: sans-serif;font-size: medium;text-align: right;"><p style="font-family: monospace;font-size: small;">13 November, 2000</p></div><div class="div1" style="color: rgb(0, 0, 0);font-family: sans-serif;font-size: medium;"><a id="Range" name="Range"></a><h1 id="Range-h1" class="div1" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 27px;font-weight: normal; background-color: violet">2. Document Object Model Range</h1><dl style="background: green"><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><i>Editors</i></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Peter Sharpe, SoftQuad Software Inc.</dd><dd style="margin-top: 0px;margin-bottom: 0px;">Vidur Apparao, Netscape Communications Corp.</dd><dd style="margin-top: 0px;margin-bottom: 0px;">Lauren Wood, SoftQuad Software Inc.</dd></dl><div class="noprint"><h2 id="table-of-contents" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">Table of contents</h2><ul class="toc" style="list-style-type: none;list-style-position: initial;list-style-image: initial;"><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-introduction" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.1. Introduction</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Definitions" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial; background: red">2.2. Definitions and Notation</a><ul class="toc" style="list-style-type: none;list-style-position: initial;list-style-image: initial;"><li class="tocline4" style="font-style: italic;"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Position" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.2.1. Position</a></li><li class="tocline4" style="font-style: italic;"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Containment" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.2.2. Selection and Partial Selection</a></li><li class="tocline4" style="font-style: italic;"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Notation" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.2.3. Notation</a></li></ul></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Creating" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.3. Creating a Range</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Changing" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.4. Changing a Range's Position</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Comparing" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.5. Comparing Range Boundary-Points</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Deleting-Content" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.6. Deleting Content with a Range</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Extracting" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.7. Extracting Content</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Cloning" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.8. Cloning Content</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Inserting" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.9. Inserting Content</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Surrounding" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.10. Surrounding Content</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Misc" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.11. Miscellaneous Members</a></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Mutation" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.12. Range modification under document mutation</a><ul class="toc" style="list-style-type: none;list-style-position: initial;list-style-image: initial;"><li class="tocline4" style="font-style: italic;"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Insertions" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.12.1. Insertions</a></li><li class="tocline4" style="font-style: italic;"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Deletions" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.12.2. Deletions</a></li></ul></li><li class="tocline3"><a class="tocxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Interface" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">2.13. Formal Description of the Range Interface</a><ul class="toc" style="list-style-type: none;list-style-position: initial;list-style-image: initial;"><li class="tocline4" style="font-style: italic;"><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">Range</a>, <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-DocumentRange-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">DocumentRange</a>, <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">RangeException</a>, <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeExceptionCode" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">RangeExceptionCode</a></li></ul></li></ul></div><div class="div2"><a id="Level-2-Range-introduction" name="Level-2-Range-introduction"></a><h2 id="Level-2-Range-introduction-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.1. Introduction</h2><p>A Range identifies a range of content in a Document, DocumentFragment or Attr. It is contiguous in the sense that it can be characterized as selecting all of the content between a pair of boundary-points.</p><p><b>Note:</b> In a text editor or a word processor, a user can make a selection by pressing down the mouse at one point in a document, moving the mouse to another point, and releasing the mouse. The resulting selection is contiguous and consists of the content between the two points.</p><p>The term 'selecting' does not mean that every Range corresponds to a selection made by a GUI user;however, such a selection can be returned to a DOM user as a Range.</p><p><b>Note:</b> In bidirectional writing (Arabic, Hebrew), a range may correspond to a logical selection that is not necessarily contiguous when displayed. A visually contiguous selection, also used in some cases, may not correspond to a single logical selection, and may therefore have to be represented by more than one range.</p><p>The Range interface provides methods for accessing and manipulating the document tree at a higher level than similar methods in the Node interface. The expectation is that each of the methods provided by the Range interface for the insertion, deletion and copying of content can be directly mapped to a series of Node editing operations enabled by DOM Core. In this sense, the Range operations can be viewed as convenience methods that also enable the implementation to optimize common editing patterns.</p><p>This chapter describes the Range interface, including methods for creating and moving a Range and methods for manipulating content with Ranges.</p><p>The interfaces found within this section are not mandatory. A DOM application may use the <code>hasFeature(feature, version)</code> method of the <code>DOMImplementation</code> interface with parameter values "Range" and "2.0" (respectively) to determine whether or not this module is supported by the implementation. In order to fully support this module, an implementation must also support the "Core" feature defined defined in the DOM Level 2 Core specification [<a class="noxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/references.html#DOMCore" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">DOM Level 2 Core</a>]. Please refer to additional information about <a href="http://www.w3.org/TR/DOM-Level-2-Core/introduction.html#ID-Conformance" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>conformance</em></a> in the DOM Level 2 Core specification [<a class="noxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/references.html#DOMCore" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">DOM Level 2 Core</a>].</p></div><div class="div2" style="background: blue;"><a id="Level-2-Range-Definitions" name="Level-2-Range-Definitions"></a><h2 id="Level-2-Range-Definitions-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal; background: red">2.2. Definitions and Notation</h2><div style="background: yellow" class="div3"><a id="Level-2-Range-Position" name="Level-2-Range-Position"></a><h3 id="Level-2-Range-Position-h3" class="div3" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 19px;font-weight: normal;">2.2.1. Position</h3><p>This chapter refers to two different representations of a document: the text or source form that includes the document markup and the tree representation similar to the one described in the introduction section of the DOM Level 2 Core [<a class="noxref" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/references.html#DOMCore" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">DOM Level 2 Core</a>].</p><p>A Range consists of two <i>boundary-points</i> corresponding to the start and the end of the Range. <a id="td-boundarypoint" name="td-boundarypoint"></a>A boundary-point's position in a Document or DocumentFragment tree can be characterized by a node and an offset. <a id="td-container" name="td-container"></a>The node is called the <i>container</i> of the boundary-point and of its position. <a id="td-ancestor-container" name="td-ancestor-container"></a>The container and its ancestors are the <i>ancestor container</i>s of the boundary-point and of its position.<a id="td-offset" name="td-offset"></a>The offset within the node is called the <i>offset</i> of the boundary-point and its position. If the container is an Attr, Document, DocumentFragment, Element or EntityReference node, the offset is between its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-child" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>child</em></a> nodes. If the container is a CharacterData, Comment or ProcessingInstruction node, the offset is between the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit units</em></a> of the UTF-16 encoded string contained by it.</p><p>The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-points</em></a> of a Range must have a common <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> which is either a Document, DocumentFragment or Attr node. That is, the content of a Range must be entirely within the subtree rooted by a single Document, DocumentFragment or Attr Node. <a id="td-root-container" name="td-root-container"></a>This common <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> is known as the <i>root container</i> of the Range. <a id="td-context-tree" name="td-context-tree"></a>The tree rooted by the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-root-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>root container</em></a> is known as the Range's <i>context tree</i>.</p><p>The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of a Range must be an Element, Comment, ProcessingInstruction, EntityReference, CDATASection, Document, DocumentFragment, Attr, or Text node. None of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a>s of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of a Range can be a DocumentType, Entity or Notation node.</p><p>In terms of the text representation of a document, the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-points</em></a> of a Range can only be on token boundaries. That is, the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of the text range cannot be in the middle of a start- or end-tag of an element or within the name of an entity or character reference. A Range locates a contiguous portion of the content of the structure model.</p><p>The relationship between locations in a text representation of the document and in the Node tree interface of the DOM is illustrated in the following diagram:<br></p><div align="center"><hr width="90%" size="2"><img src="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/images/RangeExample.gif" alt="Range Example"><hr width="90%" size="2"><b>Range Example</b><hr width="90%" size="2"></div><p>In this diagram, four different Ranges are illustrated. The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-points</em></a> of each Range are labelled with <i>s#</i> (the start of the Range) and <i>e#</i> (the end of the Range), where # is the number of the Range. For Range 2, the start is in the BODY element and is immediately after the H1 element and immediately before the P element, so its position is between the H1 and P children of BODY. The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> whose <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> is not a CharacterData node is 0 if it is before the first child, 1 if between the first and second child, and so on. So, for the start of the Range 2, the<a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> is BODY and the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> is 1. The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> whose <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> is a CharacterData node is obtained similarly but using <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit unit</em></a> positions instead. For example, the<a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> labelled s1 of the Range 1 has a Text node (the one containing "Title") as its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> and an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of 2 since it is between the second and third <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit unit</em></a>.</p><p>Notice that the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s of Ranges 3 and 4 correspond to the same location in the text representation. An important feature of the Range is that a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of a Range can unambiguously represent every position within the document tree.</p><p>The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>s and <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a>s of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s can be obtained through the following read-only Range attributes:</p><div class="eg"><pre style="margin-left: 2em;"> readonly attribute Node startContainer;readonly attribute long startOffset;readonly attribute Node endContainer;readonly attribute long endOffset;</pre></div><p><a id="td-collapsed" name="td-collapsed"></a>If the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s of a Range have the same <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>s and <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a>s, the Range is said to be a <i>collapsed</i> Range. (This is often referred to as an insertion point in a user agent.)</p></div><div class="div3"><a id="Level-2-Range-Containment" name="Level-2-Range-Containment"></a><h3 id="Level-2-Range-Containment-h3" class="div3" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 19px;font-weight: normal;">2.2.2. Selection and Partial Selection</h3><p><a id="td-selected" name="td-selected"></a>A node or <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit unit</em></a> unit is said to be <i>selected</i> by a Range if it is between the two <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s of the Range, that is, if the position immediately before the node or 16-bit unit is before the end of the Range and the position immediately after the node or 16-bit unit is after the start of the range. For example, in terms of a text representation of the document, an element would be <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>selected</em></a>by a Range if its corresponding start-tag was located after the start of the Range and its end-tag was located before the end of the Range. In the examples in the above diagram, the Range 2<a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>selects</em></a> the P node and the Range 3 <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>selects</em></a> the text node containing the text "Blah xyz."</p><p><a id="td-partially-selected" name="td-partially-selected"></a>A node is said to be <i>partially selected</i> by a Range if it is an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of exactly one <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of the Range. For example, consider Range 1 in the above diagram. The element H1 is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> by that Range since the start of the Range is within one of its children.</p></div><div class="div3"><a id="Level-2-Range-Notation" name="Level-2-Range-Notation"></a><h3 id="Level-2-Range-Notation-h3" class="div3" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 19px;font-weight: normal;">2.2.3. Notation</h3><p>Many of the examples in this chapter are illustrated using a text representation of a document. The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s of a Range are indicated by displaying the characters (be they markup or data characters) between the two <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s in bold, as in</p><div class="eg"><pre style="margin-left: 2em;"> <FOO>A<b>BC<BAR>DE</b>F</BAR></FOO></pre></div><p>When both <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s are at the same position, they are indicated with a bold caret ('<b>^</b>'), as in</p><div class="eg"><pre style="margin-left: 2em;"> <FOO>A<b>^</b>BC<BAR>DEF</BAR></FOO></pre></div></div></div><div class="div2"><a id="Level-2-Range-Creating" name="Level-2-Range-Creating"></a><h2 id="Level-2-Range-Creating-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.3. Creating a Range</h2><p>A Range is created by calling the <code>createRange()</code> method on the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-DocumentRange-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>DocumentRange</code></a> interface. This interface can be obtained from the object implementing the <code>Document</code> interface using binding-specific casting methods.</p><div class="eg"><pre style="margin-left: 2em;"> interface DocumentRange{Range createRange();}</pre></div><p>The initial state of the Range returned from this method is such that both of its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a>s are positioned at the beginning of the corresponding Document, before any content. In other words, the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of each <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> is the Document node and the offset within that node is 0.</p><p>Like some objects created using methods in the Document interface (such as Nodes and DocumentFragments), Ranges created via a particular document instance can select only content associated with that Document, or with DocumentFragments and Attrs for which that Document is the <code>ownerDocument</code>. Such Ranges, then, can not be used with other Document instances.</p></div><div class="div2"><a id="Level-2-Range-Changing" name="Level-2-Range-Changing"></a><h2 id="Level-2-Range-Changing-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.4. Changing a Range's Position</h2><p>A Range's position can be specified by setting the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> and <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of each boundary-point with the <code>setStart</code> and <code>setEnd</code> methods.</p><div class="eg"><pre style="margin-left: 2em;"> void setStart(in Node parent, in long offset) raises(RangeException);void setEnd(in Node parent, in long offset) raises(RangeException);</pre></div><p>If one boundary-point of a Range is set to have a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-root-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>root container</em></a> other than the current one for the Range, the Range is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> to the new position. This enforces the restriction that both boundary-points of a Range must have the same <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-root-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>root container</em></a>.</p><p>The start position of a Range is guaranteed to never be after the end position. To enforce this restriction, if the start is set to be at a position after the end, the Range is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> to that position. Similarly, if the end is set to be at a position before the start, the Range is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> to that position.</p><p>It is also possible to set a Range's position relative to nodes in the tree:</p><div class="eg"><pre style="margin-left: 2em;"> void setStartBefore(in Node node);raises(RangeException);void setStartAfter(in Node node);raises(RangeException);void setEndBefore(in Node node);raises(RangeException);void setEndAfter(in Node node);raises(RangeException);</pre></div><p>The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-parent" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>parent</em></a> of the node becomes the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> and the Range is subject to the same restrictions as given above in the description of <code>setStart()</code>and <code>setEnd()</code>.</p><p>A Range can be <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> to either boundary-point:</p><div class="eg"><pre style="margin-left: 2em;"> void collapse(in boolean toStart);</pre></div><p>Passing <code>TRUE</code> as the parameter <code>toStart</code> will <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapse</em></a> the Range to its start, <code>FALSE</code> to its end.</p><p>Testing whether a Range is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> can be done by examining the <code>collapsed</code> attribute:</p><div class="eg"><pre style="margin-left: 2em;"> readonly attribute boolean collapsed;</pre></div><p>The following methods can be used to make a Range select the contents of a node or the node itself.</p><div class="eg"><pre style="margin-left: 2em;"> void selectNode(in Node n);void selectNodeContents(in Node n);</pre></div><p>The following examples demonstrate the operation of the methods <code>selectNode</code> and <code>selectNodeContents</code>:</p><div class="eg"><pre style="margin-left: 2em;">Before: <b>^</b><BAR><FOO>A<MOO>B</MOO>C</FOO></BAR>After Range.selectNodeContents(FOO): <BAR><FOO><b>A<MOO>B</MOO>C</b></FOO></BAR>(In this case, FOO is the parent of both boundary-points)After Range.selectNode(FOO):<BAR><b><FOO>A<MOO>B</MOO>C</FOO></b></BAR></pre></div></div><div class="div2"><a id="Level-2-Range-Comparing" name="Level-2-Range-Comparing"></a><h2 id="Level-2-Range-Comparing-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.5. Comparing Range Boundary-Points</h2><p>It is possible to compare two Ranges by comparing their boundary-points:</p><div class="eg"><pre style="margin-left: 2em;"> short compareBoundaryPoints(in CompareHow how, in Range sourceRange) raises(RangeException);</pre></div><p>where <code>CompareHow</code> is one of four values: <code>START_TO_START</code>, <code>START_TO_END</code>, <code>END_TO_END</code> and <code>END_TO_START</code>. The return value is -1, 0 or 1 depending on whether the corresponding boundary-point of the Range is before, equal to, or after the corresponding boundary-point of <code>sourceRange</code>. An exception is thrown if the two Ranges have different <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-root-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>root container</em></a>s.</p><p>The result of comparing two boundary-points (or positions) is specified below. An informal but not always correct specification is that an boundary-point is before, equal to, or after another if it corresponds to a location in a text representation before, equal to, or after the other's corresponding location.</p><p><a id="td-comparison" name="td-comparison"></a>Let A and B be two boundary-points or positions. Then one of the following holds: A is <i>before</i> B, A is <i>equal to</i> B, or A is <i>after</i> B. Which one holds is specified in the following by examining four cases:</p><p>In the first case the boundary-points have the same <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>. A is <i>before</i> B if its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> is less than the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of B, A is <i>equal to</i> B if its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> is equal to the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of B, and A is <i>after</i> B if its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> is greater than the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of B.</p><p>In the second case a child node C of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of A is an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of B. In this case, A is <i>before</i> B if the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of A is less than or equal to the index of the child node C and A is <i>after</i>B otherwise.</p><p>In the third case a child node C of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of B is an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of A. In this case, A is <i>before</i> B if the index of the child node C is less than the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of B and A is <i>after</i> B otherwise.</p><p>In the fourth case, none of three other cases hold: the containers of A and B are <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-sibling" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>siblings</em></a> or <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-descendant" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>descendants</em></a> of sibling nodes. In this case, A is <i>before</i> B if the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of A is before the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of B in a pre-order traversal of the Ranges' <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a> and A is <i>after</i> B otherwise.</p><p>Note that because the same location in a text representation of the document can correspond to two different positions in the DOM tree, it is possible for two boundary-points to not compare equal even though they would be equal in the text representation. For this reason, the informal definition above can sometimes be incorrect.</p></div><div class="div2"><a id="Level-2-Range-Deleting-Content" name="Level-2-Range-Deleting-Content"></a><h2 id="Level-2-Range-Deleting-Content-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.6. Deleting Content with a Range</h2><p>One can delete the contents selected by a Range with:</p><div class="eg"><pre style="margin-left: 2em;"> void deleteContents();</pre></div><p><code>deleteContents()</code> deletes all nodes and characters selected by the Range. All other nodes and characters remain in the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a> of the Range. Some examples of this deletion operation are:</p><div class="eg"><pre style="margin-left: 2em;">(1) <FOO>A<b>B<MOO>CD</MOO></b>CD</FOO>--><FOO>A<b>^</b>CD</FOO></pre></div><div class="eg"><pre style="margin-left: 2em;">(2) <FOO>A<MOO>B<b>C</MOO>D</b>E</FOO>--><FOO>A<MOO>B</MOO><b>^</b>E</FOO></pre></div><div class="eg"><pre style="margin-left: 2em;">(3) <FOO>X<b>Y<BAR>Z</b>W</BAR>Q</FOO>--><FOO>X<b>^</b><BAR>W</BAR>Q</FOO></pre></div><div class="eg"><pre style="margin-left: 2em;">(4) <FOO><BAR1>A<b>B</BAR1><BAR2/><BAR3>C</b>D</BAR3></FOO>--><FOO><BAR1>A</BAR1><b>^</b><BAR3>D</BAR3></pre></div><p>After <code>deleteContents()</code> is invoked on a Range, the Range is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a>. If no node was <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> by the Range, then it is <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a> to its original start point, as in example (1). If a node was <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> by the Range and was an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of the start of the Range and no <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-ancestor" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor</em></a> of the node satisfies these two conditions, then the Range is collapsed to the position immediately after the node, as in examples (2) and (4). If a node was <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> by the Range and was an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of the end of the Range and no ancestor of the node satisfies these two conditions, then the Range is collapsed to the position immediately before the node, as in examples (3) and (4).</p><p>Note that if deletion of a Range leaves adjacent Text nodes, they are not automatically merged, and empty Text nodes are not automatically removed. Two Text nodes should be joined only if each is the container of one of the boundary-points of a Range whose contents are deleted. To merge adjacent Text nodes, or remove empty text nodes, the <code>normalize()</code> method on the <code>Node</code>interface should be used.</p></div><div class="div2"><a id="Level-2-Range-Extracting" name="Level-2-Range-Extracting"></a><h2 id="Level-2-Range-Extracting-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.7. Extracting Content</h2><p>If the contents of a Range need to be extracted rather than deleted, the following method may be used:</p><div class="eg"><pre style="margin-left: 2em;"> DocumentFragment extractContents();</pre></div><p>The <code>extractContents()</code> method removes nodes from the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a> similarly to the <code>deleteContents()</code> method. In addition, it places the deleted contents in a new <code>DocumentFragment</code>. The following examples illustrate the contents of the returned DocumentFragment:</p><div class="eg"><pre style="margin-left: 2em;">(1) <FOO>A<b>B<MOO>CD</MOO></b>CD</FOO>-->B<MOO>CD</MOO></pre></div><div class="eg"><pre style="margin-left: 2em;">(2) <FOO>A<MOO>B<b>C</MOO>D</b>E</FOO>--><MOO>C<MOO>D</pre></div><div class="eg"><pre style="margin-left: 2em;">(3) <FOO>X<b>Y<BAR>Z</b>W</BAR>Q</FOO>-->Y<BAR>Z</BAR></pre></div><div class="eg"><pre style="margin-left: 2em;">(4)<FOO><BAR1>A<b>B</BAR1><BAR2/><BAR3>C</b>D</BAR3></FOO>--><BAR1>B</BAR1><BAR2/><BAR3>C</BAR3></pre></div><p>It is important to note that nodes that are <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> by the Range are cloned. Since part of such a node's contents must remain in the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a> and part of the contents must be moved to the new DocumentFragment, a clone of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selected</em></a> node is included in the new DocumentFragment. Note that cloning does not take place for <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>selected</em></a> elements;these nodes are moved to the new DocumentFragment.</p></div><div class="div2"><a id="Level-2-Range-Cloning" name="Level-2-Range-Cloning"></a><h2 id="Level-2-Range-Cloning-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.8. Cloning Content</h2><p>The contents of a Range may be duplicated using the following method:</p><div class="eg"><pre style="margin-left: 2em;"> DocumentFragment cloneContents();</pre></div><p>This method returns a <code>DocumentFragment</code> that is similar to the one returned by the method <code>extractContents()</code>. However, in this case, the original nodes and character data in the Range are not removed from the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a>. Instead, all of the nodes and text content within the returned <code>DocumentFragment</code> are cloned.</p></div><div class="div2"><a id="Level-2-Range-Inserting" name="Level-2-Range-Inserting"></a><h2 id="Level-2-Range-Inserting-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.9. Inserting Content</h2><p>A node may be inserted into a Range using the following method:</p><div class="eg"><pre style="margin-left: 2em;"> void insertNode(in Node n) raises(RangeException);</pre></div><p>The <code>insertNode()</code> method inserts the specified node into the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a>. The node is inserted at the start <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of the Range, without modifying it.</p><p>If the start boundary point of the Range is in a <code>Text</code> node, the <code>insertNode</code> operation splits the <code>Text</code> node at the boundary point. If the node to be inserted is also a <code>Text</code> node, the resulting adjacent<code>Text</code> nodes are not normalized automatically;this operation is left to the application.</p><p>The Node passed into this method can be a <code>DocumentFragment</code>. In that case, the contents of the <code>DocumentFragment</code> are inserted at the start <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-boundarypoint" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>boundary-point</em></a> of the Range, but the <code>DocumentFragment</code>itself is not. Note that if the Node represents the root of a sub-tree, the entire sub-tree is inserted.</p><p>The same rules that apply to the <code>insertBefore()</code> method on the Node interface apply here. Specifically, the Node passed in, if it already has a parent, will be removed from its existing position.</p></div><div class="div2"><a id="Level-2-Range-Surrounding" name="Level-2-Range-Surrounding"></a><h2 id="Level-2-Range-Surrounding-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.10. Surrounding Content</h2><p>The insertion of a single node to subsume the content selected by a Range can be performed with:</p><div class="eg"><pre style="margin-left: 2em;"> void surroundContents(in Node newParent);</pre></div><p>The <code>surroundContents()</code> method causes all of the content selected by the Range to be rooted by the specified node. The nodes may not be Attr, Entity, DocumentType, Notation, Document, or DocumentFragment nodes. Calling <code>surroundContents()</code> with the Element node FOO in the following examples yields:</p><div class="eg"><pre style="margin-left: 2em;"> Before: <BAR>A<b>B<MOO>C</MOO>D</b>E</BAR>After surroundContents(FOO):<BAR>A<b><FOO>B<MOO>C</MOO>D</FOO></b>E</BAR></pre></div><p>Another way of describing the effect of this method on the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-context-tree" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>context tree</em></a> is to decompose it in terms of other operations:</p><ol><li>Remove the contents selected by the Range with a call to <code>extractContents()</code>.</li><li>Insert the node <code>newParent</code> where the Range is collapsed (after the extraction) with <code>insertNode().</code></li><li>Insert the entire contents of the extracted DocumentFragment into <code>newParent</code>. Specifically, invoke the <code>appendChild()</code> on <code>newParent</code> passing in the DocumentFragment returned as a result of the call to <code>extractContents()</code></li><li>Select <code>newParent</code> and all of its contents with <code>selectNode()</code>.</li></ol><p>The <code>surroundContents()</code> method raises an exception if the Range <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selects</em></a> a non-Text node. An example of a Range for which <code>surroundContents()</code>raises an exception is:</p><div class="eg"><pre style="margin-left: 2em;"> <FOO>A<b>B<BAR>C</b>D</BAR>E</FOO></pre></div><p>If the node <code>newParent</code> has any children, those children are removed before its insertion. Also, if the node <code>newParent</code> already has a parent, it is removed from the original parent's <code>childNodes</code> list.</p></div><div class="div2"><a id="Level-2-Range-Misc" name="Level-2-Range-Misc"></a><h2 id="Level-2-Range-Misc-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.11. Miscellaneous Members</h2><p>One can clone a Range:</p><div class="eg"><pre style="margin-left: 2em;"> Range cloneRange();</pre></div><p>This creates a new Range which selects exactly the same content as that selected by the Range on which the method <code>cloneRange</code> was invoked. No content is affected by this operation.</p><p>Because the boundary-points of a Range do not necessarily have the same <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>s, use:</p><div class="eg"><pre style="margin-left: 2em;"> readonly attribute Node commonAncestorContainer;</pre></div><p>to get the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of both boundary-points that is furthest down from the Range's <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-root-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>root container</em></a></p><p>One can get a copy of all the character data selected or partially selected by a Range with:</p><div class="eg"><pre style="margin-left: 2em;"> DOMString toString();</pre></div><p>This does nothing more than simply concatenate all the character data selected by the Range. This includes character data in both <code>Text</code> and <code>CDATASection</code> nodes.</p></div><div class="div2"><a id="Level-2-Range-Mutation" name="Level-2-Range-Mutation"></a><h2 id="Level-2-Range-Mutation-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.12. Range modification under document mutation</h2><p>As a document is modified, the Ranges within the document need to be updated. For example, if one boundary-point of a Range is within a node and that node is removed from the document, then the Range would be invalid unless it is fixed up in some way. This section describes how Ranges are modified under document mutations so that they remain valid.</p><p>There are two general principles which apply to Ranges under document mutation: The first is that all Ranges in a document will remain valid after any mutation operation and the second is that, as much as possible, all Ranges will select the same portion of the document after any mutation operation.</p><p>Any mutation of the document tree which affect Ranges can be considered to be a combination of basic deletion and insertion operations. In fact, it can be convenient to think of those operations as being accomplished using the <code>deleteContents()</code> and <code>insertNode()</code> Range methods and, in the case of Text mutations, the <code>splitText()</code> and <code>normalize()</code> methods.</p><div class="div3"><a id="Level-2-Range-Insertions" name="Level-2-Range-Insertions"></a><h3 id="Level-2-Range-Insertions-h3" class="div3" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 19px;font-weight: normal;">2.12.1. Insertions</h3><p>An insertion occurs at a single point, the insertion point, in the document. For any Range in the document tree, consider each boundary-point. The only case in which the boundary-point will be changed after the insertion is when the boundary-point and the insertion point have the same <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> and the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of the insertion point is strictly less than the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of the Range's boundary-point. In that case the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of the Range's boundary-point will be increased so that it is between the same nodes or characters as it was before the insertion.</p><p>Note that when content is inserted at a boundary-point, it is ambiguous as to where the boundary-point should be repositioned if its relative position is to be maintained. There are two possibilities: at the start or at the end of the newly inserted content. We have chosen that in this case neither the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> nor <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-offset" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>offset</em></a> of the boundary-point is changed. As a result, the boundary-point will be positioned at the start of the newly inserted content.</p><p><em>Examples:</em></p><p>Suppose the Range selects the following:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd efgh X<b>Y blah i</b>jkl</P></pre></div><p>Consider the insertion of the text "<i>inserted text</i>" at the following positions:</p><div class="eg"><pre style="margin-left: 2em;">1. Before the 'X':<P>Abcd efgh <i>inserted text</i>X<b>Y blah i</b>jkl</P>2. After the 'X':<P>Abcd efgh X<b><i>inserted text</i>Y blah i</b>jkl</P>3. After the 'Y':<P>Abcd efgh X<b>Y<i>inserted text</i> blah i</b>jkl</P>4. After the 'h' in "Y blah":<P>Abcd efgh X<b>Y blah<i>inserted text</i> i</b>jkl</P></pre></div></div><div class="div3"><a id="Level-2-Range-Deletions" name="Level-2-Range-Deletions"></a><h3 id="Level-2-Range-Deletions-h3" class="div3" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 19px;font-weight: normal;">2.12.2. Deletions</h3><p>Any deletion from the document tree can be considered as a sequence of <code>deleteContents()</code> operations applied to a minimal set of disjoint Ranges. To specify how a Range is modified under deletions we need only consider what happens to a Range under a single <code>deleteContents()</code>operation of another Range. And, in fact, we need only consider what happens to a single boundary-point of the Range since both boundary-points are modified using the same algorithm.</p><p>If a boundary-point of the original Range is within the content being deleted, then after the deletion it will be at the same position as the resulting boundary-point of the (now <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-collapsed" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>collapsed</em></a>) Range used to delete the contents.</p><p>If a boundary-point is after the content being deleted then it is not affected by the deletion unless its <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> is also the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of one of the boundary-points of the Range being deleted. If there is such a common <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>, then the index of the boundary-point is modified so that the boundary-point maintains its position relative to the content of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>.</p><p>If a boundary-point is before the content being deleted then it is not affected by the deletion at all.</p><p><em>Examples:</em></p><p>In these examples, the Range on which <code>deleteContents()</code>is invoked is indicated by the underline.</p><p><em>Example 1.</em></p><p>Before:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <u>efgh T</u><b><u>he</u> Range i</b>jkl</P></pre></div><p>After:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <b>Range i</b>jkl</P></pre></div><p><em>Example 2.</em></p><p>Before:</p><div class="eg"><pre style="margin-left: 2em;"><p>Abcd <u>efgh T<b>he Range i</b>j</u>kl</p></pre></div><p>After:</p><div class="eg"><pre style="margin-left: 2em;"><p>Abcd <b>^</b>kl</p></pre></div><p><em>Example 3.</em></p><p>Before:</p><div class="eg"><pre style="margin-left: 2em;"><P>ABCD <u>efgh T</u><b><u>he <EM>R</u>ange</b></EM>ijkl</P></pre></div><p>After:</p><div class="eg"><pre style="margin-left: 2em;"><P>ABCD <EM><b>ange</b></EM>ijkl</P></pre></div><p>In this example, the container of the start boundary-point after the deletion is the Text node holding the string "ange".</p><p><em>Example 4.</em></p><p>Before:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <u>efgh T</u><b>he Range i</b>jkl</P></pre></div><p>After:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <b>he Range i</b>jkl</P></pre></div><p><em>Example 5.</em></p><p>Before:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <u><EM>efgh T<b>he Range i</b>j</EM></u>kl</P></pre></div><p>After:</p><div class="eg"><pre style="margin-left: 2em;"><P>Abcd <b>^</b>kl</P></pre></div></div></div><div class="div2"><a id="Level-2-Range-Interface" name="Level-2-Range-Interface"></a><h2 id="Level-2-Range-Interface-h2" class="div2" style="text-align: left;color: rgb(0, 90, 156);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: white;font-size: 22px;font-weight: normal;">2.13. Formal Description of the Range Interface</h2><p>To summarize, the complete, formal description of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>Range</code></a> interface is given below:</p><dl ><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Interface <i><a id="Level-2-Range-idl" name="Level-2-Range-idl">Range</a></i></b> (introduced in <b class="since">DOM Level 2</b>)</dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><br><b>IDL Definition</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="idl-code" style="font-family: monospace;border-top-width: 1px;border-right-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-left-style: solid;border-top-color: black;border-right-color: black;border-bottom-color: black;border-left-color: black;border-image: initial;white-space: pre;background-color: rgb(223, 223, 223);"><pre style="margin-left: 2em;">// Introduced in DOM Level 2:interface Range{readonly attribute Node startContainer;// raises(DOMException) on retrieval readonly attribute long startOffset;// raises(DOMException) on retrieval readonly attribute Node endContainer;// raises(DOMException) on retrieval readonly attribute long endOffset;// raises(DOMException) on retrieval readonly attribute boolean collapsed;// raises(DOMException) on retrieval readonly attribute Node commonAncestorContainer;// raises(DOMException) on retrieval void setStart(in Node refNode, in long offset) raises(RangeException, DOMException);void setEnd(in Node refNode, in long offset) raises(RangeException, DOMException);void setStartBefore(in Node refNode) raises(RangeException, DOMException);void setStartAfter(in Node refNode) raises(RangeException, DOMException);void setEndBefore(in Node refNode) raises(RangeException, DOMException);void setEndAfter(in Node refNode) raises(RangeException, DOMException);void collapse(in boolean toStart) raises(DOMException);void selectNode(in Node refNode) raises(RangeException, DOMException);void selectNodeContents(in Node refNode) raises(RangeException, DOMException);// CompareHow const unsigned short START_TO_START=0;const unsigned short START_TO_END=1;const unsigned short END_TO_END=2;const unsigned short END_TO_START=3;short compareBoundaryPoints(in unsigned short how, in Range sourceRange) raises(DOMException);void deleteContents() raises(DOMException);DocumentFragment extractContents() raises(DOMException);DocumentFragment cloneContents() raises(DOMException);void insertNode(in Node newNode) raises(DOMException, RangeException);void surroundContents(in Node newParent) raises(DOMException, RangeException);Range cloneRange() raises(DOMException);DOMString toString() raises(DOMException);void detach() raises(DOMException);};</pre></div><br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Definition group <i><a id="Level2-Range-compareHow" name="Level2-Range-compareHow">CompareHow</a></i></b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><p>Passed as a parameter to the <code>compareBoundaryPoints</code> method.</p><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Defined Constants</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">END_TO_END</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Compare end boundary-point of <code>sourceRange</code> to end boundary-point of Range on which <code>compareBoundaryPoints</code> is invoked.</dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">END_TO_START</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Compare end boundary-point of <code>sourceRange</code> to start boundary-point of Range on which <code>compareBoundaryPoints</code> is invoked.</dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">START_TO_END</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Compare start boundary-point of <code>sourceRange</code> to end boundary-point of Range on which <code>compareBoundaryPoints</code> is invoked.</dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">START_TO_START</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Compare start boundary-point of <code>sourceRange</code> to start boundary-point of Range on which <code>compareBoundaryPoints</code> is invoked.</dd></dl></dd></dl></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Attributes</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-collapsed" name="Level-2-Range-attr-collapsed">collapsed</a></code> of type <code>boolean</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">TRUE if the Range is collapsed<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-commonParent" name="Level-2-Range-attr-commonParent">commonAncestorContainer</a></code> of type <code>Node</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-deepest" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>deepest</em></a> common <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of the Range's two boundary-points.<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-endParent" name="Level-2-Range-attr-endParent">endContainer</a></code> of type <code>Node</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">Node within which the Range ends<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-endOffset" name="Level-2-Range-attr-endOffset">endOffset</a></code> of type <code>long</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">Offset within the ending node of the Range.<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-startParent" name="Level-2-Range-attr-startParent">startContainer</a></code> of type <code>Node</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">Node within which the Range begins<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="attribute-name" style="background-color: rgb(255, 255, 210);"><a id="Level-2-Range-attr-startOffset" name="Level-2-Range-attr-startOffset">startOffset</a></code> of type <code>long</code>, readonly</dt><dd style="margin-top: 0px;margin-bottom: 0px;">Offset within the starting node of the Range.<br><div class="exceptions"><b>Exceptions on retrieval</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></dd></dl></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Methods</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-cloneContents" name="Level2-Range-method-cloneContents">cloneContents</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Duplicates the contents of a Range<div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><code>DocumentFragment</code></p></td><td><p>A DocumentFragment that contains content equivalent to this Range.</p></td></tr></tbody></table></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>HIERARCHY_REQUEST_ERR: Raised if a DocumentType node would be extracted into the new DocumentFragment.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-clone" name="Level2-Range-method-clone">cloneRange</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Produces a new Range whose boundary-points are equal to the boundary-points of the Range.<div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>Range</code></a></p></td><td><p>The duplicated Range.</p></td></tr></tbody></table></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-collapse" name="Level2-Range-method-collapse">collapse</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Collapse a Range onto one of its boundary-points<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">toStart</code> of type <code>boolean</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">If TRUE, collapses the Range onto its start;if FALSE, collapses it onto its end.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-compareBoundaryPoints" name="Level2-Range-method-compareBoundaryPoints">compareBoundaryPoints</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Compare the boundary-points of two Ranges in a document.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">how</code> of type <code>unsigned short</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">A code representing the type of comparison, as defined above.<br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">sourceRange</code> of type <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>Range</code></a></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <code>Range</code> on which this current <code>Range</code> is compared to.<br></dd></dl></div></div><div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><code>short</code></p></td><td><p>-1, 0 or 1 depending on whether the corresponding boundary-point of the Range is respectively before, equal to, or after the corresponding boundary-point of<code>sourceRange</code>.</p></td></tr></tbody></table></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>WRONG_DOCUMENT_ERR: Raised if the two Ranges are not in the same Document or DocumentFragment.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-deleteContents" name="Level2-Range-method-deleteContents">deleteContents</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Removes the contents of a Range from the containing document or document fragment without returning a reference to the removed content.<div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of the content of the Range is read-only or any of the nodes that contain any of the content of the Range are read-only.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-detach" name="Level2-Range-method-detach">detach</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Called to indicate that the Range is no longer in use and that the implementation may relinquish any resources associated with this Range. Subsequent calls to any methods or attribute getters on this Range will result in a <code>DOMException</code> being thrown with an error code of <code>INVALID_STATE_ERR</code>.<div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-extractContents" name="Level2-Range-method-extractContents">extractContents</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Moves the contents of a Range from the containing document or document fragment to a new DocumentFragment.<div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><code>DocumentFragment</code></p></td><td><p>A DocumentFragment containing the extracted contents.</p></td></tr></tbody></table></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of the content of the Range is read-only or any of the nodes which contain any of the content of the Range are read-only.</p><p>HIERARCHY_REQUEST_ERR: Raised if a DocumentType node would be extracted into the new DocumentFragment.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-insertNode" name="Level2-Range-method-insertNode">insertNode</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Inserts a node into the Document or DocumentFragment at the start of the Range. If the container is a Text node, this will be split at the start of the Range (as if the Text node's splitText method was performed at the insertion point) and the insertion will occur between the two resulting Text nodes. Adjacent Text nodes will not be automatically merged. If the node to be inserted is a DocumentFragment node, the children will be inserted rather than the DocumentFragment node itself.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">newNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The node to insert at the start of the Range<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>NO_MODIFICATION_ALLOWED_ERR: Raised if an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of the start of the Range is read-only.</p><p>WRONG_DOCUMENT_ERR: Raised if <code>newNode</code> and the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of the start of the Range were not created from the same document.</p><p>HIERARCHY_REQUEST_ERR: Raised if the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of the start of the Range is of a type that does not allow children of the type of <code>newNode</code> or if <code>newNode</code>is an ancestor of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a>.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if <code>newNode</code> is an Attr, Entity, Notation, or Document node.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-selectNode" name="Level2-Range-method-selectNode">selectNode</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Select a node and its contents<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The node to select.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if an ancestor of <code>refNode</code> is an Entity, Notation or DocumentType node or if <code>refNode</code> is a Document, DocumentFragment, Attr, Entity, or Notation node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-selectNodeContents" name="Level2-Range-method-selectNodeContents">selectNodeContents</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Select the contents within a node<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Node to select from<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code> or an ancestor of <code>refNode</code> is an Entity, Notation or DocumentType node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-setEnd" name="Level2-Range-method-setEnd">setEnd</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the attributes describing the end of a Range.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <code>refNode</code> value. This parameter must be different from <code>null</code>.<br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">offset</code> of type <code>long</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <code>endOffset</code> value.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code> or an ancestor of <code>refNode</code> is an Entity, Notation, or DocumentType node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INDEX_SIZE_ERR: Raised if <code>offset</code> is negative or greater than the number of child units in <code>refNode</code>. Child units are <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit units</em></a> if <code>refNode</code> is a type of CharacterData node (e.g., a Text or Comment node) or a ProcessingInstruction node. Child units are Nodes in all other cases.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-setEndAfter" name="Level2-Range-method-setEndAfter">setEndAfter</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the end of a Range to be after a node<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Range ends after <code>refNode</code>.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if the root container of <code>refNode</code> is not an Attr, Document or DocumentFragment node or if <code>refNode</code> is a Document, DocumentFragment, Attr, Entity, or Notation node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-setEndBefore" name="Level2-Range-method-setEndBefore">setEndBefore</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the end position to be before a node.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Range ends before <code>refNode</code><br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if the root container of <code>refNode</code> is not an Attr, Document, or DocumentFragment node or if <code>refNode</code> is a Document, DocumentFragment, Attr, Entity, or Notation node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-setStart" name="Level2-Range-method-setStart">setStart</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the attributes describing the start of the Range.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <code>refNode</code> value. This parameter must be different from <code>null</code>.<br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">offset</code> of type <code>long</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The <code>startOffset</code> value.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code> or an ancestor of <code>refNode</code> is an Entity, Notation, or DocumentType node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INDEX_SIZE_ERR: Raised if <code>offset</code> is negative or greater than the number of child units in <code>refNode</code>. Child units are <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/glossary.html#dt-16-bit-unit" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>16-bit units</em></a> if <code>refNode</code> is a type of CharacterData node (e.g., a Text or Comment node) or a ProcessingInstruction node. Child units are Nodes in all other cases.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-setStartAfter" name="Level2-Range-method-setStartAfter">setStartAfter</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the start position to be after a node<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Range starts after <code>refNode</code><br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if the root container of <code>refNode</code> is not an Attr, Document, or DocumentFragment node or if <code>refNode</code> is a Document, DocumentFragment, Attr, Entity, or Notation node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-setStartBefore" name="Level2-Range-setStartBefore">setStartBefore</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Sets the start position to be before a node<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">refNode</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">Range starts before <code>refNode</code><br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>INVALID_NODE_TYPE_ERR: Raised if the root container of <code>refNode</code> is not an Attr, Document, or DocumentFragment node or if <code>refNode</code> is a Document, DocumentFragment, Attr, Entity, or Notation node.</p></td></tr><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-surroundContents" name="Level2-Range-method-surroundContents">surroundContents</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Reparents the contents of the Range to the given node and inserts the node at the position of the start of the Range.<div class="parameters"><b>Parameters</b><div class="paramtable" style="margin-left: 1em;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="parameter-name" style="background-color: rgb(254, 230, 248);">newParent</code> of type <code>Node</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">The node to surround the contents with.<br></dd></dl></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>NO_MODIFICATION_ALLOWED_ERR: Raised if an <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-ancestor-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>ancestor container</em></a> of either boundary-point of the Range is read-only.</p><p>WRONG_DOCUMENT_ERR: Raised if <code>newParent</code> and the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of the start of the Range were not created from the same document.</p><p>HIERARCHY_REQUEST_ERR: Raised if the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of the start of the Range is of a type that does not allow children of the type of <code>newParent</code> or if<code>newParent</code> is an ancestor of the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> or if <code>node</code> would end up with a child node of a type not allowed by the type of <code>node</code>.</p><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a></p></td><td><p>BAD_BOUNDARYPOINTS_ERR: Raised if the Range <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-partially-selected" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>partially selects</em></a> a non-text node.</p><p>INVALID_NODE_TYPE_ERR: Raised if <code>node</code> is an Attr, Entity, DocumentType, Notation, Document, or DocumentFragment node.</p></td></tr></tbody></table></div></div><div><b>No Return Value</b></div></div></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-Range-method-toString" name="Level2-Range-method-toString">toString</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">Returns the contents of a Range as a string. This string contains only the data characters, not any markup.<div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMString</code></p></td><td><p>The contents of the Range.</p></td></tr></tbody></table></div></div><div class="exceptions"><b>Exceptions</b><div class="exceptiontable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the exception, the second contains the specific error code and a short description" border="0"><tbody><tr><td valign="top"><p><code>DOMException</code></p></td><td><p>INVALID_STATE_ERR: Raised if <code>detach()</code> has already been invoked on this object.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div></div></dd></dl></dd></dl></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Interface <i><a id="Level-2-DocumentRange-idl" name="Level-2-DocumentRange-idl">DocumentRange</a></i></b> (introduced in <b class="since">DOM Level 2</b>)</dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><br><b>IDL Definition</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="idl-code" style="font-family: monospace;border-top-width: 1px;border-right-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-left-style: solid;border-top-color: black;border-right-color: black;border-bottom-color: black;border-left-color: black;border-image: initial;white-space: pre;background-color: rgb(223, 223, 223);"><pre style="margin-left: 2em;">// Introduced in DOM Level 2:interface DocumentRange{Range createRange();};</pre></div><br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Methods</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="method-name" style="background-color: rgb(217, 230, 248);"><a id="Level2-DocumentRange-method-createRange" name="Level2-DocumentRange-method-createRange">createRange</a></code></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="method">This interface can be obtained from the object implementing the <code>Document</code> interface using binding-specific casting methods.<div class="return"><b>Return Value</b><div class="returntable" style="margin-left: 1em;"><table summary="Layout table: the first cell contains the type of the return value, the second contains a short description" border="0"><tbody><tr><td valign="top"><p><a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-idl" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>Range</code></a></p></td><td><p>The initial state of the Range returned from this method is such that both of its boundary-points are positioned at the beginning of the corresponding Document, before any content. The Range returned can only be used to select content associated with this Document, or with DocumentFragments and Attrs for which this Document is the <code>ownerDocument</code>.</p></td></tr></tbody></table></div></div><div><b>No Parameters</b></div><div><b>No Exceptions</b></div></div></dd></dl></dd></dl></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Exception <i><a id="RangeException" name="RangeException">RangeException</a></i></b> introduced in <b class="version">DOM Level 2</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><p>Range operations may throw a <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#RangeException" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><code>RangeException</code></a> as specified in their method descriptions.</p><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><br><b>IDL Definition</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><div class="idl-code" style="font-family: monospace;border-top-width: 1px;border-right-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-left-style: solid;border-top-color: black;border-right-color: black;border-bottom-color: black;border-left-color: black;border-image: initial;white-space: pre;background-color: rgb(223, 223, 223);"><pre style="margin-left: 2em;">// Introduced in DOM Level 2:exception RangeException{unsigned short code;};// RangeExceptionCodeconst unsigned short BAD_BOUNDARYPOINTS_ERR=1;const unsigned short INVALID_NODE_TYPE_ERR=2;</pre></div><br></dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Definition group <i><a id="RangeExceptionCode" name="RangeExceptionCode">RangeExceptionCode</a></i></b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><p>An integer indicating the type of error generated.</p><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><b>Defined Constants</b></dt><dd style="margin-top: 0px;margin-bottom: 0px;"><dl><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">BAD_BOUNDARYPOINTS_ERR</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">If the boundary-points of a Range do not meet specific requirements.</dd><dt style="margin-top: 0px;margin-bottom: 0px;font-weight: bold;"><code class="constant-name" style="background-color: rgb(221, 255, 210);">INVALID_NODE_TYPE_ERR</code></dt><dd style="margin-top: 0px;margin-bottom: 0px;">If the <a href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#td-container" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;"><em>container</em></a> of an boundary-point of a Range is being set to either a node of an invalid type or a node with an ancestor of an invalid type.</dd></dl></dd></dl></dd></dl></dd></dl></div></div><div class="navbar" align="center" style="color: rgb(0, 0, 0);font-family: sans-serif;font-size: medium;"><hr title="Navigation area separator"><a accesskey="p" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">previous</a>   <a accesskey="n" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/idl-definitions.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">next</a>   <a accesskey="c" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/Overview.html#contents" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">contents</a>   <a accesskey="i" href="http://www.w3.org/TR/DOM-Level-2-Traversal-Range/def-index.html" style="color: rgb(102, 0, 153);background-image: initial;background-attachment: initial;background-origin: initial;background-clip: initial;background-color: transparent;background-position: initial initial;background-repeat: initial initial;">index</a></div></p><dl></dl>
291 </textarea>
292
293 <h2>Deeply nested divs</h2>
294 <textarea name="editor4">
295 <p> </p><h1 id="mainHeader" style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; font-weight: normal; font-size: 26px; color: rgb(7, 130, 193); font-family: Arial, Helvetica, sans-serif; background-color: rgb(226, 226, 226); ">Jobs</h1><div id="node-438" class="node node-type-page" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 18px; color: rgb(85, 85, 85); font-family: Arial, Helvetica, sans-serif; background-color: rgb(226, 226, 226); "><div class="node-inner" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><div class="meta" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "> </div><div class="content" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><div class="contentBox" style="margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 0px; padding-top: 15px; padding-right: 15px; padding-bottom: 1px; padding-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; background-color: rgb(239, 239, 239); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(226, 226, 226); border-right-color: rgb(226, 226, 226); border-bottom-color: rgb(226, 226, 226); border-left-color: rgb(226, 226, 226); position: relative; "><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">CKSource is a successful company with thousands of customers all around the world, including top names like IBM and Oracle. Our company is growing fast, with impressive sales results. This strong growth expands our range of opportunities, followed by the growth of our team. Take this chance and&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">join us!</strong></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Working in a&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">successful Open Source project&nbsp;</strong>is certainly a lot of fun. CKEditor is one of the most frequently used text editors out there, and this success means new responsibilities. We are providing a key component for the software that is powering the Web today. It is downloaded daily by thousands of people all around the world and used by hundreds of thousands out there.</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">We are constantly looking for top-notch, creative, and enthusiastic professionals ready to join our international team.</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">We offer a work culture where ideas are free to fly and diversity is our everyday life.</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">There is no need to relocate. No matter where you are, as long as you love what you do, you are the right person for us!</p><div class="post joboffer" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 10px; padding-right: 0px; padding-bottom: 5px; padding-left: 0px; border-top-width: 1px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; border-top-style: solid; border-top-color: rgb(229, 230, 231); " id=""><h2 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; font-size: 15px; color: rgb(0, 0, 0); ">AJD - Advanced JavaScript Developer</h2><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Location:&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Europe and Its Neighbourhood</strong>&nbsp;(from GMT 0 to GMT +2).</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Employment type:&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Full time</strong>.</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">We are looking for talented people to join our team. Ideal candidates will have:</p><ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-right: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Several years of experience with professional JavaScript programming, which we consider is;<ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-right: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Writing pure, object-oriented JavaScript applications.</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Ability to create complex JavaScript applications based on your own skills only (excluding usage of external libraries such as jQuery, Prototype, Dojo, or MooTools).</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Being aware and able to solving asynchronous issues.</li></ul></li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">In-depth knowledge of core Web standards, like HTML, XML, DOM, and CSS — including their intrinsic implementation differences among browsers (with IE6 also);</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Ability to understand and fix complicated DOM manipulation problems.</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Good (enough) English speaking and writing skills. This is the language used in the company.</li></ul><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">"Wow" candidates will also have (not required though):</p><ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-right: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Experience with CKEditor or FCKeditor, having possibly collaborated with the project;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Experience with rich text editors;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Experience with HTML5, CSS3 development;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Experience with Test Cases (like YUI Test);</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">A Bachelor's or Master's degree in Computer Science;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Passion for Open Source.</li></ul></div><div class="post" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 10px; padding-right: 0px; padding-bottom: 30px; padding-left: 0px; border-top-width: 1px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; border-top-style: solid; border-top-color: rgb(229, 230, 231); " id=""><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; font-size: 14px; ">In return we offer:</h3><ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-right: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Permanent full time employment contract;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Flexible working hours;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Competitive salary;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Work&nbsp;</strong>from&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">home</strong>&nbsp;(you will forget what a traffic jam is);</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Working with smart and motivated&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">professionals</strong>;</li><li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Becoming a&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">part of great team</strong>&nbsp;who delivers worldwide known software.</li></ul><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Let us start talking. Tell us about the projects you have worked on and your role in them; point to your experience and anything you think might make you a perfect candidate. Contact us with your CV at:&nbsp;<a href="" title="jobs at (spam protection) cksource dot com" id="jobmail1" style="color: rgb(24, 157, 225); ">jobs@cksource.com</a>&nbsp;now!</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">We are sure you will enjoy it!</p></div><div class="post" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 10px; padding-right: 0px; padding-bottom: 30px; padding-left: 0px; border-top-width: 1px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; border-top-style: solid; border-top-color: rgb(229, 230, 231); "><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">Please note we only accept CV's in English. Your application must include the following note:</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; line-height: 1.5em; ">"I hereby authorize you to process my personal data included in my job application for the needs of the recruitment process (in accordance to the Personal Data Protection Act 29.08.1997 no 133 position 883).”</p></div></div></div></div></div><dl></dl>
296 </textarea>
297
298 <h2>Line custom look</h2>
299 <div id="hood">
300 <h1>
301 <img alt="" src="http://a.cksource.com/c/1/inc/img/demo-little-red.jpg" style="margin-left: 10px; margin-right: 10px; float: left; width: 120px; height: 168px;" />Little Red Riding Hood</h1>
302 <p>
303 &quot;<b>Little Red Riding Hood</b>&quot; is a famous <a href="http://en.wikipedia.org/wiki/Fairy_tale" title="Fairy tale">fairy tale</a> about a young girl&#39;s encounter with a wolf. The story has been changed considerably in its history and subject to numerous modern adaptations and readings.</p>
304 <table align="right" border="1" cellpadding="1" cellspacing="1" style="width: 200px;">
305 <caption>
306 <strong>International Names</strong></caption>
307 <tbody>
308 <tr>
309 <td>
310 Chinese</td>
311 <td>
312 <i>小紅帽</i></td>
313 </tr>
314 <tr>
315 <td>
316 Italian</td>
317 <td>
318 <i>Cappuccetto Rosso</i></td>
319 </tr>
320 <tr>
321 <td>
322 Spanish</td>
323 <td>
324 <i>Caperucita Roja</i></td>
325 </tr>
326 </tbody>
327 </table>
328 <hr>
329 <hr>
330 <p>
331 The version most widely known today is based on the <a href="http://en.wikipedia.org/wiki/Brothers_Grimm" title="Brothers Grimm">Brothers Grimm</a> variant. It is about a girl called Little Red Riding Hood, after the red <a href="http://en.wikipedia.org/wiki/Hood_%28headgear%29" title="Hood (headgear)">hooded</a> <a href="http://en.wikipedia.org/wiki/Cape" title="Cape">cape</a> or <a href="http://en.wikipedia.org/wiki/Cloak" title="Cloak">cloak</a> she wears. The girl walks through the woods to deliver food to her sick grandmother.</p>
332 <p>
333 A wolf wants to eat the girl but is afraid to do so in public. He approaches the girl, and she na&iuml;vely tells him where she is going. He suggests the girl pick some flowers, which she does. In the meantime, he goes to the grandmother&#39;s house and gains entry by pretending to be the girl. He swallows the grandmother whole, and waits for the girl, disguised as the grandmother.</p>
334 <p>
335 When the girl arrives, she notices he looks very strange to be her grandma. In most retellings, this eventually culminates with Little Red Riding Hood saying, &quot;My, what big teeth you have!&quot;<br />
336 To which the wolf replies, &quot;The better to eat you with,&quot; and swallows her whole, too.</p>
337 <p>
338 A <a href="http://en.wikipedia.org/wiki/Hunter" title="Hunter">hunter</a>, however, comes to the rescue and cuts the wolf open. Little Red Riding Hood and her grandmother emerge unharmed. They fill the wolf&#39;s body with heavy stones, which drown him when he falls into a well. Other versions of the story have had the grandmother shut in the closet instead of eaten, and some have Little Red Riding Hood saved by the hunter as the wolf advances on her rather than after she is eaten.</p>
339 <p>
340 The tale makes the clearest contrast between the safe world of the village and the dangers of the <a href="http://en.wikipedia.org/wiki/Enchanted_forest" title="Enchanted forest">forest</a>, conventional antitheses that are essentially medieval, though no written versions are as old as that.</p>
341 </div>
342
343 <h2>Extreme inline editing</h2>
344 <div id="interpret" contenteditable="true" style="left: 123px; outline: 1px solid red; border: 15px solid green; position: relative; top: 30; left: 30px;">
345 <div style="padding: 20px; background: gray; width: 300px" class="1">Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies. Curabitur et ligula. Ut molestie a, ultricies porta urna. Vestibulum commodo volutpat a, convallis ac, laoreet enim.</div>
346 <div style="background: violet; padding: 30px;" class="static">
347 Position static
348 <div style="background: green; padding: 30px; border: 14px solid orange">foo</div>
349 </div>
350 <dl class="2">
351 <dt>Key</dt><dd>Value</dd>
352 </dl>
353 <div>Whatever</div>
354 <hr id="hr">
355 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
356 <hr>
357 <hr>
358 <p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, malesuada ultricies</p>
359 <div style="background: green; padding: 30px; width: 200px">foo</div>
360 </div>
361
362 <h2>Enter mode: BR</h2>
363 <textarea cols="80" id="editor5" name="editor5" rows="10">
364 Foo<br />
365 <hr style="margin: 50px" />
366 <hr style="margin: 50px" />
367 Foo
368 </textarea>
369
370 <div id="dev">
371 <p id="mouseData">
372 <span>Mouse over: <strong id="over"></strong></span>
373 <span style="display: block">Mouse Y-pos.: <span id="my"></span></span>
374 </p>
375 <p id="triggerData">
376 <span id="tr_type"></span>
377 <span id="tr_upper"></span>
378 <span id="tr_lower"></span>
379 <span id="tr_edge"></span>
380 </dl>
381 <p id="timeData">Time: <span id="time"></span></p>
382 <p id="hiddenData">Hidden state: <span id="hid"></span></p>
383 </div>
384 <script>
385
386 'use strict';
387
388 function fixedWidthNumber( text, chars ) {
389 return ( Array( chars ).join( 0 ) + text ).slice( -chars );
390 }
391
392 var DEBUG = {
393 startTimer: function() {
394 DEBUG.timer = new Date().getTime();
395 },
396
397 stopTimer: (function() {
398 var label = CKEDITOR.document.getById( 'time' ),
399 max = 0,
400 count = 0,
401 values = [],
402 mean = 0,
403 time = 0;
404
405 return function() {
406 time = new Date().getTime() - DEBUG.timer;
407 max = Math.max( time, max );
408
409 values.unshift( time );
410 ( 20 in values ) && values.pop();
411 mean = 0;
412
413 for( var i = 0 ; i < values.length ; i++ )
414 mean += values[ i ];
415
416 mean = mean / i;
417
418 label.setText( fixedWidthNumber( time, 3 ) +
419 ' ms, mean: ' + fixedWidthNumber( 0 | mean, 3 ) +
420 ' ms, max: ' + fixedWidthNumber( max, 3 ) +
421 ' ms' )
422 count++;
423 }
424 })(),
425
426 mousePos: (function( y, element )
427 {
428 var my = CKEDITOR.document.getById( 'my' ),
429 over = CKEDITOR.document.getById( 'over' ),
430 name;
431
432 return function( y, element ) {
433 my.setText( y );
434
435 if( element && element.$ && element.type == CKEDITOR.NODE_ELEMENT ) {
436 try {
437 name = element.getName();
438 over.setText( name + '.' + element.getAttribute( 'class' ) );
439 } catch( e ) {}
440 }
441 else
442 over.setText( '-' );
443 }
444 })(),
445
446 showTrigger: (function( trigger )
447 {
448 var tr_type = CKEDITOR.document.getById( 'tr_type' ),
449 tr_upper = CKEDITOR.document.getById( 'tr_upper' ),
450 tr_lower = CKEDITOR.document.getById( 'tr_lower' ),
451 tr_edge = CKEDITOR.document.getById( 'tr_edge' ),
452 tup, tbo, upper, lower;
453
454 return function( trigger ) {
455 tup && tup.removeAttribute('id') && ( tup = null );
456 tbo && tbo.removeAttribute('id') && ( tbo = null );
457
458 if ( !trigger )
459 return tr_type.setText( '-' ) &&
460 tr_upper.setText( '-' ) &&
461 tr_lower.setText( '-' ) &&
462 tr_edge.setText( '-' );
463
464 upper = trigger.upper,
465 lower = trigger.lower;
466
467 tr_type.setText( trigger.type == 2 ? 'EXPAND': 'EDGE' );
468 tr_upper.setText( upper ? upper.getName() + '.' + upper.getAttribute( 'class' ): 'NULL' );
469 tr_lower.setText( lower ? lower.getName() + '.' + lower.getAttribute( 'class' ): 'NULL' );
470 tr_edge.setText( trigger.edge ? [ 'EDGE_TOP', 'EDGE_BOTTOM', 'EDGE_MIDDLE' ][ trigger.edge - 1 ]: 'NULL' );
471
472 upper && ( tup = upper ) && tup.setAttribute( 'id', 'tup' );
473 lower && ( tbo = lower ) && tbo.setAttribute( 'id', 'tbo' );
474 }
475 })(),
476
477 showHidden: (function( state )
478 {
479 var cnt = CKEDITOR.document.getById( 'hid' );
480
481 return function( state ) {
482 cnt[ state ? 'addClass': 'removeClass' ]( 'hl' );
483 cnt.setText( state ? 'enabled': 'disabled' );
484 }
485 })(),
486
487 markElement: function( element ) {
488 if( !isHtml( element ))
489 return;
490
491 DEBUG.marked && DEBUG.marked.setStyles( {
492 'outline': 'none'
493 } );
494
495 DEBUG.marked = element;
496
497 element.setStyles( {
498 'outline': 'red solid 2px'
499 } );
500 },
501
502 // Log functions.
503 log: function() {},
504 logElements: function() {},
505 groupStart: function() {},
506 groupEnd: function() {},
507 logEnd: function() {},
508 logElementsEnd: function() {}
509 };
510
511 var logEnable = {
512 log: function() {
513 var args = [];
514 for( var i = 0; i < arguments.length ; i++ )
515 args.push( arguments[ i ] );
516
517 console.log.apply( console, args );
518 },
519
520 logElements: function( elements, labels, info ) {
521 var log = {},
522 label;
523
524 for ( var i = 0 ; i < elements.length; i++ ) {
525 label = labels ? labels [ i ] : i;
526
527 if( !elements[ i ] ) {
528 log[ label ] = {
529 'name': 'null',
530 'class': 'null'
531 }
532 }
533 else {
534 log[ labels ? labels [ i ]: i ] = {
535 'name': elements[ i ].is ? elements[ i ].getName(): 'null',
536 'class': elements[ i ].is ? elements[ i ].getAttribute( 'class' ): 'null'
537 }
538 }
539 }
540
541 typeof JSON != 'undefined' && DEBUG.log( ( info ? info.toUpperCase() + ' ': '' ) + JSON.stringify( log ) );
542 },
543
544 groupStart: function( label ) {
545 console.group( label );
546 },
547
548 groupEnd: function() {
549 console.groupEnd();
550 },
551
552 logEnd: function() {
553 DEBUG.log.apply( null, arguments );
554 DEBUG.groupEnd();
555 },
556
557 logElementsEnd: function() {
558 DEBUG.logElements.apply( null, arguments );
559 DEBUG.groupEnd();
560 }
561 }
562
563 // Enable console.log debugging with ?debug address parameter.
564 window.location.href.match( /debug$/g ) ? CKEDITOR.tools.extend( DEBUG, logEnable, true ): null;
565
566 // CKEDITOR.addCss('\
567 // #tup { outline: #FEB2B2 solid 2px; box-shadow: 3px 3px 0 #FEB2B2; } \
568 // #tbo { outline: #B2FEB2 solid 2px; box-shadow: 3px 3px 0 #B2FEB2; } \
569 // p { background: pink }\
570 // ');
571
572 CKEDITOR.replace( 'editor1' );
573
574 CKEDITOR.replace( 'editor2', { height: 150 } );
575
576 CKEDITOR.replace( 'editor3', {
577 magicline_everywhere: 1,
578 magicline_holdDistance: .2,
579 language: 'pl'
580 });
581
582 CKEDITOR.replace( 'editor4' );
583
584 CKEDITOR.replace( 'hood', {
585 magicline_color: 'green'
586 });
587
588 CKEDITOR.replace( 'editor5', {
589 enterMode : CKEDITOR.ENTER_BR
590 });
591
592 </script>
593</body>
594</html>
diff --git a/sources/plugins/magicline/images/hidpi/icon-rtl.png b/sources/plugins/magicline/images/hidpi/icon-rtl.png
new file mode 100644
index 0000000..4a8d2bf
--- /dev/null
+++ b/sources/plugins/magicline/images/hidpi/icon-rtl.png
Binary files differ
diff --git a/sources/plugins/magicline/images/hidpi/icon.png b/sources/plugins/magicline/images/hidpi/icon.png
new file mode 100644
index 0000000..b981bb5
--- /dev/null
+++ b/sources/plugins/magicline/images/hidpi/icon.png
Binary files differ
diff --git a/sources/plugins/magicline/images/icon-rtl.png b/sources/plugins/magicline/images/icon-rtl.png
new file mode 100644
index 0000000..55b5b5f
--- /dev/null
+++ b/sources/plugins/magicline/images/icon-rtl.png
Binary files differ
diff --git a/sources/plugins/magicline/images/icon.png b/sources/plugins/magicline/images/icon.png
new file mode 100644
index 0000000..e063433
--- /dev/null
+++ b/sources/plugins/magicline/images/icon.png
Binary files differ
diff --git a/sources/plugins/magicline/lang/af.js b/sources/plugins/magicline/lang/af.js
new file mode 100644
index 0000000..9b9dc2b
--- /dev/null
+++ b/sources/plugins/magicline/lang/af.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'af', {
7 title: 'Voeg paragraaf hier in'
8} );
diff --git a/sources/plugins/magicline/lang/ar.js b/sources/plugins/magicline/lang/ar.js
new file mode 100644
index 0000000..1c411f3
--- /dev/null
+++ b/sources/plugins/magicline/lang/ar.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ar', {
7 title: 'إدراج فقرة هنا'
8} );
diff --git a/sources/plugins/magicline/lang/az.js b/sources/plugins/magicline/lang/az.js
new file mode 100644
index 0000000..02664f1
--- /dev/null
+++ b/sources/plugins/magicline/lang/az.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'az', {
7 title: 'Abzası burada əlavə et'
8} );
diff --git a/sources/plugins/magicline/lang/bg.js b/sources/plugins/magicline/lang/bg.js
new file mode 100644
index 0000000..768af06
--- /dev/null
+++ b/sources/plugins/magicline/lang/bg.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'bg', {
7 title: 'Вмъкнете параграф тук'
8} );
diff --git a/sources/plugins/magicline/lang/ca.js b/sources/plugins/magicline/lang/ca.js
new file mode 100644
index 0000000..dcd9c1a
--- /dev/null
+++ b/sources/plugins/magicline/lang/ca.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ca', {
7 title: 'Insereix el paràgraf aquí'
8} );
diff --git a/sources/plugins/magicline/lang/cs.js b/sources/plugins/magicline/lang/cs.js
new file mode 100644
index 0000000..4705efd
--- /dev/null
+++ b/sources/plugins/magicline/lang/cs.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'cs', {
7 title: 'zde vložit odstavec'
8} );
diff --git a/sources/plugins/magicline/lang/cy.js b/sources/plugins/magicline/lang/cy.js
new file mode 100644
index 0000000..13e1085
--- /dev/null
+++ b/sources/plugins/magicline/lang/cy.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'cy', {
7 title: 'Mewnosod paragraff yma'
8} );
diff --git a/sources/plugins/magicline/lang/da.js b/sources/plugins/magicline/lang/da.js
new file mode 100644
index 0000000..ee4fa17
--- /dev/null
+++ b/sources/plugins/magicline/lang/da.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'da', {
7 title: 'Indsæt afsnit'
8} );
diff --git a/sources/plugins/magicline/lang/de-ch.js b/sources/plugins/magicline/lang/de-ch.js
new file mode 100644
index 0000000..d6bd3b7
--- /dev/null
+++ b/sources/plugins/magicline/lang/de-ch.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'de-ch', {
7 title: 'Absatz hier einfügen'
8} );
diff --git a/sources/plugins/magicline/lang/de.js b/sources/plugins/magicline/lang/de.js
new file mode 100644
index 0000000..189d564
--- /dev/null
+++ b/sources/plugins/magicline/lang/de.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'de', {
7 title: 'Absatz hier einfügen'
8} );
diff --git a/sources/plugins/magicline/lang/el.js b/sources/plugins/magicline/lang/el.js
new file mode 100644
index 0000000..528a554
--- /dev/null
+++ b/sources/plugins/magicline/lang/el.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'el', {
7 title: 'Εισάγετε παράγραφο εδώ'
8} );
diff --git a/sources/plugins/magicline/lang/en-gb.js b/sources/plugins/magicline/lang/en-gb.js
new file mode 100644
index 0000000..e0d3779
--- /dev/null
+++ b/sources/plugins/magicline/lang/en-gb.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'en-gb', {
7 title: 'Insert paragraph here'
8} );
diff --git a/sources/plugins/magicline/lang/en.js b/sources/plugins/magicline/lang/en.js
new file mode 100644
index 0000000..37ef2ed
--- /dev/null
+++ b/sources/plugins/magicline/lang/en.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'en', {
7 title: 'Insert paragraph here'
8} );
diff --git a/sources/plugins/magicline/lang/eo.js b/sources/plugins/magicline/lang/eo.js
new file mode 100644
index 0000000..3cf6286
--- /dev/null
+++ b/sources/plugins/magicline/lang/eo.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'eo', {
7 title: 'Enmeti paragrafon ĉi-tien'
8} );
diff --git a/sources/plugins/magicline/lang/es.js b/sources/plugins/magicline/lang/es.js
new file mode 100644
index 0000000..f9a8f52
--- /dev/null
+++ b/sources/plugins/magicline/lang/es.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'es', {
7 title: 'Insertar párrafo aquí'
8} );
diff --git a/sources/plugins/magicline/lang/et.js b/sources/plugins/magicline/lang/et.js
new file mode 100644
index 0000000..9d2fe53
--- /dev/null
+++ b/sources/plugins/magicline/lang/et.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'et', {
7 title: 'Sisesta siia lõigu tekst'
8} );
diff --git a/sources/plugins/magicline/lang/eu.js b/sources/plugins/magicline/lang/eu.js
new file mode 100644
index 0000000..25daf45
--- /dev/null
+++ b/sources/plugins/magicline/lang/eu.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'eu', {
7 title: 'Txertatu paragrafoa hemen'
8} );
diff --git a/sources/plugins/magicline/lang/fa.js b/sources/plugins/magicline/lang/fa.js
new file mode 100644
index 0000000..d09ddfc
--- /dev/null
+++ b/sources/plugins/magicline/lang/fa.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'fa', {
7 title: 'قرار دادن بند در اینجا'
8} );
diff --git a/sources/plugins/magicline/lang/fi.js b/sources/plugins/magicline/lang/fi.js
new file mode 100644
index 0000000..094bd9d
--- /dev/null
+++ b/sources/plugins/magicline/lang/fi.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'fi', {
7 title: 'Lisää kappale tähän.'
8} );
diff --git a/sources/plugins/magicline/lang/fr-ca.js b/sources/plugins/magicline/lang/fr-ca.js
new file mode 100644
index 0000000..6319f1c
--- /dev/null
+++ b/sources/plugins/magicline/lang/fr-ca.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'fr-ca', {
7 title: 'Insérer le paragraphe ici'
8} );
diff --git a/sources/plugins/magicline/lang/fr.js b/sources/plugins/magicline/lang/fr.js
new file mode 100644
index 0000000..430fc5f
--- /dev/null
+++ b/sources/plugins/magicline/lang/fr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'fr', {
7 title: 'Insérer un paragraphe ici'
8} );
diff --git a/sources/plugins/magicline/lang/gl.js b/sources/plugins/magicline/lang/gl.js
new file mode 100644
index 0000000..5aaa968
--- /dev/null
+++ b/sources/plugins/magicline/lang/gl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'gl', {
7 title: 'Inserir aquí o parágrafo'
8} );
diff --git a/sources/plugins/magicline/lang/he.js b/sources/plugins/magicline/lang/he.js
new file mode 100644
index 0000000..9c01d48
--- /dev/null
+++ b/sources/plugins/magicline/lang/he.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'he', {
7 title: 'הכנס פסקה כאן'
8} );
diff --git a/sources/plugins/magicline/lang/hr.js b/sources/plugins/magicline/lang/hr.js
new file mode 100644
index 0000000..1916e65
--- /dev/null
+++ b/sources/plugins/magicline/lang/hr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'hr', {
7 title: 'Ubaci paragraf ovdje'
8} );
diff --git a/sources/plugins/magicline/lang/hu.js b/sources/plugins/magicline/lang/hu.js
new file mode 100644
index 0000000..86650d5
--- /dev/null
+++ b/sources/plugins/magicline/lang/hu.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'hu', {
7 title: 'Szúrja be a bekezdést ide'
8} );
diff --git a/sources/plugins/magicline/lang/id.js b/sources/plugins/magicline/lang/id.js
new file mode 100644
index 0000000..3651e37
--- /dev/null
+++ b/sources/plugins/magicline/lang/id.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'id', {
7 title: 'Masukkan paragraf disini'
8} );
diff --git a/sources/plugins/magicline/lang/it.js b/sources/plugins/magicline/lang/it.js
new file mode 100644
index 0000000..9cc27e0
--- /dev/null
+++ b/sources/plugins/magicline/lang/it.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'it', {
7 title: 'Inserisci paragrafo qui'
8} );
diff --git a/sources/plugins/magicline/lang/ja.js b/sources/plugins/magicline/lang/ja.js
new file mode 100644
index 0000000..84d6b74
--- /dev/null
+++ b/sources/plugins/magicline/lang/ja.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ja', {
7 title: 'ここに段落を挿入'
8} );
diff --git a/sources/plugins/magicline/lang/km.js b/sources/plugins/magicline/lang/km.js
new file mode 100644
index 0000000..f670a7e
--- /dev/null
+++ b/sources/plugins/magicline/lang/km.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'km', {
7 title: 'បញ្ចូល​កថាខណ្ឌ​នៅ​ទីនេះ'
8} );
diff --git a/sources/plugins/magicline/lang/ko.js b/sources/plugins/magicline/lang/ko.js
new file mode 100644
index 0000000..0e718f3
--- /dev/null
+++ b/sources/plugins/magicline/lang/ko.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ko', {
7 title: '여기에 단락 삽입'
8} );
diff --git a/sources/plugins/magicline/lang/ku.js b/sources/plugins/magicline/lang/ku.js
new file mode 100644
index 0000000..cc3f3a4
--- /dev/null
+++ b/sources/plugins/magicline/lang/ku.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ku', {
7 title: 'بڕگە لێرە دابنێ'
8} );
diff --git a/sources/plugins/magicline/lang/lv.js b/sources/plugins/magicline/lang/lv.js
new file mode 100644
index 0000000..f96cc44
--- /dev/null
+++ b/sources/plugins/magicline/lang/lv.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'lv', {
7 title: 'Ievietot šeit rindkopu'
8} );
diff --git a/sources/plugins/magicline/lang/nb.js b/sources/plugins/magicline/lang/nb.js
new file mode 100644
index 0000000..297f270
--- /dev/null
+++ b/sources/plugins/magicline/lang/nb.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'nb', {
7 title: 'Sett inn nytt avsnitt her'
8} );
diff --git a/sources/plugins/magicline/lang/nl.js b/sources/plugins/magicline/lang/nl.js
new file mode 100644
index 0000000..bfe36ff
--- /dev/null
+++ b/sources/plugins/magicline/lang/nl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'nl', {
7 title: 'Hier paragraaf invoeren'
8} );
diff --git a/sources/plugins/magicline/lang/no.js b/sources/plugins/magicline/lang/no.js
new file mode 100644
index 0000000..e78ca76
--- /dev/null
+++ b/sources/plugins/magicline/lang/no.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'no', {
7 title: 'Sett inn nytt avsnitt her'
8} );
diff --git a/sources/plugins/magicline/lang/oc.js b/sources/plugins/magicline/lang/oc.js
new file mode 100644
index 0000000..312f547
--- /dev/null
+++ b/sources/plugins/magicline/lang/oc.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'oc', {
7 title: 'Inserir un paragraf aicí'
8} );
diff --git a/sources/plugins/magicline/lang/pl.js b/sources/plugins/magicline/lang/pl.js
new file mode 100644
index 0000000..324bf1e
--- /dev/null
+++ b/sources/plugins/magicline/lang/pl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'pl', {
7 title: 'Wstaw nowy akapit'
8} );
diff --git a/sources/plugins/magicline/lang/pt-br.js b/sources/plugins/magicline/lang/pt-br.js
new file mode 100644
index 0000000..35f3daa
--- /dev/null
+++ b/sources/plugins/magicline/lang/pt-br.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'pt-br', {
7 title: 'Insera um parágrafo aqui'
8} );
diff --git a/sources/plugins/magicline/lang/pt.js b/sources/plugins/magicline/lang/pt.js
new file mode 100644
index 0000000..c03c48a
--- /dev/null
+++ b/sources/plugins/magicline/lang/pt.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'pt', {
7 title: 'Insira aqui o parágrafo'
8} );
diff --git a/sources/plugins/magicline/lang/ru.js b/sources/plugins/magicline/lang/ru.js
new file mode 100644
index 0000000..bc41703
--- /dev/null
+++ b/sources/plugins/magicline/lang/ru.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ru', {
7 title: 'Вставить здесь параграф'
8} );
diff --git a/sources/plugins/magicline/lang/si.js b/sources/plugins/magicline/lang/si.js
new file mode 100644
index 0000000..a5cdbe8
--- /dev/null
+++ b/sources/plugins/magicline/lang/si.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'si', {
7 title: 'චේදය ඇතුලත් කරන්න'
8} );
diff --git a/sources/plugins/magicline/lang/sk.js b/sources/plugins/magicline/lang/sk.js
new file mode 100644
index 0000000..84761b2
--- /dev/null
+++ b/sources/plugins/magicline/lang/sk.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'sk', {
7 title: 'Odsek vložiť sem'
8} );
diff --git a/sources/plugins/magicline/lang/sl.js b/sources/plugins/magicline/lang/sl.js
new file mode 100644
index 0000000..6d0cf76
--- /dev/null
+++ b/sources/plugins/magicline/lang/sl.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'sl', {
7 title: 'Vstavite odstavek tukaj'
8} );
diff --git a/sources/plugins/magicline/lang/sq.js b/sources/plugins/magicline/lang/sq.js
new file mode 100644
index 0000000..d405596
--- /dev/null
+++ b/sources/plugins/magicline/lang/sq.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'sq', {
7 title: 'Vendos paragraf këtu'
8} );
diff --git a/sources/plugins/magicline/lang/sv.js b/sources/plugins/magicline/lang/sv.js
new file mode 100644
index 0000000..63327fd
--- /dev/null
+++ b/sources/plugins/magicline/lang/sv.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'sv', {
7 title: 'Infoga paragraf här'
8} );
diff --git a/sources/plugins/magicline/lang/tr.js b/sources/plugins/magicline/lang/tr.js
new file mode 100644
index 0000000..02dd216
--- /dev/null
+++ b/sources/plugins/magicline/lang/tr.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'tr', {
7 title: 'Parağrafı buraya ekle'
8} );
diff --git a/sources/plugins/magicline/lang/tt.js b/sources/plugins/magicline/lang/tt.js
new file mode 100644
index 0000000..7de33bf
--- /dev/null
+++ b/sources/plugins/magicline/lang/tt.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'tt', {
7 title: 'Бирегә параграф өстәү'
8} );
diff --git a/sources/plugins/magicline/lang/ug.js b/sources/plugins/magicline/lang/ug.js
new file mode 100644
index 0000000..0017fd4
--- /dev/null
+++ b/sources/plugins/magicline/lang/ug.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'ug', {
7 title: 'بۇ جايغا ئابزاس قىستۇر'
8} );
diff --git a/sources/plugins/magicline/lang/uk.js b/sources/plugins/magicline/lang/uk.js
new file mode 100644
index 0000000..980f0e0
--- /dev/null
+++ b/sources/plugins/magicline/lang/uk.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'uk', {
7 title: 'Вставити абзац'
8} );
diff --git a/sources/plugins/magicline/lang/vi.js b/sources/plugins/magicline/lang/vi.js
new file mode 100644
index 0000000..b302bd0
--- /dev/null
+++ b/sources/plugins/magicline/lang/vi.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'vi', {
7 title: 'Chèn đoạn vào đây'
8} );
diff --git a/sources/plugins/magicline/lang/zh-cn.js b/sources/plugins/magicline/lang/zh-cn.js
new file mode 100644
index 0000000..f0a0b3b
--- /dev/null
+++ b/sources/plugins/magicline/lang/zh-cn.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'zh-cn', {
7 title: '在这插入段落'
8} );
diff --git a/sources/plugins/magicline/lang/zh.js b/sources/plugins/magicline/lang/zh.js
new file mode 100644
index 0000000..3ac9f68
--- /dev/null
+++ b/sources/plugins/magicline/lang/zh.js
@@ -0,0 +1,8 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6CKEDITOR.plugins.setLang( 'magicline', 'zh', {
7 title: '在此插入段落'
8} );
diff --git a/sources/plugins/magicline/plugin.js b/sources/plugins/magicline/plugin.js
new file mode 100644
index 0000000..ac4bb78
--- /dev/null
+++ b/sources/plugins/magicline/plugin.js
@@ -0,0 +1,1874 @@
1/**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6/**
7 * @fileOverview The [Magic Line](http://ckeditor.com/addon/magicline) plugin that makes it easier to access some document areas that
8 * are difficult to focus.
9 */
10
11'use strict';
12
13( function() {
14 CKEDITOR.plugins.add( 'magicline', {
15 lang: 'af,ar,az,bg,ca,cs,cy,da,de,de-ch,el,en,en-gb,eo,es,et,eu,fa,fi,fr,fr-ca,gl,he,hr,hu,id,it,ja,km,ko,ku,lv,nb,nl,no,oc,pl,pt,pt-br,ru,si,sk,sl,sq,sv,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
16 init: initPlugin
17 } );
18
19 // Activates the box inside of an editor.
20 function initPlugin( editor ) {
21 // Configurables
22 var config = editor.config,
23 triggerOffset = config.magicline_triggerOffset || 30,
24 enterMode = config.enterMode,
25 that = {
26 // Global stuff is being initialized here.
27 editor: editor,
28 enterMode: enterMode,
29 triggerOffset: triggerOffset,
30 holdDistance: 0 | triggerOffset * ( config.magicline_holdDistance || 0.5 ),
31 boxColor: config.magicline_color || '#ff0000',
32 rtl: config.contentsLangDirection == 'rtl',
33 tabuList: [ 'data-cke-hidden-sel' ].concat( config.magicline_tabuList || [] ),
34 triggers: config.magicline_everywhere ? DTD_BLOCK : { table: 1, hr: 1, div: 1, ul: 1, ol: 1, dl: 1, form: 1, blockquote: 1 }
35 },
36 scrollTimeout, checkMouseTimeoutPending, checkMouseTimer;
37
38 // %REMOVE_START%
39 // Internal DEBUG uses tools located in the topmost window.
40
41 // (#9701) Due to security limitations some browsers may throw
42 // errors when accessing window.top object. Do it safely first then.
43 try {
44 that.debug = window.top.DEBUG;
45 }
46 catch ( e ) {}
47
48 that.debug = that.debug || {
49 groupEnd: function() {},
50 groupStart: function() {},
51 log: function() {},
52 logElements: function() {},
53 logElementsEnd: function() {},
54 logEnd: function() {},
55 mousePos: function() {},
56 showHidden: function() {},
57 showTrigger: function() {},
58 startTimer: function() {},
59 stopTimer: function() {}
60 };
61 // %REMOVE_END%
62
63 // Simple irrelevant elements filter.
64 that.isRelevant = function( node ) {
65 return isHtml( node ) && // -> Node must be an existing HTML element.
66 !isLine( that, node ) && // -> Node can be neither the box nor its child.
67 !isFlowBreaker( node ); // -> Node can be neither floated nor positioned nor aligned.
68 };
69
70 editor.on( 'contentDom', addListeners, this );
71
72 function addListeners() {
73 var editable = editor.editable(),
74 doc = editor.document,
75 win = editor.window;
76
77 // Global stuff is being initialized here.
78 extend( that, {
79 editable: editable,
80 inInlineMode: editable.isInline(),
81 doc: doc,
82 win: win,
83 hotNode: null
84 }, true );
85
86 // This is the boundary of the editor. For inline the boundary is editable itself.
87 // For classic (`iframe`-based) editor, the HTML element is a real boundary.
88 that.boundary = that.inInlineMode ? that.editable : that.doc.getDocumentElement();
89
90 // Enabling the box inside of inline editable is pointless.
91 // There's no need to access spaces inside paragraphs, links, spans, etc.
92 if ( editable.is( dtd.$inline ) )
93 return;
94
95 // Handle in-line editing by setting appropriate position.
96 // If current position is static, make it relative and clear top/left coordinates.
97 if ( that.inInlineMode && !isPositioned( editable ) ) {
98 editable.setStyles( {
99 position: 'relative',
100 top: null,
101 left: null
102 } );
103 }
104 // Enable the box. Let it produce children elements, initialize
105 // event handlers and own methods.
106 initLine.call( this, that );
107
108 // Get view dimensions and scroll positions.
109 // At this stage (before any checkMouse call) it is used mostly
110 // by tests. Nevertheless it a crucial thing.
111 updateWindowSize( that );
112
113 // Remove the box before an undo image is created.
114 // This is important. If we didn't do that, the *undo thing* would revert the box into an editor.
115 // Thanks to that, undo doesn't even know about the existence of the box.
116 editable.attachListener( editor, 'beforeUndoImage', function() {
117 that.line.detach();
118 } );
119
120 // Removes the box HTML from editor data string if getData is called.
121 // Thanks to that, an editor never yields data polluted by the box.
122 // Listen with very high priority, so line will be removed before other
123 // listeners will see it.
124 editable.attachListener( editor, 'beforeGetData', function() {
125 // If the box is in editable, remove it.
126 if ( that.line.wrap.getParent() ) {
127 that.line.detach();
128
129 // Restore line in the last listener for 'getData'.
130 editor.once( 'getData', function() {
131 that.line.attach();
132 }, null, null, 1000 );
133 }
134 }, null, null, 0 );
135
136 // Hide the box on mouseout if mouse leaves document.
137 editable.attachListener( that.inInlineMode ? doc : doc.getWindow().getFrame(), 'mouseout', function( event ) {
138 if ( editor.mode != 'wysiwyg' )
139 return;
140
141 // Check for inline-mode editor. If so, check mouse position
142 // and remove the box if mouse outside of an editor.
143 if ( that.inInlineMode ) {
144 var mouse = {
145 x: event.data.$.clientX,
146 y: event.data.$.clientY
147 };
148
149 updateWindowSize( that );
150 updateEditableSize( that, true );
151
152 var size = that.view.editable,
153 scroll = that.view.scroll;
154
155 // If outside of an editor...
156 if ( !inBetween( mouse.x, size.left - scroll.x, size.right - scroll.x ) || !inBetween( mouse.y, size.top - scroll.y, size.bottom - scroll.y ) ) {
157 clearTimeout( checkMouseTimer );
158 checkMouseTimer = null;
159 that.line.detach();
160 }
161 }
162
163 else {
164 clearTimeout( checkMouseTimer );
165 checkMouseTimer = null;
166 that.line.detach();
167 }
168 } );
169
170 // This one deactivates hidden mode of an editor which
171 // prevents the box from being shown.
172 editable.attachListener( editable, 'keyup', function() {
173 that.hiddenMode = 0;
174 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
175 } );
176
177 editable.attachListener( editable, 'keydown', function( event ) {
178 if ( editor.mode != 'wysiwyg' )
179 return;
180
181 var keyStroke = event.data.getKeystroke();
182
183 switch ( keyStroke ) {
184 // Shift pressed
185 case 2228240: // IE
186 case 16:
187 that.hiddenMode = 1;
188 that.line.detach();
189 }
190
191 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
192 } );
193
194 // This method ensures that checkMouse aren't executed
195 // in parallel and no more frequently than specified in timeout function.
196 // In classic (`iframe`-based) editor, document is used as a trigger, to provide magicline
197 // functionality when mouse is below the body (short content, short body).
198 editable.attachListener( that.inInlineMode ? editable : doc, 'mousemove', function( event ) {
199 checkMouseTimeoutPending = true;
200
201 if ( editor.mode != 'wysiwyg' || editor.readOnly || checkMouseTimer )
202 return;
203
204 // IE<9 requires this event-driven object to be created
205 // outside of the setTimeout statement.
206 // Otherwise it loses the event object with its properties.
207 var mouse = {
208 x: event.data.$.clientX,
209 y: event.data.$.clientY
210 };
211
212 checkMouseTimer = setTimeout( function() {
213 checkMouse( mouse );
214 }, 30 ); // balances performance and accessibility
215 } );
216
217 // This one removes box on scroll event.
218 // It is to avoid box displacement.
219 editable.attachListener( win, 'scroll', function() {
220 if ( editor.mode != 'wysiwyg' )
221 return;
222
223 that.line.detach();
224
225 // To figure this out just look at the mouseup
226 // event handler below.
227 if ( env.webkit ) {
228 that.hiddenMode = 1;
229
230 clearTimeout( scrollTimeout );
231 scrollTimeout = setTimeout( function() {
232 // Don't leave hidden mode until mouse remains pressed and
233 // scroll is being used, i.e. when dragging something.
234 if ( !that.mouseDown )
235 that.hiddenMode = 0;
236 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
237 }, 50 );
238
239 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
240 }
241 } );
242
243 // Those event handlers remove the box on mousedown
244 // and don't reveal it until the mouse is released.
245 // It is to prevent box insertion e.g. while scrolling
246 // (w/ scrollbar), selecting and so on.
247 editable.attachListener( env_ie8 ? doc : win, 'mousedown', function() {
248 if ( editor.mode != 'wysiwyg' )
249 return;
250
251 that.line.detach();
252 that.hiddenMode = 1;
253 that.mouseDown = 1;
254
255 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
256 } );
257
258 // Google Chrome doesn't trigger this on the scrollbar (since 2009...)
259 // so it is totally useless to check for scroll finish
260 // see: http://code.google.com/p/chromium/issues/detail?id=14204
261 editable.attachListener( env_ie8 ? doc : win, 'mouseup', function() {
262 that.hiddenMode = 0;
263 that.mouseDown = 0;
264 that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
265 } );
266
267 // Editor commands for accessing difficult focus spaces.
268 editor.addCommand( 'accessPreviousSpace', accessFocusSpaceCmd( that ) );
269 editor.addCommand( 'accessNextSpace', accessFocusSpaceCmd( that, true ) );
270
271 editor.setKeystroke( [
272 [ config.magicline_keystrokePrevious, 'accessPreviousSpace' ],
273 [ config.magicline_keystrokeNext, 'accessNextSpace' ]
274 ] );
275
276 // Revert magicline hot node on undo/redo.
277 editor.on( 'loadSnapshot', function() {
278 var elements, element, i;
279
280 for ( var t in { p: 1, br: 1, div: 1 } ) {
281 // document.find is not available in QM (#11149).
282 elements = editor.document.getElementsByTag( t );
283
284 for ( i = elements.count(); i--; ) {
285 if ( ( element = elements.getItem( i ) ).data( 'cke-magicline-hot' ) ) {
286 // Restore hotNode
287 that.hotNode = element;
288 // Restore last access direction
289 that.lastCmdDirection = element.data( 'cke-magicline-dir' ) === 'true' ? true : false;
290
291 return;
292 }
293 }
294 }
295 } );
296
297 // This method handles mousemove mouse for box toggling.
298 // It uses mouse position to determine underlying element, then
299 // it tries to use different trigger type in order to place the box
300 // in correct place. The following procedure is executed periodically.
301 function checkMouse( mouse ) {
302 that.debug.groupStart( 'CheckMouse' ); // %REMOVE_LINE%
303 that.debug.startTimer(); // %REMOVE_LINE%
304
305 that.mouse = mouse;
306 that.trigger = null;
307
308 checkMouseTimer = null;
309 updateWindowSize( that );
310
311 if (
312 checkMouseTimeoutPending && // There must be an event pending.
313 !that.hiddenMode && // Can't be in hidden mode.
314 editor.focusManager.hasFocus && // Editor must have focus.
315 !that.line.mouseNear() && // Mouse pointer can't be close to the box.
316 ( that.element = elementFromMouse( that, true ) ) // There must be valid element.
317 ) {
318 // If trigger exists, and trigger is correct -> show the box.
319 // Don't show the line if trigger is a descendant of some tabu-list element.
320 if ( ( that.trigger = triggerEditable( that ) || triggerEdge( that ) || triggerExpand( that ) ) &&
321 !isInTabu( that, that.trigger.upper || that.trigger.lower ) ) {
322 that.line.attach().place();
323 }
324
325 // Otherwise remove the box
326 else {
327 that.trigger = null;
328 that.line.detach();
329 }
330
331 that.debug.showTrigger( that.trigger ); // %REMOVE_LINE%
332 that.debug.mousePos( mouse.y, that.element ); // %REMOVE_LINE%
333
334 checkMouseTimeoutPending = false;
335 }
336
337 that.debug.stopTimer(); // %REMOVE_LINE%
338 that.debug.groupEnd(); // %REMOVE_LINE%
339 }
340
341 // This one allows testing and debugging. It reveals some
342 // inner methods to the world.
343 this.backdoor = {
344 accessFocusSpace: accessFocusSpace,
345 boxTrigger: boxTrigger,
346 isLine: isLine,
347 getAscendantTrigger: getAscendantTrigger,
348 getNonEmptyNeighbour: getNonEmptyNeighbour,
349 getSize: getSize,
350 that: that,
351 triggerEdge: triggerEdge,
352 triggerEditable: triggerEditable,
353 triggerExpand: triggerExpand
354 };
355 }
356 }
357
358 // Some shorthands for common methods to save bytes
359 var extend = CKEDITOR.tools.extend,
360 newElement = CKEDITOR.dom.element,
361 newElementFromHtml = newElement.createFromHtml,
362 env = CKEDITOR.env,
363 env_ie8 = CKEDITOR.env.ie && CKEDITOR.env.version < 9,
364 dtd = CKEDITOR.dtd,
365
366 // Global object associating enter modes with elements.
367 enterElements = {},
368
369 // Constant values, types and so on.
370 EDGE_TOP = 128,
371 EDGE_BOTTOM = 64,
372 EDGE_MIDDLE = 32,
373 TYPE_EDGE = 16,
374 TYPE_EXPAND = 8,
375 LOOK_TOP = 4,
376 LOOK_BOTTOM = 2,
377 LOOK_NORMAL = 1,
378 WHITE_SPACE = '\u00A0',
379 DTD_LISTITEM = dtd.$listItem,
380 DTD_TABLECONTENT = dtd.$tableContent,
381 DTD_NONACCESSIBLE = extend( {}, dtd.$nonEditable, dtd.$empty ),
382 DTD_BLOCK = dtd.$block,
383
384 // Minimum time that must elapse between two update*Size calls.
385 // It prevents constant getComuptedStyle calls and improves performance.
386 CACHE_TIME = 100,
387
388 // Shared CSS stuff for box elements
389 CSS_COMMON = 'width:0px;height:0px;padding:0px;margin:0px;display:block;' + 'z-index:9999;color:#fff;position:absolute;font-size: 0px;line-height:0px;',
390 CSS_TRIANGLE = CSS_COMMON + 'border-color:transparent;display:block;border-style:solid;',
391 TRIANGLE_HTML = '<span>' + WHITE_SPACE + '</span>';
392
393 enterElements[ CKEDITOR.ENTER_BR ] = 'br';
394 enterElements[ CKEDITOR.ENTER_P ] = 'p';
395 enterElements[ CKEDITOR.ENTER_DIV ] = 'div';
396
397 function areSiblings( that, upper, lower ) {
398 return isHtml( upper ) && isHtml( lower ) && lower.equals( upper.getNext( function( node ) {
399 return !( isEmptyTextNode( node ) || isComment( node ) || isFlowBreaker( node ) );
400 } ) );
401 }
402
403 // boxTrigger is an abstract type which describes
404 // the relationship between elements that may result
405 // in showing the box.
406 //
407 // The following type is used by numerous methods
408 // to share information about the hypothetical box placement
409 // and look by referring to boxTrigger properties.
410 function boxTrigger( triggerSetup ) {
411 this.upper = triggerSetup[ 0 ];
412 this.lower = triggerSetup[ 1 ];
413 this.set.apply( this, triggerSetup.slice( 2 ) );
414 }
415
416 boxTrigger.prototype = {
417 set: function( edge, type, look ) {
418 this.properties = edge + type + ( look || LOOK_NORMAL );
419 return this;
420 },
421
422 is: function( property ) {
423 return ( this.properties & property ) == property;
424 }
425 };
426
427 var elementFromMouse = ( function() {
428 function elementFromPoint( doc, mouse ) {
429 var pointedElement = doc.$.elementFromPoint( mouse.x, mouse.y );
430
431 // IE9QM: from times to times it will return an empty object on scroll bar hover. (#12185)
432 return pointedElement && pointedElement.nodeType ?
433 new CKEDITOR.dom.element( pointedElement ) :
434 null;
435 }
436
437 return function( that, ignoreBox, forceMouse ) {
438 if ( !that.mouse )
439 return null;
440
441 var doc = that.doc,
442 lineWrap = that.line.wrap,
443 mouse = forceMouse || that.mouse,
444 // Note: element might be null.
445 element = elementFromPoint( doc, mouse );
446
447 // If ignoreBox is set and element is the box, it means that we
448 // need to hide the box for a while, repeat elementFromPoint
449 // and show it again.
450 if ( ignoreBox && isLine( that, element ) ) {
451 lineWrap.hide();
452 element = elementFromPoint( doc, mouse );
453 lineWrap.show();
454 }
455
456 // Return nothing if:
457 // \-> Element is not HTML.
458 if ( !( element && element.type == CKEDITOR.NODE_ELEMENT && element.$ ) )
459 return null;
460
461 // Also return nothing if:
462 // \-> We're IE<9 and element is out of the top-level element (editable for inline and HTML for classic (`iframe`-based)).
463 // This is due to the bug which allows IE<9 firing mouse events on element
464 // with contenteditable=true while doing selection out (far, away) of the element.
465 // Thus we must always be sure that we stay in editable or HTML.
466 if ( env.ie && env.version < 9 ) {
467 if ( !( that.boundary.equals( element ) || that.boundary.contains( element ) ) )
468 return null;
469 }
470
471 return element;
472 };
473 } )();
474
475 // Gets the closest parent node that belongs to triggers group.
476 function getAscendantTrigger( that ) {
477 var node = that.element,
478 trigger;
479
480 if ( node && isHtml( node ) ) {
481 trigger = node.getAscendant( that.triggers, true );
482
483 // If trigger is an element, neither editable nor editable's ascendant.
484 if ( trigger && that.editable.contains( trigger ) ) {
485 // Check for closest editable limit.
486 // Don't consider trigger as a limit as it may be nested editable (includeSelf=false) (#12009).
487 var limit = getClosestEditableLimit( trigger );
488
489 // Trigger in nested editable area.
490 if ( limit.getAttribute( 'contenteditable' ) == 'true' )
491 return trigger;
492 // Trigger in non-editable area.
493 else if ( limit.is( that.triggers ) )
494 return limit;
495 else
496 return null;
497 } else {
498 return null;
499 }
500 }
501
502 return null;
503 }
504
505 function getMidpoint( that, upper, lower ) {
506 updateSize( that, upper );
507 updateSize( that, lower );
508
509 var upperSizeBottom = upper.size.bottom,
510 lowerSizeTop = lower.size.top;
511
512 return upperSizeBottom && lowerSizeTop ? 0 | ( upperSizeBottom + lowerSizeTop ) / 2 : upperSizeBottom || lowerSizeTop;
513 }
514
515 // Get nearest node (either text or HTML), but:
516 // \-> Omit all empty text nodes (containing white characters only).
517 // \-> Omit BR elements
518 // \-> Omit flow breakers.
519 function getNonEmptyNeighbour( that, node, goBack ) {
520 node = node[ goBack ? 'getPrevious' : 'getNext' ]( function( node ) {
521 return ( isTextNode( node ) && !isEmptyTextNode( node ) ) ||
522 ( isHtml( node ) && !isFlowBreaker( node ) && !isLine( that, node ) );
523 } );
524
525 return node;
526 }
527
528 function inBetween( val, lower, upper ) {
529 return val > lower && val < upper;
530 }
531
532 // Returns the closest ancestor that has contenteditable attribute.
533 // Such ancestor is the limit of (non-)editable DOM branch that element
534 // belongs to. This method omits editor editable.
535 function getClosestEditableLimit( element, includeSelf ) {
536 if ( element.data( 'cke-editable' ) )
537 return null;
538
539 if ( !includeSelf )
540 element = element.getParent();
541
542 while ( element ) {
543 if ( element.data( 'cke-editable' ) )
544 return null;
545
546 if ( element.hasAttribute( 'contenteditable' ) )
547 return element;
548
549 element = element.getParent();
550 }
551
552 return null;
553 }
554
555 // Access space line consists of a few elements (spans):
556 // \-> Line wrapper.
557 // \-> Line.
558 // \-> Line triangles: left triangle (LT), right triangle (RT).
559 // \-> Button handler (BTN).
560 //
561 // +--------------------------------------------------- line.wrap (span) -----+
562 // | +---------------------------------------------------- line (span) -----+ |
563 // | | +- LT \ +- BTN -+ / RT -+ | |
564 // | | | \ | | | / | | |
565 // | | | / | <__| | \ | | |
566 // | | +-----/ +-------+ \-----+ | |
567 // | +----------------------------------------------------------------------+ |
568 // +--------------------------------------------------------------------------+
569 //
570 function initLine( that ) {
571 var doc = that.doc,
572 // This the main box element that holds triangles and the insertion button
573 line = newElementFromHtml( '<span contenteditable="false" style="' + CSS_COMMON + 'position:absolute;border-top:1px dashed ' + that.boxColor + '"></span>', doc ),
574 iconPath = CKEDITOR.getUrl( this.path + 'images/' + ( env.hidpi ? 'hidpi/' : '' ) + 'icon' + ( that.rtl ? '-rtl' : '' ) + '.png' );
575
576 extend( line, {
577
578 attach: function() {
579 // Only if not already attached
580 if ( !this.wrap.getParent() )
581 this.wrap.appendTo( that.editable, true );
582
583 return this;
584 },
585
586 // Looks are as follows: [ LOOK_TOP, LOOK_BOTTOM, LOOK_NORMAL ].
587 lineChildren: [
588 extend(
589 newElementFromHtml(
590 '<span title="' + that.editor.lang.magicline.title +
591 '" contenteditable="false">&#8629;</span>', doc
592 ), {
593 base: CSS_COMMON + 'height:17px;width:17px;' + ( that.rtl ? 'left' : 'right' ) + ':17px;' +
594 'background:url(' + iconPath + ') center no-repeat ' + that.boxColor + ';cursor:pointer;' +
595 ( env.hc ? 'font-size: 15px;line-height:14px;border:1px solid #fff;text-align:center;' : '' ) +
596 ( env.hidpi ? 'background-size: 9px 10px;' : '' ),
597 looks: [
598 'top:-8px; border-radius: 2px;',
599 'top:-17px; border-radius: 2px 2px 0px 0px;',
600 'top:-1px; border-radius: 0px 0px 2px 2px;'
601 ]
602 }
603 ),
604 extend( newElementFromHtml( TRIANGLE_HTML, doc ), {
605 base: CSS_TRIANGLE + 'left:0px;border-left-color:' + that.boxColor + ';',
606 looks: [
607 'border-width:8px 0 8px 8px;top:-8px',
608 'border-width:8px 0 0 8px;top:-8px',
609 'border-width:0 0 8px 8px;top:0px'
610 ]
611 } ),
612 extend( newElementFromHtml( TRIANGLE_HTML, doc ), {
613 base: CSS_TRIANGLE + 'right:0px;border-right-color:' + that.boxColor + ';',
614 looks: [
615 'border-width:8px 8px 8px 0;top:-8px',
616 'border-width:8px 8px 0 0;top:-8px',
617 'border-width:0 8px 8px 0;top:0px'
618 ]
619 } )
620 ],
621
622 detach: function() {
623 // Detach only if already attached.
624 if ( this.wrap.getParent() )
625 this.wrap.remove();
626
627 return this;
628 },
629
630 // Checks whether mouseY is around an element by comparing boundaries and considering
631 // an offset distance.
632 mouseNear: function() {
633 that.debug.groupStart( 'mouseNear' ); // %REMOVE_LINE%
634
635 updateSize( that, this );
636 var offset = that.holdDistance,
637 size = this.size;
638
639 // Determine neighborhood by element dimensions and offsets.
640 if ( size && inBetween( that.mouse.y, size.top - offset, size.bottom + offset ) && inBetween( that.mouse.x, size.left - offset, size.right + offset ) ) {
641 that.debug.logEnd( 'Mouse is near.' ); // %REMOVE_LINE%
642 return true;
643 }
644
645 that.debug.logEnd( 'Mouse isn\'t near.' ); // %REMOVE_LINE%
646 return false;
647 },
648
649 // Adjusts position of the box according to the trigger properties.
650 // If also affects look of the box depending on the type of the trigger.
651 place: function() {
652 var view = that.view,
653 editable = that.editable,
654 trigger = that.trigger,
655 upper = trigger.upper,
656 lower = trigger.lower,
657 any = upper || lower,
658 parent = any.getParent(),
659 styleSet = {};
660
661 // Save recent trigger for further insertion.
662 // It is necessary due to the fact, that that.trigger may
663 // contain different boxTrigger at the moment of insertion
664 // or may be even null.
665 this.trigger = trigger;
666
667 upper && updateSize( that, upper, true );
668 lower && updateSize( that, lower, true );
669 updateSize( that, parent, true );
670
671 // Yeah, that's gonna be useful in inline-mode case.
672 if ( that.inInlineMode )
673 updateEditableSize( that, true );
674
675 // Set X coordinate (left, right, width).
676 if ( parent.equals( editable ) ) {
677 styleSet.left = view.scroll.x;
678 styleSet.right = -view.scroll.x;
679 styleSet.width = '';
680 } else {
681 styleSet.left = any.size.left - any.size.margin.left + view.scroll.x - ( that.inInlineMode ? view.editable.left + view.editable.border.left : 0 );
682 styleSet.width = any.size.outerWidth + any.size.margin.left + any.size.margin.right + view.scroll.x;
683 styleSet.right = '';
684 }
685
686 // Set Y coordinate (top) for trigger consisting of two elements.
687 if ( upper && lower ) {
688 // No margins at all or they're equal. Place box right between.
689 if ( upper.size.margin.bottom === lower.size.margin.top )
690 styleSet.top = 0 | ( upper.size.bottom + upper.size.margin.bottom / 2 );
691 else {
692 // Upper margin < lower margin. Place at lower margin.
693 if ( upper.size.margin.bottom < lower.size.margin.top )
694 styleSet.top = upper.size.bottom + upper.size.margin.bottom;
695 // Upper margin > lower margin. Place at upper margin - lower margin.
696 else
697 styleSet.top = upper.size.bottom + upper.size.margin.bottom - lower.size.margin.top;
698 }
699 }
700 // Set Y coordinate (top) for single-edge trigger.
701 else if ( !upper )
702 styleSet.top = lower.size.top - lower.size.margin.top;
703 else if ( !lower ) {
704 styleSet.top = upper.size.bottom + upper.size.margin.bottom;
705 }
706
707 // Set box button modes if close to the viewport horizontal edge
708 // or look forced by the trigger.
709 if ( trigger.is( LOOK_TOP ) || inBetween( styleSet.top, view.scroll.y - 15, view.scroll.y + 5 ) ) {
710 styleSet.top = that.inInlineMode ? 0 : view.scroll.y;
711 this.look( LOOK_TOP );
712 } else if ( trigger.is( LOOK_BOTTOM ) || inBetween( styleSet.top, view.pane.bottom - 5, view.pane.bottom + 15 ) ) {
713 styleSet.top = that.inInlineMode ? (
714 view.editable.height + view.editable.padding.top + view.editable.padding.bottom
715 ) : (
716 view.pane.bottom - 1
717 );
718
719 this.look( LOOK_BOTTOM );
720 } else {
721 if ( that.inInlineMode )
722 styleSet.top -= view.editable.top + view.editable.border.top;
723
724 this.look( LOOK_NORMAL );
725 }
726
727 if ( that.inInlineMode ) {
728 // 1px bug here...
729 styleSet.top--;
730
731 // Consider the editable to be an element with overflow:scroll
732 // and non-zero scrollTop/scrollLeft value.
733 // For example: divarea editable. (#9383)
734 styleSet.top += view.editable.scroll.top;
735 styleSet.left += view.editable.scroll.left;
736 }
737
738 // Append `px` prefixes.
739 for ( var style in styleSet )
740 styleSet[ style ] = CKEDITOR.tools.cssLength( styleSet[ style ] );
741
742 this.setStyles( styleSet );
743 },
744
745 // Changes look of the box according to current needs.
746 // Three different styles are available: [ LOOK_TOP, LOOK_BOTTOM, LOOK_NORMAL ].
747 look: function( look ) {
748 if ( this.oldLook == look )
749 return;
750
751 for ( var i = this.lineChildren.length, child; i--; )
752 ( child = this.lineChildren[ i ] ).setAttribute( 'style', child.base + child.looks[ 0 | look / 2 ] );
753
754 this.oldLook = look;
755 },
756
757 wrap: new newElement( 'span', that.doc )
758
759 } );
760
761 // Insert children into the box.
762 for ( var i = line.lineChildren.length; i--; )
763 line.lineChildren[ i ].appendTo( line );
764
765 // Set default look of the box.
766 line.look( LOOK_NORMAL );
767
768 // Using that wrapper prevents IE (8,9) from resizing editable area at the moment
769 // of box insertion. This works thanks to the fact, that positioned box is wrapped by
770 // an inline element. So much tricky.
771 line.appendTo( line.wrap );
772
773 // Make the box unselectable.
774 line.unselectable();
775
776 // Handle accessSpace node insertion.
777 line.lineChildren[ 0 ].on( 'mouseup', function( event ) {
778 line.detach();
779
780 accessFocusSpace( that, function( accessNode ) {
781 // Use old trigger that was saved by 'place' method. Look: line.place
782 var trigger = that.line.trigger;
783
784 accessNode[ trigger.is( EDGE_TOP ) ? 'insertBefore' : 'insertAfter' ](
785 trigger.is( EDGE_TOP ) ? trigger.lower : trigger.upper );
786 }, true );
787
788 that.editor.focus();
789
790 if ( !env.ie && that.enterMode != CKEDITOR.ENTER_BR )
791 that.hotNode.scrollIntoView();
792
793 event.data.preventDefault( true );
794 } );
795
796 // Prevents IE9 from displaying the resize box and disables drag'n'drop functionality.
797 line.on( 'mousedown', function( event ) {
798 event.data.preventDefault( true );
799 } );
800
801 that.line = line;
802 }
803
804 // This function allows accessing any focus space according to the insert function:
805 // * For enterMode ENTER_P it creates P element filled with dummy white-space.
806 // * For enterMode ENTER_DIV it creates DIV element filled with dummy white-space.
807 // * For enterMode ENTER_BR it creates BR element or &nbsp; in IE.
808 //
809 // The node is being inserted according to insertFunction. Finally the method
810 // selects the non-breaking space making the node ready for typing.
811 function accessFocusSpace( that, insertFunction, doSave ) {
812 var range = new CKEDITOR.dom.range( that.doc ),
813 editor = that.editor,
814 accessNode;
815
816 // IE requires text node of &nbsp; in ENTER_BR mode.
817 if ( env.ie && that.enterMode == CKEDITOR.ENTER_BR )
818 accessNode = that.doc.createText( WHITE_SPACE );
819
820 // In other cases a regular element is used.
821 else {
822 // Use the enterMode of editable's limit or editor's
823 // enter mode if not in nested editable.
824 var limit = getClosestEditableLimit( that.element, true ),
825
826 // This is an enter mode for the context. We cannot use
827 // editor.activeEnterMode because the focused nested editable will
828 // have a different enterMode as editor but magicline will be inserted
829 // directly into editor's editable.
830 enterMode = limit && limit.data( 'cke-enter-mode' ) || that.enterMode;
831
832 accessNode = new newElement( enterElements[ enterMode ], that.doc );
833
834 if ( !accessNode.is( 'br' ) ) {
835 var dummy = that.doc.createText( WHITE_SPACE );
836 dummy.appendTo( accessNode );
837 }
838 }
839
840 doSave && editor.fire( 'saveSnapshot' );
841
842 insertFunction( accessNode );
843 //dummy.appendTo( accessNode );
844 range.moveToPosition( accessNode, CKEDITOR.POSITION_AFTER_START );
845 editor.getSelection().selectRanges( [ range ] );
846 that.hotNode = accessNode;
847
848 doSave && editor.fire( 'saveSnapshot' );
849 }
850
851 // Access focus space on demand by taking an element under the caret as a reference.
852 // The space is accessed provided the element under the caret is trigger AND:
853 //
854 // 1. First/last-child of its parent:
855 // +----------------------- Parent element -+
856 // | +------------------------------ DIV -+ | <-- Access before
857 // | | Foo^ | |
858 // | | | |
859 // | +------------------------------------+ | <-- Access after
860 // +----------------------------------------+
861 //
862 // OR
863 //
864 // 2. It has a direct sibling element, which is also a trigger:
865 // +-------------------------------- DIV#1 -+
866 // | Foo^ |
867 // | |
868 // +----------------------------------------+
869 // <-- Access here
870 // +-------------------------------- DIV#2 -+
871 // | Bar |
872 // | |
873 // +----------------------------------------+
874 //
875 // OR
876 //
877 // 3. It has a direct sibling, which is a trigger and has a valid neighbour trigger,
878 // but belongs to dtd.$.empty/nonEditable:
879 // +------------------------------------ P -+
880 // | Foo^ |
881 // | |
882 // +----------------------------------------+
883 // +----------------------------------- HR -+
884 // <-- Access here
885 // +-------------------------------- DIV#2 -+
886 // | Bar |
887 // | |
888 // +----------------------------------------+
889 //
890 function accessFocusSpaceCmd( that, insertAfter ) {
891 return {
892 canUndo: true,
893 modes: { wysiwyg: 1 },
894 exec: ( function() {
895
896 // Inserts line (accessNode) at the position by taking target node as a reference.
897 function doAccess( target ) {
898 // Remove old hotNode under certain circumstances.
899 var hotNodeChar = ( env.ie && env.version < 9 ? ' ' : WHITE_SPACE ),
900 removeOld = that.hotNode && // Old hotNode must exist.
901 that.hotNode.getText() == hotNodeChar && // Old hotNode hasn't been changed.
902 that.element.equals( that.hotNode ) && // Caret is inside old hotNode.
903 // Command is executed in the same direction.
904 that.lastCmdDirection === !!insertAfter; // jshint ignore:line
905
906 accessFocusSpace( that, function( accessNode ) {
907 if ( removeOld && that.hotNode )
908 that.hotNode.remove();
909
910 accessNode[ insertAfter ? 'insertAfter' : 'insertBefore' ]( target );
911
912 // Make this element distinguishable. Also remember the direction
913 // it's been inserted into document.
914 accessNode.setAttributes( {
915 'data-cke-magicline-hot': 1,
916 'data-cke-magicline-dir': !!insertAfter
917 } );
918
919 // Save last direction of the command (is insertAfter?).
920 that.lastCmdDirection = !!insertAfter;
921 } );
922
923 if ( !env.ie && that.enterMode != CKEDITOR.ENTER_BR )
924 that.hotNode.scrollIntoView();
925
926 // Detach the line if was visible (previously triggered by mouse).
927 that.line.detach();
928 }
929
930 return function( editor ) {
931 var selected = editor.getSelection().getStartElement(),
932 limit;
933
934 // (#9833) Go down to the closest non-inline element in DOM structure
935 // since inline elements don't participate in in magicline.
936 selected = selected.getAscendant( DTD_BLOCK, 1 );
937
938 // Stop if selected is a child of a tabu-list element.
939 if ( isInTabu( that, selected ) )
940 return;
941
942 // Sometimes it may happen that there's no parent block below selected element
943 // or, for example, getAscendant reaches editable or editable parent.
944 // We must avoid such pathological cases.
945 if ( !selected || selected.equals( that.editable ) || selected.contains( that.editable ) )
946 return;
947
948 // Executing the command directly in nested editable should
949 // access space before/after it.
950 if ( ( limit = getClosestEditableLimit( selected ) ) && limit.getAttribute( 'contenteditable' ) == 'false' )
951 selected = limit;
952
953 // That holds element from mouse. Replace it with the
954 // element under the caret.
955 that.element = selected;
956
957 // (3.) Handle the following cases where selected neighbour
958 // is a trigger inaccessible for the caret AND:
959 // - Is first/last-child
960 // OR
961 // - Has a sibling, which is also a trigger.
962 var neighbor = getNonEmptyNeighbour( that, selected, !insertAfter ),
963 neighborSibling;
964
965 // Check for a neighbour that belongs to triggers.
966 // Consider only non-accessible elements (they cannot have any children)
967 // since they cannot be given a caret inside, to run the command
968 // the regular way (1. & 2.).
969 if (
970 isHtml( neighbor ) && neighbor.is( that.triggers ) && neighbor.is( DTD_NONACCESSIBLE ) &&
971 (
972 // Check whether neighbor is first/last-child.
973 !getNonEmptyNeighbour( that, neighbor, !insertAfter ) ||
974 // Check for a sibling of a neighbour that also is a trigger.
975 (
976 ( neighborSibling = getNonEmptyNeighbour( that, neighbor, !insertAfter ) ) &&
977 isHtml( neighborSibling ) &&
978 neighborSibling.is( that.triggers )
979 )
980 )
981 ) {
982 doAccess( neighbor );
983 return;
984 }
985
986 // Look for possible target element DOWN "selected" DOM branch (towards editable)
987 // that belong to that.triggers
988 var target = getAscendantTrigger( that, selected );
989
990 // No HTML target -> no access.
991 if ( !isHtml( target ) )
992 return;
993
994 // (1.) Target is first/last child -> access.
995 if ( !getNonEmptyNeighbour( that, target, !insertAfter ) ) {
996 doAccess( target );
997 return;
998 }
999
1000 var sibling = getNonEmptyNeighbour( that, target, !insertAfter );
1001
1002 // (2.) Target has a sibling that belongs to that.triggers -> access.
1003 if ( sibling && isHtml( sibling ) && sibling.is( that.triggers ) ) {
1004 doAccess( target );
1005 return;
1006 }
1007 };
1008 } )()
1009 };
1010 }
1011
1012 function isLine( that, node ) {
1013 if ( !( node && node.type == CKEDITOR.NODE_ELEMENT && node.$ ) )
1014 return false;
1015
1016 var line = that.line;
1017
1018 return line.wrap.equals( node ) || line.wrap.contains( node );
1019 }
1020
1021 // Is text node containing white-spaces only?
1022 var isEmptyTextNode = CKEDITOR.dom.walker.whitespaces();
1023
1024 // Is fully visible HTML node?
1025 function isHtml( node ) {
1026 return node && node.type == CKEDITOR.NODE_ELEMENT && node.$; // IE requires that
1027 }
1028
1029 function isFloated( element ) {
1030 if ( !isHtml( element ) )
1031 return false;
1032
1033 var options = { left: 1, right: 1, center: 1 };
1034
1035 return !!( options[ element.getComputedStyle( 'float' ) ] || options[ element.getAttribute( 'align' ) ] );
1036 }
1037
1038 function isFlowBreaker( element ) {
1039 if ( !isHtml( element ) )
1040 return false;
1041
1042 return isPositioned( element ) || isFloated( element );
1043 }
1044
1045 // Isn't node of NODE_COMMENT type?
1046 var isComment = CKEDITOR.dom.walker.nodeType( CKEDITOR.NODE_COMMENT );
1047
1048 function isPositioned( element ) {
1049 return !!{ absolute: 1, fixed: 1 }[ element.getComputedStyle( 'position' ) ];
1050 }
1051
1052 // Is text node?
1053 function isTextNode( node ) {
1054 return node && node.type == CKEDITOR.NODE_TEXT;
1055 }
1056
1057 function isTrigger( that, element ) {
1058 return isHtml( element ) ? element.is( that.triggers ) : null;
1059 }
1060
1061 function isInTabu( that, element ) {
1062 if ( !element )
1063 return false;
1064
1065 var parents = element.getParents( 1 );
1066
1067 for ( var i = parents.length ; i-- ; ) {
1068 for ( var j = that.tabuList.length ; j-- ; ) {
1069 if ( parents[ i ].hasAttribute( that.tabuList[ j ] ) )
1070 return true;
1071 }
1072 }
1073
1074 return false;
1075 }
1076
1077 // This function checks vertically is there's a relevant child between element's edge
1078 // and the pointer.
1079 // \-> Table contents are omitted.
1080 function isChildBetweenPointerAndEdge( that, parent, edgeBottom ) {
1081 var edgeChild = parent[ edgeBottom ? 'getLast' : 'getFirst' ]( function( node ) {
1082 return that.isRelevant( node ) && !node.is( DTD_TABLECONTENT );
1083 } );
1084
1085 if ( !edgeChild )
1086 return false;
1087
1088 updateSize( that, edgeChild );
1089
1090 return edgeBottom ? edgeChild.size.top > that.mouse.y : edgeChild.size.bottom < that.mouse.y;
1091 }
1092
1093 // This method handles edge cases:
1094 // \-> Mouse is around upper or lower edge of view pane.
1095 // \-> Also scroll position is either minimal or maximal.
1096 // \-> It's OK to show LOOK_TOP(BOTTOM) type line.
1097 //
1098 // This trigger doesn't need additional post-filtering.
1099 //
1100 // +----------------------------- Editable -+ /--
1101 // | +---------------------- First child -+ | | <-- Top edge (first child)
1102 // | | | | |
1103 // | | | | | * Mouse activation area *
1104 // | | | | |
1105 // | | ... | | \-- Top edge + trigger offset
1106 // | . . |
1107 // | |
1108 // | . . |
1109 // | | ... | | /-- Bottom edge - trigger offset
1110 // | | | | |
1111 // | | | | | * Mouse activation area *
1112 // | | | | |
1113 // | +----------------------- Last child -+ | | <-- Bottom edge (last child)
1114 // +----------------------------------------+ \--
1115 //
1116 function triggerEditable( that ) {
1117 that.debug.groupStart( 'triggerEditable' ); // %REMOVE_LINE%
1118
1119 var editable = that.editable,
1120 mouse = that.mouse,
1121 view = that.view,
1122 triggerOffset = that.triggerOffset,
1123 triggerLook;
1124
1125 // Update editable dimensions.
1126 updateEditableSize( that );
1127
1128 // This flag determines whether checking bottom trigger.
1129 var bottomTrigger = mouse.y > (
1130 that.inInlineMode ? (
1131 view.editable.top + view.editable.height / 2
1132 ) : (
1133 // This is to handle case when editable.height / 2 <<< pane.height.
1134 Math.min( view.editable.height, view.pane.height ) / 2
1135 )
1136 ),
1137
1138 // Edge node according to bottomTrigger.
1139 edgeNode = editable[ bottomTrigger ? 'getLast' : 'getFirst' ]( function( node ) {
1140 return !( isEmptyTextNode( node ) || isComment( node ) );
1141 } );
1142
1143 // There's no edge node. Abort.
1144 if ( !edgeNode ) {
1145 that.debug.logEnd( 'ABORT. No edge node found.' ); // %REMOVE_LINE%
1146 return null;
1147 }
1148
1149 // If the edgeNode in editable is ML, get the next one.
1150 if ( isLine( that, edgeNode ) ) {
1151 edgeNode = that.line.wrap[ bottomTrigger ? 'getPrevious' : 'getNext' ]( function( node ) {
1152 return !( isEmptyTextNode( node ) || isComment( node ) );
1153 } );
1154 }
1155
1156 // Exclude bad nodes (no ML needed then):
1157 // \-> Edge node is text.
1158 // \-> Edge node is floated, etc.
1159 //
1160 // Edge node *must be* a valid trigger at this stage as well.
1161 if ( !isHtml( edgeNode ) || isFlowBreaker( edgeNode ) || !isTrigger( that, edgeNode ) ) {
1162 that.debug.logEnd( 'ABORT. Invalid edge node.' ); // %REMOVE_LINE%
1163 return null;
1164 }
1165
1166 // Update size of edge node. Dimensions will be necessary.
1167 updateSize( that, edgeNode );
1168
1169 // Return appropriate trigger according to bottomTrigger.
1170 // \-> Top edge trigger case first.
1171 if ( !bottomTrigger && // Top trigger case.
1172 edgeNode.size.top >= 0 && // Check if the first element is fully visible.
1173 inBetween( mouse.y, 0, edgeNode.size.top + triggerOffset ) ) { // Check if mouse in [0, edgeNode.top + triggerOffset].
1174
1175 // Determine trigger look.
1176 triggerLook = that.inInlineMode || view.scroll.y === 0 ?
1177 LOOK_TOP : LOOK_NORMAL;
1178
1179 that.debug.logEnd( 'SUCCESS. Created box trigger. EDGE_TOP.' ); // %REMOVE_LINE%
1180
1181 return new boxTrigger( [ null, edgeNode,
1182 EDGE_TOP,
1183 TYPE_EDGE,
1184 triggerLook
1185 ] );
1186 }
1187
1188 // \-> Bottom case.
1189 else if ( bottomTrigger &&
1190 edgeNode.size.bottom <= view.pane.height && // Check if the last element is fully visible
1191 inBetween( mouse.y, // Check if mouse in...
1192 edgeNode.size.bottom - triggerOffset, view.pane.height ) ) { // [ edgeNode.bottom - triggerOffset, paneHeight ]
1193
1194 // Determine trigger look.
1195 triggerLook = that.inInlineMode ||
1196 inBetween( edgeNode.size.bottom, view.pane.height - triggerOffset, view.pane.height ) ?
1197 LOOK_BOTTOM : LOOK_NORMAL;
1198
1199 that.debug.logEnd( 'SUCCESS. Created box trigger. EDGE_BOTTOM.' ); // %REMOVE_LINE%
1200
1201 return new boxTrigger( [ edgeNode, null,
1202 EDGE_BOTTOM,
1203 TYPE_EDGE,
1204 triggerLook
1205 ] );
1206 }
1207
1208 that.debug.logEnd( 'ABORT. No trigger created.' ); // %REMOVE_LINE%
1209 return null;
1210 }
1211
1212 // This method covers cases *inside* of an element:
1213 // \-> The pointer is in the top (bottom) area of an element and there's
1214 // HTML node before (after) this element.
1215 // \-> An element being the first or last child of its parent.
1216 //
1217 // +----------------------- Parent element -+
1218 // | +----------------------- Element #1 -+ | /--
1219 // | | | | | * Mouse activation area (as first child) *
1220 // | | | | \--
1221 // | | | | /--
1222 // | | | | | * Mouse activation area (Element #2) *
1223 // | +------------------------------------+ | \--
1224 // | |
1225 // | +----------------------- Element #2 -+ | /--
1226 // | | | | | * Mouse activation area (Element #1) *
1227 // | | | | \--
1228 // | | | |
1229 // | +------------------------------------+ |
1230 // | |
1231 // | Text node is here. |
1232 // | |
1233 // | +----------------------- Element #3 -+ |
1234 // | | | |
1235 // | | | |
1236 // | | | | /--
1237 // | | | | | * Mouse activation area (as last child) *
1238 // | +------------------------------------+ | \--
1239 // +----------------------------------------+
1240 //
1241 function triggerEdge( that ) {
1242 that.debug.groupStart( 'triggerEdge' ); // %REMOVE_LINE%
1243
1244 var mouse = that.mouse,
1245 view = that.view,
1246 triggerOffset = that.triggerOffset;
1247
1248 // Get the ascendant trigger basing on elementFromMouse.
1249 var element = getAscendantTrigger( that );
1250
1251 that.debug.logElements( [ element ], [ 'Ascendant trigger' ], 'First stage' ); // %REMOVE_LINE%
1252
1253 // Abort if there's no appropriate element.
1254 if ( !element ) {
1255 that.debug.logEnd( 'ABORT. No element, element is editable or element contains editable.' ); // %REMOVE_LINE%
1256 return null;
1257 }
1258
1259 // Dimensions will be necessary.
1260 updateSize( that, element );
1261
1262 // If triggerOffset is larger than a half of element's height,
1263 // use an offset of 1/2 of element's height. If the offset wasn't reduced,
1264 // top area would cover most (all) cases.
1265 var fixedOffset = Math.min( triggerOffset,
1266 0 | ( element.size.outerHeight / 2 ) ),
1267
1268 // This variable will hold the trigger to be returned.
1269 triggerSetup = [],
1270 triggerLook,
1271
1272 // This flag determines whether dealing with a bottom trigger.
1273 bottomTrigger;
1274
1275 // \-> Top trigger.
1276 if ( inBetween( mouse.y, element.size.top - 1, element.size.top + fixedOffset ) )
1277 bottomTrigger = false;
1278 // \-> Bottom trigger.
1279 else if ( inBetween( mouse.y, element.size.bottom - fixedOffset, element.size.bottom + 1 ) )
1280 bottomTrigger = true;
1281 // \-> Abort. Not in a valid trigger space.
1282 else {
1283 that.debug.logEnd( 'ABORT. Not around of any edge.' ); // %REMOVE_LINE%
1284 return null;
1285 }
1286
1287 // Reject wrong elements.
1288 // \-> Reject an element which is a flow breaker.
1289 // \-> Reject an element which has a child above/below the mouse pointer.
1290 // \-> Reject an element which belongs to list items.
1291 if (
1292 isFlowBreaker( element ) ||
1293 isChildBetweenPointerAndEdge( that, element, bottomTrigger ) ||
1294 element.getParent().is( DTD_LISTITEM )
1295 ) {
1296 that.debug.logEnd( 'ABORT. element is wrong', element ); // %REMOVE_LINE%
1297 return null;
1298 }
1299
1300 // Get sibling according to bottomTrigger.
1301 var elementSibling = getNonEmptyNeighbour( that, element, !bottomTrigger );
1302
1303 // No sibling element.
1304 // This is a first or last child case.
1305 if ( !elementSibling ) {
1306 // No need to reject the element as it has already been done before.
1307 // Prepare a trigger.
1308
1309 // Determine trigger look.
1310 if ( element.equals( that.editable[ bottomTrigger ? 'getLast' : 'getFirst' ]( that.isRelevant ) ) ) {
1311 updateEditableSize( that );
1312
1313 if (
1314 bottomTrigger && inBetween( mouse.y,
1315 element.size.bottom - fixedOffset, view.pane.height ) &&
1316 inBetween( element.size.bottom, view.pane.height - fixedOffset, view.pane.height )
1317 ) {
1318 triggerLook = LOOK_BOTTOM;
1319 } else if ( inBetween( mouse.y, 0, element.size.top + fixedOffset ) ) {
1320 triggerLook = LOOK_TOP;
1321 }
1322 } else {
1323 triggerLook = LOOK_NORMAL;
1324 }
1325
1326 triggerSetup = [ null, element ][ bottomTrigger ? 'reverse' : 'concat' ]().concat( [
1327 bottomTrigger ? EDGE_BOTTOM : EDGE_TOP,
1328 TYPE_EDGE,
1329 triggerLook,
1330 element.equals( that.editable[ bottomTrigger ? 'getLast' : 'getFirst' ]( that.isRelevant ) ) ?
1331 ( bottomTrigger ? LOOK_BOTTOM : LOOK_TOP ) : LOOK_NORMAL
1332 ] );
1333
1334 that.debug.log( 'Configured edge trigger of ' + ( bottomTrigger ? 'EDGE_BOTTOM' : 'EDGE_TOP' ) ); // %REMOVE_LINE%
1335 }
1336
1337 // Abort. Sibling is a text element.
1338 else if ( isTextNode( elementSibling ) ) {
1339 that.debug.logEnd( 'ABORT. Sibling is non-empty text element' ); // %REMOVE_LINE%
1340 return null;
1341 }
1342
1343 // Check if the sibling is a HTML element.
1344 // If so, create an TYPE_EDGE, EDGE_MIDDLE trigger.
1345 else if ( isHtml( elementSibling ) ) {
1346 // Reject wrong elementSiblings.
1347 // \-> Reject an elementSibling which is a flow breaker.
1348 // \-> Reject an elementSibling which isn't a trigger.
1349 // \-> Reject an elementSibling which belongs to list items.
1350 if (
1351 isFlowBreaker( elementSibling ) ||
1352 !isTrigger( that, elementSibling ) ||
1353 elementSibling.getParent().is( DTD_LISTITEM )
1354 ) {
1355 that.debug.logEnd( 'ABORT. elementSibling is wrong', elementSibling ); // %REMOVE_LINE%
1356 return null;
1357 }
1358
1359 // Prepare a trigger.
1360 triggerSetup = [ elementSibling, element ][ bottomTrigger ? 'reverse' : 'concat' ]().concat( [
1361 EDGE_MIDDLE,
1362 TYPE_EDGE
1363 ] );
1364
1365 that.debug.log( 'Configured edge trigger of EDGE_MIDDLE' ); // %REMOVE_LINE%
1366 }
1367
1368 if ( 0 in triggerSetup ) {
1369 that.debug.logEnd( 'SUCCESS. Returning a trigger.' ); // %REMOVE_LINE%
1370 return new boxTrigger( triggerSetup );
1371 }
1372
1373 that.debug.logEnd( 'ABORT. No trigger generated.' ); // %REMOVE_LINE%
1374 return null;
1375 }
1376
1377 // Checks iteratively up and down in search for elements using elementFromMouse method.
1378 // Useful if between two triggers.
1379 //
1380 // +----------------------- Parent element -+
1381 // | +----------------------- Element #1 -+ |
1382 // | | | |
1383 // | | | |
1384 // | | | |
1385 // | +------------------------------------+ |
1386 // | | /--
1387 // | . | |
1388 // | . +-- Floated -+ | |
1389 // | | | | | | * Mouse activation area *
1390 // | | | IGNORE | | |
1391 // | X | | | | Method searches vertically for sibling elements.
1392 // | | +------------+ | | Start point is X (mouse-y coordinate).
1393 // | | | | Floated elements, comments and empty text nodes are omitted.
1394 // | . | |
1395 // | . | |
1396 // | | \--
1397 // | +----------------------- Element #2 -+ |
1398 // | | | |
1399 // | | | |
1400 // | | | |
1401 // | | | |
1402 // | +------------------------------------+ |
1403 // +----------------------------------------+
1404 //
1405 var triggerExpand = ( function() {
1406 // The heart of the procedure. This method creates triggers that are
1407 // filtered by expandFilter method.
1408 function expandEngine( that ) {
1409 that.debug.groupStart( 'expandEngine' ); // %REMOVE_LINE%
1410
1411 var startElement = that.element,
1412 upper, lower, trigger;
1413
1414 if ( !isHtml( startElement ) || startElement.contains( that.editable ) ) {
1415 that.debug.logEnd( 'ABORT. No start element, or start element contains editable.' ); // %REMOVE_LINE%
1416 return null;
1417 }
1418
1419 // Stop searching if element is in non-editable branch of DOM.
1420 if ( startElement.isReadOnly() )
1421 return null;
1422
1423 trigger = verticalSearch( that,
1424 function( current, startElement ) {
1425 return !startElement.equals( current ); // stop when start element and the current one differ
1426 }, function( that, mouse ) {
1427 return elementFromMouse( that, true, mouse );
1428 }, startElement ),
1429
1430 upper = trigger.upper,
1431 lower = trigger.lower;
1432
1433 that.debug.logElements( [ upper, lower ], [ 'Upper', 'Lower' ], 'Pair found' ); // %REMOVE_LINE%
1434
1435 // Success: two siblings have been found
1436 if ( areSiblings( that, upper, lower ) ) {
1437 that.debug.logEnd( 'SUCCESS. Expand trigger created.' ); // %REMOVE_LINE%
1438 return trigger.set( EDGE_MIDDLE, TYPE_EXPAND );
1439 }
1440
1441 that.debug.logElements( [ startElement, upper, lower ], // %REMOVE_LINE%
1442 [ 'Start', 'Upper', 'Lower' ], 'Post-processing' ); // %REMOVE_LINE%
1443
1444 // Danger. Dragons ahead.
1445 // No siblings have been found during previous phase, post-processing may be necessary.
1446 // We can traverse DOM until a valid pair of elements around the pointer is found.
1447
1448 // Prepare for post-processing:
1449 // 1. Determine if upper and lower are children of startElement.
1450 // 1.1. If so, find their ascendants that are closest to startElement (one level deeper than startElement).
1451 // 1.2. Otherwise use first/last-child of the startElement as upper/lower. Why?:
1452 // a) upper/lower belongs to another branch of the DOM tree.
1453 // b) verticalSearch encountered an edge of the viewport and failed.
1454 // 1.3. Make sure upper and lower still exist. Why?:
1455 // a) Upper and lower may be not belong to the branch of the startElement (may not exist at all) and
1456 // startElement has no children.
1457 // 2. Perform the post-processing.
1458 // 2.1. Gather dimensions of an upper element.
1459 // 2.2. Abort if lower edge of upper is already under the mouse pointer. Why?:
1460 // a) We expect upper to be above and lower below the mouse pointer.
1461 // 3. Perform iterative search while upper != lower.
1462 // 3.1. Find the upper-next element. If there's no such element, break current search. Why?:
1463 // a) There's no point in further search if there are only text nodes ahead.
1464 // 3.2. Calculate the distance between the middle point of ( upper, upperNext ) and mouse-y.
1465 // 3.3. If the distance is shorter than the previous best, save it (save upper, upperNext as well).
1466 // 3.4. If the optimal pair is found, assign it back to the trigger.
1467
1468 // 1.1., 1.2.
1469 if ( upper && startElement.contains( upper ) ) {
1470 while ( !upper.getParent().equals( startElement ) )
1471 upper = upper.getParent();
1472 } else {
1473 upper = startElement.getFirst( function( node ) {
1474 return expandSelector( that, node );
1475 } );
1476 }
1477
1478 if ( lower && startElement.contains( lower ) ) {
1479 while ( !lower.getParent().equals( startElement ) )
1480 lower = lower.getParent();
1481 } else {
1482 lower = startElement.getLast( function( node ) {
1483 return expandSelector( that, node );
1484 } );
1485 }
1486
1487 // 1.3.
1488 if ( !upper || !lower ) {
1489 that.debug.logEnd( 'ABORT. There is no upper or no lower element.' ); // %REMOVE_LINE%
1490 return null;
1491 }
1492
1493 // 2.1.
1494 updateSize( that, upper );
1495 updateSize( that, lower );
1496
1497 if ( !checkMouseBetweenElements( that, upper, lower ) ) {
1498 that.debug.logEnd( 'ABORT. Mouse is already above upper or below lower.' ); // %REMOVE_LINE%
1499 return null;
1500 }
1501
1502 var minDistance = Number.MAX_VALUE,
1503 currentDistance, upperNext, minElement, minElementNext;
1504
1505 while ( lower && !lower.equals( upper ) ) {
1506 // 3.1.
1507 if ( !( upperNext = upper.getNext( that.isRelevant ) ) )
1508 break;
1509
1510 // 3.2.
1511 currentDistance = Math.abs( getMidpoint( that, upper, upperNext ) - that.mouse.y );
1512
1513 // 3.3.
1514 if ( currentDistance < minDistance ) {
1515 minDistance = currentDistance;
1516 minElement = upper;
1517 minElementNext = upperNext;
1518 }
1519
1520 upper = upperNext;
1521 updateSize( that, upper );
1522 }
1523
1524 that.debug.logElements( [ minElement, minElementNext ], // %REMOVE_LINE%
1525 [ 'Min', 'MinNext' ], 'Post-processing results' ); // %REMOVE_LINE%
1526
1527 // 3.4.
1528 if ( !minElement || !minElementNext ) {
1529 that.debug.logEnd( 'ABORT. No Min or MinNext' ); // %REMOVE_LINE%
1530 return null;
1531 }
1532
1533 if ( !checkMouseBetweenElements( that, minElement, minElementNext ) ) {
1534 that.debug.logEnd( 'ABORT. Mouse is already above minElement or below minElementNext.' ); // %REMOVE_LINE%
1535 return null;
1536 }
1537
1538 // An element of minimal distance has been found. Assign it to the trigger.
1539 trigger.upper = minElement;
1540 trigger.lower = minElementNext;
1541
1542 // Success: post-processing revealed a pair of elements.
1543 that.debug.logEnd( 'SUCCESSFUL post-processing. Trigger created.' ); // %REMOVE_LINE%
1544 return trigger.set( EDGE_MIDDLE, TYPE_EXPAND );
1545 }
1546
1547 // This is default element selector used by the engine.
1548 function expandSelector( that, node ) {
1549 return !( isTextNode( node ) ||
1550 isComment( node ) ||
1551 isFlowBreaker( node ) ||
1552 isLine( that, node ) ||
1553 ( node.type == CKEDITOR.NODE_ELEMENT && node.$ && node.is( 'br' ) ) );
1554 }
1555
1556 // This method checks whether mouse-y is between the top edge of upper
1557 // and bottom edge of lower.
1558 //
1559 // NOTE: This method assumes that updateSize has already been called
1560 // for the elements and is up-to-date.
1561 //
1562 // +---------------------------- Upper -+ /--
1563 // | | |
1564 // +------------------------------------+ |
1565 // |
1566 // ... |
1567 // |
1568 // X | * Return true for mouse-y in this range *
1569 // |
1570 // ... |
1571 // |
1572 // +---------------------------- Lower -+ |
1573 // | | |
1574 // +------------------------------------+ \--
1575 //
1576 function checkMouseBetweenElements( that, upper, lower ) {
1577 return inBetween( that.mouse.y, upper.size.top, lower.size.bottom );
1578 }
1579
1580 // A method for trigger filtering. Accepts or rejects trigger pairs
1581 // by their location in DOM etc.
1582 function expandFilter( that, trigger ) {
1583 that.debug.groupStart( 'expandFilter' ); // %REMOVE_LINE%
1584
1585 var upper = trigger.upper,
1586 lower = trigger.lower;
1587
1588 if (
1589 !upper || !lower || // NOT: EDGE_MIDDLE trigger ALWAYS has two elements.
1590 isFlowBreaker( lower ) || isFlowBreaker( upper ) || // NOT: one of the elements is floated or positioned
1591 lower.equals( upper ) || upper.equals( lower ) || // NOT: two trigger elements, one equals another.
1592 lower.contains( upper ) || upper.contains( lower )
1593 ) { // NOT: two trigger elements, one contains another.
1594 that.debug.logEnd( 'REJECTED. No upper or no lower or they contain each other.' ); // %REMOVE_LINE%
1595
1596 return false;
1597 }
1598
1599 // YES: two trigger elements, pure siblings.
1600 else if ( isTrigger( that, upper ) && isTrigger( that, lower ) && areSiblings( that, upper, lower ) ) {
1601 that.debug.logElementsEnd( [ upper, lower ], // %REMOVE_LINE%
1602 [ 'upper', 'lower' ], 'APPROVED EDGE_MIDDLE' ); // %REMOVE_LINE%
1603
1604 return true;
1605 }
1606
1607 that.debug.logElementsEnd( [ upper, lower ], // %REMOVE_LINE%
1608 [ 'upper', 'lower' ], 'Rejected unknown pair' ); // %REMOVE_LINE%
1609
1610 return false;
1611 }
1612
1613 // Simple wrapper for expandEngine and expandFilter.
1614 return function( that ) {
1615 that.debug.groupStart( 'triggerExpand' ); // %REMOVE_LINE%
1616
1617 var trigger = expandEngine( that );
1618
1619 that.debug.groupEnd(); // %REMOVE_LINE%
1620 return trigger && expandFilter( that, trigger ) ? trigger : null;
1621 };
1622 } )();
1623
1624 // Collects dimensions of an element.
1625 var sizePrefixes = [ 'top', 'left', 'right', 'bottom' ];
1626
1627 function getSize( that, element, ignoreScroll, force ) {
1628 var docPosition = element.getDocumentPosition(),
1629 border = {},
1630 margin = {},
1631 padding = {},
1632 box = {};
1633
1634 for ( var i = sizePrefixes.length; i--; ) {
1635 border[ sizePrefixes[ i ] ] = parseInt( getStyle( 'border-' + sizePrefixes[ i ] + '-width' ), 10 ) || 0;
1636 padding[ sizePrefixes[ i ] ] = parseInt( getStyle( 'padding-' + sizePrefixes[ i ] ), 10 ) || 0;
1637 margin[ sizePrefixes[ i ] ] = parseInt( getStyle( 'margin-' + sizePrefixes[ i ] ), 10 ) || 0;
1638 }
1639
1640 // updateWindowSize if forced to do so OR NOT ignoring scroll.
1641 if ( !ignoreScroll || force )
1642 updateWindowSize( that, force );
1643
1644 box.top = docPosition.y - ( ignoreScroll ? 0 : that.view.scroll.y ), box.left = docPosition.x - ( ignoreScroll ? 0 : that.view.scroll.x ),
1645
1646 // w/ borders and paddings.
1647 box.outerWidth = element.$.offsetWidth, box.outerHeight = element.$.offsetHeight,
1648
1649 // w/o borders and paddings.
1650 box.height = box.outerHeight - ( padding.top + padding.bottom + border.top + border.bottom ), box.width = box.outerWidth - ( padding.left + padding.right + border.left + border.right ),
1651
1652 box.bottom = box.top + box.outerHeight, box.right = box.left + box.outerWidth;
1653
1654 if ( that.inInlineMode ) {
1655 box.scroll = {
1656 top: element.$.scrollTop,
1657 left: element.$.scrollLeft
1658 };
1659 }
1660
1661 return extend( {
1662 border: border,
1663 padding: padding,
1664 margin: margin,
1665 ignoreScroll: ignoreScroll
1666 }, box, true );
1667
1668 function getStyle( propertyName ) {
1669 return element.getComputedStyle.call( element, propertyName );
1670 }
1671 }
1672
1673 function updateSize( that, element, ignoreScroll ) {
1674 if ( !isHtml( element ) ) // i.e. an element is hidden
1675 return ( element.size = null ); // -> reset size to make it useless for other methods
1676
1677 if ( !element.size )
1678 element.size = {};
1679
1680 // Abort if there was a similar query performed recently.
1681 // This kind of caching provides great performance improvement.
1682 else if ( element.size.ignoreScroll == ignoreScroll && element.size.date > new Date() - CACHE_TIME ) {
1683 that.debug.log( 'element.size: get from cache' ); // %REMOVE_LINE%
1684 return null;
1685 }
1686
1687 that.debug.log( 'element.size: capture' ); // %REMOVE_LINE%
1688
1689 return extend( element.size, getSize( that, element, ignoreScroll ), {
1690 date: +new Date()
1691 }, true );
1692 }
1693
1694 // Updates that.view.editable object.
1695 // This one must be called separately outside of updateWindowSize
1696 // to prevent cyclic dependency getSize<->updateWindowSize.
1697 // It calls getSize with force flag to avoid getWindowSize cache (look: getSize).
1698 function updateEditableSize( that, ignoreScroll ) {
1699 that.view.editable = getSize( that, that.editable, ignoreScroll, true );
1700 }
1701
1702 function updateWindowSize( that, force ) {
1703 if ( !that.view )
1704 that.view = {};
1705
1706 var view = that.view;
1707
1708 if ( !force && view && view.date > new Date() - CACHE_TIME ) {
1709 that.debug.log( 'win.size: get from cache' ); // %REMOVE_LINE%
1710 return;
1711 }
1712
1713 that.debug.log( 'win.size: capturing' ); // %REMOVE_LINE%
1714
1715 var win = that.win,
1716 scroll = win.getScrollPosition(),
1717 paneSize = win.getViewPaneSize();
1718
1719 extend( that.view, {
1720 scroll: {
1721 x: scroll.x,
1722 y: scroll.y,
1723 width: that.doc.$.documentElement.scrollWidth - paneSize.width,
1724 height: that.doc.$.documentElement.scrollHeight - paneSize.height
1725 },
1726 pane: {
1727 width: paneSize.width,
1728 height: paneSize.height,
1729 bottom: paneSize.height + scroll.y
1730 },
1731 date: +new Date()
1732 }, true );
1733 }
1734
1735 // This method searches document vertically using given
1736 // select criterion until stop criterion is fulfilled.
1737 function verticalSearch( that, stopCondition, selectCriterion, startElement ) {
1738 var upper = startElement,
1739 lower = startElement,
1740 mouseStep = 0,
1741 upperFound = false,
1742 lowerFound = false,
1743 viewPaneHeight = that.view.pane.height,
1744 mouse = that.mouse;
1745
1746 while ( mouse.y + mouseStep < viewPaneHeight && mouse.y - mouseStep > 0 ) {
1747 if ( !upperFound )
1748 upperFound = stopCondition( upper, startElement );
1749
1750 if ( !lowerFound )
1751 lowerFound = stopCondition( lower, startElement );
1752
1753 // Still not found...
1754 if ( !upperFound && mouse.y - mouseStep > 0 )
1755 upper = selectCriterion( that, { x: mouse.x, y: mouse.y - mouseStep } );
1756
1757 if ( !lowerFound && mouse.y + mouseStep < viewPaneHeight )
1758 lower = selectCriterion( that, { x: mouse.x, y: mouse.y + mouseStep } );
1759
1760 if ( upperFound && lowerFound )
1761 break;
1762
1763 // Instead of ++ to reduce the number of invocations by half.
1764 // It's trades off accuracy in some edge cases for improved performance.
1765 mouseStep += 2;
1766 }
1767
1768 return new boxTrigger( [ upper, lower, null, null ] );
1769 }
1770
1771} )();
1772
1773/**
1774 * Sets the default vertical distance between the edge of the element and the mouse pointer that
1775 * causes the magic line to appear. This option accepts a value in pixels, without the unit (for example:
1776 * `15` for 15 pixels).
1777 *
1778 * Read more in the [documentation](#!/guide/dev_magicline)
1779 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1780 *
1781 * // Changes the offset to 15px.
1782 * CKEDITOR.config.magicline_triggerOffset = 15;
1783 *
1784 * @cfg {Number} [magicline_triggerOffset=30]
1785 * @member CKEDITOR.config
1786 * @see CKEDITOR.config#magicline_holdDistance
1787 */
1788
1789/**
1790 * Defines the distance between the mouse pointer and the box within
1791 * which the magic line stays revealed and no other focus space is offered to be accessed.
1792 * This value is relative to {@link #magicline_triggerOffset}.
1793 *
1794 * Read more in the [documentation](#!/guide/dev_magicline)
1795 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1796 *
1797 * // Increases the distance to 80% of CKEDITOR.config.magicline_triggerOffset.
1798 * CKEDITOR.config.magicline_holdDistance = .8;
1799 *
1800 * @cfg {Number} [magicline_holdDistance=0.5]
1801 * @member CKEDITOR.config
1802 * @see CKEDITOR.config#magicline_triggerOffset
1803 */
1804
1805/**
1806 * Defines the default keystroke that accesses the closest unreachable focus space **before**
1807 * the caret (start of the selection). If there is no focus space available, the selection remains unchanged.
1808 *
1809 * Read more in the [documentation](#!/guide/dev_magicline)
1810 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1811 *
1812 * // Changes the default keystroke to "Ctrl + ,".
1813 * CKEDITOR.config.magicline_keystrokePrevious = CKEDITOR.CTRL + 188;
1814 *
1815 * @cfg {Number} [magicline_keystrokePrevious=CKEDITOR.CTRL + CKEDITOR.SHIFT + 51 (CTRL + SHIFT + 3)]
1816 * @member CKEDITOR.config
1817 */
1818CKEDITOR.config.magicline_keystrokePrevious = CKEDITOR.CTRL + CKEDITOR.SHIFT + 51; // CTRL + SHIFT + 3
1819
1820/**
1821 * Defines the default keystroke that accesses the closest unreachable focus space **after**
1822 * the caret (start of the selection). If there is no focus space available, the selection remains unchanged.
1823 *
1824 * Read more in the [documentation](#!/guide/dev_magicline)
1825 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1826 *
1827 * // Changes keystroke to "Ctrl + .".
1828 * CKEDITOR.config.magicline_keystrokeNext = CKEDITOR.CTRL + 190;
1829 *
1830 * @cfg {Number} [magicline_keystrokeNext=CKEDITOR.CTRL + CKEDITOR.SHIFT + 52 (CTRL + SHIFT + 4)]
1831 * @member CKEDITOR.config
1832 */
1833CKEDITOR.config.magicline_keystrokeNext = CKEDITOR.CTRL + CKEDITOR.SHIFT + 52; // CTRL + SHIFT + 4
1834
1835/**
1836 * Defines a list of attributes that, if assigned to some elements, prevent the magic line from being
1837 * used within these elements.
1838 *
1839 * Read more in the [documentation](#!/guide/dev_magicline)
1840 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1841 *
1842 * // Adds the "data-tabu" attribute to the magic line tabu list.
1843 * CKEDITOR.config.magicline_tabuList = [ 'data-tabu' ];
1844 *
1845 * @cfg {Number} [magicline_tabuList=[ 'data-widget-wrapper' ]]
1846 * @member CKEDITOR.config
1847 */
1848
1849/**
1850 * Defines the color of the magic line. The color may be adjusted to enhance readability.
1851 *
1852 * Read more in the [documentation](#!/guide/dev_magicline)
1853 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1854 *
1855 * // Changes magic line color to blue.
1856 * CKEDITOR.config.magicline_color = '#0000FF';
1857 *
1858 * @cfg {String} [magicline_color='#FF0000']
1859 * @member CKEDITOR.config
1860 */
1861
1862/**
1863 * Activates the special all-encompassing mode that considers all focus spaces between
1864 * {@link CKEDITOR.dtd#$block} elements as accessible by the magic line.
1865 *
1866 * Read more in the [documentation](#!/guide/dev_magicline)
1867 * and see the [SDK sample](http://sdk.ckeditor.com/samples/magicline.html).
1868 *
1869 * // Enables the greedy "put everywhere" mode.
1870 * CKEDITOR.config.magicline_everywhere = true;
1871 *
1872 * @cfg {Boolean} [magicline_everywhere=false]
1873 * @member CKEDITOR.config
1874 */
diff --git a/sources/plugins/magicline/samples/magicline.html b/sources/plugins/magicline/samples/magicline.html
new file mode 100644
index 0000000..8fff40e
--- /dev/null
+++ b/sources/plugins/magicline/samples/magicline.html
@@ -0,0 +1,209 @@
1<!DOCTYPE html>
2<!--
3Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
4For licensing, see LICENSE.md or http://ckeditor.com/license
5-->
6<html>
7<head>
8 <meta charset="utf-8">
9 <title>Using Magicline plugin &mdash; CKEditor Sample</title>
10 <script src="../../../ckeditor.js"></script>
11 <link rel="stylesheet" href="../../../samples/old/sample.css">
12 <meta name="ckeditor-sample-name" content="Magicline plugin">
13 <meta name="ckeditor-sample-group" content="Plugins">
14 <meta name="ckeditor-sample-description" content="Using the Magicline plugin to access difficult focus spaces.">
15</head>
16<body>
17 <h1 class="samples">
18 <a href="../../../samples/old/index.html">CKEditor Samples</a> &raquo; Using Magicline plugin
19 </h1>
20 <div class="warning deprecated">
21 This sample is not maintained anymore. Check out its <a href="http://sdk.ckeditor.com/samples/magicline.html">brand new version in CKEditor SDK</a>.
22 </div>
23 <div class="description">
24 <p>
25 This sample shows the advantages of <strong>Magicline</strong> plugin
26 which is to enhance the editing process. Thanks to this plugin,
27 a number of difficult focus spaces which are inaccessible due to
28 browser issues can now be focused.
29 </p>
30 <p>
31 <strong>Magicline</strong> plugin shows a red line with a handler
32 which, when clicked, inserts a paragraph and allows typing. To see this,
33 focus an editor and move your mouse above the focus space you want
34 to access. The plugin is enabled by default so no additional
35 configuration is necessary.
36 </p>
37 </div>
38 <div>
39 <label for="editor1">
40 Editor 1:
41 </label>
42 <div class="description">
43 <p>
44 This editor uses a default <strong>Magicline</strong> setup.
45 </p>
46 </div>
47 <textarea cols="80" id="editor1" name="editor1" rows="10">
48 &lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot; style=&quot;width: 100%; &quot;&gt;
49 &lt;tbody&gt;
50 &lt;tr&gt;
51 &lt;td&gt;This table&lt;/td&gt;
52 &lt;td&gt;is the&lt;/td&gt;
53 &lt;td&gt;very first&lt;/td&gt;
54 &lt;td&gt;element of the document.&lt;/td&gt;
55 &lt;/tr&gt;
56 &lt;tr&gt;
57 &lt;td&gt;We are still&lt;/td&gt;
58 &lt;td&gt;able to acces&lt;/td&gt;
59 &lt;td&gt;the space before it.&lt;/td&gt;
60 &lt;td&gt;
61 &lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot; style=&quot;width: 100%; &quot;&gt;
62 &lt;tbody&gt;
63 &lt;tr&gt;
64 &lt;td&gt;This table is inside of a cell of another table.&lt;/td&gt;
65 &lt;/tr&gt;
66 &lt;tr&gt;
67 &lt;td&gt;We can type&amp;nbsp;either before or after it though.&lt;/td&gt;
68 &lt;/tr&gt;
69 &lt;/tbody&gt;
70 &lt;/table&gt;
71 &lt;/td&gt;
72 &lt;/tr&gt;
73 &lt;/tbody&gt;
74 &lt;/table&gt;
75
76 &lt;p&gt;Two succesive horizontal lines (&lt;tt&gt;HR&lt;/tt&gt; tags). We can access the space in between:&lt;/p&gt;
77
78 &lt;hr /&gt;
79 &lt;hr /&gt;
80 &lt;ol&gt;
81 &lt;li&gt;This numbered list...&lt;/li&gt;
82 &lt;li&gt;...is a neighbour of a horizontal line...&lt;/li&gt;
83 &lt;li&gt;...and another list.&lt;/li&gt;
84 &lt;/ol&gt;
85
86 &lt;ul&gt;
87 &lt;li&gt;We can type between the lists...&lt;/li&gt;
88 &lt;li&gt;...thanks to &lt;strong&gt;Magicline&lt;/strong&gt;.&lt;/li&gt;
89 &lt;/ul&gt;
90
91 &lt;p&gt;Lorem ipsum dolor sit amet dui. Morbi vel turpis. Nullam et leo. Etiam rutrum, urna tellus dui vel tincidunt mattis egestas, justo fringilla vel, massa. Phasellus.&lt;/p&gt;
92
93 &lt;p&gt;Quisque iaculis, dui lectus varius vitae, tortor. Proin lacus. Pellentesque ac lacus. Aenean nonummy commodo nec, pede. Etiam blandit risus elit.&lt;/p&gt;
94
95 &lt;p&gt;Ut pretium. Vestibulum rutrum in, adipiscing elit. Sed in quam in purus sem vitae pede. Pellentesque bibendum, urna sem vel risus. Vivamus posuere metus. Aliquam gravida iaculis nisl. Nam enim. Aliquam erat ac lacus tellus ac felis.&lt;/p&gt;
96
97 &lt;div style=&quot;border: 2px dashed green; background: #ddd; text-align: center;&quot;&gt;
98 &lt;p&gt;This text is wrapped in a&amp;nbsp;&lt;tt&gt;DIV&lt;/tt&gt;&amp;nbsp;element. We can type after this element though.&lt;/p&gt;
99 &lt;/div&gt;
100 </textarea>
101 <script>
102
103 // This call can be placed at any point after the
104 // <textarea>, or inside a <head><script> in a
105 // window.onload event handler.
106
107 CKEDITOR.replace( 'editor1', {
108 extraPlugins: 'magicline', // Ensure that magicline plugin, which is required for this sample, is loaded.
109 allowedContent: true // Switch off the ACF, so very complex content created to
110 // show magicline's power isn't filtered.
111 } );
112
113 </script>
114 </div>
115 <br>
116 <div>
117 <label for="editor2">
118 Editor 2:
119 </label>
120 <div class="description">
121 <p>
122 This editor is using a blue line.
123 </p>
124<pre class="samples">
125CKEDITOR.replace( 'editor2', {
126 magicline_color: 'blue'
127});</pre>
128 </div>
129 <textarea cols="80" id="editor2" name="editor2" rows="10">
130 &lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot; style=&quot;width: 100%; &quot;&gt;
131 &lt;tbody&gt;
132 &lt;tr&gt;
133 &lt;td&gt;This table&lt;/td&gt;
134 &lt;td&gt;is the&lt;/td&gt;
135 &lt;td&gt;very first&lt;/td&gt;
136 &lt;td&gt;element of the document.&lt;/td&gt;
137 &lt;/tr&gt;
138 &lt;tr&gt;
139 &lt;td&gt;We are still&lt;/td&gt;
140 &lt;td&gt;able to acces&lt;/td&gt;
141 &lt;td&gt;the space before it.&lt;/td&gt;
142 &lt;td&gt;
143 &lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot; style=&quot;width: 100%; &quot;&gt;
144 &lt;tbody&gt;
145 &lt;tr&gt;
146 &lt;td&gt;This table is inside of a cell of another table.&lt;/td&gt;
147 &lt;/tr&gt;
148 &lt;tr&gt;
149 &lt;td&gt;We can type&amp;nbsp;either before or after it though.&lt;/td&gt;
150 &lt;/tr&gt;
151 &lt;/tbody&gt;
152 &lt;/table&gt;
153 &lt;/td&gt;
154 &lt;/tr&gt;
155 &lt;/tbody&gt;
156 &lt;/table&gt;
157
158 &lt;p&gt;Two succesive horizontal lines (&lt;tt&gt;HR&lt;/tt&gt; tags). We can access the space in between:&lt;/p&gt;
159
160 &lt;hr /&gt;
161 &lt;hr /&gt;
162 &lt;ol&gt;
163 &lt;li&gt;This numbered list...&lt;/li&gt;
164 &lt;li&gt;...is a neighbour of a horizontal line...&lt;/li&gt;
165 &lt;li&gt;...and another list.&lt;/li&gt;
166 &lt;/ol&gt;
167
168 &lt;ul&gt;
169 &lt;li&gt;We can type between the lists...&lt;/li&gt;
170 &lt;li&gt;...thanks to &lt;strong&gt;Magicline&lt;/strong&gt;.&lt;/li&gt;
171 &lt;/ul&gt;
172
173 &lt;p&gt;Lorem ipsum dolor sit amet dui. Morbi vel turpis. Nullam et leo. Etiam rutrum, urna tellus dui vel tincidunt mattis egestas, justo fringilla vel, massa. Phasellus.&lt;/p&gt;
174
175 &lt;p&gt;Quisque iaculis, dui lectus varius vitae, tortor. Proin lacus. Pellentesque ac lacus. Aenean nonummy commodo nec, pede. Etiam blandit risus elit.&lt;/p&gt;
176
177 &lt;p&gt;Ut pretium. Vestibulum rutrum in, adipiscing elit. Sed in quam in purus sem vitae pede. Pellentesque bibendum, urna sem vel risus. Vivamus posuere metus. Aliquam gravida iaculis nisl. Nam enim. Aliquam erat ac lacus tellus ac felis.&lt;/p&gt;
178
179 &lt;div style=&quot;border: 2px dashed green; background: #ddd; text-align: center;&quot;&gt;
180 &lt;p&gt;This text is wrapped in a&amp;nbsp;&lt;tt&gt;DIV&lt;/tt&gt;&amp;nbsp;element. We can type after this element though.&lt;/p&gt;
181 &lt;/div&gt;
182 </textarea>
183 <script>
184
185 // This call can be placed at any point after the
186 // <textarea>, or inside a <head><script> in a
187 // window.onload event handler.
188
189 CKEDITOR.replace( 'editor2', {
190 extraPlugins: 'magicline', // Ensure that magicline plugin, which is required for this sample, is loaded.
191 magicline_color: 'blue', // Blue line
192 allowedContent: true // Switch off the ACF, so very complex content created to
193 // show magicline's power isn't filtered.
194 });
195
196 </script>
197 </div>
198 <div id="footer">
199 <hr>
200 <p>
201 CKEditor - The text editor for the Internet - <a class="samples" href="http://ckeditor.com/">http://ckeditor.com</a>
202 </p>
203 <p id="copy">
204 Copyright &copy; 2003-2017, <a class="samples" href="http://cksource.com/">CKSource</a> - Frederico
205 Knabben. All rights reserved.
206 </p>
207 </div>
208</body>
209</html>