Mercurial > hg > OKFNAnnotator
comparison annotator_files/lib/plugin/filter.js @ 3:6356e78ccf5c
new version contains Annotator JS files to be used with FilesystemSite.
author | casties |
---|---|
date | Thu, 05 Apr 2012 19:37:27 +0200 |
parents | |
children | 6979313586cf |
comparison
equal
deleted
inserted
replaced
2:4c6c8835fc5c | 3:6356e78ccf5c |
---|---|
1 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, | |
2 __hasProp = Object.prototype.hasOwnProperty, | |
3 __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; | |
4 | |
5 Annotator.Plugin.Filter = (function(_super) { | |
6 | |
7 __extends(Filter, _super); | |
8 | |
9 Filter.prototype.events = { | |
10 ".annotator-filter-property input focus": "_onFilterFocus", | |
11 ".annotator-filter-property input blur": "_onFilterBlur", | |
12 ".annotator-filter-property input keyup": "_onFilterKeyup", | |
13 ".annotator-filter-previous click": "_onPreviousClick", | |
14 ".annotator-filter-next click": "_onNextClick", | |
15 ".annotator-filter-clear click": "_onClearClick" | |
16 }; | |
17 | |
18 Filter.prototype.classes = { | |
19 active: 'annotator-filter-active', | |
20 hl: { | |
21 hide: 'annotator-hl-filtered', | |
22 active: 'annotator-hl-active' | |
23 } | |
24 }; | |
25 | |
26 Filter.prototype.html = { | |
27 element: "<div class=\"annotator-filter\">\n <strong>" + Annotator._t('Navigate:') + "</strong>\n<span class=\"annotator-filter-navigation\">\n <button class=\"annotator-filter-previous\">" + Annotator._t('Previous') + "</button>\n<button class=\"annotator-filter-next\">" + Annotator._t('Next') + "</button>\n</span>\n<strong>" + Annotator._t('Filter by:') + "</strong>\n</div>", | |
28 filter: "<span class=\"annotator-filter-property\">\n <label></label>\n <input/>\n <button class=\"annotator-filter-clear\">" + Annotator._t('Clear') + "</button>\n</span>" | |
29 }; | |
30 | |
31 Filter.prototype.options = { | |
32 appendTo: 'body', | |
33 filters: [], | |
34 addAnnotationFilter: true, | |
35 isFiltered: function(input, property) { | |
36 var keyword, _i, _len, _ref; | |
37 if (!(input && property)) return false; | |
38 _ref = input.split(/\s*/); | |
39 for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
40 keyword = _ref[_i]; | |
41 if (property.indexOf(keyword) === -1) return false; | |
42 } | |
43 return true; | |
44 } | |
45 }; | |
46 | |
47 function Filter(element, options) { | |
48 this._onPreviousClick = __bind(this._onPreviousClick, this); | |
49 this._onNextClick = __bind(this._onNextClick, this); | |
50 this._onFilterKeyup = __bind(this._onFilterKeyup, this); | |
51 this._onFilterBlur = __bind(this._onFilterBlur, this); | |
52 this._onFilterFocus = __bind(this._onFilterFocus, this); | |
53 this.updateHighlights = __bind(this.updateHighlights, this); element = $(this.html.element).appendTo(this.options.appendTo); | |
54 Filter.__super__.constructor.call(this, element, options); | |
55 this.filter = $(this.html.filter); | |
56 this.filters = []; | |
57 this.current = 0; | |
58 } | |
59 | |
60 Filter.prototype.pluginInit = function() { | |
61 var filter, _i, _len, _ref; | |
62 _ref = this.options.filters; | |
63 for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
64 filter = _ref[_i]; | |
65 this.addFilter(filter); | |
66 } | |
67 this.updateHighlights(); | |
68 this._setupListeners()._insertSpacer(); | |
69 if (this.options.addAnnotationFilter === true) { | |
70 return this.addFilter({ | |
71 label: Annotator._t('Annotation'), | |
72 property: 'text' | |
73 }); | |
74 } | |
75 }; | |
76 | |
77 Filter.prototype._insertSpacer = function() { | |
78 var currentMargin, html; | |
79 html = $('html'); | |
80 currentMargin = parseInt(html.css('padding-top'), 10) || 0; | |
81 html.css('padding-top', currentMargin + this.element.outerHeight()); | |
82 return this; | |
83 }; | |
84 | |
85 Filter.prototype._setupListeners = function() { | |
86 var event, events, _i, _len; | |
87 events = ['annotationsLoaded', 'annotationCreated', 'annotationUpdated', 'annotationDeleted']; | |
88 for (_i = 0, _len = events.length; _i < _len; _i++) { | |
89 event = events[_i]; | |
90 this.annotator.subscribe(event, this.updateHighlights); | |
91 } | |
92 return this; | |
93 }; | |
94 | |
95 Filter.prototype.addFilter = function(options) { | |
96 var f, filter; | |
97 filter = $.extend({ | |
98 label: '', | |
99 property: '', | |
100 isFiltered: this.options.isFiltered | |
101 }, options); | |
102 if (!((function() { | |
103 var _i, _len, _ref, _results; | |
104 _ref = this.filters; | |
105 _results = []; | |
106 for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
107 f = _ref[_i]; | |
108 if (f.property === filter.property) _results.push(f); | |
109 } | |
110 return _results; | |
111 }).call(this)).length) { | |
112 filter.id = 'annotator-filter-' + filter.property; | |
113 filter.annotations = []; | |
114 filter.element = this.filter.clone().appendTo(this.element); | |
115 filter.element.find('label').html(filter.label).attr('for', filter.id); | |
116 filter.element.find('input').attr({ | |
117 id: filter.id, | |
118 placeholder: Annotator._t('Filter by ') + filter.label + '\u2026' | |
119 }); | |
120 filter.element.find('button').hide(); | |
121 filter.element.data('filter', filter); | |
122 this.filters.push(filter); | |
123 } | |
124 return this; | |
125 }; | |
126 | |
127 Filter.prototype.updateFilter = function(filter) { | |
128 var annotation, annotations, input, property, _i, _len, _ref; | |
129 filter.annotations = []; | |
130 this.updateHighlights(); | |
131 this.resetHighlights(); | |
132 input = $.trim(filter.element.find('input').val()); | |
133 if (input) { | |
134 annotations = this.highlights.map(function() { | |
135 return $(this).data('annotation'); | |
136 }); | |
137 _ref = $.makeArray(annotations); | |
138 for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
139 annotation = _ref[_i]; | |
140 property = annotation[filter.property]; | |
141 if (filter.isFiltered(input, property)) { | |
142 filter.annotations.push(annotation); | |
143 } | |
144 } | |
145 return this.filterHighlights(); | |
146 } | |
147 }; | |
148 | |
149 Filter.prototype.updateHighlights = function() { | |
150 this.highlights = this.annotator.element.find('.annotator-hl:visible'); | |
151 return this.filtered = this.highlights.not(this.classes.hl.hide); | |
152 }; | |
153 | |
154 Filter.prototype.filterHighlights = function() { | |
155 var activeFilters, annotation, annotations, filtered, highlights, index, uniques, _len, _ref; | |
156 activeFilters = $.grep(this.filters, function(filter) { | |
157 return !!filter.annotations.length; | |
158 }); | |
159 filtered = ((_ref = activeFilters[0]) != null ? _ref.annotations : void 0) || []; | |
160 if (activeFilters.length > 1) { | |
161 annotations = []; | |
162 $.each(activeFilters, function() { | |
163 return $.merge(annotations, this.annotations); | |
164 }); | |
165 uniques = []; | |
166 filtered = []; | |
167 $.each(annotations, function() { | |
168 if ($.inArray(this, uniques) === -1) { | |
169 return uniques.push(this); | |
170 } else { | |
171 return filtered.push(this); | |
172 } | |
173 }); | |
174 } | |
175 highlights = this.highlights; | |
176 for (index = 0, _len = filtered.length; index < _len; index++) { | |
177 annotation = filtered[index]; | |
178 highlights = highlights.not(annotation.highlights); | |
179 } | |
180 highlights.addClass(this.classes.hl.hide); | |
181 this.filtered = this.highlights.not(this.classes.hl.hide); | |
182 return this; | |
183 }; | |
184 | |
185 Filter.prototype.resetHighlights = function() { | |
186 this.highlights.removeClass(this.classes.hl.hide); | |
187 this.filtered = this.highlights; | |
188 return this; | |
189 }; | |
190 | |
191 Filter.prototype._onFilterFocus = function(event) { | |
192 var input; | |
193 input = $(event.target); | |
194 input.parent().addClass(this.classes.active); | |
195 return input.next('button').show(); | |
196 }; | |
197 | |
198 Filter.prototype._onFilterBlur = function(event) { | |
199 var input; | |
200 if (!event.target.value) { | |
201 input = $(event.target); | |
202 input.parent().removeClass(this.classes.active); | |
203 return input.next('button').hide(); | |
204 } | |
205 }; | |
206 | |
207 Filter.prototype._onFilterKeyup = function(event) { | |
208 var filter; | |
209 filter = $(event.target).parent().data('filter'); | |
210 if (filter) return this.updateFilter(filter); | |
211 }; | |
212 | |
213 Filter.prototype._findNextHighlight = function(previous) { | |
214 var active, annotation, current, index, next, offset, operator, resetOffset; | |
215 if (!this.highlights.length) return this; | |
216 offset = previous ? 0 : -1; | |
217 resetOffset = previous ? -1 : 0; | |
218 operator = previous ? 'lt' : 'gt'; | |
219 active = this.highlights.not('.' + this.classes.hl.hide); | |
220 current = active.filter('.' + this.classes.hl.active); | |
221 if (!current.length) current = active.eq(offset); | |
222 annotation = current.data('annotation'); | |
223 index = active.index(current[0]); | |
224 next = active.filter(":" + operator + "(" + index + ")").not(annotation.highlights).eq(resetOffset); | |
225 if (!next.length) next = active.eq(resetOffset); | |
226 return this._scrollToHighlight(next.data('annotation').highlights); | |
227 }; | |
228 | |
229 Filter.prototype._onNextClick = function(event) { | |
230 return this._findNextHighlight(); | |
231 }; | |
232 | |
233 Filter.prototype._onPreviousClick = function(event) { | |
234 return this._findNextHighlight(true); | |
235 }; | |
236 | |
237 Filter.prototype._scrollToHighlight = function(highlight) { | |
238 highlight = $(highlight); | |
239 this.highlights.removeClass(this.classes.hl.active); | |
240 highlight.addClass(this.classes.hl.active); | |
241 return $('html, body').animate({ | |
242 scrollTop: highlight.offset().top - (this.element.height() + 20) | |
243 }, 150); | |
244 }; | |
245 | |
246 Filter.prototype._onClearClick = function(event) { | |
247 return $(event.target).prev('input').val('').keyup().blur(); | |
248 }; | |
249 | |
250 return Filter; | |
251 | |
252 })(Annotator.Plugin); |