editor: tweak link ui, handle very long urls better
[fnpeditor.git] / src / editor / modules / nodeFamilyTree / nodeFamilyTree.js
1 define([
2 'libs/jquery',
3 'libs/underscore',
4 'utils/wlxml',
5 'libs/text!./template.html'
6 ], function($, _, wlxmlUtils, templateSrc) {
7
8 'use strict';
9
10 return function(sandbox) {
11     
12     var template = _.template(templateSrc),
13         listens = false,
14         items = [];
15
16     var getItemId = function(item) {
17         var idx = -1;
18         var found = _.find(items, function(i) {
19             idx += 1;
20             return item.sameNode(i);
21         });
22         if(found) {
23             return idx;
24         }
25         return -1;
26     };
27     
28     var startListening = function(document) {
29         listens = true;
30         document.on('change', function(event) {
31             if(event.type === 'nodeTextChange' && event.meta.node.parent().sameNode(view.currentNodeElement)) {
32                 view.setElement(view.currentNodeElement);
33             }
34         }, this);
35     };
36
37     var view = {
38         dom: $('<div>' + template({contents: null, parent: null}) + '</div>'),
39         setup: function() {
40             this.dom.on('click', 'a', function(e) {
41                 var target = $(e.target);
42                 sandbox.publish('nodeClicked', target.data('element'));
43             });
44             
45             this.dom.on('mouseenter', 'a', function(e) {
46                 var target = $(e.target);
47                 sandbox.publish('nodeEntered', target.data('element'));
48             });
49             this.dom.on('mouseleave', 'a', function(e) {
50                 var target = $(e.target);
51                 sandbox.publish('nodeLeft', target.data('element'));
52             });
53         },
54         setElement: function(element) {
55             var contents = [],
56                 parent, nodeElementParent;
57
58             if(element) {
59                 element = element || this.currentNodeElement;
60                 var textElement = element.getText ? element : null,
61                     nodeElement = element.getText ? element.parent() : element, // TODO: better type detection
62                     items;
63                 
64                 this.currentNodeElement = nodeElement;
65                 items = [];
66                 nodeElementParent = nodeElement.parent();
67
68                 if(nodeElementParent) {
69                     items.push(nodeElementParent);
70                     parent = {
71                         id: items.length - 1,
72                         repr: wlxmlUtils.getTagLabel(nodeElementParent.getTagName()) + (nodeElementParent.getClass() ? ' / ' + wlxmlUtils.getClassLabel(nodeElementParent.getClass()) : '')
73                     };
74                     
75                 }
76             
77                 var nodeContents = nodeElement.contents();
78                 nodeContents.forEach(function(child) {
79                     if(child.getText) {
80                         var text = child.getText();
81                         if(!text) {
82                             text = '<pusty tekst>';
83                         }
84                         else {
85                             if(text.length > 13) {
86                                 text = text.substr(0,13) + '...';
87                             }
88                             text = '"' + text + '"';
89                         }
90                         contents.push({
91                             id: items.length,
92                             repr: _.escape(text), bold: child.sameNode(textElement)
93                         });
94                     } else {
95                         contents.push({
96                             id: items.length,
97                             repr: wlxmlUtils.getTagLabel(child.getTagName()) + (child.getClass() ? ' / ' + wlxmlUtils.getClassLabel(child.getClass()) : '')
98                         });
99                     }
100                     items.push(child);
101                 });
102             }
103             this.dom.empty();
104             this.dom.append($(template({parent: parent, contents: contents})));
105
106             if(parent) {
107                 this.dom.find('.rng-module-nodeFamilyTree-parent').data('element', nodeElementParent);
108             }
109             this.dom.find('li a').each(function(idx, a) {
110                 $(a).data('element', nodeContents[idx]);
111             });
112         },
113         highlightNode: function(canvasNode) {
114             var id = getItemId(canvasNode);
115             this.dom.find('a[rng-module-nodeFamilyTree-item-id="'+id+'"]').addClass('rng-common-hoveredNode');
116         },
117         dimNode: function(canvasNode) {
118             var id = getItemId(canvasNode);
119             this.dom.find('a[rng-module-nodeFamilyTree-item-id="'+id+'"]').removeClass('rng-common-hoveredNode');
120         }
121     };
122     
123     view.setup();
124     
125     return {
126         start: function() {
127             sandbox.publish('ready');
128         },
129         setElement: function(element) {
130             if(!listens && element) {
131                 startListening(element.document);
132             }
133             if(!element || !(element.sameNode(view.currentNodeElement))) {
134                 view.setElement(element);
135             }
136         },
137         getView: function() {
138             return view.dom;
139         },
140         highlightElement: function(canvasNode) {
141             view.highlightNode(canvasNode);
142         },
143         dimElement: function(canvasNode) {
144             view.dimNode(canvasNode);
145         }
146     };
147 };
148
149 });