editor: canvas containers
[fnpeditor.git] / src / editor / modules / documentCanvas / canvas / container.js
1 define(function(require) {
2     
3 'use strict';
4
5 var $ = require('libs/jquery'),
6     _ = require('libs/underscore'),
7     utils = require('./utils');
8
9
10 var Container = function(nodes, params, element) {
11     _.extend(this, params);
12     this.dom = this.dom || $('<div>');
13     this.dom.addClass('canvas-container');
14     this.element = element;
15
16     nodes.forEach(function(node) {
17         var el = this.element.canvas.createElement(node);
18         if(el.dom) {
19             this.dom.append(el.dom);
20         }
21     }.bind(this));
22 };
23
24 _.extend(Container.prototype, {
25     remove: function() {
26         this.element.removeContainer(this);
27     },
28
29     onNodeAdded: function(event) {
30         if(event.meta.node.isRoot()) {
31             this.element.canvas.reloadRoot();//
32             return;
33         }
34
35         var ptr = event.meta.node.prev(),
36             referenceElement, referenceAction, actionArg;
37             
38         while(ptr && !(referenceElement = utils.getElementForElementRootNode(ptr))) {
39             ptr = ptr.prev();
40         }
41
42         if(referenceElement) {
43             referenceAction = 'after';
44         } else {
45             referenceElement = this;
46             referenceAction = '_prepend';
47         }
48       
49         if(event.meta.move) {
50             /* Let's check if this node had its own canvas element and it's accessible. */
51             actionArg = utils.getElementForElementRootNode(event.meta.node);
52         }
53         if(!actionArg) {
54             actionArg = event.meta.node;
55         }
56
57         referenceElement[referenceAction](actionArg);
58     },
59     onNodeDetached: function(event) {
60         var container = this;
61         this.dom.contents().each(function() {
62             var childElement = container.element.canvas.getDocumentElement(this);
63             if(childElement && childElement.wlxmlNode.sameNode(event.meta.node)) {
64                 childElement.detach();
65                 return false;
66             }
67         });
68     },
69     getVerticallyFirstTextElement: function(params) {
70         var documentElement = require('./documentElement'),
71             toret;
72         
73         params = _.extend({
74             considerChildren: true
75         }, params);
76         
77         this.children().some(function(child) {
78             if(child instanceof documentElement.DocumentTextElement) {
79                 toret = child;
80                 return true; // break
81             } else if(params.considerChildren) {
82                 toret = child.getVerticallyFirstTextElement();
83                 if(toret) {
84                     return true; // break
85                 }
86             }
87         });
88         return toret;
89     },
90     getFirst: function(e1, e2) {
91         var idx1 = this._childIndex(e1),
92             idx2 = this._childIndex(e2);
93         if(e1 === null || e2 === null) {
94             return undefined;
95         }
96         return idx1 <= idx2 ? e1: e2;
97     },
98
99     _prepend: function(param) {
100         var documentElement = require('./documentElement'),
101             element;
102         if(param instanceof documentElement.DocumentElement) {
103             element = param;
104         } else {
105             element = this.element.canvas.createElement(param);//
106         }
107         if(element.dom) {
108             this.dom.prepend(element.dom);
109         }
110         return element;
111     },
112     _childIndex: function(child) {
113         var children = this.children(),
114             toret = null;
115         children.forEach(function(c, idx) {
116             if(c.sameNode(child)) {
117                 toret = idx;
118                 return false;
119             }
120         });
121         return toret;
122     },
123     containsBlock: function() {
124         var documentElement = require('./documentElement');
125         return this.children()
126             .filter(function(child) {
127                 return child instanceof documentElement.DocumentNodeElement;
128             })
129             .some(function(child) {
130                 if(child.isBlock()) {
131                     return true;
132                 } else {
133                     return child.containsBlock();
134                 }
135             });
136     },
137     children: function() {
138         var element = this.element.canvas,
139             toret = [];
140         this.dom.contents().each(function() {
141             var childElement = element.getDocumentElement(this);
142             if(childElement === undefined) {
143                 return true;
144             }
145
146             toret.push(childElement);
147         });
148         return toret;
149     },
150 });
151
152 return {
153     create: function(nodes, params, element) {
154         return new Container(nodes, params, element);
155     }
156 };
157
158 });