prevent empty span in a new node
[fnpeditor.git] / src / editor / modules / rng / rng.js
1 define([
2 './documentSummary',
3 'libs/underscore',
4 'fnpjs/layout',
5 'fnpjs/logging/logging',
6 'views/tabs/tabs',
7 'libs/text!./mainLayout.html',
8 'libs/text!./editingLayout.html',
9 'libs/text!./diffLayout.html',
10 ], function(documentSummary, _, layout, logging, tabs, mainLayoutTemplate, visualEditingLayoutTemplate, diffLayoutTemplate) {
11
12 'use strict';
13
14 return function(sandbox) {
15
16     /* globals gettext */
17
18     var logger = logging.getLogger('editor.modules.rng');
19     
20     function addMainTab(title, slug, view) {
21         views.mainTabs.addTab(title, slug, view);
22     }
23      
24     var commands = {
25         refreshCanvasSelection: function(selection) {
26             var fragment = selection.toDocumentFragment();
27             sandbox.getModule('documentToolbar').setDocumentFragment(fragment);
28         },
29     };
30     
31
32     var views = {
33         mainLayout: new layout.Layout(mainLayoutTemplate),
34         mainTabs: (new tabs.View()).render(),
35         visualEditing: new layout.Layout(visualEditingLayoutTemplate),
36         diffLayout: new layout.Layout(diffLayoutTemplate)
37     };
38     
39     addMainTab(gettext('Editor'), 'editor', views.visualEditing.getAsView());
40     addMainTab(gettext('Source'), 'sourceEditor',  '');
41     addMainTab(gettext('History'), 'history', views.diffLayout.getAsView());
42     
43     sandbox.getDOM().append(views.mainLayout.getAsView());
44     
45     var wlxmlDocument, documentIsDirty;
46     
47     /* Events handling */
48     
49     var eventHandlers = {};
50      
51     eventHandlers.sourceEditor = {
52         ready: function() {
53             addMainTab(gettext('Source'), 'sourceEditor',  sandbox.getModule('sourceEditor').getView());
54             sandbox.getModule('sourceEditor').setDocument(sandbox.getModule('data').getDocument());
55         }
56     };
57     
58     eventHandlers.data = {
59         ready: function(usingDraft, draftTimestamp, xmlValid) {
60             wlxmlDocument = sandbox.getModule('data').getDocument();
61
62             views.mainLayout.setView('mainView', views.mainTabs.getAsView());
63             
64             documentSummary.init(sandbox.getConfig().documentSummaryView, wlxmlDocument);
65             documentSummary.render();
66             documentSummary.setDraftField(usingDraft ? (draftTimestamp || '???') : '-');
67             sandbox.getModule('mainBar').setSummaryView(documentSummary.dom);
68
69             sandbox.getModule('mainBar').setCommandEnabled('drop-draft', usingDraft);
70             sandbox.getModule('mainBar').setCommandEnabled('save', usingDraft);
71
72             
73             var toStart = ['sourceEditor', 'documentToolbar', 'mainBar', 'indicator', 'documentHistory', 'diffViewer', 'statusBar'];
74             if(xmlValid) {
75                 toStart.push('documentCanvas');
76             }
77             _.each(toStart, function(moduleName) {
78                 sandbox.getModule(moduleName).start();
79             });
80             
81             documentIsDirty = false;
82             wlxmlDocument.on('change', function() {
83                 documentIsDirty = true;
84                 sandbox.getModule('mainBar').setCommandEnabled('save', true);
85             });
86             wlxmlDocument.on('contentSet', function() {
87                 documentIsDirty = true;
88             });
89         },
90         draftDropped: function() {
91             documentSummary.setDraftField('-');
92             sandbox.getModule('mainBar').setCommandEnabled('drop-draft', false);
93             sandbox.getModule('mainBar').setCommandEnabled('save', false);
94         },
95         savingStarted: function(what) {
96             var msg = {
97                 remote: gettext('Saving document'),
98                 local: gettext('Saving local copy')
99             };
100             sandbox.getModule('mainBar').setCommandEnabled('save', false);
101             sandbox.getModule('indicator').showMessage(msg[what] + '...');
102         },
103         savingEnded: function(status, what, data) {
104             void(status);
105             var msg = {
106                 remote: gettext('Document saved'),
107                 local: gettext('Local copy saved'),
108                 error: gettext('Failed to save')
109             };
110             documentIsDirty = false;
111
112             if (status === 'success') {
113                 sandbox.getModule('indicator').clearMessage({message: msg[what]});
114                 if (what === 'remote') {
115                     documentSummary.setDraftField('-');
116                     sandbox.getModule('mainBar').setCommandEnabled('drop-draft', false);
117                     sandbox.getModule('mainBar').setCommandEnabled('save', false);
118                 }
119                 if (what === 'local') {
120                     documentSummary.setDraftField(data.timestamp);
121                     sandbox.getModule('mainBar').setCommandEnabled('drop-draft', true);
122                     sandbox.getModule('mainBar').setCommandEnabled('save', true);
123                 }
124             } else {
125                 sandbox.getModule('indicator').clearMessage({message: msg[status]});
126             }
127         },
128         restoringStarted: function(event) {
129             sandbox.getModule('mainBar').setCommandEnabled('save', false);
130             sandbox.getModule('indicator').showMessage(gettext('Restoring version ') + event.version + '...');
131         },
132         historyItemAdded: function(item) {
133             sandbox.getModule('documentHistory').addHistory([item], {animate: true});
134         },
135         diffFetched: function(diff) {
136             sandbox.getModule('diffViewer').setDiff(diff);
137         },
138         documentReverted: function(version) {
139             documentIsDirty = false;
140             sandbox.getModule('indicator').clearMessage({message:'Revision restored'});
141         },
142         publishingStarted: function(version) {
143             sandbox.getModule('indicator').showMessage(gettext('Publishing...'));
144         },
145         documentPublished: function(version) {
146             sandbox.getModule('indicator').clearMessage({message:'Published.'});
147         }
148     };
149     
150     eventHandlers.mainBar = {
151         ready: function() {
152             views.mainLayout.setView('topPanel', sandbox.getModule('mainBar').getView());
153         },
154         'cmd.save': function() {
155             var sourceEditor = sandbox.getModule('sourceEditor');
156             if(!sourceEditor.changesCommited()) {
157                 logger.debug('Source editor has uncommited changes, commiting...');
158                 sourceEditor.commitChanges();
159             }
160             sandbox.getModule('data').saveDocument();
161         },
162         'cmd.drop-draft': function() {
163             sandbox.getModule('data').dropDraft();
164         }
165     };
166     
167     eventHandlers.indicator = {
168         ready: function() {
169             views.mainLayout.setView('messages', sandbox.getModule('indicator').getView());
170         }
171     };
172     
173
174     
175     eventHandlers.documentCanvas = {
176         ready: function() {
177             sandbox.getModule('documentCanvas').setDocument(sandbox.getModule('data').getDocument());
178             views.visualEditing.setView('leftColumn', sandbox.getModule('documentCanvas').getView());
179         },
180         
181         selectionChanged: function(selection) {
182             commands.refreshCanvasSelection(selection);
183         }
184     };
185     
186     eventHandlers.documentToolbar = {
187         ready: function() {
188             views.visualEditing.setView('toolbar', sandbox.getModule('documentToolbar').getView());
189             sandbox.getModule('documentToolbar').setCanvas(sandbox.getModule('documentCanvas').getCanvas());
190         },
191         actionExecuted: function(action, ret) {
192             sandbox.getModule('documentCanvas').onAfterActionExecuted(action, ret);
193         }
194     };
195     
196     eventHandlers.documentHistory = {
197         ready: function() {
198             sandbox.getModule('documentHistory').addHistory(sandbox.getModule('data').getHistory());
199             views.diffLayout.setView('left', sandbox.getModule('documentHistory').getView());
200         },
201         compare: function(ver1, ver2) {
202             sandbox.getModule('data').fetchDiff(ver1, ver2);
203         },
204         restoreVersion: function(version) {
205             sandbox.getModule('data').restoreVersion(version);
206         },
207         displayVersion: function(revision) {
208             /* globals window */
209             //window.open(sandbox.getConfig().documentPreviewUrl(revision), _.uniqueId());
210             window.open(sandbox.getConfig().documentPreviewUrl(revision), 'preview');
211         },
212         publishVersion: function(version) {
213             sandbox.getModule('data').publishVersion(version);
214         }
215     };
216     
217     eventHandlers.diffViewer = {
218         ready: function() {
219             views.diffLayout.setView('right', sandbox.getModule('diffViewer').getView());
220         }
221     };
222
223     eventHandlers.statusBar = {
224         ready: function() {
225             views.mainLayout.setView('bottomPanel', sandbox.getModule('statusBar').getView());
226         }
227     };
228
229     eventHandlers.__all__ = {
230         actionHovered: function(action) {
231             sandbox.getModule('statusBar').showAction(action);
232         },
233         actionOff: function() {
234             sandbox.getModule('statusBar').clearAction();
235         }
236     };
237
238     window.addEventListener('beforeunload', function(event) {
239         var txt = gettext('Do you really want to exit?');
240         if(documentIsDirty) {
241             txt += ' ' + gettext('Document contains unsaved changes!');
242             event.returnValue = txt; // FF
243             return txt; // Chrome
244         }
245     });
246     
247     /* api */
248     
249     return {
250         start: function() {
251             sandbox.registerActionsAppObject({
252                 getUser: function() {
253                     return sandbox.getConfig().user;
254                 }
255             });
256             sandbox.getModule('data').start();
257         },
258         handleEvent: function(moduleName, eventName, args) {
259             var eventRepr = moduleName + '.' + eventName;
260             if(eventHandlers[moduleName] && eventHandlers[moduleName][eventName]) {
261                 logger.debug('Handling event ' + eventRepr);
262                 eventHandlers[moduleName][eventName].apply(eventHandlers, args);
263                 return;
264             }
265
266             if(eventHandlers.__all__[eventName]) {
267                 logger.debug('Handling event ' + eventRepr);
268                 eventHandlers.__all__[eventName].apply(eventHandlers.__all__, args);
269                 return;
270             }
271
272             logger.warning('No event handler for ' + eventRepr);
273         }
274     };
275 };
276
277 });