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 | __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; |
---|
5 | |
---|
6 | Annotator.Plugin.Store = (function(_super) { |
---|
7 | |
---|
8 | __extends(Store, _super); |
---|
9 | |
---|
10 | Store.prototype.events = { |
---|
11 | 'annotationCreated': 'annotationCreated', |
---|
12 | 'annotationDeleted': 'annotationDeleted', |
---|
13 | 'annotationUpdated': 'annotationUpdated' |
---|
14 | }; |
---|
15 | |
---|
16 | Store.prototype.options = { |
---|
17 | prefix: '/store', |
---|
18 | autoFetch: true, |
---|
19 | annotationData: {}, |
---|
20 | loadFromSearch: false, |
---|
21 | urls: { |
---|
22 | create: '/annotations', |
---|
23 | read: '/annotations/:id', |
---|
24 | update: '/annotations/:id', |
---|
25 | destroy: '/annotations/:id', |
---|
26 | search: '/search' |
---|
27 | } |
---|
28 | }; |
---|
29 | |
---|
30 | function Store(element, options) { |
---|
31 | this._onError = __bind(this._onError, this); |
---|
32 | this._onLoadAnnotationsFromSearch = __bind(this._onLoadAnnotationsFromSearch, this); |
---|
33 | this._onLoadAnnotations = __bind(this._onLoadAnnotations, this); |
---|
34 | this._getAnnotations = __bind(this._getAnnotations, this); Store.__super__.constructor.apply(this, arguments); |
---|
35 | this.annotations = []; |
---|
36 | } |
---|
37 | |
---|
38 | Store.prototype.pluginInit = function() { |
---|
39 | if (!Annotator.supported()) return; |
---|
40 | if (this.annotator.plugins.Auth) { |
---|
41 | return this.annotator.plugins.Auth.withToken(this._getAnnotations); |
---|
42 | } else { |
---|
43 | return this._getAnnotations(); |
---|
44 | } |
---|
45 | }; |
---|
46 | |
---|
47 | Store.prototype._getAnnotations = function() { |
---|
48 | if (this.options.loadFromSearch) { |
---|
49 | return this.loadAnnotationsFromSearch(this.options.loadFromSearch); |
---|
50 | } else { |
---|
51 | return this.loadAnnotations(); |
---|
52 | } |
---|
53 | }; |
---|
54 | |
---|
55 | Store.prototype.annotationCreated = function(annotation) { |
---|
56 | var _this = this; |
---|
57 | if (__indexOf.call(this.annotations, annotation) < 0) { |
---|
58 | this.registerAnnotation(annotation); |
---|
59 | return this._apiRequest('create', annotation, function(data) { |
---|
60 | if (!(data.id != null)) { |
---|
61 | console.warn(Annotator._t("Warning: No ID returned from server for annotation "), annotation); |
---|
62 | } |
---|
63 | return _this.updateAnnotation(annotation, data); |
---|
64 | }); |
---|
65 | } else { |
---|
66 | return this.updateAnnotation(annotation, {}); |
---|
67 | } |
---|
68 | }; |
---|
69 | |
---|
70 | Store.prototype.annotationUpdated = function(annotation) { |
---|
71 | var _this = this; |
---|
72 | if (__indexOf.call(this.annotations, annotation) >= 0) { |
---|
73 | return this._apiRequest('update', annotation, (function(data) { |
---|
74 | return _this.updateAnnotation(annotation, data); |
---|
75 | })); |
---|
76 | } |
---|
77 | }; |
---|
78 | |
---|
79 | Store.prototype.annotationDeleted = function(annotation) { |
---|
80 | var _this = this; |
---|
81 | if (__indexOf.call(this.annotations, annotation) >= 0) { |
---|
82 | return this._apiRequest('destroy', annotation, (function() { |
---|
83 | return _this.unregisterAnnotation(annotation); |
---|
84 | })); |
---|
85 | } |
---|
86 | }; |
---|
87 | |
---|
88 | Store.prototype.registerAnnotation = function(annotation) { |
---|
89 | return this.annotations.push(annotation); |
---|
90 | }; |
---|
91 | |
---|
92 | Store.prototype.unregisterAnnotation = function(annotation) { |
---|
93 | return this.annotations.splice(this.annotations.indexOf(annotation), 1); |
---|
94 | }; |
---|
95 | |
---|
96 | Store.prototype.updateAnnotation = function(annotation, data) { |
---|
97 | if (__indexOf.call(this.annotations, annotation) < 0) { |
---|
98 | console.error(Annotator._t("Trying to update unregistered annotation!")); |
---|
99 | } else { |
---|
100 | $.extend(annotation, data); |
---|
101 | } |
---|
102 | return $(annotation.highlights).data('annotation', annotation); |
---|
103 | }; |
---|
104 | |
---|
105 | Store.prototype.loadAnnotations = function() { |
---|
106 | return this._apiRequest('read', null, this._onLoadAnnotations); |
---|
107 | }; |
---|
108 | |
---|
109 | Store.prototype._onLoadAnnotations = function(data) { |
---|
110 | if (data == null) data = []; |
---|
111 | this.annotations = data; |
---|
112 | return this.annotator.loadAnnotations(data.slice()); |
---|
113 | }; |
---|
114 | |
---|
115 | Store.prototype.loadAnnotationsFromSearch = function(searchOptions) { |
---|
116 | return this._apiRequest('search', searchOptions, this._onLoadAnnotationsFromSearch); |
---|
117 | }; |
---|
118 | |
---|
119 | Store.prototype._onLoadAnnotationsFromSearch = function(data) { |
---|
120 | if (data == null) data = {}; |
---|
121 | return this._onLoadAnnotations(data.rows || []); |
---|
122 | }; |
---|
123 | |
---|
124 | Store.prototype.dumpAnnotations = function() { |
---|
125 | var ann, _i, _len, _ref, _results; |
---|
126 | _ref = this.annotations; |
---|
127 | _results = []; |
---|
128 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { |
---|
129 | ann = _ref[_i]; |
---|
130 | _results.push(JSON.parse(this._dataFor(ann))); |
---|
131 | } |
---|
132 | return _results; |
---|
133 | }; |
---|
134 | |
---|
135 | Store.prototype._apiRequest = function(action, obj, onSuccess) { |
---|
136 | var id, options, request, url; |
---|
137 | id = obj && obj.id; |
---|
138 | url = this._urlFor(action, id); |
---|
139 | options = this._apiRequestOptions(action, obj, onSuccess); |
---|
140 | request = $.ajax(url, options); |
---|
141 | request._id = id; |
---|
142 | request._action = action; |
---|
143 | return request; |
---|
144 | }; |
---|
145 | |
---|
146 | Store.prototype._apiRequestOptions = function(action, obj, onSuccess) { |
---|
147 | var opts; |
---|
148 | opts = { |
---|
149 | type: this._methodFor(action), |
---|
150 | headers: this.element.data('annotator:headers'), |
---|
151 | dataType: "json", |
---|
152 | success: onSuccess || function() {}, |
---|
153 | error: this._onError |
---|
154 | }; |
---|
155 | if (action === "search") { |
---|
156 | opts = $.extend(opts, { |
---|
157 | data: obj |
---|
158 | }); |
---|
159 | } else { |
---|
160 | opts = $.extend(opts, { |
---|
161 | data: obj && this._dataFor(obj), |
---|
162 | contentType: "application/json; charset=utf-8" |
---|
163 | }); |
---|
164 | } |
---|
165 | return opts; |
---|
166 | }; |
---|
167 | |
---|
168 | Store.prototype._urlFor = function(action, id) { |
---|
169 | var replaceWith, url; |
---|
170 | replaceWith = id != null ? '/' + id : ''; |
---|
171 | url = this.options.prefix || '/'; |
---|
172 | url += this.options.urls[action]; |
---|
173 | url = url.replace(/\/:id/, replaceWith); |
---|
174 | return url; |
---|
175 | }; |
---|
176 | |
---|
177 | Store.prototype._methodFor = function(action) { |
---|
178 | var table; |
---|
179 | table = { |
---|
180 | 'create': 'POST', |
---|
181 | 'read': 'GET', |
---|
182 | 'update': 'PUT', |
---|
183 | 'destroy': 'DELETE', |
---|
184 | 'search': 'GET' |
---|
185 | }; |
---|
186 | return table[action]; |
---|
187 | }; |
---|
188 | |
---|
189 | Store.prototype._dataFor = function(annotation) { |
---|
190 | var data, highlights; |
---|
191 | highlights = annotation.highlights; |
---|
192 | delete annotation.highlights; |
---|
193 | $.extend(annotation, this.options.annotationData); |
---|
194 | data = JSON.stringify(annotation); |
---|
195 | if (highlights) annotation.highlights = highlights; |
---|
196 | return data; |
---|
197 | }; |
---|
198 | |
---|
199 | Store.prototype._onError = function(xhr) { |
---|
200 | var action, message; |
---|
201 | action = xhr._action; |
---|
202 | message = Annotator._t("Sorry we could not ") + action + Annotator._t(" this annotation"); |
---|
203 | if (xhr._action === 'search') { |
---|
204 | message = Annotator._t("Sorry we could not search the store for annotations"); |
---|
205 | } else if (xhr._action === 'read' && !xhr._id) { |
---|
206 | message = Annotator._t("Sorry we could not ") + action + Annotator._t(" the annotations from the store"); |
---|
207 | } |
---|
208 | switch (xhr.status) { |
---|
209 | case 401: |
---|
210 | message = Annotator._t("Sorry you are not allowed to ") + action + Annotator._t(" this annotation"); |
---|
211 | break; |
---|
212 | case 404: |
---|
213 | message = Annotator._t("Sorry we could not connect to the annotations store"); |
---|
214 | break; |
---|
215 | case 500: |
---|
216 | message = Annotator._t("Sorry something went wrong with the annotation store"); |
---|
217 | } |
---|
218 | Annotator.showNotification(message, Annotator.Notification.ERROR); |
---|
219 | return console.error(Annotator._t("API request failed:") + (" '" + xhr.status + "'")); |
---|
220 | }; |
---|
221 | |
---|
222 | return Store; |
---|
223 | |
---|
224 | })(Annotator.Plugin); |
---|