4a4da5a71f8f4b2a1b4e6305461dbf2ad37362c0
[redakcja.git] / redakcja / static / js / wiki / wikiapi.js
1 (function($) {
2         $.wikiapi = {};
3         var noop = function() {
4         };
5         var noops = {
6                 success: noop,
7                 failure: noop
8         };
9         /*
10          * Return absolute reverse path of given named view. (at least he have it
11          * hard-coded in one place)
12          *
13          * TODO: think of a way, not to hard-code it here ;)
14          *
15          */
16         function reverse() {
17                 var vname = arguments[0];
18                 var base_path = "/editor";
19
20                 if (vname == "ajax_document_text") {
21                         var path = "/text/" + arguments[1] + '/';
22
23                 if (arguments[2] !== undefined)
24                                 path += arguments[2] + '/';
25
26                         return base_path + path;
27                 }
28
29         if (vname == "ajax_document_revert") {
30             return base_path + "/revert/" + arguments[1] + '/';
31         }
32
33
34                 if (vname == "ajax_document_history") {
35
36                         return base_path + "/history/" + arguments[1] + '/';
37                 }
38
39                 if (vname == "ajax_document_gallery") {
40
41                         return base_path + "/gallery/" + arguments[1] + '/';
42                 }
43
44                 if (vname == "ajax_document_diff")
45                         return base_path + "/diff/" + arguments[1] + '/';
46
47         if (vname == "ajax_document_rev")
48             return base_path + "/rev/" + arguments[1] + '/';
49
50                 if (vname == "ajax_document_pubmark")
51                         return base_path + "/pubmark/" + arguments[1] + '/';
52
53                 console.log("Couldn't reverse match:", vname);
54                 return "/404.html";
55         };
56
57         /*
58          * Document Abstraction
59          */
60         function WikiDocument(element_id) {
61                 var meta = $('#' + element_id);
62                 this.id = meta.attr('data-chunk-id');
63
64                 this.revision = $("*[data-key='revision']", meta).text();
65                 this.readonly = !!$("*[data-key='readonly']", meta).text();
66
67                 this.galleryLink = $("*[data-key='gallery']", meta).text();
68         this.galleryStart = parseInt($("*[data-key='gallery-start']", meta).text());
69
70         var diff = $("*[data-key='diff']", meta).text();
71         if (diff) {
72             diff = diff.split(',');
73             if (diff.length == 2 && diff[0] < diff[1])
74                 this.diff = diff;
75             else if (diff.length == 1) {
76                 diff = parseInt(diff);
77                 if (diff != NaN)
78                     this.diff = [diff - 1, diff];
79             }
80         }
81
82                 this.galleryImages = [];
83                 this.text = null;
84                 this.has_local_changes = false;
85                 this._lock = -1;
86                 this._context_lock = -1;
87                 this._lock_count = 0;
88         };
89
90         WikiDocument.prototype.triggerDocumentChanged = function() {
91                 $(document).trigger('wlapi_document_changed', this);
92         };
93         /*
94          * Fetch text of this document.
95          */
96         WikiDocument.prototype.fetch = function(params) {
97                 params = $.extend({}, noops, params);
98                 var self = this;
99                 $.ajax({
100                         method: "GET",
101                         url: reverse("ajax_document_text", self.id),
102                         data: {"revision": self.revision},
103                         dataType: 'json',
104                         success: function(data) {
105                                 var changed = false;
106
107                                 if (self.text === null || self.revision !== data.revision) {
108                                         self.text = data.text;
109                                         self.revision = data.revision;
110                                         self.gallery = data.gallery;
111                                         changed = true;
112                                         self.triggerDocumentChanged();
113                                 };
114
115                                 self.has_local_changes = false;
116                                 params['success'](self, changed);
117                         },
118                         error: function() {
119                                 params['failure'](self, "Nie udało się wczytać treści dokumentu.");
120                         }
121                 });
122         };
123         /*
124          * Fetch history of this document.
125          *
126          * from - First revision to fetch (default = 0) upto - Last revision to
127          * fetch (default = tip)
128          *
129          */
130         WikiDocument.prototype.fetchHistory = function(params) {
131                 /* this doesn't modify anything, so no locks */
132                 params = $.extend({}, noops, params);
133                 var self = this;
134                 $.ajax({
135                         method: "GET",
136                         url: reverse("ajax_document_history", self.id),
137                         dataType: 'json',
138                         data: {
139                                 "from": params['from'],
140                                 "upto": params['upto']
141                         },
142                         success: function(data) {
143                                 params['success'](self, data);
144                         },
145                         error: function() {
146                                 params['failure'](self, "Nie udało się wczytać historii dokumentu.");
147                         }
148                 });
149         };
150         WikiDocument.prototype.fetchDiff = function(params) {
151                 /* this doesn't modify anything, so no locks */
152                 var self = this;
153                 params = $.extend({
154                         'from': self.revision,
155                         'to': self.revision
156                 }, noops, params);
157                 $.ajax({
158                         method: "GET",
159                         url: reverse("ajax_document_diff", self.id),
160                         dataType: 'html',
161                         data: {
162                                 "from": params['from'],
163                                 "to": params['to']
164                         },
165                         success: function(data) {
166                                 params['success'](self, data);
167                         },
168                         error: function() {
169                                 params['failure'](self, "Nie udało się wczytać porównania wersji.");
170                         }
171                 });
172         };
173
174     WikiDocument.prototype.checkRevision = function(params) {
175         /* this doesn't modify anything, so no locks */
176         var self = this;
177         $.ajax({
178             method: "GET",
179             url: reverse("ajax_document_rev", self.id),
180             dataType: 'text',
181             success: function(data) {
182                 if (data == '') {
183                     if (params.error)
184                         params.error();
185                 }
186                 else if (data != self.revision)
187                     params.outdated();
188             }
189         });
190     };
191
192         /*
193          * Fetch gallery
194          */
195         WikiDocument.prototype.refreshGallery = function(params) {
196                 params = $.extend({}, noops, params);
197                 var self = this;
198                 $.ajax({
199                         method: "GET",
200                         url: reverse("ajax_document_gallery", self.galleryLink),
201                         dataType: 'json',
202                         // data: {},
203                         success: function(data) {
204                                 self.galleryImages = data;
205                                 params['success'](self, data);
206                         },
207                         error: function(xhr) {
208                 switch (xhr.status) {
209                     case 403:
210                         var msg = 'Galerie dostępne tylko dla zalogowanych użytkowników.';
211                         break;
212                     case 404:
213                         var msg = "Nie znaleziono galerii o nazwie: '" + self.galleryLink + "'.";
214                     default:
215                         var msg = "Nie udało się wczytać galerii o nazwie: '" + self.galleryLink + "'.";
216                 }
217                                 self.galleryImages = [];
218                                 params['failure'](self, "<p>" + msg + "</p>");
219                         }
220                 });
221         };
222
223         /*
224          * Set document's text
225          */
226         WikiDocument.prototype.setText = function(text) {
227                 this.text = text;
228                 this.has_local_changes = true;
229         };
230
231         /*
232          * Set document's gallery link
233          */
234         WikiDocument.prototype.setGalleryLink = function(gallery) {
235                 this.galleryLink = gallery;
236                 this.has_local_changes = true;
237         };
238
239         /*
240          * Save text back to the server
241          */
242         WikiDocument.prototype.save = function(params) {
243                 params = $.extend({}, noops, params);
244                 var self = this;
245
246                 if (!self.has_local_changes) {
247                         console.log("Abort: no changes.");
248                         return params['success'](self, false, "Nie ma zmian do zapisania.");
249                 };
250
251                 // Serialize form to dictionary
252                 var data = {};
253                 $.each(params['form'].serializeArray(), function() {
254                         data[this.name] = this.value;
255                 });
256
257                 data['textsave-text'] = self.text;
258
259                 $.ajax({
260                         url: reverse("ajax_document_text", self.id),
261                         type: "POST",
262                         dataType: "json",
263                         data: data,
264                         success: function(data) {
265                                 var changed = false;
266
267                 $('#header').removeClass('saving');
268
269                                 if (data.text) {
270                                         self.text = data.text;
271                                         self.revision = data.revision;
272                                         self.gallery = data.gallery;
273                                         changed = true;
274                                         self.triggerDocumentChanged();
275                                 };
276
277                                 params['success'](self, changed, ((changed && "Udało się zapisać :)") || "Twoja wersja i serwera jest identyczna"));
278                         },
279                         error: function(xhr) {
280                 if ($('#header').hasClass('saving')) {
281                     $('#header').removeClass('saving');
282                     $.blockUI({
283                         message: "<p>Nie udało się zapisać zmian. <br/><button onclick='$.unblockUI()'>OK</button></p>"
284                     })
285                 }
286                 else {
287                     try {
288                         params['failure'](self, $.parseJSON(xhr.responseText));
289                     }
290                     catch (e) {
291                         params['failure'](self, {
292                             "__message": "<p>Nie udało się zapisać - błąd serwera.</p>"
293                         });
294                     };
295                 }
296
297                         }
298                 });
299
300         $('#save-hide').click(function(){
301             $('#header').addClass('saving');
302             $.unblockUI();
303             $.wiki.blocking.unblock();
304         });
305         }; /* end of save() */
306
307     WikiDocument.prototype.revertToVersion = function(params) {
308         var self = this;
309         params = $.extend({}, noops, params);
310
311         if (params.revision >= this.revision) {
312             params.failure(self, 'Proszę wybrać rewizję starszą niż aktualna.');
313             return;
314         }
315
316         // Serialize form to dictionary
317         var data = {};
318         $.each(params['form'].serializeArray(), function() {
319             data[this.name] = this.value;
320         });
321
322         $.ajax({
323             url: reverse("ajax_document_revert", self.id),
324             type: "POST",
325             dataType: "json",
326             data: data,
327             success: function(data) {
328                 if (data.text) {
329                     self.text = data.text;
330                     self.revision = data.revision;
331                     self.gallery = data.gallery;
332                     self.triggerDocumentChanged();
333
334                     params.success(self, "Udało się przywrócić wersję :)");
335                 }
336                 else {
337                     params.failure(self, "Przywracana wersja identyczna z aktualną. Anulowano przywracanie.");
338                 }
339             },
340             error: function(xhr) {
341                 params.failure(self, "Nie udało się przywrócić wersji - błąd serwera.");
342             }
343         });
344     };
345
346         WikiDocument.prototype.pubmark = function(params) {
347                 params = $.extend({}, noops, params);
348                 var self = this;
349                 var data = {
350                         "pubmark-id": self.id,
351                 };
352
353                 /* unpack form */
354                 $.each(params.form.serializeArray(), function() {
355                         data[this.name] = this.value;
356                 });
357
358                 $.ajax({
359                         url: reverse("ajax_document_pubmark", self.id),
360                         type: "POST",
361                         dataType: "json",
362                         data: data,
363                         success: function(data) {
364                                 params.success(self, data.message);
365                         },
366                         error: function(xhr) {
367                                 if (xhr.status == 403 || xhr.status == 401) {
368                                         params.failure(self, {
369                                                 "__all__": ["Nie masz uprawnień lub nie jesteś zalogowany."]
370                                         });
371                                 }
372                                 else {
373                                         try {
374                                                 params.failure(self, $.parseJSON(xhr.responseText));
375                                         }
376                                         catch (e) {
377                                                 params.failure(self, {
378                                                         "__all__": ["Nie udało się - błąd serwera."]
379                                                 });
380                                         };
381                                 };
382                         }
383                 });
384         };
385
386     WikiDocument.prototype.getLength = function(params) {
387         var xml = this.text.replace(/\/(\s+)/g, '<br />$1');
388         var parser = new DOMParser();
389         var doc = parser.parseFromString(xml, 'text/xml');
390         var error = $('parsererror', doc);
391
392         if (error.length > 0) {
393             throw "Not an XML document.";
394         }
395         $.xmlns["rdf"] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; 
396         $('rdf|RDF, motyw, pa, pe, pr, pt', doc).remove();
397         var text = $(doc).text();
398         text = $.trim(text.replace(/\s{2,}/g, ' '));
399         return text.length;
400     }
401
402
403         $.wikiapi.WikiDocument = WikiDocument;
404 })(jQuery);