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