3     var noop = function() {
 
  10      * Return absolute reverse path of given named view. (at least he have it
 
  11      * hard-coded in one place)
 
  13      * TODO: think of a way, not to hard-code it here ;)
 
  17         var vname = arguments[0];
 
  18         var base_path = "/editor";
 
  20         if (vname == "ajax_document_text") {
 
  21             var path = "/text/" + arguments[1] + '/';
 
  23             if (arguments[2] !== undefined)
 
  24                 path += arguments[2] + '/';
 
  26             return base_path + path;
 
  29         if (vname == "ajax_document_revert") {
 
  30             return base_path + "/revert/" + arguments[1] + '/';
 
  34         if (vname == "ajax_document_history") {
 
  35             return base_path + "/history/" + arguments[1] + '/';
 
  38         if (vname == "ajax_document_scans") {
 
  39             return base_path + "/scans/" + arguments[1] + '/';
 
  41         if (vname == "ajax_document_gallery") {
 
  42             return base_path + "/gallery/" + arguments[1] + '/';
 
  45         if (vname == "ajax_document_diff")
 
  46             return base_path + "/diff/" + arguments[1] + '/';
 
  48         if (vname == "ajax_document_rev")
 
  49             return base_path + "/rev/" + arguments[1] + '/';
 
  51         if (vname == "ajax_document_pubmark")
 
  52             return base_path + "/pubmark/" + arguments[1] + '/';
 
  54         if (vname == "ajax_cover_preview")
 
  55             return "/cover/preview/";
 
  57         console.log("Couldn't reverse match:", vname);
 
  61         static csrf = $('input[name="csrfmiddlewaretoken"]').val();
 
  63         // TODO: Add waiting marker, error reporting.
 
  64         static post(url, data) {
 
  65             data['csrfmiddlewaretoken'] = this.csrf;
 
  73         static get(url, callback) {
 
  77                 success: function(data) {
 
  83         static setGallery(id, gallery) {
 
  85                 '/editor/set-gallery/' + id + '/',
 
  89         static setGalleryStart(id, start) {
 
  91                 '/editor/set-gallery-start/' + id + '/',
 
  96         static openGalleryEdit(bookSlug) {
 
  98                 '/documents/book/' + bookSlug + '/gallery/',
 
 103         static withGalleryList(callback) {
 
 105                 '/editor/galleries/',
 
 112      * Document Abstraction
 
 115         constructor(element_id) {
 
 116             var meta = $('#' + element_id);
 
 117             this.id = meta.attr('data-chunk-id');
 
 119             this.revision = $("*[data-key='revision']", meta).text();
 
 120             this.readonly = !!$("*[data-key='readonly']", meta).text();
 
 122             this.bookSlug = $("*[data-key='book-slug']", meta).text();
 
 123             this.scansLink = $("*[data-key='scans']", meta).text();
 
 124             this.galleryLink = $("*[data-key='gallery']", meta).text();
 
 125             this.galleryStart = parseInt($("*[data-key='gallery-start']", meta).text());
 
 126             this.fullUri = $("*[data-key='full-uri']", meta).text();
 
 130             this.has_local_changes = false;
 
 131             this.active = new Date();
 
 133             this._context_lock = -1;
 
 134             this._lock_count = 0;
 
 137         triggerDocumentChanged() {
 
 138             $(document).trigger('wlapi_document_changed', this);
 
 142          * Fetch text of this document.
 
 145             params = $.extend({}, noops, params);
 
 149                 url: reverse("ajax_document_text", self.id),
 
 150                 data: {"revision": self.revision},
 
 152                 success: function(data) {
 
 155                     if (self.text === null || self.revision !== data.revision) {
 
 156                         self.text = data.text;
 
 157                         $.wiki.undo.push(data.text);
 
 158                         self.revision = data.revision;
 
 159                         self.gallery = data.gallery;
 
 161                         self.triggerDocumentChanged();
 
 164                     self.has_local_changes = false;
 
 165                     params['success'](self, changed);
 
 168                     params['failure'](self, "Nie udało się wczytać treści dokumentu.");
 
 174          * Fetch history of this document.
 
 176         fetchHistory(params) {
 
 177             /* this doesn't modify anything, so no locks */
 
 178             params = $.extend({}, noops, params);
 
 182                 url: reverse("ajax_document_history", self.id) + "?before=" + params.before,
 
 184                 success: function(data) {
 
 185                     params['success'](self, data);
 
 188                     params['failure'](self, "Nie udało się wczytać historii dokumentu.");
 
 194             /* this doesn't modify anything, so no locks */
 
 197                 'from': self.revision,
 
 202                 url: reverse("ajax_document_diff", self.id),
 
 205                     "from": params['from'],
 
 208                 success: function(data) {
 
 209                     params['success'](self, data);
 
 212                     params['failure'](self, "Nie udało się wczytać porównania wersji.");
 
 217         checkRevision(params) {
 
 218             /* this doesn't modify anything, so no locks */
 
 220             let active = new Date() - self.active < 30 * 1000;
 
 221             let saving = self.saving;
 
 224                 url: reverse("ajax_document_rev", self.id),
 
 230                 success: function(data) {
 
 236                         let people = $('<div>');
 
 237                         data.people.forEach((p) => {
 
 238                             let item = $('<img>');
 
 239                             item.attr('src', p.gravatar),
 
 243                                     (p.active ? 'akt.' : 'nieakt.') +
 
 244                                     ' od ' + p.since + ')')
 
 246                                 item.addClass('active');
 
 250                         $("#people").html(people);
 
 252                         if (!saving && (data.rev != self.revision)) {
 
 260         refreshImageGallery(params) {
 
 261             if (this.galleryLink) {
 
 262                 params = $.extend({}, params, {
 
 263                     url: reverse("ajax_document_gallery", this.galleryLink)
 
 266             this.refreshGallery(params);
 
 269         refreshScansGallery(params) {
 
 270             if (this.scansLink) {
 
 271                 params = $.extend({}, params, {
 
 272                     url: reverse("ajax_document_scans", this.scansLink)
 
 274                 this.refreshGallery(params);
 
 276                 // Fallback to image gallery.
 
 277                 this.refreshImageGallery(params)
 
 284         refreshGallery(params) {
 
 285             params = $.extend({}, noops, params);
 
 288                 params.failure('Brak galerii.');
 
 295                 success: function(data) {
 
 296                     params.success(data);
 
 298                 error: function(xhr) {
 
 299                     switch (xhr.status) {
 
 301                         var msg = 'Galerie dostępne tylko dla zalogowanych użytkowników.';
 
 304                         var msg = "Nie znaleziono galerii.";
 
 306                         var msg = "Nie udało się wczytać galerii.";
 
 313         setGallery(gallery) {
 
 314             this.galleryLink = gallery;
 
 315             Api.setGallery(this.id, gallery);
 
 318         setGalleryStart(start) {
 
 319             this.galleryStart = start;
 
 320             Api.setGalleryStart(this.id, start);
 
 323         openGalleryEdit(start) {
 
 324             Api.openGalleryEdit(this.bookSlug);
 
 327         withGalleryList(callback) {
 
 328             Api.withGalleryList(callback);
 
 332          * Set document's text
 
 334         setText(text, silent=false) {
 
 335             if (text == this.text) return;
 
 337                 $.wiki.undo.push(text);
 
 340             this.has_local_changes = true;
 
 344             let ctx = $.wiki.exitContext();
 
 349             $.wiki.enterContext(ctx);
 
 352             let ctx = $.wiki.exitContext();
 
 357             $.wiki.enterContext(ctx);
 
 361          * Save text back to the server
 
 364             params = $.extend({}, noops, params);
 
 367             if (!self.has_local_changes) {
 
 368                 console.log("Abort: no changes.");
 
 369                 return params['success'](self, false, "Nie ma zmian do zapisania.");
 
 372             // Serialize form to dictionary
 
 374             $.each(params['form'].serializeArray(), function() {
 
 375                 data[this.name] = this.value;
 
 378             data['textsave-text'] = self.text;
 
 382                 url: reverse("ajax_document_text", self.id),
 
 386                 success: function(data) {
 
 389                     $('#header').removeClass('saving');
 
 392                         self.text = data.text;
 
 393                         self.revision = data.revision;
 
 394                         self.gallery = data.gallery;
 
 396                         self.triggerDocumentChanged();
 
 400                     params['success'](self, changed, ((changed && "Udało się zapisać :)") || "Twoja wersja i serwera jest identyczna"));
 
 402                 error: function(xhr) {
 
 404                     if ($('#header').hasClass('saving')) {
 
 405                         $('#header').removeClass('saving');
 
 407                             message: "<p>Nie udało się zapisać zmian. <br/><button onclick='$.unblockUI()'>OK</button></p>"
 
 412                             params['failure'](self, $.parseJSON(xhr.responseText));
 
 415                             params['failure'](self, {
 
 416                                 "__message": "<p>Nie udało się zapisać - błąd serwera.</p>"
 
 423             $('#save-hide').click(function(){
 
 424                 $('#header').addClass('saving');
 
 426                 $.wiki.blocking.unblock();
 
 428         } /* end of save() */
 
 430         revertToVersion(params) {
 
 432             params = $.extend({}, noops, params);
 
 434             if (params.revision >= this.revision) {
 
 435                 params.failure(self, 'Proszę wybrać rewizję starszą niż aktualna.');
 
 439             // Serialize form to dictionary
 
 441             $.each(params['form'].serializeArray(), function() {
 
 442                 data[this.name] = this.value;
 
 446                 url: reverse("ajax_document_revert", self.id),
 
 450                 success: function(data) {
 
 452                         self.text = data.text;
 
 453                         self.revision = data.revision;
 
 454                         self.gallery = data.gallery;
 
 455                         self.triggerDocumentChanged();
 
 457                         params.success(self, "Udało się przywrócić wersję :)");
 
 460                         params.failure(self, "Przywracana wersja identyczna z aktualną. Anulowano przywracanie.");
 
 463                 error: function(xhr) {
 
 464                     params.failure(self, "Nie udało się przywrócić wersji - błąd serwera.");
 
 470             params = $.extend({}, noops, params);
 
 473                 "pubmark-id": self.id,
 
 477             $.each(params.form.serializeArray(), function() {
 
 478                 data[this.name] = this.value;
 
 482                 url: reverse("ajax_document_pubmark", self.id),
 
 486                 success: function(data) {
 
 487                     params.success(self, data.message);
 
 489                 error: function(xhr) {
 
 490                     if (xhr.status == 403 || xhr.status == 401) {
 
 491                         params.failure(self, {
 
 492                             "__all__": ["Nie masz uprawnień lub nie jesteś zalogowany."]
 
 497                             params.failure(self, $.parseJSON(xhr.responseText));
 
 500                             params.failure(self, {
 
 501                                 "__all__": ["Nie udało się - błąd serwera."]
 
 509         refreshCover(params) {
 
 512                 xml: self.text // TODO: send just DC
 
 515                 url: reverse("ajax_cover_preview"),
 
 518                 success: function(data) {
 
 519                     params.success(data);
 
 521                 error: function(xhr) {
 
 522                     // params.failure("Nie udało się odświeżyć okładki - błąd serwera.");
 
 528             params = $.extend({}, noops, params);
 
 529             var xml = this.text.replace(/\/(\s+)/g, '<br />$1');
 
 530             var parser = new DOMParser();
 
 531             var doc = parser.parseFromString(xml, 'text/xml');
 
 532             var error = $('parsererror', doc);
 
 534             if (error.length > 0) {
 
 535                 throw "Not an XML document.";
 
 537             $.xmlns["rdf"] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
 
 538             $('rdf|RDF', doc).remove();
 
 539             if (params.noFootnotes) {
 
 540                 $('pa, pe, pr, pt, ptrad', doc).remove();
 
 542             if (params.noThemes) {
 
 543                 $('motyw', doc).remove();
 
 545             var text = $(doc).text();
 
 546             text = $.trim(text.replace(/\s{2,}/g, ' '));
 
 550         /* Temporary workaround for relative images. */
 
 552             return '/media/dynamic/images/' + this.galleryLink + '/';
 
 556     $.wikiapi.WikiDocument = WikiDocument;