Wrapping in node text with subnodes
[fnpeditor.git] / modules / documentCanvas / canvas.js
1 define([\r
2 'libs/jquery-1.9.1.min',\r
3 'libs/underscore-min',\r
4 'modules/documentCanvas/transformations',\r
5 'modules/documentCanvas/canvasNode',\r
6 'libs/text!./template.html'\r
7 ], function($, _, transformations, canvasNode, template) {\r
8 \r
9 'use strict';\r
10 \r
11 var Canvas = function(html) {\r
12     this.dom = $(template);\r
13     this.content = this.dom.find('#rng-module-documentCanvas-content');\r
14     this.setHTML(html);\r
15 };\r
16 \r
17 Canvas.prototype.setHTML = function(html) {\r
18     if(html) {\r
19         this.content.html(html);\r
20     }\r
21 };\r
22 \r
23 Canvas.prototype.getContent = function() {\r
24     return this.content.contents();\r
25 };\r
26 \r
27 Canvas.prototype.findNodes = function(desc) {\r
28     var selector = '';\r
29     if(typeof desc === 'string') {\r
30         selector = desc;\r
31     }\r
32     else {\r
33         if(desc.klass)\r
34             selector += '[wlxml-class=' + desc.klass + ']';\r
35         if(desc.tag)\r
36             selector += '[wlxml-tag=' + desc.tag + ']';\r
37     }\r
38     var toret = [];\r
39     this.content.find(selector).each(function() {\r
40         toret.push(canvasNode.create($(this)));\r
41     });\r
42     return toret;\r
43 };\r
44 \r
45 Canvas.prototype.getNodeById = function(id) {\r
46     return canvasNode.create($(this.content.find('#' +id)));\r
47 }\r
48 \r
49 Canvas.prototype.nodeAppend = function(options) {\r
50     var element; // = $(this.content.find('#' + options.context.id).get(0));\r
51     if(options.to === 'root') {\r
52         element = this.content;\r
53     } else {\r
54         element = $(this.content.find('#' + options.to.getId()).get(0));\r
55     }\r
56     element.append(options.node.dom);\r
57 };\r
58 \r
59 Canvas.prototype.nodeInsertAfter = function(options) {\r
60     var element = $(this.content.find('#' + options.after.getId()).get(0));\r
61     element.after(options.node.dom);\r
62 };\r
63 \r
64 Canvas.prototype.nodeWrap2 = function(options) {\r
65     var container = $(this.content.find('#' + options.inside.getId()).get(0));\r
66     \r
67     var containerContent = container.contents();\r
68     var idx1 = Math.min.apply(Math, options.textNodeIdx);\r
69     var idx2 = Math.max.apply(Math, options.textNodeIdx);\r
70     var textNode1 = $(containerContent.get(idx1));\r
71     var textNode2 = $(containerContent.get(idx2));\r
72     \r
73     textNode1.after(options._with.dom);\r
74     textNode1.detach();\r
75     textNode2.detach();\r
76     \r
77     \r
78     options._with.dom.before(textNode1.text().substr(0, options.offsetStart));\r
79     options._with.dom.append(textNode1.text().substr(options.offsetStart));\r
80     for(var i = idx1 + 1; i < idx2; i++) {\r
81         options._with.dom.append(containerContent[i]);\r
82     }\r
83     options._with.dom.append(textNode2.text().substr(0, options.offsetEnd));\r
84     options._with.dom.after(textNode2.text().substr(options.offsetEnd));\r
85 };\r
86 \r
87 Canvas.prototype.nodeWrap = function(options) {\r
88     options = _.extend({textNodeIdx: 0}, options);\r
89     \r
90     if(options.textNodeIdx instanceof Array)\r
91         return this.nodeWrap2(options);\r
92 \r
93     var element = $(this.content.find('#' + options.inside.getId()).get(0));\r
94     \r
95     var elementContents = element.contents();\r
96     if(elementContents.length === 0 || \r
97        elementContents.length - 1 < options.textNodeIdx || \r
98        elementContents.get(options.textNodeIdx).nodeType != 3)\r
99         return false;\r
100     var textElement = elementContents.get(options.textNodeIdx);\r
101 \r
102     var prefix = textElement.data.substr(0, options.offsetStart);\r
103     var suffix = textElement.data.substr(options.offsetEnd);\r
104     var core = textElement.data.substr(options.offsetStart, options.offsetEnd - options.offsetStart);\r
105     options._with.setContent(core);\r
106 \r
107     $(textElement).replaceWith(options._with.dom);\r
108     options._with.dom.before(prefix);\r
109     options._with.dom.after(suffix);\r
110 };\r
111 \r
112 Canvas.prototype.nodeSplit = function(options) {\r
113     options = _.extend({textNodeIdx: 0}, options);\r
114     \r
115     var nodeToSplit = $(this.content.find('#' + options.node.getId()).get(0));\r
116     \r
117     var nodeContents = nodeToSplit.contents();\r
118     if(nodeContents.length === 0 || \r
119        nodeContents.length - 1 < options.textNodeIdx || \r
120        nodeContents.get(options.textNodeIdx).nodeType != 3)\r
121         return false;\r
122     \r
123     var textNode = $(nodeContents.get(options.textNodeIdx));\r
124 \r
125     var succeedingNodes = [];\r
126     var passed = false;\r
127     nodeContents.each(function() {\r
128         var node = this;\r
129         if(passed)\r
130             succeedingNodes.push(node);\r
131         if(node === textNode.get(0))\r
132             passed = true;\r
133     });\r
134     \r
135     var prefix = $.trim(textNode.text().substr(0, options.offset));\r
136     var suffix = $.trim(textNode.text().substr(options.offset));\r
137     \r
138     textNode.before(prefix);\r
139     textNode.remove();\r
140     \r
141     var newNode = canvasNode.create({tag: nodeToSplit.attr('wlxml-tag'), klass: nodeToSplit.attr('wlxml-class')});\r
142     newNode.dom.append(suffix);\r
143     succeedingNodes.forEach(function(node) {\r
144         newNode.dom.append(node)\r
145     });\r
146     nodeToSplit.after(newNode.dom);\r
147     return newNode;\r
148 };\r
149 \r
150 Canvas.prototype.nodeRemove = function(options) {\r
151     var toRemove = $(this.content.find('#' + options.node.getId()).get(0));\r
152     toRemove.remove();\r
153 };\r
154 \r
155 Canvas.prototype.listCreate = function(options) {\r
156     var element1 = $(this.content.find('#' + options.start.getId()).get(0));\r
157     var element2 = $(this.content.find('#' + options.end.getId()).get(0));\r
158     if(!element1.parent().get(0) === element2.parent().get(0))\r
159         return false;\r
160         \r
161     var parent = element1.parent();\r
162     \r
163     if(parent.contents().index(element1) > parent.contents().index(element2)) {\r
164         var tmp = element1;\r
165         element1 = element2;\r
166         element2 = tmp;\r
167     }\r
168     \r
169     var nodesToWrap = [];\r
170     \r
171     var place = 'before';\r
172     var canvas = this;\r
173     parent.contents().each(function() {\r
174         var node = this;\r
175         if(node === element1.get(0))\r
176             place = 'inside';\r
177         if(place === 'inside') {\r
178             var $node;\r
179             if(node.nodeType === 3) {\r
180                 $node = canvasNode.create({tag: 'div', content: $.trim(node.data)}).dom; //canvas._createNode('div').text(node.data);\r
181                 $(node).remove();\r
182             }\r
183             else {\r
184                 $node = $(node);\r
185             }\r
186             $node.attr('wlxml-class', 'item');\r
187             nodesToWrap.push($node);\r
188         }\r
189         if(node === element2.get(0))\r
190             return false;\r
191     });\r
192     \r
193     var list = canvasNode.create({tag: 'div', klass: 'list-items' + (options.type === 'enum' ? '-enum' : '')}).dom; //this._createNode('div', 'list-items');\r
194     \r
195     var parentNode = options.start.parent();\r
196     \r
197     var toret;\r
198     if(parentNode && parentNode.isOfClass('list-items')) {\r
199         list.wrap('<div wlxml-tag="div" wlxml-class="item" class="canvas-silent-item">');\r
200         toret = list.parent();\r
201     } else {\r
202         toret = list;\r
203     }\r
204         \r
205     \r
206     element1.before(toret);\r
207     \r
208     nodesToWrap.forEach(function(node) {\r
209         node.remove();\r
210         list.append(node);\r
211     });\r
212 };\r
213 \r
214 Canvas.prototype.listRemove = function(options) {\r
215     var pointerElement = $(this.content.find('#' + options.pointer.getId()));\r
216     var listElement = options.pointer.getClass() === 'list-items' ? pointerElement : \r
217         pointerElement.parents('[wlxml-class|="list-items"][wlxml-tag]');\r
218     \r
219     var nested = false;\r
220     if(listElement.length > 1) {\r
221         listElement = $(listElement[0]);\r
222         nested = true;\r
223     }\r
224     \r
225     if(nested) {\r
226         listElement.unwrap();\r
227     } else {\r
228         listElement.find('[wlxml-class=item]').each(function() {\r
229             $(this).removeAttr('wlxml-class');\r
230         });\r
231     }\r
232     listElement.children().unwrap();\r
233 };\r
234 \r
235 Canvas.prototype.getPrecedingNode = function(options) {\r
236     var element = $(this.content.find('#' + options.node.getId()).get(0));\r
237     var prev = element.prev()\r
238     if(prev.length === 0)\r
239         prev = element.parent();\r
240     return canvasNode.create(prev);\r
241 };\r
242 \r
243 Canvas.prototype.nodeInsideList = function(options) {\r
244     if(options.node) {\r
245         if(options.node.isOfClass('list-items') || options.node.isOfClass('item'))\r
246             return true;\r
247         var pointerElement = $(this.content.find('#' + options.node.getId()));\r
248         return pointerElement.parents('[wlxml-class=list-items], [wlxml-class=item]').length > 0;\r
249     }\r
250     return false;\r
251 };\r
252 \r
253 \r
254 return {\r
255     create: function(desc) { return new Canvas(desc); }\r
256 };\r
257 \r
258 });