Faster transitions
[p5sagit/Devel-Size.git] / static / public / tm.js
1 var labelType, useGradients, nativeTextSupport, animate;
2
3 (function() {
4   var ua = navigator.userAgent,
5       iStuff = ua.match(/iPhone/i) || ua.match(/iPad/i),
6       typeOfCanvas = typeof HTMLCanvasElement,
7       nativeCanvasSupport = (typeOfCanvas == 'object' || typeOfCanvas == 'function'),
8       textSupport = nativeCanvasSupport 
9         && (typeof document.createElement('canvas').getContext('2d').fillText == 'function');
10   //I'm setting this based on the fact that ExCanvas provides text support for IE
11   //and that as of today iPhone/iPad current text support is lame
12   labelType = (!nativeCanvasSupport || (textSupport && !iStuff))? 'Native' : 'HTML';
13   nativeTextSupport = labelType == 'Native';
14   useGradients = nativeCanvasSupport;
15   animate = !(iStuff || !nativeCanvasSupport);
16   console.log({ "labelType":labelType, "useGradients":useGradients, "nativeTextSupport":nativeTextSupport });
17 })();
18
19 var Log = {
20   elem: false,
21   write: function(text){
22     if (!this.elem) 
23       this.elem = document.getElementById('log');
24     this.elem.innerHTML = text;
25     this.elem.style.left = (500 - this.elem.offsetWidth / 2) + 'px';
26   }
27 };
28
29 // http://stackoverflow.com/questions/5199901/how-to-sort-an-associative-array-by-its-values-in-javascript
30 function bySortedValue(obj, comparitor, callback, context) {
31     var tuples = [];
32     for (var key in obj) {
33         if (obj.hasOwnProperty(key)) {
34             tuples.push([key, obj[key]]);
35         }
36     }
37
38     tuples.sort(comparitor);
39
40     if (callback) {
41         var length = tuples.length;
42         while (length--) callback.call(context, tuples[length][0], tuples[length][1]);
43     }
44     return tuples;
45 }
46
47
48
49 function request_jit_tree(nodeId, level, depth, onComplete){
50     var params = { logarea: 0 };
51     jQuery.getJSON('jit_tree/'+nodeId+'/'+depth, params, onComplete);
52 }
53
54
55 function init(){
56   var levelsToShow = 2;
57   //init TreeMap
58   var tm = new $jit.TM.Squarified({
59     //where to inject the visualization
60     injectInto: 'infovis',
61     //show only one tree level
62     levelsToShow: levelsToShow,
63     //parent box title heights
64     titleHeight: 14,
65     //enable animations
66     animate: animate,
67     //box offsets
68     offset: 1,
69     //use canvas text
70     Label: {
71       type: labelType,
72       size: 10,
73       family: 'Tahoma, Verdana, Arial'
74     },
75     //enable specific canvas styles
76     //when rendering nodes
77     Node: {
78       CanvasStyles: {
79         shadowBlur: 0,
80         shadowColor: '#000'
81       }
82     },
83     //Attach left and right click events
84     Events: {
85       enable: true,
86       onClick: function(node) {
87         if(node) tm.enter(node);
88       },
89       onRightClick: function() {
90         tm.out();
91       },
92       //change node styles and canvas styles
93       //when hovering a node
94       onMouseEnter: function(node, eventInfo) {
95         if(node) {
96           //add node selected styles and replot node
97           node.setCanvasStyle('shadowBlur', 7);
98           node.setData('color', '#888');
99           tm.fx.plotNode(node, tm.canvas);
100           tm.labels.plotLabel(tm.canvas, node);
101         }
102       },
103       onMouseLeave: function(node) {
104         if(node) {
105           node.removeData('color');
106           node.removeCanvasStyle('shadowBlur');
107           tm.plot();
108         }
109       }
110     },
111     //duration of the animations
112     duration: 300,
113     //Enable tips
114     Tips: {
115       enable: true,
116       type: 'Native',
117       //add positioning offsets
118       offsetX: 20,
119       offsetY: 20,
120       //implement the onShow method to
121       //add content to the tooltip when a node
122       //is hovered
123       onShow: function(tip, node, isLeaf, domElement) {
124         var data = node.data;
125         var html = "<div class=\"tip-title\">"
126           + (data.title ? data.title : "")
127           + " " + data.name
128           + "</div><div class=\"tip-text\">";
129
130         html += "<br />";
131         html += sprintf("Size: %d (%d + %d)<br />", data.self_size+data.kids_size, data.self_size, data.kids_size);
132
133         if (data.self_size) {
134             html += sprintf("Memory usage:<br />");
135             bySortedValue(data.leaves,
136                 function(a, b) { return a[1] - b[1] },
137                 function(k, v) { html += sprintf(" %10s: %5d<br />", k, v);
138             });
139             html += "<br />";
140         }
141
142
143         html += sprintf("Attributes:<br />");
144         bySortedValue(data.attr,
145             function(a, b) { return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0 },
146             function(k, v) { html += sprintf(" %10s: %5d<br />", k, v);
147         });
148         html += "<br />";
149
150         if (data.child_count) {
151             html += sprintf("Children: %d of %d<br />", data.child_count, data.kids_node_count);
152         }
153         html += sprintf("Id: %s%s<br />", node.id, data._ids_merged ? data._ids_merged : "");
154         html += sprintf("Depth: %d<br />", data.depth);
155         html += sprintf("Parent: %d<br />", data.parent_id);
156
157         html += JSON.stringify(data.attr, undefined, 4);
158         //html += JSON.stringify(data, undefined, 4);
159
160         tip.innerHTML =  html; 
161       }  
162     },
163     //Implement this method for retrieving a requested  
164     //subtree that has as root a node with id = nodeId,  
165     //and level as depth. This method could also make a server-side  
166     //call for the requested subtree. When completed, the onComplete   
167     //callback method should be called.  
168     request: function(nodeId, level, onComplete){  
169             request_jit_tree(nodeId, level, levelsToShow, function(data) {
170                 console.log("Fetched node "+nodeId);
171                 console.log(data);
172                 onComplete.onComplete(nodeId, data);  
173             });
174             // XXX workaround jit bug where old tooltip is still shown till the
175             // mouse moves
176             jQuery("#_tooltip").fadeOut("fast");
177     },
178     //Add the name of the node in the corresponding label
179     //This method is called once, on label creation and only for DOM labels.
180     onCreateLabel: function(domElement, node){
181         domElement.innerHTML = node.name;
182
183         // this doesn't work with Label:{} above
184         var style = domElement.style;  
185         style.display = '';  
186         style.border = '1px solid transparent';  
187         domElement.onmouseover = function() {  
188             style.border = '1px solid #9FD4FF';  
189         };  
190         domElement.onmouseout = function() {  
191             style.border = '1px solid transparent';  
192         };  
193
194     }
195   });
196
197   request_jit_tree(1, 0, levelsToShow, function(data) {
198         console.log(data);
199         tm.loadJSON(data);
200         tm.refresh();
201     });
202
203     //add event to buttons
204     $jit.util.addEvent($jit.id('back'), 'click', function() { tm.out() });
205     $jit.util.addEvent($jit.id('logarea'), 'onchange', function() { tm.refresh() });
206
207 }
208
209