editor: Support for selecting metadata keys from a list in the metadata editor
[fnpeditor.git] / src / editor / modules / documentCanvas / commands.js
1 define([
2 './canvas/utils'
3 ], function(utils) {
4     
5 'use strict';
6
7
8 var gridToggled = false;
9
10 var commands = {
11     _cmds: {},
12     register: function(name, command) {
13         this._cmds[name] = command;
14     },
15
16     run: function(name, params, canvas, user) {
17         return this._cmds[name](canvas, params, user);
18     }
19 };
20
21 commands.register('undo', function(canvas) {
22     var doc = canvas.wlxmlDocument;
23
24     doc.undo();
25 });
26
27 commands.register('redo', function(canvas) {
28     var doc = canvas.wlxmlDocument;
29
30     doc.redo();
31 });
32
33 commands.register('remove-node', function(canvas) {
34     canvas.getCurrentNodeElement().data('wlxmlNode').detach();
35 });
36
37 commands.register('unwrap-node', function(canvas) {
38     var cursor = canvas.getCursor(),
39         selectionStart = cursor.getSelectionStart(),
40         selectionEnd = cursor.getSelectionEnd(),
41         parent1 = selectionStart.element.parent() || undefined,
42         parent2 = selectionEnd.element.parent() || undefined;
43
44     var selectionAnchor = cursor.getSelectionAnchor(),
45         node1 = parent1.data('wlxmlNode'),
46         node2 = parent2.data('wlxmlNode'),
47         doc = node1.document;
48     if(doc.areItemsOfSameList({node1: node1, node2: node2})) {
49         doc.extractItems({item1: node1, item2: node2});
50         canvas.setCurrentElement(selectionAnchor.element, {caretTo: selectionAnchor.offset});
51     } else if(!cursor.isSelecting()) {
52         var nodeToUnwrap = cursor.getPosition().element.data('wlxmlNode'),
53             parentNode = nodeToUnwrap.unwrap();
54         if(parentNode) {
55             canvas.setCurrentElement(utils.findCanvasElement(parentNode));
56         }
57     }
58 });
59
60 commands.register('wrap-node', function(canvas) {
61     var cursor = canvas.getCursor(),
62         selectionStart = cursor.getSelectionStart(),
63         selectionEnd = cursor.getSelectionEnd(),
64         parent1 = selectionStart.element.parent() || undefined,
65         parent2 = selectionEnd.element.parent() || undefined;
66
67     var node1 = parent1.data('wlxmlNode'),
68         node2 = parent2.data('wlxmlNode'),
69         doc = node1.document;
70
71     if(doc.areItemsOfSameList({node1: node1, node2: node2})) {
72         doc.createList({node1: node1, node2: node2});
73     }
74 });
75
76 commands.register('list', function(canvas, params) {
77     void(params);
78     var cursor = canvas.getCursor(),
79         selectionStart = cursor.getSelectionStart(),
80         selectionEnd = cursor.getSelectionEnd(),
81         parent1 = selectionStart.element.parent() || undefined,
82         parent2 = selectionEnd.element.parent() || undefined;
83
84     var selectionFocus = cursor.getSelectionFocus();
85
86     if(selectionStart.element.isInsideList() || selectionEnd.element.isInsideList()) {
87         return;
88     }
89
90     var node1 = parent1.data('wlxmlNode'),
91         node2 = parent2.data('wlxmlNode'),
92         doc = node1.document;
93     
94     doc.createList({node1: node1, node2: node2});
95     canvas.setCurrentElement(selectionFocus.element, {caretTo: selectionFocus.offset});
96 });
97
98 commands.register('toggle-grid', function(canvas, params) {
99     canvas.doc().dom().parent().toggleClass('grid-on', params.toggle);
100     gridToggled = params.toggle;
101 });
102
103 commands.register('newNodeRequested', function(canvas, params, user) {
104     var cursor = canvas.getCursor(),
105         selectionStart = cursor.getSelectionStart(),
106         selectionEnd = cursor.getSelectionEnd(),
107         wlxmlNode, caretTo, wrapper, wrapperCanvasElement;
108
109     var insertNode = function(insertion) {
110         var doc = canvas.wlxmlDocument,
111             node, metadata, creator, currentDate, dt;
112
113         var pad = function(number) {
114             if(number < 10) {
115                 number = '0' + number;
116             }
117             return number;
118         };
119
120         doc.startTransaction();
121         node = insertion();
122         if(node.getTagName() === 'aside' && node.getClass() === 'comment') {
123             if(user) {
124                 creator = user.name;
125                 if(user.email) {
126                     creator += ' (' + user.email + ')';
127                 }
128             } else {
129                 creator = 'anonymous';
130             }
131
132             currentDate = new Date();
133             dt = pad(currentDate.getDate()) + '-' +
134                             pad((currentDate.getMonth() + 1))  + '-' +
135                             pad(currentDate.getFullYear()) + ' ' +
136                             pad(currentDate.getHours()) + ':' +
137                             pad(currentDate.getMinutes()) + ':' +
138                             pad(currentDate.getSeconds());
139
140             metadata = node.getMetadata();
141             metadata.add({key: 'creator', value: creator});
142             metadata.add({key: 'date', value: dt});
143         }
144         doc.endTransaction();
145         return node;
146     };
147
148
149     if(cursor.isSelecting()) {
150         if(cursor.isSelectingSiblings()) {
151             if(cursor.isSelectingWithinElement()) {
152                 wlxmlNode = selectionStart.element.data('wlxmlNode');
153                 caretTo = selectionStart.offset < selectionEnd.offset ? 'start' : 'end';
154
155                 wrapper = insertNode(function() {
156                     return wlxmlNode.wrapWith({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}, start: selectionStart.offset, end: selectionEnd.offset});
157                 });
158                 wrapperCanvasElement = utils.findCanvasElement(wrapper);
159                 canvas.setCurrentElement(wrapperCanvasElement.children()[0], {caretTo: caretTo});
160             }
161             else {
162                 wlxmlNode = selectionStart.element.data('wlxmlNode').parent();
163                 caretTo = selectionStart.element.sameNode(cursor.getSelectionAnchor().element) ? 'end' : 'start';
164
165                 wrapper = insertNode(function() {
166                     return wlxmlNode.wrapText({
167                         _with: {tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}},
168                         offsetStart: selectionStart.offset,
169                         offsetEnd: selectionEnd.offset,
170                         textNodeIdx: [wlxmlNode.indexOf(selectionStart.element.data('wlxmlNode')), wlxmlNode.indexOf(selectionEnd.element.data('wlxmlNode'))] //parent.childIndex(selectionEnd.element)]
171                     });
172                 });
173                 wrapperCanvasElement = utils.findCanvasElement(wrapper);
174                 canvas.setCurrentElement(wrapperCanvasElement.children()[caretTo === 0 ? 0 : wrapperCanvasElement.children().length - 1], {caretTo: caretTo});
175             }
176         } else {
177             var node1 = selectionStart.element.data('wlxmlNode'),
178                 node2 = selectionEnd.element.data('wlxmlNode'),
179                 siblingParents = canvas.wlxmlDocument.getSiblingParents({node1: node1, node2: node2});
180
181             if(siblingParents) {
182                 insertNode(function() {
183                     return canvas.wlxmlDocument.wrapNodes({
184                         node1: siblingParents.node1,
185                         node2: siblingParents.node2,
186                         _with: {tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}}
187                     });
188                 });
189             }
190         }
191     } else if(canvas.getCurrentNodeElement()) {
192         wlxmlNode = canvas.getCurrentNodeElement().data('wlxmlNode');
193         if(params.ctrlKey) {
194             wrapper = insertNode(function() {
195                 return wlxmlNode.wrapWith({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}});
196             });
197         } else {
198             wrapper = insertNode(function() {
199                 var node = wlxmlNode.after({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}});
200                 node.append({text:''});
201                 return node;
202             });
203         }
204         canvas.setCurrentElement(utils.findCanvasElement(wrapper));
205     }
206
207
208 });
209
210 commands.register('footnote', function(canvas, params) {
211     void(params);
212     var cursor = canvas.getCursor(),
213         position = cursor.getPosition(),
214         asideNode, asideElement, node;
215         
216
217     if(cursor.isSelectingWithinElement()) {
218         asideNode = position.element.data('wlxmlNode').wrapWith({tagName: 'aside', attrs:{'class': 'footnote'}, start: cursor.getSelectionStart().offset, end: cursor.getSelectionEnd().offset});
219     } else {
220         node = position.element.data('wlxmlNode');
221         node.document.transaction(function() {
222             asideNode = node.divideWithElementNode({tagName: 'aside', attrs:{'class': 'footnote'}}, {offset: position.offset});
223             asideNode.append({text: ''});
224         });
225     }
226
227     asideElement = utils.findCanvasElement(asideNode);
228     asideElement.toggle(true);
229     canvas.setCurrentElement(asideElement);
230 });
231
232 commands.register('take-away-node', function(canvas) {
233     var position = canvas.getCursor().getPosition(),
234         element = position.element,
235         nodeElement = element ? element.parent() : canvas.getCurrentNodeElement();
236
237     if(!nodeElement || !(nodeElement.parent())) {
238         return;
239     }
240
241     var range = nodeElement.data('wlxmlNode').unwrapContent();
242
243     if(element) {
244         var elementIsFirstChild = nodeElement.childIndex(element);
245         if(element.bound()) {
246             canvas.setCurrentElement(element, {caretTo: position.offset});
247         } else {
248             if(elementIsFirstChild) {
249                 canvas.setCurrentElement(utils.findCanvasElement(range.element1), {caretTo: 'end'});
250             } else {
251                 canvas.setCurrentElement(utils.findCanvasElement(range.element2), {caretTo: 'end'});
252             }
253         }
254     } else {
255         canvas.setCurrentElement(utils.findCanvasElement(range.element1), {caretTo: 'start'});
256     }
257
258 });
259
260
261 return {
262     run: function(name, params, canvas, user) {
263         return commands.run(name, params, canvas, user);
264     }
265 };
266
267 });