diff --git a/src/ui/filter.js b/src/ui/filter.js index 5e37c4513..29a8bf2ab 100644 --- a/src/ui/filter.js +++ b/src/ui/filter.js @@ -160,10 +160,14 @@ Filter.prototype.updateFilter = function (filter) { return; } - var annotations = this.highlights.map(function () { - return $(this).data('annotation'); - }); - annotations = $.makeArray(annotations); + var annotations = (function (highlights) { + var annotationsById = {}; + highlights.each(function () { + var a = $(this).data('annotation'); + annotationsById[a._local.id] = a; + }); + return $.map(annotationsById, function(a) { return a; }); + }(this.highlights)); for (var i = 0, len = annotations.length; i < len; i++) { var annotation = annotations[i], diff --git a/src/ui/highlighter.js b/src/ui/highlighter.js index a4ebb5ce5..bc1b05a42 100644 --- a/src/ui/highlighter.js +++ b/src/ui/highlighter.js @@ -119,6 +119,15 @@ Highlighter.prototype.drawAll = function (annotations) { return p; }; +// local unique IDs for annotations, used to deduplicate when recovering them +// from highlights. +var id = (function () { + var counter = 0; + return function() { + return '_local_id_' + (++counter); + } +}()); + // Public: Draw highlights for the annotation. // // annotation - An annotation Object for which to draw highlights. @@ -140,10 +149,15 @@ Highlighter.prototype.draw = function (annotation) { annotation._local = {}; } var hasHighlights = (typeof annotation._local.highlights !== 'undefined' && - annotation._local.highlights === null); + annotation._local.highlights !== null); if (!hasHighlights) { annotation._local.highlights = []; } + var hasLocalId = (typeof annotation._local.id !== 'undefined' && + annotation._local.id === null); + if (!hasLocalId) { + annotation._local.id = id(); + } for (var j = 0, jlen = normedRanges.length; j < jlen; j++) { var normed = normedRanges[j]; diff --git a/test/spec/ui/filter_spec.js b/test/spec/ui/filter_spec.js index ad49a28bb..79d3f2c4f 100644 --- a/test/spec/ui/filter_spec.js +++ b/test/spec/ui/filter_spec.js @@ -124,15 +124,27 @@ describe('ui.filter.Filter', function () { } }; annotations = [{text: 'cat'}, {text: 'dog'}, {text: 'car'}]; + $.each(annotations, function(i, annotation) { + this._local = {id: this.text}; + for (var j = 0; j < annotation.text.length; j++) { + var ch = annotation.text[j] + $('') + .text(ch) + .data('annotation', annotation) + .appendTo(element); + } + }); plugin.filters = {'text': testFilter}; - plugin.highlights = { - map: function () { return annotations; } - }; + plugin.highlights = $(element).find('.annotator-hl'); sandbox.stub(plugin, 'updateHighlights'); sandbox.stub(plugin, 'resetHighlights'); sandbox.stub(plugin, 'filterHighlights'); }); + afterEach(function () { + $(element).empty(); + }); + it("should call Filter#updateHighlights()", function () { plugin.updateFilter(testFilter); assert(plugin.updateHighlights.calledOnce);