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 setGallery: function(path) {
424 success: this.settingGallerySucceeded.bind(this)
428 settingGallerySucceeded: function(data) {
429 console.log('settingGallerySucceeded');
433 load: function(force) {
434 if (force || this.get('state') == 'empty') {
435 console.log("setting state");
436 this.set('state', 'loading');
437 console.log("going ajax");
441 success: this.loadingSucceeded.bind(this),
442 error: this.loadingFailed.bind(this)
447 loadingSucceeded: function(data)
449 console.log("success");
451 if (this.get('state') != 'loading') {
452 alert('erroneous state:', this.get('state'));
455 console.log('galleries:', data);
457 if (data.length === 0) {
458 this.set('data', []);
460 this.set('data', data[0].pages);
463 this.set('state', 'synced');
466 loadingFailed: function(data) {
467 console.log("failed");
469 if (this.get('state') != 'loading') {
470 alert('erroneous state:', this.get('state'));
473 this.set('state', 'error');
476 set: function(property, value) {
477 if (property == 'state') {
478 console.log(this.description(), ':', property, '=', value);
480 return this._super(property, value);
485 Editor.DocumentModel = Editor.Model.extend({
486 _className: 'Editor.DocumentModel',
487 data: null, // name, text_url, revision, latest_shared_rev, parts_url, dc_url, size, merge_url
496 this.set('state', 'empty');
500 if (this.get('state') == 'empty') {
501 this.set('state', 'loading');
502 messageCenter.addMessage('info', 'docload', 'Ładuję dane dokumentu...');
505 url: documentInfo.docURL,
507 success: this.successfulLoad.bind(this),
508 error: this.failedLoad.bind(this)
513 successfulLoad: function(data) {
514 this.set('data', data);
515 this.set('state', 'synced');
517 this.set('revision', data.revision);
518 this.set('user', data.user);
520 this.contentModels = {
521 'xml': new Editor.XMLModel(this, data.text_url),
522 'html': new Editor.HTMLModel(this, data.text_url),
523 'gallery': new Editor.ImageGalleryModel(this, data.gallery_url)
526 for (var key in this.contentModels) {
527 this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
532 messageCenter.addMessage('success', 'docload', 'Dokument załadowany poprawnie :-)');
535 failedLoad: function(response) {
536 if (this.get('state') != 'loading') {
537 alert('erroneous state:', this.get('state'));
540 var err = parseXHRError(response);
541 this.set('error', '<h2>Nie udało się wczytać dokumentu</h2><p>'+err.error_message+"</p>");
542 this.set('state', 'error');
545 contentModelStateChanged: function(property, value, contentModel) {
546 if (value == 'dirty') {
547 this.set('state', 'dirty');
548 for (var key in this.contentModels) {
549 if (this.contentModels[key].guid() != contentModel.guid()) {
550 this.contentModels[key].set('state', 'unsynced');
553 } else if (value == 'updated') {
554 this.set('state', 'synced');
555 for (key in this.contentModels) {
556 if (this.contentModels[key].guid() == contentModel.guid()) {
557 this.contentModels[key].set('state', 'synced');
558 this.revision = this.contentModels[key].get('revision');
562 for (key in this.contentModels) {
563 if (this.contentModels[key].guid() != contentModel.guid()) {
564 this.contentModels[key].set('revision', this.revision);
565 this.contentModels[key].set('state', 'empty');
571 saveDirtyContentModel: function(message) {
572 for (var key in this.contentModels) {
573 if (this.contentModels[key].get('state') == 'dirty') {
574 this.contentModels[key].save(message);
581 this.set('state', 'loading');
583 messageCenter.addMessage('info', 'doc_update',
584 'Uaktualniam dokument...');
587 url: this.data.merge_url,
592 revision: this.get('revision'),
593 user: this.get('user')
595 complete: this.updateCompleted.bind(this)
599 updateCompleted: function(xhr, textStatus)
601 console.log(xhr.status, xhr.responseText);
602 var response = parseXHRResponse(xhr);
605 if( (response.data.result == 'no-op')
606 || (response.data.timestamp == response.data.parent_timestamp))
608 if( (response.data.revision) && (response.data.revision != this.get('revision')) )
611 this.set('state', 'unsynced');
615 messageCenter.addMessage('info', 'doc_update',
616 'Już posiadasz najbardziej aktualną wersję.');
617 this.set('state', 'synced');
622 this.set('revision', response.data.revision);
623 this.set('user', response.data.user);
625 messageCenter.addMessage('info', 'doc_update',
626 'Uaktualnienie dokumentu do wersji ' + response.data.revision);
628 for (var key in this.contentModels) {
629 this.contentModels[key].set('revision', this.get('revision') );
630 this.contentModels[key].set('state', 'empty');
633 this.set('state', 'synced');
637 // no success means trouble
638 messageCenter.addMessage(response.error_level, 'doc_update',
639 response.error_message);
641 this.set('state', 'unsynced');
644 merge: function(message) {
645 this.set('state', 'loading');
646 messageCenter.addMessage('info', 'doc_merge',
647 'Scalam dokument z głównym repozytorium...');
650 url: this.data.merge_url,
655 revision: this.get('revision'),
656 user: this.get('user'),
659 complete: this.mergeCompleted.bind(this),
660 success: function(data) {
661 this.set('mergeData', data);
666 mergeCompleted: function(xhr, textStatus) {
667 console.log(xhr.status, xhr.responseText);
668 var response = parseXHRResponse(xhr);
670 if(response.success) {
672 if( (response.data.result == 'no-op') ||
673 ( response.data.shared_parent_timestamp
674 && response.data.shared_timestamp
675 && (response.data.shared_timestamp == response.data.shared_parent_timestamp)) )
677 if( (response.data.revision) && (response.data.revision != this.get('revision')) )
680 this.set('state', 'unsynced');
684 messageCenter.addMessage('info', 'doc_merge',
685 'Twoja aktualna wersja nie różni się od ostatnio zatwierdzonej.');
686 this.set('state', 'synced');
690 if( response.data.result == 'accepted')
692 messageCenter.addMessage('info', 'doc_merge',
693 'Prośba o zatwierdzenie została przyjęta i oczekuję na przyjęcie.');
694 this.set('state', 'synced');
699 this.set('revision', response.data.revision);
700 this.set('user', response.data.user);
702 messageCenter.addMessage('info', 'doc_merge',
703 'Twoja wersja dokumentu została zatwierdzona.');
705 this.set('state', 'synced');
709 // no success means trouble
710 messageCenter.addMessage(response.error_level, 'doc_merge',
711 response.error_message);
713 this.set('state', 'unsynced');
717 set: function(property, value) {
718 if (property == 'state') {
719 console.log(this.description(), ':', property, '=', value);
721 return this._super(property, value);
726 var leftPanelView, rightPanelContainer, doc;
730 var flashView = new FlashView('#flashview', messageCenter);
732 doc = new Editor.DocumentModel();
734 EditorView = new EditorView('#body-wrap', doc);
735 EditorView.freeze("<h1>Wczytuję dokument...</h1>");
737 leftPanelView = new PanelContainerView('#left-panel-container', doc);
738 rightPanelContainer = new PanelContainerView('#right-panel-container', doc);