1 /*globals Editor fileId SplitView PanelContainerView EditorView FlashView messageCenter*/
2 Editor.Model = Editor.Object.extend({
7 Editor.ToolbarButtonsModel = Editor.Model.extend({
8 className: 'Editor.ToolbarButtonsModel',
16 if (!this.get('buttons').length) {
18 url: documentInfo.toolbarURL,
20 success: this.loadSucceeded.bind(this)
25 loadSucceeded: function(data)
28 $.each(data, function() {
29 $.each(this.buttons, function() {
30 //do some lame escapes
31 this.tooltip = this.tooltip.replace(/"/g, """);
34 this.set('buttons', data);
40 // HTML Document Model
42 Editor.HTMLModel = Editor.Model.extend({
43 _className: 'Editor.HTMLModel',
47 init: function(document, textURL) {
49 this.set('state', 'empty');
50 this.set('revision', document.get('revision'));
51 this.document = document;
53 this.textURL = textURL;
59 // create a parser and a serializer
60 this.parser = new DOMParser();
61 this.serializer = new XMLSerializer();
63 this.addObserver(this, 'data', this.dataChanged.bind(this));
66 load: function(force) {
67 if (force || this.get('state') == 'empty') {
68 this.set('state', 'loading');
69 messageCenter.addMessage('info', 'xmlload', 'Wczytuję HTML...');
71 // request all stylesheets
73 url: documentInfo.staticURL + 'xsl/wl2html_client.xsl',
75 success: this.htmlXSLLoadSuccess.bind(this),
76 error: this.loadingFailed.bind(this)
80 url: documentInfo.staticURL + 'xsl/html2wl_client.xsl',
82 success: this.wlmlXSLLoadSuccess.bind(this),
83 error: this.loadingFailed.bind(this)
90 revision: this.get('revision'),
91 user: this.document.get('user')
93 success: this.textLoadSuccess.bind(this),
94 error: this.loadingFailed.bind(this)
101 asWLML: function(element)
103 console.log("Source", element);
104 var doc = this.parser.parseFromString(this.serializer.serializeToString(element), 'text/xml');
106 var result = this.wlmlXSL.transformToDocument(doc);
109 console.log("Failed", this.wlmlXSL, doc);
110 throw "Failed to transform fragment";
113 console.log("Transformed", doc, " to: ", result.documentElement);
114 return this.serializer.serializeToString(result.documentElement);
117 updateWithWLML: function($element, text)
120 text = text.replace(/\/\s+/g, '<br />');
121 var chunk = this.parser.parseFromString("<chunk>"+text+"</chunk>", "text/xml");
123 var errors = $('parsererror', chunk);
125 // check if chunk is parsable
126 if(errors.length > 0)
127 throw {text: errors.text(), html: errors.html()};
129 var result = this.htmlXSL.transformToFragment(chunk, document);
131 console.log("RESULT", this.serializer.serializeToString(result));
134 throw "WLML->HTML transformation failed.";
136 $element.replaceWith(result);
137 this.set('state', 'dirty');
140 createXSLT: function(xslt_doc) {
141 var p = new XSLTProcessor();
142 p.importStylesheet(xslt_doc);
146 htmlXSLLoadSuccess: function(data)
149 this.htmlXSL = this.createXSLT(data);
151 if(this.wlmlXSL && this.htmlXSL && this.rawText)
154 this.loadingFailed();
158 wlmlXSLLoadSuccess: function(data)
161 this.wlmlXSL = this.createXSLT(data);
163 if(this.wlmlXSL && this.htmlXSL && this.rawText)
166 this.loadingFailed();
170 textLoadSuccess: function(data) {
173 if(this.wlmlXSL && this.htmlXSL && this.rawText)
177 loadSuccess: function() {
178 if (this.get('state') != 'loading') {
179 alert('erroneous state:', this.get('state'));
184 doc = this.rawText.replace(/\/\s+/g, '<br />');
185 doc = this.parser.parseFromString(doc, 'text/xml');
186 doc = this.htmlXSL.transformToFragment(doc, document).firstChild;
188 this.set('data', doc);
189 this.set('state', 'synced');
190 messageCenter.addMessage('success', 'xmlload', 'Wczytałem HTML :-)');
193 loadingFailed: function(response)
195 if (this.get('state') != 'loading') {
196 alert('erroneous state:', this.get('state'));
199 var message = parseXHRError(response);
201 this.set('error', '<h2>Błąd przy ładowaniu XML</h2><p>'+message+'</p>');
202 this.set('state', 'error');
203 messageCenter.addMessage('error', 'xmlload', 'Nie udało mi się wczytać HTML. Spróbuj ponownie :-(');
206 save: function(message) {
207 if (this.get('state') == 'dirty') {
208 this.set('state', 'saving');
210 messageCenter.addMessage('info', 'htmlsave', 'Zapisuję HTML...');
211 var wlml = this.asWLML(this.get('data'));
215 revision: this.get('revision'),
216 user: this.document.get('user')
220 payload.message = message;
228 success: this.saveSucceeded.bind(this),
229 error: this.saveFailed.bind(this)
236 saveSucceeded: function(data) {
237 if (this.get('state') != 'saving') {
238 alert('erroneous state:', this.get('state'));
240 this.set('revision', data.revision);
241 this.set('state', 'updated');
242 messageCenter.addMessage('success', 'htmlsave', 'Zapisałem :-)');
245 saveFailed: function() {
246 if (this.get('state') != 'saving') {
247 alert('erroneous state:', this.get('state'));
249 messageCenter.addMessage('error', 'htmlsave', 'Nie udało mi się zapisać.');
250 this.set('state', 'dirty');
254 set: function(property, value) {
255 if (property == 'state') {
256 console.log(this.description(), ':', property, '=', value);
258 return this._super(property, value);
261 dataChanged: function(property, value) {
262 if (this.get('state') == 'synced') {
263 this.set('state', 'dirty');
267 dispose: function() {
268 this.removeObserver(this);
276 // -> error -> loading
278 // empty -> loading -> synced -> unsynced -> loading
280 // -> dirty -> updating -> updated -> synced
282 Editor.XMLModel = Editor.Model.extend({
283 _className: 'Editor.XMLModel',
288 init: function(document, serverURL) {
290 this.set('state', 'empty');
291 this.set('revision', document.get('revision'));
292 this.document = document;
293 this.serverURL = serverURL;
294 this.toolbarButtonsModel = new Editor.ToolbarButtonsModel();
295 this.addObserver(this, 'data', this.dataChanged.bind(this));
298 load: function(force) {
299 if (force || this.get('state') == 'empty') {
300 this.set('state', 'loading');
301 messageCenter.addMessage('info', 'xmlload', 'Wczytuję XML...');
306 revision: this.get('revision'),
307 user: this.document.get('user')
309 success: this.loadingSucceeded.bind(this),
310 error: this.loadingFailed.bind(this)
317 loadingSucceeded: function(data) {
318 if (this.get('state') != 'loading') {
319 alert('erroneous state:', this.get('state'));
321 this.set('data', data);
322 this.set('state', 'synced');
323 messageCenter.addMessage('success', 'xmlload', 'Wczytałem XML :-)');
326 loadingFailed: function(response)
328 if (this.get('state') != 'loading') {
329 alert('erroneous state:', this.get('state'));
332 var message = parseXHRError(response);
334 this.set('error', '<h2>Błąd przy ładowaniu XML</h2><p>'+message+'</p>');
335 this.set('state', 'error');
336 messageCenter.addMessage('error', 'xmlload', 'Nie udało mi się wczytać XML. Spróbuj ponownie :-(');
339 save: function(message) {
340 if (this.get('state') == 'dirty') {
341 this.set('state', 'updating');
342 messageCenter.addMessage('info', 'xmlsave', 'Zapisuję XML...');
345 contents: this.get('data'),
346 revision: this.get('revision'),
347 user: this.document.get('user')
350 payload.message = message;
358 success: this.saveSucceeded.bind(this),
359 error: this.saveFailed.bind(this)
366 saveSucceeded: function(data) {
367 if (this.get('state') != 'updating') {
368 alert('erroneous state:', this.get('state'));
370 this.set('revision', data.revision);
371 this.set('state', 'updated');
372 messageCenter.addMessage('success', 'xmlsave', 'Zapisałem XML :-)');
375 saveFailed: function() {
376 if (this.get('state') != 'updating') {
377 alert('erroneous state:', this.get('state'));
379 messageCenter.addMessage('error', 'xmlsave', 'Nie udało mi się zapisać XML. Spróbuj ponownie :-(');
380 this.set('state', 'dirty');
384 set: function(property, value) {
385 if (property == 'state') {
386 console.log(this.description(), ':', property, '=', value);
388 return this._super(property, value);
391 dataChanged: function(property, value) {
392 if (this.get('state') == 'synced') {
393 this.set('state', 'dirty');
397 dispose: function() {
398 this.removeObserver(this);
403 Editor.ImageGalleryModel = Editor.Model.extend({
404 _className: 'Editor.ImageGalleryModel',
409 init: function(document, serverURL) {
411 this.set('state', 'empty');
412 this.serverURL = serverURL;
417 load: function(force) {
418 if (force || this.get('state') == 'empty') {
419 console.log("setting state");
420 this.set('state', 'loading');
421 console.log("going ajax");
425 success: this.loadingSucceeded.bind(this),
426 error: this.loadingFailed.bind(this)
431 loadingSucceeded: function(data)
433 console.log("success");
435 if (this.get('state') != 'loading') {
436 alert('erroneous state:', this.get('state'));
439 console.log('galleries:', data);
441 if (data.length === 0) {
442 this.set('data', []);
444 this.set('data', data[0].pages);
447 this.set('state', 'synced');
450 loadingFailed: function(data) {
451 console.log("failed");
453 if (this.get('state') != 'loading') {
454 alert('erroneous state:', this.get('state'));
457 this.set('state', 'error');
460 set: function(property, value) {
461 if (property == 'state') {
462 console.log(this.description(), ':', property, '=', value);
464 return this._super(property, value);
469 Editor.DocumentModel = Editor.Model.extend({
470 _className: 'Editor.DocumentModel',
471 data: null, // name, text_url, revision, latest_shared_rev, parts_url, dc_url, size, merge_url
480 this.set('state', 'empty');
484 if (this.get('state') == 'empty') {
485 this.set('state', 'loading');
486 messageCenter.addMessage('info', 'docload', 'Ładuję dane dokumentu...');
489 url: documentInfo.docURL,
491 success: this.successfulLoad.bind(this),
492 error: this.failedLoad.bind(this)
497 successfulLoad: function(data) {
498 this.set('data', data);
499 this.set('state', 'synced');
501 this.set('revision', data.revision);
502 this.set('user', data.user);
504 this.contentModels = {
505 'xml': new Editor.XMLModel(this, data.text_url),
506 'html': new Editor.HTMLModel(this, data.text_url),
507 'gallery': new Editor.ImageGalleryModel(this, data.gallery_url)
510 for (var key in this.contentModels) {
511 this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
516 messageCenter.addMessage('success', 'docload', 'Dokument załadowany poprawnie :-)');
519 failedLoad: function(response) {
520 if (this.get('state') != 'loading') {
521 alert('erroneous state:', this.get('state'));
524 var err = parseXHRError(response);
525 this.set('error', '<h2>Nie udało się wczytać dokumentu</h2><p>'+err.error_message+"</p>");
526 this.set('state', 'error');
529 contentModelStateChanged: function(property, value, contentModel) {
530 if (value == 'dirty') {
531 this.set('state', 'dirty');
532 for (var key in this.contentModels) {
533 if (this.contentModels[key].guid() != contentModel.guid()) {
534 this.contentModels[key].set('state', 'unsynced');
537 } else if (value == 'updated') {
538 this.set('state', 'synced');
539 for (key in this.contentModels) {
540 if (this.contentModels[key].guid() == contentModel.guid()) {
541 this.contentModels[key].set('state', 'synced');
542 this.revision = this.contentModels[key].get('revision');
546 for (key in this.contentModels) {
547 if (this.contentModels[key].guid() != contentModel.guid()) {
548 this.contentModels[key].set('revision', this.revision);
549 this.contentModels[key].set('state', 'empty');
555 saveDirtyContentModel: function(message) {
556 for (var key in this.contentModels) {
557 if (this.contentModels[key].get('state') == 'dirty') {
558 this.contentModels[key].save(message);
565 this.set('state', 'loading');
567 messageCenter.addMessage('info', 'doc_update',
568 'Uaktualniam dokument...');
571 url: this.data.merge_url,
576 revision: this.get('revision'),
577 user: this.get('user')
579 complete: this.updateCompleted.bind(this)
583 updateCompleted: function(xhr, textStatus)
585 console.log(xhr.status, xhr.responseText);
586 var response = parseXHRResponse(xhr);
589 if( (response.data.result == 'no-op')
590 || (response.data.timestamp == response.data.parent_timestamp))
592 if( (response.data.revision) && (response.data.revision != this.get('revision')) )
595 this.set('state', 'unsynced');
599 messageCenter.addMessage('info', 'doc_update',
600 'Już posiadasz najbardziej aktualną wersję.');
601 this.set('state', 'synced');
606 this.set('revision', response.data.revision);
607 this.set('user', response.data.user);
609 messageCenter.addMessage('info', 'doc_update',
610 'Uaktualnienie dokumentu do wersji ' + response.data.revision);
612 for (var key in this.contentModels) {
613 this.contentModels[key].set('revision', this.get('revision') );
614 this.contentModels[key].set('state', 'empty');
617 this.set('state', 'synced');
621 // no success means trouble
622 messageCenter.addMessage(response.error_level, 'doc_update',
623 response.error_message);
625 this.set('state', 'unsynced');
628 merge: function(message) {
629 this.set('state', 'loading');
630 messageCenter.addMessage('info', 'doc_merge',
631 'Scalam dokument z głównym repozytorium...');
634 url: this.data.merge_url,
639 revision: this.get('revision'),
640 user: this.get('user'),
643 complete: this.mergeCompleted.bind(this),
644 success: function(data) {
645 this.set('mergeData', data);
650 mergeCompleted: function(xhr, textStatus) {
651 console.log(xhr.status, xhr.responseText);
652 var response = parseXHRResponse(xhr);
654 if(response.success) {
656 if( (response.data.result == 'no-op') ||
657 ( response.data.shared_parent_timestamp
658 && response.data.shared_timestamp
659 && (response.data.shared_timestamp == response.data.shared_parent_timestamp)) )
661 if( (response.data.revision) && (response.data.revision != this.get('revision')) )
664 this.set('state', 'unsynced');
668 messageCenter.addMessage('info', 'doc_merge',
669 'Twoja aktualna wersja nie różni się od ostatnio zatwierdzonej.');
670 this.set('state', 'synced');
674 if( response.data.result == 'accepted')
676 messageCenter.addMessage('info', 'doc_merge',
677 'Prośba o zatwierdzenie została przyjęta i oczekuję na przyjęcie.');
678 this.set('state', 'synced');
683 this.set('revision', response.data.revision);
684 this.set('user', response.data.user);
686 messageCenter.addMessage('info', 'doc_merge',
687 'Twoja wersja dokumentu została zatwierdzona.');
689 this.set('state', 'synced');
693 // no success means trouble
694 messageCenter.addMessage(response.error_level, 'doc_merge',
695 response.error_message);
697 this.set('state', 'unsynced');
701 set: function(property, value) {
702 if (property == 'state') {
703 console.log(this.description(), ':', property, '=', value);
705 return this._super(property, value);
710 var leftPanelView, rightPanelContainer, doc;
714 var flashView = new FlashView('#flashview', messageCenter);
716 doc = new Editor.DocumentModel();
718 EditorView = new EditorView('#body-wrap', doc);
719 EditorView.freeze("<h1>Wczytuję dokument...</h1>");
721 leftPanelView = new PanelContainerView('#left-panel-container', doc);
722 rightPanelContainer = new PanelContainerView('#right-panel-container', doc);