Splitting text
[fnpeditor.git] / modules / documentCanvas / canvas / canvas.js
1 define([
2 'libs/jquery-1.9.1.min',
3 'libs/underscore-min',
4 'modules/documentCanvas/canvas/documentElement'
5 ], function($, _, documentElement) {
6     
7 'use strict';
8
9 var Canvas = function(xml) {
10     xml = $.parseXML(xml);
11     this.d = xml !== null ? $(xml.childNodes[0]) : null;
12     if(this.d) {
13         var wrapper = $('<div>');
14         wrapper.append(this.d);
15         wrapper.find(':not(iframe)').addBack().contents()
16             .filter(function() {return this.nodeType === Node.TEXT_NODE})
17             .each(function() {
18
19                 var el = $(this);
20                 
21                 // TODO: use DocumentElement API
22                 var spanParent = el.parent().prop('tagName') === 'span',
23                     spanBefore = el.prev().length > 0  && $(el.prev()[0]).prop('tagName') === 'span',
24                     spanAfter = el.next().length > 0 && $(el.next()[0]).prop('tagName') === 'span';
25                     
26                 if(spanParent || spanBefore || spanAfter) {
27                     var startSpace = /\s/g.test(this.data.substr(0,1));
28                     var endSpace = /\s/g.test(this.data.substr(-1)) && this.data.length > 1;
29                     var trimmed = $.trim(this.data);
30                     this.data = (startSpace && (spanParent || spanBefore) ? ' ' : '')
31                                 + trimmed
32                                 + (endSpace && (spanParent || spanAfter) ? ' ' : '');
33
34                 } else {
35                     this.data = $.trim(this.data);
36                 }
37             });
38         this.d.unwrap();
39     };
40 };
41
42 $.extend(Canvas.prototype, {
43
44     doc: function() {
45         if(this.d === null)
46             return null;
47         return documentElement.wrap(this.d.get(0), this); //{wlxmlTag: this.d.prop('tagName')};
48     },
49
50     wrapText: function(params) {
51         params = _.extend({textNodeIdx: 0}, params);
52         if(typeof params.textNodeIdx === 'number')
53             params.textNodeIdx = [params.textNodeIdx];
54         
55         var childrenInside = params.inside.children(),
56             idx1 = Math.min.apply(Math, params.textNodeIdx),
57             idx2 = Math.max.apply(Math, params.textNodeIdx),
58             textNode1 = childrenInside[idx1],
59             textNode2 = childrenInside[idx2],
60             sameNode = textNode1.sameNode(textNode2),
61             prefixOutside = textNode1.getText().substr(0, params.offsetStart),
62             prefixInside = textNode1.getText().substr(params.offsetStart),
63             suffixInside = textNode2.getText().substr(0, params.offsetEnd),
64             suffixOutside = textNode2.getText().substr(params.offsetEnd)
65         ;
66         
67         var wrapperElement = documentElement.DocumentNodeElement.create({tag: params._with.tag, klass: params._with.klass});
68         textNode1.after(wrapperElement);
69         textNode1.detach();
70         
71         if(prefixOutside.length > 0)
72             wrapperElement.before({text:prefixOutside});
73         if(sameNode) {
74             var core = textNode1.getText().substr(params.offsetStart, params.offsetEnd - params.offsetStart);
75             wrapperElement.append({text: core});
76         } else {
77             textNode2.detach();
78             if(prefixInside.length > 0)
79                 wrapperElement.append({text: prefixInside});
80             for(var i = idx1 + 1; i < idx2; i++) {
81                 wrapperElement.append(childrenInside[i]);
82             }
83             if(suffixInside.length > 0)
84                 wrapperElement.append({text: suffixInside});
85         }
86         if(suffixOutside.length > 0)
87             wrapperElement.after({text: suffixOutside});
88         return wrapperElement;
89     }
90
91 });
92
93 return {
94     fromXML: function(xml) {
95         return new Canvas(xml);
96     }
97 };
98
99 });