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 var result = this.wlmlXSL.transformToFragment(element, document);
106 console.log(this.wlmlXSL.transformToDocument(element));
107 throw "Failed to transform fragment";
110 console.log("Transform result:", result);
111 return this.serializer.serializeToString(result);
114 updateWithWLML: function($element, text)
117 text = text.replace(/\/\s+/g, '<br />');
118 var chunk = this.parser.parseFromString("<chunk>"+text+"</chunk>", "text/xml");
120 var errors = $('parsererror', chunk);
122 // check if chunk is parsable
123 if(errors.length > 0)
124 throw {text: errors.text(), html: errors.html()};
126 var result = this.htmlXSL.transformToFragment(chunk, document);
128 console.log("RESULT", this.serializer.serializeToString(result));
131 throw "WLML->HTML transformation failed.";
133 $element.replaceWith(result);
136 createXSLT: function(xslt_doc) {
137 var p = new XSLTProcessor();
138 p.importStylesheet(xslt_doc);
142 htmlXSLLoadSuccess: function(data)
145 this.htmlXSL = this.createXSLT(data);
147 if(this.wlmlXSL && this.htmlXSL && this.rawText)
150 this.loadingFailed();
154 wlmlXSLLoadSuccess: function(data)
157 this.wlmlXSL = this.createXSLT(data);
159 if(this.wlmlXSL && this.htmlXSL && this.rawText)
162 this.loadingFailed();
166 textLoadSuccess: function(data) {
169 if(this.wlmlXSL && this.htmlXSL && this.rawText)
173 loadSuccess: function() {
174 if (this.get('state') != 'loading') {
175 alert('erroneous state:', this.get('state'));
180 doc = this.rawText.replace(/\/\s+/g, '<br />');
181 doc = this.parser.parseFromString(doc, 'text/xml');
182 doc = this.htmlXSL.transformToFragment(doc, document).firstChild;
184 this.set('data', doc);
185 this.set('state', 'synced');
186 messageCenter.addMessage('success', 'xmlload', 'Wczytałem HTML :-)');
189 loadingFailed: function(response)
191 if (this.get('state') != 'loading') {
192 alert('erroneous state:', this.get('state'));
195 var message = parseXHRError(response);
197 this.set('error', '<h2>Błąd przy ładowaniu XML</h2><p>'+message+'</p>');
198 this.set('state', 'error');
199 messageCenter.addMessage('error', 'xmlload', 'Nie udało mi się wczytać HTML. Spróbuj ponownie :-(');
202 save: function(message) {
203 if (this.get('state') == 'dirty') {
204 this.set('state', 'updating');
205 messageCenter.addMessage('info', 'xmlsave', 'Zapisuję XML...');
208 contents: this.get('data'),
209 revision: this.get('revision'),
210 user: this.document.get('user')
213 payload.message = message;
221 success: this.saveSucceeded.bind(this),
222 error: this.saveFailed.bind(this)
229 saveSucceeded: function(data) {
230 if (this.get('state') != 'updating') {
231 alert('erroneous state:', this.get('state'));
233 this.set('revision', data.revision);
234 this.set('state', 'updated');
235 messageCenter.addMessage('success', 'xmlsave', 'Zapisałem XML :-)');
238 saveFailed: function() {
239 if (this.get('state') != 'updating') {
240 alert('erroneous state:', this.get('state'));
242 messageCenter.addMessage('error', 'xmlsave', 'Nie udało mi się zapisać XML. Spróbuj ponownie :-(');
243 this.set('state', 'dirty');
247 set: function(property, value) {
248 if (property == 'state') {
249 console.log(this.description(), ':', property, '=', value);
251 return this._super(property, value);
254 dataChanged: function(property, value) {
255 if (this.get('state') == 'synced') {
256 this.set('state', 'dirty');
260 dispose: function() {
261 this.removeObserver(this);
269 // -> error -> loading
271 // empty -> loading -> synced -> unsynced -> loading
273 // -> dirty -> updating -> updated -> synced
275 Editor.XMLModel = Editor.Model.extend({
276 _className: 'Editor.XMLModel',
281 init: function(document, serverURL) {
283 this.set('state', 'empty');
284 this.set('revision', document.get('revision'));
285 this.document = document;
286 this.serverURL = serverURL;
287 this.toolbarButtonsModel = new Editor.ToolbarButtonsModel();
288 this.addObserver(this, 'data', this.dataChanged.bind(this));
291 load: function(force) {
292 if (force || this.get('state') == 'empty') {
293 this.set('state', 'loading');
294 messageCenter.addMessage('info', 'xmlload', 'Wczytuję XML...');
299 revision: this.get('revision'),
300 user: this.document.get('user')
302 success: this.loadingSucceeded.bind(this),
303 error: this.loadingFailed.bind(this)
310 loadingSucceeded: function(data) {
311 if (this.get('state') != 'loading') {
312 alert('erroneous state:', this.get('state'));
314 this.set('data', data);
315 this.set('state', 'synced');
316 messageCenter.addMessage('success', 'xmlload', 'Wczytałem XML :-)');
319 loadingFailed: function(response)
321 if (this.get('state') != 'loading') {
322 alert('erroneous state:', this.get('state'));
325 var message = parseXHRError(response);
327 this.set('error', '<h2>Błąd przy ładowaniu XML</h2><p>'+message+'</p>');
328 this.set('state', 'error');
329 messageCenter.addMessage('error', 'xmlload', 'Nie udało mi się wczytać XML. Spróbuj ponownie :-(');
332 save: function(message) {
333 if (this.get('state') == 'dirty') {
334 this.set('state', 'updating');
335 messageCenter.addMessage('info', 'xmlsave', 'Zapisuję XML...');
338 contents: this.get('data'),
339 revision: this.get('revision'),
340 user: this.document.get('user')
343 payload.message = message;
351 success: this.saveSucceeded.bind(this),
352 error: this.saveFailed.bind(this)
359 saveSucceeded: function(data) {
360 if (this.get('state') != 'updating') {
361 alert('erroneous state:', this.get('state'));
363 this.set('revision', data.revision);
364 this.set('state', 'updated');
365 messageCenter.addMessage('success', 'xmlsave', 'Zapisałem XML :-)');
368 saveFailed: function() {
369 if (this.get('state') != 'updating') {
370 alert('erroneous state:', this.get('state'));
372 messageCenter.addMessage('error', 'xmlsave', 'Nie udało mi się zapisać XML. Spróbuj ponownie :-(');
373 this.set('state', 'dirty');
377 set: function(property, value) {
378 if (property == 'state') {
379 console.log(this.description(), ':', property, '=', value);
381 return this._super(property, value);
384 dataChanged: function(property, value) {
385 if (this.get('state') == 'synced') {
386 this.set('state', 'dirty');
390 dispose: function() {
391 this.removeObserver(this);
396 Editor.ImageGalleryModel = Editor.Model.extend({
397 _className: 'Editor.ImageGalleryModel',
402 init: function(document, serverURL) {
404 this.set('state', 'empty');
405 this.serverURL = serverURL;
410 load: function(force) {
411 if (force || this.get('state') == 'empty') {
412 console.log("setting state");
413 this.set('state', 'loading');
414 console.log("going ajax");
418 success: this.loadingSucceeded.bind(this),
419 error: this.loadingFailed.bind(this)
424 loadingSucceeded: function(data)
426 console.log("success");
428 if (this.get('state') != 'loading') {
429 alert('erroneous state:', this.get('state'));
432 console.log('galleries:', data);
434 if (data.length === 0) {
435 this.set('data', []);
437 this.set('data', data[0].pages);
440 this.set('state', 'synced');
443 loadingFailed: function(data) {
444 console.log("failed");
446 if (this.get('state') != 'loading') {
447 alert('erroneous state:', this.get('state'));
450 this.set('state', 'error');
453 set: function(property, value) {
454 if (property == 'state') {
455 console.log(this.description(), ':', property, '=', value);
457 return this._super(property, value);
462 Editor.DocumentModel = Editor.Model.extend({
463 _className: 'Editor.DocumentModel',
464 data: null, // name, text_url, revision, latest_shared_rev, parts_url, dc_url, size, merge_url
473 this.set('state', 'empty');
477 if (this.get('state') == 'empty') {
478 this.set('state', 'loading');
479 messageCenter.addMessage('info', 'docload', 'Ładuję dane dokumentu...');
482 url: documentInfo.docURL,
484 success: this.successfulLoad.bind(this),
485 error: this.failedLoad.bind(this)
490 successfulLoad: function(data) {
491 this.set('data', data);
492 this.set('state', 'synced');
494 this.set('revision', data.revision);
495 this.set('user', data.user);
497 this.contentModels = {
498 'xml': new Editor.XMLModel(this, data.text_url),
499 'html': new Editor.HTMLModel(this, data.text_url),
500 'gallery': new Editor.ImageGalleryModel(this, data.gallery_url)
503 for (var key in this.contentModels) {
504 this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
509 messageCenter.addMessage('success', 'docload', 'Dokument załadowany poprawnie :-)');
512 failedLoad: function(response) {
513 if (this.get('state') != 'loading') {
514 alert('erroneous state:', this.get('state'));
517 var err = parseXHRError(response);
518 this.set('error', '<h2>Nie udało się wczytać dokumentu</h2><p>'+err.error_message+"</p>");
519 this.set('state', 'error');
522 contentModelStateChanged: function(property, value, contentModel) {
523 if (value == 'dirty') {
524 this.set('state', 'dirty');
525 for (var key in this.contentModels) {
526 if (this.contentModels[key].guid() != contentModel.guid()) {
527 this.contentModels[key].set('state', 'unsynced');
530 } else if (value == 'updated') {
531 this.set('state', 'synced');
532 for (key in this.contentModels) {
533 if (this.contentModels[key].guid() == contentModel.guid()) {
534 this.contentModels[key].set('state', 'synced');
535 this.revision = this.contentModels[key].get('revision');
539 for (key in this.contentModels) {
540 if (this.contentModels[key].guid() != contentModel.guid()) {
541 this.contentModels[key].set('revision', this.revision);
542 this.contentModels[key].set('state', 'empty');
548 saveDirtyContentModel: function(message) {
549 for (var key in this.contentModels) {
550 if (this.contentModels[key].get('state') == 'dirty') {
551 this.contentModels[key].save(message);
558 this.set('state', 'loading');
560 messageCenter.addMessage('info', 'doc_update',
561 'Uaktualniam dokument...');
564 url: this.data.merge_url,
569 revision: this.get('revision'),
570 user: this.get('user')
572 complete: this.updateCompleted.bind(this)
576 updateCompleted: function(xhr, textStatus)
578 console.log(xhr.status, xhr.responseText);
579 var response = parseXHRResponse(xhr);
582 if( (response.data.result == 'no-op')
583 || (response.data.timestamp == response.data.parent_timestamp))
585 if( (response.data.revision) && (response.data.revision != this.get('revision')) )
588 this.set('state', 'unsynced');
592 messageCenter.addMessage('info', 'doc_update',
593 'Już posiadasz najbardziej aktualną wersję.');
594 this.set('state', 'synced');
599 this.set('revision', response.data.revision);
600 this.set('user', response.data.user);
602 messageCenter.addMessage('info', 'doc_update',
603 'Uaktualnienie dokumentu do wersji ' + response.data.revision);
605 for (var key in this.contentModels) {
606 this.contentModels[key].set('revision', this.get('revision') );
607 this.contentModels[key].set('state', 'empty');
610 this.set('state', 'synced');
614 // no success means trouble
615 messageCenter.addMessage(response.error_level, 'doc_update',
616 response.error_message);
618 this.set('state', 'unsynced');
621 merge: function(message) {
622 this.set('state', 'loading');
623 messageCenter.addMessage('info', 'doc_merge',
624 'Scalam dokument z głównym repozytorium...');
627 url: this.data.merge_url,
632 revision: this.get('revision'),
633 user: this.get('user'),
636 complete: this.mergeCompleted.bind(this),
637 success: function(data) {
638 this.set('mergeData', data);
643 mergeCompleted: function(xhr, textStatus) {
644 console.log(xhr.status, xhr.responseText);
645 var response = parseXHRResponse(xhr);
647 if(response.success) {
649 if( (response.data.result == 'no-op') ||
650 ( response.data.shared_parent_timestamp
651 && response.data.shared_timestamp
652 && (response.data.shared_timestamp == response.data.shared_parent_timestamp)) )
654 if( (response.data.revision) && (response.data.revision != this.get('revision')) )
657 this.set('state', 'unsynced');
661 messageCenter.addMessage('info', 'doc_merge',
662 'Twoja aktualna wersja nie różni się od ostatnio zatwierdzonej.');
663 this.set('state', 'synced');
667 if( response.data.result == 'accepted')
669 messageCenter.addMessage('info', 'doc_merge',
670 'Prośba o zatwierdzenie została przyjęta i oczekuję na przyjęcie.');
671 this.set('state', 'synced');
676 this.set('revision', response.data.revision);
677 this.set('user', response.data.user);
679 messageCenter.addMessage('info', 'doc_merge',
680 'Twoja wersja dokumentu została zatwierdzona.');
682 this.set('state', 'synced');
686 // no success means trouble
687 messageCenter.addMessage(response.error_level, 'doc_merge',
688 response.error_message);
690 this.set('state', 'unsynced');
694 set: function(property, value) {
695 if (property == 'state') {
696 console.log(this.description(), ':', property, '=', value);
698 return this._super(property, value);
703 var leftPanelView, rightPanelContainer, doc;
707 var flashView = new FlashView('#flashview', messageCenter);
709 doc = new Editor.DocumentModel();
711 EditorView = new EditorView('#body-wrap', doc);
712 EditorView.freeze("<h1>Wczytuję dokument...</h1>");
714 leftPanelView = new PanelContainerView('#left-panel-container', doc);
715 rightPanelContainer = new PanelContainerView('#right-panel-container', doc);