integration wip: highlight/dim/select node via breadcrumbs
[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();
33             }
34         }, this);
35     }
36
37     var view = {
38         dom: $('<div>' + template({contents: null, parent: null}) + '</div>'),
39         setup: function() {
40             var view = this;
41             this.dom.on('click', 'a', function(e) {
42                 var target = $(e.target);
43                 sandbox.publish('nodeClicked', target.data('element'));
44             });
45             
46             this.dom.on('mouseenter', 'a', function(e) {
47                 var target = $(e.target);
48                 sandbox.publish('nodeEntered', target.data('element'));
49             });
50             this.dom.on('mouseleave', 'a', function(e) {
51                 var target = $(e.target);
52                 sandbox.publish('nodeLeft', target.data('element'));
53             });
54         },
55         setElement: function(element) {
56             element = element || this.currentNodeElement;
57             console.log('familyTree sets node');
58             var textElement = element.getText ? element : null,
59                 nodeElement = element.getText ? element.parent() : element, // TODO: better type detection
60                 nodeElementParent = nodeElement.parent(),
61                 parent;
62             
63             this.currentNodeElement = nodeElement;
64             items = [];
65
66             if(nodeElementParent) {
67                 items.push(nodeElementParent);
68                 parent = {
69                     id: items.length - 1,
70                     repr: wlxmlUtils.wlxmlTagNames[nodeElementParent.getTagName()] + (nodeElementParent.getClass() ? ' / ' + wlxmlUtils.wlxmlClassNames[nodeElementParent.getClass()] : '')
71                 };
72                 
73             }
74         
75             var nodeContents = nodeElement.contents(),
76                 contents = [];
77             nodeContents.forEach(function(child) {
78                 if(child.getText) {
79                     var text = child.getText();
80                     if(!text)
81                         text = '<pusty tekst>';
82                     else {
83                         if(text.length > 13) {
84                             text = text.substr(0,13) + '...';
85                         }
86                         text = '"' + text + '"';
87                     }
88                     contents.push({
89                         id: items.length,
90                         repr: _.escape(text), bold: child.sameNode(textElement)
91                     });
92                 } else {
93                     contents.push({
94                         id: items.length,
95                         repr: wlxmlUtils.wlxmlTagNames[child.getTagName()] + (child.getClass() ? ' / ' + wlxmlUtils.wlxmlClassNames[child.getClass()] : '')
96                     });
97                 }
98                 items.push(child);
99             });
100             this.dom.empty();
101             this.dom.append($(template({parent: parent, contents: contents})));
102
103             if(parent) {
104                 this.dom.find('.rng-module-nodeFamilyTree-parent').data('element', nodeElementParent)
105             }
106             this.dom.find('li a').each(function(idx, a) {
107                 $(a).data('element', nodeContents[idx]);
108             });
109         },
110         highlightNode: function(canvasNode) {
111             var id = getItemId(canvasNode);
112             this.dom.find('a[rng-module-nodeFamilyTree-item-id="'+id+'"]').addClass('rng-common-hoveredNode');
113         },
114         dimNode: function(canvasNode) {
115             var id = getItemId(canvasNode);
116             this.dom.find('a[rng-module-nodeFamilyTree-item-id="'+id+'"]').removeClass('rng-common-hoveredNode');
117         }
118     };
119     
120     view.setup();
121     
122     return {
123         start: function() {
124             sandbox.publish('ready');
125         },
126         setElement: function(element) {
127             if(!listens) {
128                 startListening(element.document);
129             }
130             if(!(element.sameNode(view.currentNodeElement)))
131                 view.setElement(element);
132         },
133         getView: function() {
134             return view.dom;
135         },
136         highlightElement: function(canvasNode) {
137             view.highlightNode(canvasNode);
138         },
139         dimElement: function(canvasNode) {
140             view.dimNode(canvasNode);
141         }
142     };
143 };
144
145 });