From 4004c0cb0d6cb8f9980716e30f3544b4b02cf575 Mon Sep 17 00:00:00 2001 From: alexbrekken Date: Fri, 20 Oct 2017 16:42:18 -0500 Subject: [PATCH] Added ability to partially un-highlight selected text. --- src/modules/rangy-highlighter.js | 37 ++++++++++++++++++ test/highlightertests.js | 67 +++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/src/modules/rangy-highlighter.js b/src/modules/rangy-highlighter.js index 4527d5d6..3b7dfcfd 100644 --- a/src/modules/rangy-highlighter.js +++ b/src/modules/rangy-highlighter.js @@ -291,6 +291,43 @@ rangy.createModule("Highlighter", ["ClassApplier"], function(api, module) { } }, + /** + * Removes all highlights for the currently selected text and preserves any existing highlights + * that were partially selected. + */ + removeHighlightsFromSelection: function(containerElementId) { + var _self = this; + var doc = this.doc; + var currentSelection = api.getSelection(doc); + var scope = getContainerElement(currentSelection.win.document, containerElementId); + var charRanges = []; + + forEach(currentSelection.getAllRanges(), function(range) { + var charRangeScoped = _self.converter.rangeToCharacterRange(range, scope); + charRanges.push(charRangeScoped); + }); + + var newHighlights = []; + var intersectingHighlights = this.getHighlightsInSelection(currentSelection); + if (intersectingHighlights.length > 0) { + forEach(charRanges, function(charRange) { + //for each charRange in the selection, see if it intersects with any existing highlights + //and preserve unselected portions of existing highlights + forEach(intersectingHighlights, function(highlight) { + var complements = highlight.characterRange.getComplements(charRange); + forEach(complements, function(complement) { + newHighlights.push(new Highlight(doc, complement, highlight.classApplier, _self.converter, null, containerElementId)); + }); + }); + }); + } + this.removeHighlights(intersectingHighlights); + forEach(newHighlights, function(highlight) { + highlight.apply(); + _self.highlights.push(highlight); + }); + }, + removeAllHighlights: function() { this.removeHighlights(this.highlights); }, diff --git a/test/highlightertests.js b/test/highlightertests.js index d95162df..c21b5605 100644 --- a/test/highlightertests.js +++ b/test/highlightertests.js @@ -30,4 +30,69 @@ xn.test.suite("Highlighter module tests", function(s) { highlighter.highlightSelection("c1", { selection: rangy.getSelection() }); }); -}, false); + s.test("partial unhighlight test", function(t) { + var applier = rangy.createClassApplier("yellow"); + var highlighter = rangy.createHighlighter(); + highlighter.addClassApplier(applier); + + var testEl = document.getElementById("test"); + var range = rangyTestUtils.createRangeInHtml(testEl, '[one two three four]'); + range.select(); + + highlighter.highlightSelection("yellow"); + + t.assertEquals(highlighter.highlights[0].characterRange.start, 9); + t.assertEquals(highlighter.highlights[0].characterRange.end, 27); + + var range2 = rangyTestUtils.createRangeInHtml(testEl, '[one two] three four'); + range2.select(); + + highlighter.removeHighlightsFromSelection(); + + t.assertEquals(highlighter.highlights[0].characterRange.start, 16); + t.assertEquals(highlighter.highlights[0].characterRange.end, 27); + }); + + s.test("partial unhighlight test 2", function(t) { + var yellow = rangy.createClassApplier("yellow"); + var green = rangy.createClassApplier("green"); + var highlighter = rangy.createHighlighter(); + highlighter.addClassApplier(yellow); + highlighter.addClassApplier(green); + + var testEl = document.getElementById("test"); + var range = rangyTestUtils.createRangeInHtml(testEl, '[one two three four]'); + range.select(); + + highlighter.highlightSelection("yellow"); + + var range2 = rangyTestUtils.createRangeInHtml(testEl, '[one two] three four'); + range2.select(); + highlighter.highlightSelection("green"); + + //yellow + t.assertEquals(highlighter.highlights[0].classApplier.className, "yellow"); + t.assertEquals(highlighter.highlights[0].characterRange.start, 16); + t.assertEquals(highlighter.highlights[0].characterRange.end, 27); + //green + t.assertEquals(highlighter.highlights[1].classApplier.className, "green"); + t.assertEquals(highlighter.highlights[1].characterRange.start, 9); + t.assertEquals(highlighter.highlights[1].characterRange.end, 16); + + var range3 = rangyTestUtils.createRangeInHtml(testEl, 'one [two three] four'); + range3.select(); + + highlighter.removeHighlightsFromSelection(); + + //yellow + t.assertEquals(highlighter.highlights[0].classApplier.className, "yellow"); + t.assertEquals(highlighter.highlights[0].characterRange.start, 22); + t.assertEquals(highlighter.highlights[0].characterRange.end, 27); + //green + t.assertEquals(highlighter.highlights[1].classApplier.className, "green"); + t.assertEquals(highlighter.highlights[1].characterRange.start, 9); + t.assertEquals(highlighter.highlights[1].characterRange.end, 13); + + }); + +}, false); \ No newline at end of file