diff --git a/src/annotator.coffee b/src/annotator.coffee index 766d4cb30..9f934d894 100644 --- a/src/annotator.coffee +++ b/src/annotator.coffee @@ -411,15 +411,19 @@ class Annotator extends Delegator highlightRange: (normedRange, cssClass='annotator-hl') -> white = /^\s*$/ - hl = $("") - + results = [] # Ignore text nodes that contain only whitespace characters. This prevents # spans being injected between elements that can only contain a restricted # subset of nodes such as table rows and lists. This does mean that there # may be the odd abandoned whitespace node in a paragraph that is skipped # but better than breaking table layouts. for node in normedRange.textNodes() when not white.test(node.nodeValue) - $(node).wrapAll(hl).parent().show()[0] + hl = document.createElement('span') + hl.className = cssClass + node.parentNode.replaceChild(hl, node) + hl.appendChild(node) + results.push(hl) + return results # Public: highlight a list of ranges # diff --git a/src/range.coffee b/src/range.coffee index e51214e18..833cba6f9 100644 --- a/src/range.coffee +++ b/src/range.coffee @@ -252,13 +252,22 @@ class Range.NormalizedRange # # Returns updated self or null. limit: (bounds) -> - nodes = $.grep this.textNodes(), (node) -> - node.parentNode == bounds or $.contains(bounds, node.parentNode) + if @commonAncestor == bounds or $.contains(bounds, @commonAncestor) + return this - return null unless nodes.length + if not $.contains(@commonAncestor, bounds) + return null + document = bounds.ownerDocument - @start = nodes[0] - @end = nodes[nodes.length - 1] + if not $.contains(bounds, @start) + walker = document.createTreeWalker(bounds, NodeFilter.SHOW_TEXT) + @start = walker.firstChild() + + if not $.contains(bounds, @end) + walker = document.createTreeWalker(bounds, NodeFilter.SHOW_TEXT) + @end = walker.lastChild() + + return null unless @start and @end startParents = $(@start).parents() for parent in $(@end).parents() diff --git a/src/util.coffee b/src/util.coffee index 4921516d6..34e0d0006 100644 --- a/src/util.coffee +++ b/src/util.coffee @@ -50,27 +50,13 @@ Util.contains = (parent, child) -> # # Returns a new jQuery collection of text nodes. Util.getTextNodes = (jq) -> - getTextNodes = (node) -> - if node and node.nodeType != Node.TEXT_NODE - nodes = [] - - # If not a comment then traverse children collecting text nodes. - # We traverse the child nodes manually rather than using the .childNodes - # property because IE9 does not update the .childNodes property after - # .splitText() is called on a child text node. - if node.nodeType != Node.COMMENT_NODE - # Start at the last child and walk backwards through siblings. - node = node.lastChild - while node - nodes.push getTextNodes(node) - node = node.previousSibling - - # Finally reverse the array so that nodes are in the correct order. - return nodes.reverse() - else - return node + getTextNodes = (root) -> + document = root.ownerDocument + walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT) + nodes = (node while node = walker.nextNode()) + return nodes - jq.map -> Util.flatten(getTextNodes(this)) + jq.map -> getTextNodes(this) # Public: determine the last text node inside or before the given node Util.getLastTextNodeUpTo = (n) ->