* Takes range object as parameter and refines it boundaries * @param range * @returns {object} refined boundaries and initial state of highlighting algorithm.
(range)
| 92 | * @returns {object} refined boundaries and initial state of highlighting algorithm. |
| 93 | */ |
| 94 | function refineRangeBoundaries(range) { |
| 95 | var startContainer = range.startContainer, |
| 96 | endContainer = range.endContainer, |
| 97 | ancestor = range.commonAncestorContainer, |
| 98 | goDeeper = true; |
| 99 | |
| 100 | if (range.endOffset === 0) { |
| 101 | while (!endContainer.previousSibling && endContainer.parentNode !== ancestor) { |
| 102 | endContainer = endContainer.parentNode; |
| 103 | } |
| 104 | endContainer = endContainer.previousSibling; |
| 105 | } else if (endContainer.nodeType === NODE_TYPE.TEXT_NODE) { |
| 106 | if (range.endOffset < endContainer.nodeValue.length) { |
| 107 | endContainer.splitText(range.endOffset); |
| 108 | } |
| 109 | } else if (range.endOffset > 0) { |
| 110 | endContainer = endContainer.childNodes.item(range.endOffset - 1); |
| 111 | } |
| 112 | |
| 113 | if (startContainer.nodeType === NODE_TYPE.TEXT_NODE) { |
| 114 | if (range.startOffset === startContainer.nodeValue.length) { |
| 115 | goDeeper = false; |
| 116 | } else if (range.startOffset > 0) { |
| 117 | startContainer = startContainer.splitText(range.startOffset); |
| 118 | if (endContainer === startContainer.previousSibling) { |
| 119 | endContainer = startContainer; |
| 120 | } |
| 121 | } |
| 122 | } else if (range.startOffset < startContainer.childNodes.length) { |
| 123 | startContainer = startContainer.childNodes.item(range.startOffset); |
| 124 | } else { |
| 125 | startContainer = startContainer.nextSibling; |
| 126 | } |
| 127 | |
| 128 | return { |
| 129 | startContainer: startContainer, |
| 130 | endContainer: endContainer, |
| 131 | goDeeper: goDeeper |
| 132 | }; |
| 133 | } |
| 134 | |
| 135 | /** |
| 136 | * Sorts array of DOM elements by its depth in DOM tree. |