WIP: Refactoring canvas api - canvas, canvasNode + tests
[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     if(html) {\r
15         this.content.html(html);\r
16     }\r
17 };\r
18 \r
19 Canvas.prototype.getContent = function() {\r
20     return this.content.contents();\r
21 };\r
22 \r
23 Canvas.prototype.findNodes = function(desc) {\r
24     var selector = '';\r
25     if(typeof desc === 'string') {\r
26         selector = desc;\r
27     }\r
28     else {\r
29         if(desc.klass)\r
30             selector += '[wlxml-class=' + desc.klass + ']';\r
31         if(desc.tag)\r
32             selector += '[wlxml-tag=' + desc.tag + ']';\r
33     }\r
34     var toret = [];\r
35     this.content.find(selector).each(function() {\r
36         toret.push(canvasNode.create($(this)));\r
37     });\r
38     return toret;\r
39 };\r
40 \r
41 Canvas.prototype.nodeAppend = function(options) {\r
42     var element; // = $(this.content.find('#' + options.context.id).get(0));\r
43     if(options.to === 'root') {\r
44         element = this.content;\r
45     } else {\r
46         element = $(this.content.find('#' + options.to.getId()).get(0));\r
47     }\r
48     element.append(options.node.dom);\r
49 };\r
50 \r
51 Canvas.prototype.nodeInsertAfter = function(options) {\r
52     var element = $(this.content.find('#' + options.after.getId()).get(0));\r
53     element.after(options.node.dom);\r
54 };\r
55 \r
56 Canvas.prototype.nodeWrap = function(options) {\r
57     var element = $(this.content.find('#' + options.inside.getId()).get(0));\r
58 \r
59     var elementContents = element.contents();\r
60     if(elementContents.length !== 1 || elementContents.get(0).nodeType != 3)\r
61         return false;\r
62     var textElement = elementContents.get(0);\r
63 \r
64     var prefix = textElement.data.substr(0, options.offsetStart);\r
65     var suffix = textElement.data.substr(options.offsetEnd);\r
66     var core = textElement.data.substr(options.offsetStart, options.offsetEnd - options.offsetStart);\r
67     options._with.setContent(core);\r
68 \r
69     $(textElement).replaceWith(options._with.dom);\r
70     options._with.dom.before(prefix);\r
71     options._with.dom.after(suffix);\r
72 };\r
73 \r
74 Canvas.prototype.nodeSplit = function(options) {\r
75     options = _.extend({textNodeIdx: 0}, options);\r
76     \r
77     var nodeToSplit = $(this.content.find('#' + options.node.getId()).get(0));\r
78     \r
79     var nodeContents = nodeToSplit.contents();\r
80     if(nodeContents.length === 0 || \r
81        nodeContents.length - 1 < options.textNodeIdx || \r
82        nodeContents.get(options.textNodeIdx).nodeType != 3)\r
83         return false;\r
84     \r
85     var textNode = $(nodeContents.get(options.textNodeIdx));\r
86 \r
87     var succeedingNodes = [];\r
88     var passed = false;\r
89     nodeContents.each(function() {\r
90         var node = this;\r
91         if(passed)\r
92             succeedingNodes.push(node);\r
93         if(node.isSameNode(textNode.get(0)))\r
94             passed = true;\r
95     });\r
96     \r
97     var prefix = $.trim(textNode.text().substr(0, options.offset));\r
98     var suffix = $.trim(textNode.text().substr(options.offset));\r
99     \r
100     textNode.before(prefix);\r
101     textNode.remove();\r
102     \r
103     var newNode = canvasNode.create({tag: nodeToSplit.attr('wlxml-tag'), klass: nodeToSplit.attr('wlxml-class')});\r
104     newNode.dom.append(suffix);\r
105     succeedingNodes.forEach(function(node) {\r
106         newNode.dom.append(node)\r
107     });\r
108     nodeToSplit.after(newNode.dom);\r
109     return newNode;\r
110 };\r
111 \r
112 Canvas.prototype.nodeRemove = function(options) {\r
113     var toRemove = $(this.content.find('#' + options.node.getId()).get(0));\r
114     toRemove.remove();\r
115 };\r
116 \r
117 Canvas.prototype.listCreate = function(options) {\r
118     var element1 = $(this.content.find('#' + options.start.getId()).get(0));\r
119     var element2 = $(this.content.find('#' + options.end.getId()).get(0));\r
120     if(!element1.parent().get(0).isSameNode(element2.parent().get(0)))\r
121         return false;\r
122         \r
123     var parent = element1.parent();\r
124     \r
125     if(parent.contents().index(element1) > parent.contents().index(element2)) {\r
126         var tmp = element1;\r
127         element1 = element2;\r
128         element2 = tmp;\r
129     }\r
130     \r
131     var nodesToWrap = [];\r
132     \r
133     var place = 'before';\r
134     var canvas = this;\r
135     parent.contents().each(function() {\r
136         var node = this;\r
137         if(node.isSameNode(element1.get(0)))\r
138             place = 'inside';\r
139         if(place === 'inside') {\r
140             var $node;\r
141             if(node.nodeType === 3) {\r
142                 $node = canvasNode.create({tag: 'div', content: $.trim(node.data)}).dom; //canvas._createNode('div').text(node.data);\r
143                 $(node).remove();\r
144             }\r
145             else {\r
146                 $node = $(node);\r
147             }\r
148             $node.attr('wlxml-class', 'item');\r
149             nodesToWrap.push($node);\r
150         }\r
151         if(node.isSameNode(element2.get(0)))\r
152             return false;\r
153     });\r
154     \r
155     var list = canvasNode.create({tag: 'div', klass: 'list-items'}).dom; //this._createNode('div', 'list-items');\r
156     element1.before(list);\r
157     \r
158     nodesToWrap.forEach(function(node) {\r
159         node.remove();\r
160         list.append(node);\r
161     });\r
162 };\r
163 \r
164 Canvas.prototype.listRemove = function(options) {\r
165     var pointerElement = $(this.content.find('#' + options.pointer.getId()));\r
166     var listElement = options.pointer.getClass() === 'list-items' ? pointerElement : \r
167         pointerElement.parent('[wlxml-class="list-items"][wlxml-tag]');\r
168     \r
169     listElement.find('[wlxml-class=item]').each(function() {\r
170         $(this).removeAttr('wlxml-class');\r
171     });\r
172     listElement.children().unwrap();\r
173 };\r
174 \r
175 Canvas.prototype.getPrecedingNode = function(options) {\r
176     var element = $(this.content.find('#' + options.node.getId()).get(0));\r
177     var prev = element.prev()\r
178     if(prev.length === 0)\r
179         prev = element.parent();\r
180     return canvasNode.create(prev);\r
181 };\r
182 \r
183 Canvas.prototype.nodeInsideList = function(options) {\r
184     if(options.pointer) {\r
185         if(options.pointer.getClass() === 'list-items' || options.pointer.getClass() === 'item')\r
186             return true;\r
187         var pointerElement = $(this.content.find('#' + options.pointer.getId()));\r
188         return pointerElement.parents('list-items, item').length > 0;\r
189     }\r
190     return false;\r
191 };\r
192 \r
193 \r
194 return {\r
195     create: function(desc) { return new Canvas(desc); }\r
196 };\r
197 \r
198 });