4 'modules/documentCanvas/canvas/utils',
5 'modules/documentCanvas/canvas/wlxmlManagers'
6 ], function($, _, utils, wlxmlManagers) {
9 /* global Node:false, document:false */
12 // DocumentElement represents a text or an element node from WLXML document rendered inside Canvas
13 var DocumentElement = function(wlxmlNode, canvas) {
14 this.wlxmlNode = wlxmlNode;
17 this.$element = this.createDOM();
18 this.$element.data('canvas-element', this);
21 $.extend(DocumentElement.prototype, {
23 return $.contains(document.documentElement, this.dom()[0]);
29 var parents = this.$element.parents('[document-node-element]');
31 return this.canvas.getDocumentElement(parents[0]);
38 parent = this.parent();
41 parent = parent.parent();
46 sameNode: function(other) {
47 return other && (typeof other === typeof this) && other.dom()[0] === this.dom()[0];
50 markAsCurrent: function() {
51 this.canvas.markAsCurrent(this);
54 getVerticallyFirstTextElement: function() {
56 this.children().some(function(child) {
57 if(child instanceof DocumentTextElement) {
61 toret = child.getVerticallyFirstTextElement();
70 getPreviousTextElement: function(includeInvisible) {
71 return this.getNearestTextElement('above', includeInvisible);
74 getNextTextElement: function(includeInvisible) {
75 return this.getNearestTextElement('below', includeInvisible);
78 getNearestTextElement: function(direction, includeInvisible) {
79 includeInvisible = includeInvisible !== undefined ? includeInvisible : false;
80 var selector = '[document-text-element]' + (includeInvisible ? '' : ':visible');
81 return this.canvas.getDocumentElement(utils.nearestInDocumentOrder(selector, direction, this.dom()[0]));
84 exec: function(method) {
85 if(this.manager && this.manager[method]) {
86 return this.manager[method].apply(this.manager, Array.prototype.slice.call(arguments, 1));
92 // DocumentNodeElement represents an element node from WLXML document rendered inside Canvas
93 var DocumentNodeElement = function(wlxmlNode, canvas) {
94 DocumentElement.call(this, wlxmlNode, canvas);
95 wlxmlNode.setData('canvasElement', this);
99 var manipulate = function(e, params, action) {
101 if(params instanceof DocumentElement) {
104 element = e.canvas.createElement(params);
106 var target = (action === 'append' || action === 'prepend') ? e._container() : e.dom();
107 target[action](element.dom());
111 DocumentNodeElement.prototype = Object.create(DocumentElement.prototype);
114 $.extend(DocumentNodeElement.prototype, {
115 createDOM: function() {
117 .attr('document-node-element', ''),
118 widgetsContainer = $('<div>')
119 .addClass('canvas-widgets')
120 .attr('contenteditable', false),
121 container = $('<div>')
122 .attr('document-element-content', '');
124 dom.append(widgetsContainer, container);
125 // Make sure widgets aren't navigable with arrow keys
126 widgetsContainer.find('*').add(widgetsContainer).attr('tabindex', -1);
127 this.$element = dom; //@!!!
129 this.setWlxmlTag(this.wlxmlNode.getTagName());
130 this.setWlxmlClass(this.wlxmlNode.getClass());
132 this.wlxmlNode.contents().forEach(function(node) {
133 container.append(this.canvas.createElement(node).dom());
137 _container: function() {
138 return this.dom().children('[document-element-content]');
145 append: function(params) {
146 return manipulate(this, params, 'append');
148 prepend: function(params) {
149 return manipulate(this, params, 'prepend');
151 before: function(params) {
152 return manipulate(this, params, 'before');
155 after: function(params) {
156 return manipulate(this, params, 'after');
158 children: function() {
160 if(this instanceof DocumentTextElement) {
165 var elementContent = this._container().contents();
167 elementContent.each(function() {
168 var childElement = element.canvas.getDocumentElement(this);
169 if(childElement === undefined) {
172 toret.push(childElement);
176 childIndex: function(child) {
177 var children = this.children(),
179 children.forEach(function(c, idx) {
180 if(c.sameNode(child)) {
187 getWlxmlTag: function() {
188 return this._container().attr('wlxml-tag');
190 setWlxmlTag: function(tag) {
191 this._container().attr('wlxml-tag', tag);
193 getWlxmlClass: function() {
194 var klass = this._container().attr('wlxml-class');
196 return klass.replace(/-/g, '.');
200 setWlxmlClass: function(klass) {
201 if(klass === this.getWlxmlClass()) {
205 this._container().attr('wlxml-class', klass.replace(/\./g, '-'));
208 this._container().removeAttr('wlxml-class');
210 this.manager = wlxmlManagers.getFor(this);
211 this.manager.setup();
213 toggleLabel: function(toggle) {
214 var displayCss = toggle ? 'inline-block' : 'none';
215 var label = this.dom().children('.canvas-widgets').find('.canvas-widget-label');
216 label.css('display', displayCss);
217 this.toggleHighlight(toggle);
220 toggleHighlight: function(toggle) {
221 this._container().toggleClass('highlighted-element', toggle);
224 toggle: function(toggle) {
226 this.manager.toggle(toggle);
232 // DocumentNodeElement represents a text node from WLXML document rendered inside Canvas
233 var DocumentTextElement = function(wlxmlTextNode, canvas) {
234 DocumentElement.call(this, wlxmlTextNode, canvas);
237 $.extend(DocumentTextElement, {
238 isContentContainer: function(htmlElement) {
239 return htmlElement.nodeType === Node.TEXT_NODE && $(htmlElement).parent().is('[document-text-element]');
243 DocumentTextElement.prototype = Object.create(DocumentElement.prototype);
245 $.extend(DocumentTextElement.prototype, {
246 createDOM: function() {
248 .attr('document-text-element', '')
249 .text(this.wlxmlNode.getText() || utils.unicode.ZWS);
256 setText: function(text) {
257 this.dom().contents()[0].data = text;
259 getText: function(options) {
260 options = _.extend({raw: false}, options || {});
261 var toret = this.dom().text();
263 toret = toret.replace(utils.unicode.ZWS, '');
267 isEmpty: function() {
268 // Having at least Zero Width Space is guaranteed be Content Observer
269 return this.dom().contents()[0].data === utils.unicode.ZWS;
271 after: function(params) {
272 if(params instanceof DocumentTextElement || params.text) {
276 if(params instanceof DocumentNodeElement) {
279 element = this.canvas.createElement(params);
281 this.dom().wrap('<div>');
282 this.dom().parent().after(element.dom());
286 before: function(params) {
287 if(params instanceof DocumentTextElement || params.text) {
291 if(params instanceof DocumentNodeElement) {
294 element = this.canvas.createElement(params);
296 this.dom().wrap('<div>');
297 this.dom().parent().before(element.dom());
302 toggleHighlight: function() {
303 // do nothing for now
308 DocumentElement: DocumentElement,
309 DocumentNodeElement: DocumentNodeElement,
310 DocumentTextElement: DocumentTextElement