4b29e67afc902f2b24580c5cebb7b8bb466d9510
[redakcja.git] / project / static / js / models.js
1 /*globals Editor fileId SplitView PanelContainerView EditorView*/
2 var documentsUrl = '/api/documents/';
3
4
5 Editor.Model = Editor.Object.extend({
6   synced: false,
7   data: null
8 });
9
10
11 Editor.ToolbarButtonsModel = Editor.Model.extend({
12   _className: 'Editor.ToolbarButtonsModel',
13   serverURL: '/api/toolbar/buttons',
14   buttons: {},
15   
16   init: function() {
17     this._super();
18   },
19   
20   load: function() {
21     if (!this.get('buttons').length) {
22       $.ajax({
23         url: this.serverURL,
24         dataType: 'json',
25         success: this.loadSucceeded.bind(this)
26       });
27     }
28   },
29   
30   loadSucceeded: function(data) {
31     this.set('buttons', data);
32   }
33 });
34
35
36 // Stany modelu:
37 //
38 // empty -> loading -> synced -> unsynced -> loading
39 //                           \
40 //                            -> dirty -> updating -> synced
41 //
42 Editor.XMLModel = Editor.Model.extend({
43   _className: 'Editor.XMLModel',
44   serverURL: null,
45   data: '',
46   state: 'empty',
47   
48   init: function(serverURL) {
49     this._super();
50     this.set('state', 'empty');
51     this.serverURL = serverURL;
52     this.toolbarButtonsModel = new Editor.ToolbarButtonsModel();
53     this.addObserver(this, 'data', this.dataChanged.bind(this));
54   },
55   
56   load: function() {
57     if (this.get('state') == 'empty') {
58       this.set('state', 'loading');
59       $.ajax({
60         url: this.serverURL,
61         dataType: 'text',
62         success: this.loadingSucceeded.bind(this)
63       });
64     }
65   },
66   
67   set: function(property, value) {
68     if (property == 'state') {
69       console.log(this.description(), ':', property, '=', value);
70     }
71     return this._super(property, value);
72   },
73   
74   dataChanged: function(property, value) {
75     if (this.get('state') == 'synced') {
76       this.set('state', 'dirty');
77     }
78   },
79   
80   loadingSucceeded: function(data) {
81     if (this.get('state') != 'loading') {
82       alert('erroneous state:', this.get('state'));
83     }
84     this.set('data', data);
85     this.set('state', 'synced');
86   },
87   
88   dispose: function() {
89     this.removeObserver(this);
90     this._super();
91   }
92 });
93
94
95 Editor.HTMLModel = Editor.Model.extend({
96   _className: 'Editor.HTMLModel',
97   serverURL: null,
98   data: '',
99   state: 'empty',
100   
101   init: function(serverURL) {
102     this._super();
103     this.set('state', 'empty');
104     this.serverURL = serverURL;
105   },
106   
107   load: function() {
108     if (this.get('state') == 'empty') {
109       this.set('state', 'loading');
110       $.ajax({
111         url: this.serverURL,
112         dataType: 'text',
113         success: this.loadingSucceeded.bind(this)
114       });
115     }
116   },
117   
118   loadingSucceeded: function(data) {
119     if (this.get('state') != 'loading') {
120       alert('erroneous state:', this.get('state'));
121     }
122     this.set('data', data);
123     this.set('state', 'synced');
124   },
125   
126   set: function(property, value) {
127     if (property == 'state') {
128       console.log(this.description(), ':', property, '=', value);
129     }
130     return this._super(property, value);
131   }
132 });
133
134
135 Editor.DocumentModel = Editor.Model.extend({
136   _className: 'Editor.DocumentModel',
137   data: null, // name, text_url, latest_rev, latest_shared_rev, parts_url, dc_url, size
138   contentModels: {},
139   state: 'empty',
140   
141   init: function() {
142     this._super();
143     this.set('state', 'empty');
144     this.load();
145   },
146   
147   load: function() {
148     if (this.get('state') == 'empty') {
149       this.set('state', 'loading');
150       $.ajax({
151         cache: false,
152         url: documentsUrl + fileId,
153         dataType: 'json',
154         success: this.successfulLoad.bind(this)
155       });
156     }
157   },
158   
159   successfulLoad: function(data) {
160     this.set('data', data);
161     this.set('state', 'synced');
162     this.contentModels = {
163       'xml': new Editor.XMLModel(data.text_url),
164       'html': new Editor.HTMLModel(data.html_url)
165     };
166     for (var key in this.contentModels) {
167       this.contentModels[key].addObserver(this, 'state', this.contentModelStateChanged.bind(this));
168     }
169   },
170   
171   contentModelStateChanged: function(property, value, contentModel) {
172     if (value == 'dirty') {
173       for (var key in this.contentModels) {
174         if (this.contentModels[key].guid() != contentModel.guid()) {
175           // console.log(this.contentModels[key].description(), 'frozen');
176           this.contentModels[key].set('state', 'unsynced');
177         }
178       }
179     }
180   }
181 });
182
183
184 var leftPanelView, rightPanelContainer, doc;
185
186 $(function() {
187   doc = new Editor.DocumentModel();
188   var editor = new EditorView('#body-wrap', doc);
189   var splitView = new SplitView('#splitview', doc);
190   leftPanelView = new PanelContainerView('#left-panel-container', doc);
191   rightPanelContainer = new PanelContainerView('#right-panel-container', doc);
192 });