Add logarea param via referer. add bytesToSize. Polish formatting of tooltip
[p5sagit/Devel-Size.git] / static / public / tm.js
CommitLineData
b2fc39a5 1var 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);
c065a0c3 16 console.log({ "labelType":labelType, "useGradients":useGradients, "nativeTextSupport":nativeTextSupport });
b2fc39a5 17})();
18
19var 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
ee6e37bf 29/**
30 * Convert number of bytes into human readable format
31 *
32 * @param integer bytes Number of bytes to convert
33 * @param integer precision Number of digits after the decimal separator
34 * @return string
35 * via http://codeaid.net/javascript/convert-size-in-bytes-to-human-readable-format-(javascript)
36 */
37function bytesToSize(bytes, precision) {
38 var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
39 var posttxt = 0;
40 while( bytes >= 1024 ) {
41 posttxt++;
42 bytes = bytes / 1024;
43 }
44 var num = (posttxt) ? Number(bytes).toFixed(precision) : bytes;
45 return num + " " + sizes[posttxt];
46}
47
48
5ab994e6 49// http://stackoverflow.com/questions/5199901/how-to-sort-an-associative-array-by-its-values-in-javascript
50function bySortedValue(obj, comparitor, callback, context) {
51 var tuples = [];
52 for (var key in obj) {
53 if (obj.hasOwnProperty(key)) {
54 tuples.push([key, obj[key]]);
55 }
56 }
57
58 tuples.sort(comparitor);
59
60 if (callback) {
61 var length = tuples.length;
62 while (length--) callback.call(context, tuples[length][0], tuples[length][1]);
63 }
64 return tuples;
65}
66
67
b2fc39a5 68
8f4f09eb 69function request_jit_tree(nodeId, level, depth, onComplete){
ee6e37bf 70 var params = { };//logarea: 0 };
8f4f09eb 71 jQuery.getJSON('jit_tree/'+nodeId+'/'+depth, params, onComplete);
e8f4c506 72}
73
74
b2fc39a5 75function init(){
8f4f09eb 76 var levelsToShow = 2;
b2fc39a5 77 //init TreeMap
78 var tm = new $jit.TM.Squarified({
79 //where to inject the visualization
80 injectInto: 'infovis',
81 //show only one tree level
8f4f09eb 82 levelsToShow: levelsToShow,
b2fc39a5 83 //parent box title heights
a74b795d 84 titleHeight: 14,
b2fc39a5 85 //enable animations
86 animate: animate,
87 //box offsets
88 offset: 1,
89 //use canvas text
ee6e37bf 90 XXX_Label: {
b2fc39a5 91 type: labelType,
a74b795d 92 size: 10,
b2fc39a5 93 family: 'Tahoma, Verdana, Arial'
94 },
95 //enable specific canvas styles
96 //when rendering nodes
97 Node: {
98 CanvasStyles: {
99 shadowBlur: 0,
100 shadowColor: '#000'
101 }
102 },
103 //Attach left and right click events
104 Events: {
105 enable: true,
106 onClick: function(node) {
107 if(node) tm.enter(node);
108 },
109 onRightClick: function() {
110 tm.out();
111 },
112 //change node styles and canvas styles
113 //when hovering a node
114 onMouseEnter: function(node, eventInfo) {
115 if(node) {
116 //add node selected styles and replot node
117 node.setCanvasStyle('shadowBlur', 7);
118 node.setData('color', '#888');
119 tm.fx.plotNode(node, tm.canvas);
120 tm.labels.plotLabel(tm.canvas, node);
121 }
122 },
123 onMouseLeave: function(node) {
124 if(node) {
125 node.removeData('color');
126 node.removeCanvasStyle('shadowBlur');
127 tm.plot();
128 }
129 }
130 },
131 //duration of the animations
a3382177 132 duration: 300,
b2fc39a5 133 //Enable tips
134 Tips: {
135 enable: true,
136 type: 'Native',
137 //add positioning offsets
138 offsetX: 20,
139 offsetY: 20,
140 //implement the onShow method to
141 //add content to the tooltip when a node
142 //is hovered
143 onShow: function(tip, node, isLeaf, domElement) {
b2fc39a5 144 var data = node.data;
e8f4c506 145 var html = "<div class=\"tip-title\">"
ee6e37bf 146 + (data.title ? "\""+data.title+"\"" : "")
e8f4c506 147 + " " + data.name
148 + "</div><div class=\"tip-text\">";
bb66f8a1 149
5ab994e6 150 html += "<br />";
ee6e37bf 151 html += sprintf("Memory use: %s<br />", bytesToSize(data.self_size+data.kids_size,2));
152 if (data.kids_size) {
153 html += sprintf("Child use: %s<br />", bytesToSize(data.kids_size,2));
154 }
5ab994e6 155 if (data.self_size) {
ee6e37bf 156 html += sprintf("Own use: %s<br />", bytesToSize(data.self_size,2));
157 html += sprintf("<div style=\"color:grey\">");
5ab994e6 158 bySortedValue(data.leaves,
159 function(a, b) { return a[1] - b[1] },
ee6e37bf 160 function(k, v) { html += sprintf(" %9s: %s<br />", k, bytesToSize(v,2));
5ab994e6 161 });
ee6e37bf 162 html += sprintf("</div>");
5ab994e6 163 }
ee6e37bf 164 html += "<br />";
5ab994e6 165
e8f4c506 166
ee6e37bf 167 if (0) {
5ab994e6 168 html += sprintf("Attributes:<br />");
169 bySortedValue(data.attr,
170 function(a, b) { return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0 },
171 function(k, v) { html += sprintf(" %10s: %5d<br />", k, v);
172 });
173 html += "<br />";
ee6e37bf 174 }
5ab994e6 175
ee6e37bf 176 html += sprintf("<div style=\"color:grey\">");
bb66f8a1 177 if (data.child_count) {
178 html += sprintf("Children: %d of %d<br />", data.child_count, data.kids_node_count);
b2fc39a5 179 }
5ab994e6 180 html += sprintf("Id: %s%s<br />", node.id, data._ids_merged ? data._ids_merged : "");
5a78486c 181 html += sprintf("Depth: %d<br />", data.depth);
182 html += sprintf("Parent: %d<br />", data.parent_id);
bb66f8a1 183
ee6e37bf 184 //html += JSON.stringify(data.attr, undefined, 4);
e8f4c506 185 //html += JSON.stringify(data, undefined, 4);
ee6e37bf 186 html += sprintf("</div>");
e8f4c506 187
b2fc39a5 188 tip.innerHTML = html;
189 }
190 },
191 //Implement this method for retrieving a requested
192 //subtree that has as root a node with id = nodeId,
193 //and level as depth. This method could also make a server-side
194 //call for the requested subtree. When completed, the onComplete
195 //callback method should be called.
196 request: function(nodeId, level, onComplete){
8f4f09eb 197 request_jit_tree(nodeId, level, levelsToShow, function(data) {
e8f4c506 198 console.log("Fetched node "+nodeId);
f9d8678b 199 console.log(data);
b2fc39a5 200 onComplete.onComplete(nodeId, data);
201 });
a74b795d 202 // XXX workaround jit bug where old tooltip is still shown till the
203 // mouse moves
204 jQuery("#_tooltip").fadeOut("fast");
b2fc39a5 205 },
206 //Add the name of the node in the corresponding label
207 //This method is called once, on label creation and only for DOM labels.
208 onCreateLabel: function(domElement, node){
209 domElement.innerHTML = node.name;
c065a0c3 210
211 // this doesn't work with Label:{} above
212 var style = domElement.style;
213 style.display = '';
214 style.border = '1px solid transparent';
215 domElement.onmouseover = function() {
216 style.border = '1px solid #9FD4FF';
217 };
218 domElement.onmouseout = function() {
219 style.border = '1px solid transparent';
220 };
221
ee6e37bf 222 },
223 onPlaceLabel: function(domElement, node){ },
b2fc39a5 224 });
e8f4c506 225
8f4f09eb 226 request_jit_tree(1, 0, levelsToShow, function(data) {
f9d8678b 227 console.log(data);
b2fc39a5 228 tm.loadJSON(data);
229 tm.refresh();
230 });
b2fc39a5 231
e8f4c506 232 //add event to buttons
233 $jit.util.addEvent($jit.id('back'), 'click', function() { tm.out() });
234 $jit.util.addEvent($jit.id('logarea'), 'onchange', function() { tm.refresh() });
235
b2fc39a5 236}
e8f4c506 237
238