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 getVerticallyFirstTextElement: function() {
52 this.children().some(function(child) {
53 if(child instanceof DocumentTextElement) {
57 toret = child.getVerticallyFirstTextElement();
66 getPreviousTextElement: function(includeInvisible) {
67 return this.getNearestTextElement('above', includeInvisible);
70 getNextTextElement: function(includeInvisible) {
71 return this.getNearestTextElement('below', includeInvisible);
74 getNearestTextElement: function(direction, includeInvisible) {
75 includeInvisible = includeInvisible !== undefined ? includeInvisible : false;
76 var selector = '[document-text-element]' + (includeInvisible ? '' : ':visible');
77 return this.canvas.getDocumentElement(utils.nearestInDocumentOrder(selector, direction, this.dom()[0]));
80 exec: function(method) {
81 if(this.manager && this.manager[method]) {
82 return this.manager[method].apply(this.manager, Array.prototype.slice.call(arguments, 1));
88 // DocumentNodeElement represents an element node from WLXML document rendered inside Canvas
89 var DocumentNodeElement = function(wlxmlNode, canvas) {
90 DocumentElement.call(this, wlxmlNode, canvas);
91 wlxmlNode.setData('canvasElement', this);
95 var manipulate = function(e, params, action) {
97 if(params instanceof DocumentElement) {
100 element = e.canvas.createElement(params);
102 var target = (action === 'append' || action === 'prepend') ? e._container() : e.dom();
103 target[action](element.dom());
107 DocumentNodeElement.prototype = Object.create(DocumentElement.prototype);
110 $.extend(DocumentNodeElement.prototype, {
111 createDOM: function() {
113 .attr('document-node-element', ''),
114 widgetsContainer = $('<div>')
115 .addClass('canvas-widgets')
116 .attr('contenteditable', false),
117 container = $('<div>')
118 .attr('document-element-content', '');
120 dom.append(widgetsContainer, container);
121 // Make sure widgets aren't navigable with arrow keys
122 widgetsContainer.find('*').add(widgetsContainer).attr('tabindex', -1);
123 this.$element = dom; //@!!!
125 this.setWlxmlTag(this.wlxmlNode.getTagName());
126 this.setWlxmlClass(this.wlxmlNode.getClass());
128 this.wlxmlNode.contents().forEach(function(node) {
129 container.append(this.canvas.createElement(node).dom());
133 _container: function() {
134 return this.dom().children('[document-element-content]');
141 append: function(params) {
142 return manipulate(this, params, 'append');
144 prepend: function(params) {
145 return manipulate(this, params, 'prepend');
147 before: function(params) {
148 return manipulate(this, params, 'before');
151 after: function(params) {
152 return manipulate(this, params, 'after');
154 children: function() {
156 if(this instanceof DocumentTextElement) {
161 var elementContent = this._container().contents();
163 elementContent.each(function() {
164 var childElement = element.canvas.getDocumentElement(this);
165 if(childElement === undefined) {
168 toret.push(childElement);
172 childIndex: function(child) {
173 var children = this.children(),
175 children.forEach(function(c, idx) {
176 if(c.sameNode(child)) {
183 getWlxmlTag: function() {
184 return this._container().attr('wlxml-tag');
186 setWlxmlTag: function(tag) {
187 this._container().attr('wlxml-tag', tag);
189 getWlxmlClass: function() {
190 var klass = this._container().attr('wlxml-class');
192 return klass.replace(/-/g, '.');
196 setWlxmlClass: function(klass) {
197 if(klass === this.getWlxmlClass()) {
201 this._container().attr('wlxml-class', klass.replace(/\./g, '-'));
204 this._container().removeAttr('wlxml-class');
206 this.manager = wlxmlManagers.getFor(this);
207 this.manager.setup();
209 toggleLabel: function(toggle) {
210 var displayCss = toggle ? 'inline-block' : 'none';
211 var label = this.dom().children('.canvas-widgets').find('.canvas-widget-label');
212 label.css('display', displayCss);
213 this.toggleHighlight(toggle);
216 toggleHighlight: function(toggle) {
217 this._container().toggleClass('highlighted-element', toggle);
220 toggle: function(toggle) {
222 this.manager.toggle(toggle);
228 // DocumentNodeElement represents a text node from WLXML document rendered inside Canvas
229 var DocumentTextElement = function(wlxmlTextNode, canvas) {
230 DocumentElement.call(this, wlxmlTextNode, canvas);
233 $.extend(DocumentTextElement, {
234 isContentContainer: function(htmlElement) {
235 return htmlElement.nodeType === Node.TEXT_NODE && $(htmlElement).parent().is('[document-text-element]');
239 DocumentTextElement.prototype = Object.create(DocumentElement.prototype);
241 $.extend(DocumentTextElement.prototype, {
242 createDOM: function() {
244 .attr('document-text-element', '')
245 .text(this.wlxmlNode.getText() || utils.unicode.ZWS);
252 setText: function(text) {
253 this.dom().contents()[0].data = text;
255 getText: function(options) {
256 options = _.extend({raw: false}, options || {});
257 var toret = this.dom().text();
259 toret = toret.replace(utils.unicode.ZWS, '');
263 isEmpty: function() {
264 // Having at least Zero Width Space is guaranteed be Content Observer
265 return this.dom().contents()[0].data === utils.unicode.ZWS;
267 after: function(params) {
268 if(params instanceof DocumentTextElement || params.text) {
272 if(params instanceof DocumentNodeElement) {
275 element = this.canvas.createElement(params);
277 this.dom().wrap('<div>');
278 this.dom().parent().after(element.dom());
282 before: function(params) {
283 if(params instanceof DocumentTextElement || params.text) {
287 if(params instanceof DocumentNodeElement) {
290 element = this.canvas.createElement(params);
292 this.dom().wrap('<div>');
293 this.dom().parent().before(element.dom());
298 toggleHighlight: function() {
299 // do nothing for now
304 DocumentElement: DocumentElement,
305 DocumentNodeElement: DocumentNodeElement,
306 DocumentTextElement: DocumentTextElement