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