]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/debian/missing-sources/framework/Web/Javascripts/source/tinymce-405/classes/dom/Range.js
baculum: Add missing-sources directory in debian metadata structure
[bacula/bacula] / gui / baculum / debian / missing-sources / framework / Web / Javascripts / source / tinymce-405 / classes / dom / Range.js
1 /**
2  * Range.js
3  *
4  * Copyright, Moxiecode Systems AB
5  * Released under LGPL License.
6  *
7  * License: http://www.tinymce.com/license
8  * Contributing: http://www.tinymce.com/contributing
9  */
10
11 define("tinymce/dom/Range", [
12         "tinymce/util/Tools"
13 ], function(Tools) {
14         // Range constructor
15         function Range(dom) {
16                 var t = this,
17                         doc = dom.doc,
18                         EXTRACT = 0,
19                         CLONE = 1,
20                         DELETE = 2,
21                         TRUE = true,
22                         FALSE = false,
23                         START_OFFSET = 'startOffset',
24                         START_CONTAINER = 'startContainer',
25                         END_CONTAINER = 'endContainer',
26                         END_OFFSET = 'endOffset',
27                         extend = Tools.extend,
28                         nodeIndex = dom.nodeIndex;
29
30                 function createDocumentFragment() {
31                         return doc.createDocumentFragment();
32                 }
33
34                 function setStart(n, o) {
35                         _setEndPoint(TRUE, n, o);
36                 }
37
38                 function setEnd(n, o) {
39                         _setEndPoint(FALSE, n, o);
40                 }
41
42                 function setStartBefore(n) {
43                         setStart(n.parentNode, nodeIndex(n));
44                 }
45
46                 function setStartAfter(n) {
47                         setStart(n.parentNode, nodeIndex(n) + 1);
48                 }
49
50                 function setEndBefore(n) {
51                         setEnd(n.parentNode, nodeIndex(n));
52                 }
53
54                 function setEndAfter(n) {
55                         setEnd(n.parentNode, nodeIndex(n) + 1);
56                 }
57
58                 function collapse(ts) {
59                         if (ts) {
60                                 t[END_CONTAINER] = t[START_CONTAINER];
61                                 t[END_OFFSET] = t[START_OFFSET];
62                         } else {
63                                 t[START_CONTAINER] = t[END_CONTAINER];
64                                 t[START_OFFSET] = t[END_OFFSET];
65                         }
66
67                         t.collapsed = TRUE;
68                 }
69
70                 function selectNode(n) {
71                         setStartBefore(n);
72                         setEndAfter(n);
73                 }
74
75                 function selectNodeContents(n) {
76                         setStart(n, 0);
77                         setEnd(n, n.nodeType === 1 ? n.childNodes.length : n.nodeValue.length);
78                 }
79
80                 function compareBoundaryPoints(h, r) {
81                         var sc = t[START_CONTAINER], so = t[START_OFFSET], ec = t[END_CONTAINER], eo = t[END_OFFSET],
82                         rsc = r.startContainer, rso = r.startOffset, rec = r.endContainer, reo = r.endOffset;
83
84                         // Check START_TO_START
85                         if (h === 0) {
86                                 return _compareBoundaryPoints(sc, so, rsc, rso);
87                         }
88
89                         // Check START_TO_END
90                         if (h === 1) {
91                                 return _compareBoundaryPoints(ec, eo, rsc, rso);
92                         }
93
94                         // Check END_TO_END
95                         if (h === 2) {
96                                 return _compareBoundaryPoints(ec, eo, rec, reo);
97                         }
98
99                         // Check END_TO_START
100                         if (h === 3) {
101                                 return _compareBoundaryPoints(sc, so, rec, reo);
102                         }
103                 }
104
105                 function deleteContents() {
106                         _traverse(DELETE);
107                 }
108
109                 function extractContents() {
110                         return _traverse(EXTRACT);
111                 }
112
113                 function cloneContents() {
114                         return _traverse(CLONE);
115                 }
116
117                 function insertNode(n) {
118                         var startContainer = this[START_CONTAINER],
119                                 startOffset = this[START_OFFSET], nn, o;
120
121                         // Node is TEXT_NODE or CDATA
122                         if ((startContainer.nodeType === 3 || startContainer.nodeType === 4) && startContainer.nodeValue) {
123                                 if (!startOffset) {
124                                         // At the start of text
125                                         startContainer.parentNode.insertBefore(n, startContainer);
126                                 } else if (startOffset >= startContainer.nodeValue.length) {
127                                         // At the end of text
128                                         dom.insertAfter(n, startContainer);
129                                 } else {
130                                         // Middle, need to split
131                                         nn = startContainer.splitText(startOffset);
132                                         startContainer.parentNode.insertBefore(n, nn);
133                                 }
134                         } else {
135                                 // Insert element node
136                                 if (startContainer.childNodes.length > 0) {
137                                         o = startContainer.childNodes[startOffset];
138                                 }
139
140                                 if (o) {
141                                         startContainer.insertBefore(n, o);
142                                 } else {
143                                         startContainer.appendChild(n);
144                                 }
145                         }
146                 }
147
148                 function surroundContents(n) {
149                         var f = t.extractContents();
150
151                         t.insertNode(n);
152                         n.appendChild(f);
153                         t.selectNode(n);
154                 }
155
156                 function cloneRange() {
157                         return extend(new Range(dom), {
158                                 startContainer: t[START_CONTAINER],
159                                 startOffset: t[START_OFFSET],
160                                 endContainer: t[END_CONTAINER],
161                                 endOffset: t[END_OFFSET],
162                                 collapsed: t.collapsed,
163                                 commonAncestorContainer: t.commonAncestorContainer
164                         });
165                 }
166
167                 // Private methods
168
169                 function _getSelectedNode(container, offset) {
170                         var child;
171
172                         if (container.nodeType == 3 /* TEXT_NODE */) {
173                                 return container;
174                         }
175
176                         if (offset < 0) {
177                                 return container;
178                         }
179
180                         child = container.firstChild;
181                         while (child && offset > 0) {
182                                 --offset;
183                                 child = child.nextSibling;
184                         }
185
186                         if (child) {
187                                 return child;
188                         }
189
190                         return container;
191                 }
192
193                 function _isCollapsed() {
194                         return (t[START_CONTAINER] == t[END_CONTAINER] && t[START_OFFSET] == t[END_OFFSET]);
195                 }
196
197                 function _compareBoundaryPoints(containerA, offsetA, containerB, offsetB) {
198                         var c, offsetC, n, cmnRoot, childA, childB;
199
200                         // In the first case the boundary-points have the same container. A is before B
201                         // if its offset is less than the offset of B, A is equal to B if its offset is
202                         // equal to the offset of B, and A is after B if its offset is greater than the
203                         // offset of B.
204                         if (containerA == containerB) {
205                                 if (offsetA == offsetB) {
206                                         return 0; // equal
207                                 }
208
209                                 if (offsetA < offsetB) {
210                                         return -1; // before
211                                 }
212
213                                 return 1; // after
214                         }
215
216                         // In the second case a child node C of the container of A is an ancestor
217                         // container of B. In this case, A is before B if the offset of A is less than or
218                         // equal to the index of the child node C and A is after B otherwise.
219                         c = containerB;
220                         while (c && c.parentNode != containerA) {
221                                 c = c.parentNode;
222                         }
223
224                         if (c) {
225                                 offsetC = 0;
226                                 n = containerA.firstChild;
227
228                                 while (n != c && offsetC < offsetA) {
229                                         offsetC++;
230                                         n = n.nextSibling;
231                                 }
232
233                                 if (offsetA <= offsetC) {
234                                         return -1; // before
235                                 }
236
237                                 return 1; // after
238                         }
239
240                         // In the third case a child node C of the container of B is an ancestor container
241                         // of A. In this case, A is before B if the index of the child node C is less than
242                         // the offset of B and A is after B otherwise.
243                         c = containerA;
244                         while (c && c.parentNode != containerB) {
245                                 c = c.parentNode;
246                         }
247
248                         if (c) {
249                                 offsetC = 0;
250                                 n = containerB.firstChild;
251
252                                 while (n != c && offsetC < offsetB) {
253                                         offsetC++;
254                                         n = n.nextSibling;
255                                 }
256
257                                 if (offsetC < offsetB) {
258                                         return -1; // before
259                                 }
260
261                                 return 1; // after
262                         }
263
264                         // In the fourth case, none of three other cases hold: the containers of A and B
265                         // are siblings or descendants of sibling nodes. In this case, A is before B if
266                         // the container of A is before the container of B in a pre-order traversal of the
267                         // Ranges' context tree and A is after B otherwise.
268                         cmnRoot = dom.findCommonAncestor(containerA, containerB);
269                         childA = containerA;
270
271                         while (childA && childA.parentNode != cmnRoot) {
272                                 childA = childA.parentNode;
273                         }
274
275                         if (!childA) {
276                                 childA = cmnRoot;
277                         }
278
279                         childB = containerB;
280                         while (childB && childB.parentNode != cmnRoot) {
281                                 childB = childB.parentNode;
282                         }
283
284                         if (!childB) {
285                                 childB = cmnRoot;
286                         }
287
288                         if (childA == childB) {
289                                 return 0; // equal
290                         }
291
292                         n = cmnRoot.firstChild;
293                         while (n) {
294                                 if (n == childA) {
295                                         return -1; // before
296                                 }
297
298                                 if (n == childB) {
299                                         return 1; // after
300                                 }
301
302                                 n = n.nextSibling;
303                         }
304                 }
305
306                 function _setEndPoint(st, n, o) {
307                         var ec, sc;
308
309                         if (st) {
310                                 t[START_CONTAINER] = n;
311                                 t[START_OFFSET] = o;
312                         } else {
313                                 t[END_CONTAINER] = n;
314                                 t[END_OFFSET] = o;
315                         }
316
317                         // If one boundary-point of a Range is set to have a root container
318                         // other than the current one for the Range, the Range is collapsed to
319                         // the new position. This enforces the restriction that both boundary-
320                         // points of a Range must have the same root container.
321                         ec = t[END_CONTAINER];
322                         while (ec.parentNode) {
323                                 ec = ec.parentNode;
324                         }
325
326                         sc = t[START_CONTAINER];
327                         while (sc.parentNode) {
328                                 sc = sc.parentNode;
329                         }
330
331                         if (sc == ec) {
332                                 // The start position of a Range is guaranteed to never be after the
333                                 // end position. To enforce this restriction, if the start is set to
334                                 // be at a position after the end, the Range is collapsed to that
335                                 // position.
336                                 if (_compareBoundaryPoints(t[START_CONTAINER], t[START_OFFSET], t[END_CONTAINER], t[END_OFFSET]) > 0) {
337                                         t.collapse(st);
338                                 }
339                         } else {
340                                 t.collapse(st);
341                         }
342
343                         t.collapsed = _isCollapsed();
344                         t.commonAncestorContainer = dom.findCommonAncestor(t[START_CONTAINER], t[END_CONTAINER]);
345                 }
346
347                 function _traverse(how) {
348                         var c, endContainerDepth = 0, startContainerDepth = 0, p, depthDiff, startNode, endNode, sp, ep;
349
350                         if (t[START_CONTAINER] == t[END_CONTAINER]) {
351                                 return _traverseSameContainer(how);
352                         }
353
354                         for (c = t[END_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) {
355                                 if (p == t[START_CONTAINER]) {
356                                         return _traverseCommonStartContainer(c, how);
357                                 }
358
359                                 ++endContainerDepth;
360                         }
361
362                         for (c = t[START_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) {
363                                 if (p == t[END_CONTAINER]) {
364                                         return _traverseCommonEndContainer(c, how);
365                                 }
366
367                                 ++startContainerDepth;
368                         }
369
370                         depthDiff = startContainerDepth - endContainerDepth;
371
372                         startNode = t[START_CONTAINER];
373                         while (depthDiff > 0) {
374                                 startNode = startNode.parentNode;
375                                 depthDiff--;
376                         }
377
378                         endNode = t[END_CONTAINER];
379                         while (depthDiff < 0) {
380                                 endNode = endNode.parentNode;
381                                 depthDiff++;
382                         }
383
384                         // ascend the ancestor hierarchy until we have a common parent.
385                         for (sp = startNode.parentNode, ep = endNode.parentNode; sp != ep; sp = sp.parentNode, ep = ep.parentNode) {
386                                 startNode = sp;
387                                 endNode = ep;
388                         }
389
390                         return _traverseCommonAncestors(startNode, endNode, how);
391                 }
392
393                  function _traverseSameContainer(how) {
394                         var frag, s, sub, n, cnt, sibling, xferNode, start, len;
395
396                         if (how != DELETE) {
397                                 frag = createDocumentFragment();
398                         }
399
400                         // If selection is empty, just return the fragment
401                         if (t[START_OFFSET] == t[END_OFFSET]) {
402                                 return frag;
403                         }
404
405                         // Text node needs special case handling
406                         if (t[START_CONTAINER].nodeType == 3 /* TEXT_NODE */) {
407                                 // get the substring
408                                 s = t[START_CONTAINER].nodeValue;
409                                 sub = s.substring(t[START_OFFSET], t[END_OFFSET]);
410
411                                 // set the original text node to its new value
412                                 if (how != CLONE) {
413                                         n = t[START_CONTAINER];
414                                         start = t[START_OFFSET];
415                                         len = t[END_OFFSET] - t[START_OFFSET];
416
417                                         if (start === 0 && len >= n.nodeValue.length - 1) {
418                                                 n.parentNode.removeChild(n);
419                                         } else {
420                                                 n.deleteData(start, len);
421                                         }
422
423                                         // Nothing is partially selected, so collapse to start point
424                                         t.collapse(TRUE);
425                                 }
426
427                                 if (how == DELETE) {
428                                         return;
429                                 }
430
431                                 if (sub.length > 0) {
432                                         frag.appendChild(doc.createTextNode(sub));
433                                 }
434
435                                 return frag;
436                         }
437
438                         // Copy nodes between the start/end offsets.
439                         n = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]);
440                         cnt = t[END_OFFSET] - t[START_OFFSET];
441
442                         while (n && cnt > 0) {
443                                 sibling = n.nextSibling;
444                                 xferNode = _traverseFullySelected(n, how);
445
446                                 if (frag) {
447                                         frag.appendChild(xferNode);
448                                 }
449
450                                 --cnt;
451                                 n = sibling;
452                         }
453
454                         // Nothing is partially selected, so collapse to start point
455                         if (how != CLONE) {
456                                 t.collapse(TRUE);
457                         }
458
459                         return frag;
460                 }
461
462                 function _traverseCommonStartContainer(endAncestor, how) {
463                         var frag, n, endIdx, cnt, sibling, xferNode;
464
465                         if (how != DELETE) {
466                                 frag = createDocumentFragment();
467                         }
468
469                         n = _traverseRightBoundary(endAncestor, how);
470
471                         if (frag) {
472                                 frag.appendChild(n);
473                         }
474
475                         endIdx = nodeIndex(endAncestor);
476                         cnt = endIdx - t[START_OFFSET];
477
478                         if (cnt <= 0) {
479                                 // Collapse to just before the endAncestor, which
480                                 // is partially selected.
481                                 if (how != CLONE) {
482                                         t.setEndBefore(endAncestor);
483                                         t.collapse(FALSE);
484                                 }
485
486                                 return frag;
487                         }
488
489                         n = endAncestor.previousSibling;
490                         while (cnt > 0) {
491                                 sibling = n.previousSibling;
492                                 xferNode = _traverseFullySelected(n, how);
493
494                                 if (frag) {
495                                         frag.insertBefore(xferNode, frag.firstChild);
496                                 }
497
498                                 --cnt;
499                                 n = sibling;
500                         }
501
502                         // Collapse to just before the endAncestor, which
503                         // is partially selected.
504                         if (how != CLONE) {
505                                 t.setEndBefore(endAncestor);
506                                 t.collapse(FALSE);
507                         }
508
509                         return frag;
510                 }
511
512                 function _traverseCommonEndContainer(startAncestor, how) {
513                         var frag, startIdx, n, cnt, sibling, xferNode;
514
515                         if (how != DELETE) {
516                                 frag = createDocumentFragment();
517                         }
518
519                         n = _traverseLeftBoundary(startAncestor, how);
520                         if (frag) {
521                                 frag.appendChild(n);
522                         }
523
524                         startIdx = nodeIndex(startAncestor);
525                         ++startIdx; // Because we already traversed it
526
527                         cnt = t[END_OFFSET] - startIdx;
528                         n = startAncestor.nextSibling;
529                         while (n && cnt > 0) {
530                                 sibling = n.nextSibling;
531                                 xferNode = _traverseFullySelected(n, how);
532
533                                 if (frag) {
534                                         frag.appendChild(xferNode);
535                                 }
536
537                                 --cnt;
538                                 n = sibling;
539                         }
540
541                         if (how != CLONE) {
542                                 t.setStartAfter(startAncestor);
543                                 t.collapse(TRUE);
544                         }
545
546                         return frag;
547                 }
548
549                 function _traverseCommonAncestors(startAncestor, endAncestor, how) {
550                         var n, frag, commonParent, startOffset, endOffset, cnt, sibling, nextSibling;
551
552                         if (how != DELETE) {
553                                 frag = createDocumentFragment();
554                         }
555
556                         n = _traverseLeftBoundary(startAncestor, how);
557                         if (frag) {
558                                 frag.appendChild(n);
559                         }
560
561                         commonParent = startAncestor.parentNode;
562                         startOffset = nodeIndex(startAncestor);
563                         endOffset = nodeIndex(endAncestor);
564                         ++startOffset;
565
566                         cnt = endOffset - startOffset;
567                         sibling = startAncestor.nextSibling;
568
569                         while (cnt > 0) {
570                                 nextSibling = sibling.nextSibling;
571                                 n = _traverseFullySelected(sibling, how);
572
573                                 if (frag) {
574                                         frag.appendChild(n);
575                                 }
576
577                                 sibling = nextSibling;
578                                 --cnt;
579                         }
580
581                         n = _traverseRightBoundary(endAncestor, how);
582
583                         if (frag) {
584                                 frag.appendChild(n);
585                         }
586
587                         if (how != CLONE) {
588                                 t.setStartAfter(startAncestor);
589                                 t.collapse(TRUE);
590                         }
591
592                         return frag;
593                 }
594
595                 function _traverseRightBoundary(root, how) {
596                         var next = _getSelectedNode(t[END_CONTAINER], t[END_OFFSET] - 1), parent, clonedParent;
597                         var prevSibling, clonedChild, clonedGrandParent, isFullySelected = next != t[END_CONTAINER];
598
599                         if (next == root) {
600                                 return _traverseNode(next, isFullySelected, FALSE, how);
601                         }
602
603                         parent = next.parentNode;
604                         clonedParent = _traverseNode(parent, FALSE, FALSE, how);
605
606                         while (parent) {
607                                 while (next) {
608                                         prevSibling = next.previousSibling;
609                                         clonedChild = _traverseNode(next, isFullySelected, FALSE, how);
610
611                                         if (how != DELETE) {
612                                                 clonedParent.insertBefore(clonedChild, clonedParent.firstChild);
613                                         }
614
615                                         isFullySelected = TRUE;
616                                         next = prevSibling;
617                                 }
618
619                                 if (parent == root) {
620                                         return clonedParent;
621                                 }
622
623                                 next = parent.previousSibling;
624                                 parent = parent.parentNode;
625
626                                 clonedGrandParent = _traverseNode(parent, FALSE, FALSE, how);
627
628                                 if (how != DELETE) {
629                                         clonedGrandParent.appendChild(clonedParent);
630                                 }
631
632                                 clonedParent = clonedGrandParent;
633                         }
634                 }
635
636                 function _traverseLeftBoundary(root, how) {
637                         var next = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]), isFullySelected = next != t[START_CONTAINER];
638                         var parent, clonedParent, nextSibling, clonedChild, clonedGrandParent;
639
640                         if (next == root) {
641                                 return _traverseNode(next, isFullySelected, TRUE, how);
642                         }
643
644                         parent = next.parentNode;
645                         clonedParent = _traverseNode(parent, FALSE, TRUE, how);
646
647                         while (parent) {
648                                 while (next) {
649                                         nextSibling = next.nextSibling;
650                                         clonedChild = _traverseNode(next, isFullySelected, TRUE, how);
651
652                                         if (how != DELETE) {
653                                                 clonedParent.appendChild(clonedChild);
654                                         }
655
656                                         isFullySelected = TRUE;
657                                         next = nextSibling;
658                                 }
659
660                                 if (parent == root) {
661                                         return clonedParent;
662                                 }
663
664                                 next = parent.nextSibling;
665                                 parent = parent.parentNode;
666
667                                 clonedGrandParent = _traverseNode(parent, FALSE, TRUE, how);
668
669                                 if (how != DELETE) {
670                                         clonedGrandParent.appendChild(clonedParent);
671                                 }
672
673                                 clonedParent = clonedGrandParent;
674                         }
675                 }
676
677                 function _traverseNode(n, isFullySelected, isLeft, how) {
678                         var txtValue, newNodeValue, oldNodeValue, offset, newNode;
679
680                         if (isFullySelected) {
681                                 return _traverseFullySelected(n, how);
682                         }
683
684                         if (n.nodeType == 3 /* TEXT_NODE */) {
685                                 txtValue = n.nodeValue;
686
687                                 if (isLeft) {
688                                         offset = t[START_OFFSET];
689                                         newNodeValue = txtValue.substring(offset);
690                                         oldNodeValue = txtValue.substring(0, offset);
691                                 } else {
692                                         offset = t[END_OFFSET];
693                                         newNodeValue = txtValue.substring(0, offset);
694                                         oldNodeValue = txtValue.substring(offset);
695                                 }
696
697                                 if (how != CLONE) {
698                                         n.nodeValue = oldNodeValue;
699                                 }
700
701                                 if (how == DELETE) {
702                                         return;
703                                 }
704
705                                 newNode = dom.clone(n, FALSE);
706                                 newNode.nodeValue = newNodeValue;
707
708                                 return newNode;
709                         }
710
711                         if (how == DELETE) {
712                                 return;
713                         }
714
715                         return dom.clone(n, FALSE);
716                 }
717
718                 function _traverseFullySelected(n, how) {
719                         if (how != DELETE) {
720                                 return how == CLONE ? dom.clone(n, TRUE) : n;
721                         }
722
723                         n.parentNode.removeChild(n);
724                 }
725
726                 function toStringIE() {
727                         return dom.create('body', null, cloneContents()).outerText;
728                 }
729
730                 extend(t, {
731                         // Inital states
732                         startContainer: doc,
733                         startOffset: 0,
734                         endContainer: doc,
735                         endOffset: 0,
736                         collapsed: TRUE,
737                         commonAncestorContainer: doc,
738
739                         // Range constants
740                         START_TO_START: 0,
741                         START_TO_END: 1,
742                         END_TO_END: 2,
743                         END_TO_START: 3,
744
745                         // Public methods
746                         setStart: setStart,
747                         setEnd: setEnd,
748                         setStartBefore: setStartBefore,
749                         setStartAfter: setStartAfter,
750                         setEndBefore: setEndBefore,
751                         setEndAfter: setEndAfter,
752                         collapse: collapse,
753                         selectNode: selectNode,
754                         selectNodeContents: selectNodeContents,
755                         compareBoundaryPoints: compareBoundaryPoints,
756                         deleteContents: deleteContents,
757                         extractContents: extractContents,
758                         cloneContents: cloneContents,
759                         insertNode: insertNode,
760                         surroundContents: surroundContents,
761                         cloneRange: cloneRange,
762                         toStringIE: toStringIE
763                 });
764
765                 return t;
766         }
767
768         // Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype
769         Range.prototype.toString = function() {
770                 return this.toStringIE();
771         };
772
773         return Range;
774 });