smartxml: pass transformation instance to impl & undo when needed
[fnpeditor.git] / src / wlxml / extensions / list / list.js
1 define(function() {
2
3 'use strict';
4
5 var extension = {document: {transformations: {}}, wlxmlClass: {list: {methods: {}}}};
6
7
8 extension.wlxmlClass.list.methods = {
9     itemIndex: function(listItem) {
10         var toret = -1;
11         this.contents('.item').some(function(item, index) {
12             if(item.sameNode(listItem)) {
13                 toret = index;
14                 return true; // break
15             }
16         });
17         return toret;
18     },
19     getItem: function(index) {
20         return this.contents('.item')[index];
21     }
22 }
23
24 extension.documentMethods = {
25     areItemsOfSameList: function(params) {
26         return params.node1.parent().sameNode(params.node2.parent()) && params.node2.parent().is('list');
27     }
28 }
29
30
31
32 extension.document.transformations.createList = {
33     impl: function(params) {          
34         var parent = params.node1.parent(),
35             parentContents = parent.contents(),
36             nodeIndexes = [params.node1.getIndex(), params.node2.getIndex()].sort(),
37             nodesToWrap = [],
38             listNode = params.node1.document.createDocumentNode({tagName: 'div', attrs: {'class': 'list'}}),
39             node, i;
40
41         for(i = nodeIndexes[0]; i <= nodeIndexes[1]; i++) {
42             node = parentContents[i];
43             if(node.nodeType === Node.TEXT_NODE) {
44                 node = node.wrapWith({tagName: 'div', attrs: {'class': 'item'}}); //t
45             } else {
46                 node.setClass('item'); //t
47             }
48             nodesToWrap.push(node);
49         }
50
51         var toInsert;
52         if(parent.is('list') && parent.object.itemIndex(nodesToWrap[0]) > 0) { // object api
53             // var prevItem = parent.object.getItem(parent.object.itemIndex(nodesToWrap[0])-1); // object api
54             // prevItem.append(listNode); //t
55             toInsert = listNode.wrapWith({tagName: 'div', attrs: {'class': 'item'}});
56         } else {
57             //nodesToWrap[0].before(listNode); //t
58             toInsert = listNode;
59         }  
60
61         params.node1.before(toInsert);
62
63         nodesToWrap.forEach(function(node) {
64             listNode.append(node); //t
65         });
66     },
67     getChangeRoot: function() {
68         return this.args[0].node1.parent();
69     },
70     isAllowed: function() {
71         return this.args[0].node1.parent().sameNode(this.args[0].node2.parent());
72     }
73 };
74
75 extension.document.transformations.extractItems = {
76     impl: function(params) {
77         params = _.extend({}, {merge: true}, params);
78         var list = params.item1.parent(),
79             indexes = [params.item1.getIndex(), params.item2.getIndex()].sort(),
80             precedingItems = [],
81             extractedItems = [],
82             succeedingItems = [],
83             items = list.contents(), // lub list.object.items()
84             listIsNested = list.parent().is('item'),
85             i;
86         
87         items.forEach(function(item, idx) {
88             if(idx < indexes[0]) {
89                 precedingItems.push(item);
90             }
91             else if(idx >= indexes[0] && idx <= indexes[1]) {
92                 extractedItems.push(item);
93             }
94             else {
95                 succeedingItems.push(item);
96             }
97         });
98
99         var reference = listIsNested ? list.parent() : list;
100         if(succeedingItems.length === 0) {
101             var reference_orig = reference;
102             extractedItems.forEach(function(item) {
103                 reference.after(item); //t
104                 reference = item;
105                 if(!listIsNested) {
106                     item.setClass(null); //t
107                 }
108             });
109             if(precedingItems.length === 0)
110                 reference_orig.detach(); //t
111         } else if(precedingItems.length === 0) {
112             extractedItems.forEach(function(item) {
113                 reference.before(item); //t
114                 if(!listIsNested) {
115                     item.setClass(null); //t
116                 }
117             });
118         } else {
119             extractedItems.forEach(function(item) {
120                 reference.after(item); //t
121                 if(!listIsNested)
122                     item.setClass(null); //t
123                 reference = item;
124             });
125             var secondList = params.item1.document.createDocumentNode({tagName: 'div', attrs: {'class':'list'}}),
126                 toAdd = secondList;
127             
128             if(listIsNested) {
129                 toAdd = secondList.wrapWith({tagName: 'div', attrs: {'class':'item'}});
130             }
131             succeedingItems.forEach(function(item) {
132                 secondList.append(item);
133             });
134
135             reference.after(toAdd);
136         }
137         if(!params.merge && listIsNested) {
138             return this.extractItems({item1: extractedItems[0], item2: extractedItems[extractedItems.length-1]});
139         }
140         return true;
141     },
142     isAllowed: function() {
143         var parent = this.args[0].nodel1.parent();
144         return parent.is('list') && parent.sameNode(this.args[0].node2.parent());
145     }
146 };
147
148 return extension;
149
150
151 });