comparison annotator_files/lib/plugin/store.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 __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);