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