second batch: works, but failing tests - ie blocking span
[fnpeditor.git] / src / editor / modules / documentCanvas / canvas / genericElement.js
1 define(function(require) {
2     
3 'use strict';
4
5 var documentElement = require('./documentElement'),
6     utils = require('./utils'),
7     wlxmlUtils = require('utils/wlxml');
8
9 var labelWidget = function(tag, klass) {
10     return $('<span>')
11         .addClass('canvas-widget canvas-widget-label')
12         .text(wlxmlUtils.getTagLabel(tag) + (klass ? ' / ' + wlxmlUtils.getClassLabel(klass) : ''));
13 };
14 void(labelWidget); // for linters; labelWidget is unused on purpose for now
15
16
17 var generic = {
18     onNodeAttrChange: function(event) {
19         if(event.meta.attr === 'class') {
20             this.setWlxmlClass(event.meta.newVal); //
21         }
22     },
23     onNodeAdded: function(event) {
24         if(event.meta.node.isRoot()) {
25             this.canvas.reloadRoot();
26             return;
27         }
28
29         var nodeIndex = event.meta.node.getIndex(),
30             referenceElement, referenceAction, actionArg;
31
32         if(nodeIndex === 0) {
33             referenceElement = this;
34             referenceAction = 'prepend';
35         } else {
36             referenceElement = this.children()[nodeIndex-1];
37             referenceAction = 'after';
38         }
39
40         actionArg = (event.type === 'nodeMoved' && utils.findCanvasElement(event.meta.node, event.meta.parent)) || event.meta.node;
41         referenceElement[referenceAction](actionArg);
42     },
43     onNodeMoved: function(event) {
44         return this.onNodeAdded.call(this, event, true);
45     },
46     onNodeDetached: function(event) {
47         if(event.meta.node.sameNode(this)) {
48             this.detach();
49         } else {
50             this.children().some(function(child) {
51                 if(child.wlxmlNode.sameNode(event.meta.node)) {
52                     child.detach();
53                     return true;
54                 }
55             });
56         }
57     },
58     onNodeTextChange: function(event) {
59         var toSet = event.meta.node.getText();
60         this.children().some(function(child) {
61             if(child.wlxmlNode.sameNode(event.meta.node)) {
62                 if(toSet === '') {
63                     toSet = utils.unicode.ZWS;
64                 }
65                 if(toSet !== child.getText()) {
66                     child.setText(toSet);
67                 }
68                 return true;
69             }
70         });
71     },
72
73     prepend: function(param) {
74         var element;
75         if(param instanceof documentElement.DocumentElement) {
76             element = param;
77         } else {
78             element = this.canvas.createElement(param);
79         }
80         this._container().prepend(element.dom());
81         this.refreshPath();
82         return element;
83     },
84
85     children: function() {
86         var element = this,
87             toret = [];
88         this._container().contents().each(function() {
89             var childElement = element.canvas.getDocumentElement(this);
90             if(childElement === undefined) {
91                 return true;
92             }
93
94             toret.push(childElement);
95         });
96         return toret;
97     },
98
99     getFirst: function(e1, e2) {
100         var idx1 = this.childIndex(e1),
101             idx2 = this.childIndex(e2);
102         if(e1 === null || e2 === null) {
103             return undefined;
104         }
105         return idx1 <= idx2 ? e1: e2;
106     },
107
108     childIndex: function(child) {
109         var children = this.children(),
110             toret = null;
111         children.forEach(function(c, idx) {
112             if(c.sameNode(child)) {
113                 toret = idx;
114                 return false;
115             }
116         });
117         return toret;
118     },
119
120     getWlxmlClass: function() {
121         var klass = this._container().attr('wlxml-class');
122         if(klass) {
123             return klass.replace(/-/g, '.');
124         }
125         return undefined;
126     },
127     setWlxmlClass: function(klass) {
128         if(klass === this.getWlxmlClass()) {
129             return;
130         }
131         if(klass) {
132             this._container().attr('wlxml-class', klass.replace(/\./g, '-'));
133         }
134         else {
135             this._container().removeAttr('wlxml-class');
136         }
137         this.refreshPath();
138     },
139     init: function() {
140         this._container()
141             .attr('wlxml-tag', this.wlxmlNode.getTagName());
142         this.setWlxmlClass(this.wlxmlNode.getClass());
143         this.wlxmlNode.contents().forEach(function(node) {
144             this._container().append(this.canvas.createElement(node).dom());
145         }.bind(this));
146     },
147     containsBlock: function() {
148         return this.children()
149             .filter(function(child) {
150                 return child instanceof documentElement.DocumentNodeElement;
151             })
152             .some(function(child) {
153                 if(child.isBlock()) {
154                     return true;
155                 } else {
156                     return child.containsBlock();
157                 }
158             });
159     },
160     getVerticallyFirstTextElement: function() {
161         var toret;
162         this.children().some(function(child) {
163             if(child instanceof documentElement.DocumentTextElement) {
164                 toret = child;
165                 return true; // break
166             } else {
167                 toret = child.getVerticallyFirstTextElement();
168                 if(toret) {
169                     return true; // break
170                 }
171             }
172         });
173         return toret;
174     },
175 };
176
177
178 return generic;
179
180
181
182 });