1 var labelType, useGradients, nativeTextSupport, animate;
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 });
21 write: function(text){
23 this.elem = document.getElementById('log');
24 this.elem.innerHTML = text;
25 this.elem.style.left = (500 - this.elem.offsetWidth / 2) + 'px';
30 * Convert number of bytes into human readable format
32 * @param integer bytes Number of bytes to convert
33 * @param integer precision Number of digits after the decimal separator
35 * via http://codeaid.net/javascript/convert-size-in-bytes-to-human-readable-format-(javascript)
37 function bytesToSize(bytes, precision) {
38 var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
40 while( bytes >= 1024 ) {
44 var num = (posttxt) ? Number(bytes).toFixed(precision) : bytes;
45 return num + " " + sizes[posttxt];
49 // http://stackoverflow.com/questions/5199901/how-to-sort-an-associative-array-by-its-values-in-javascript
50 function bySortedValue(obj, comparitor, callback, context) {
52 for (var key in obj) {
53 if (obj.hasOwnProperty(key)) {
54 tuples.push([key, obj[key]]);
58 tuples.sort(comparitor);
61 var length = tuples.length;
62 while (length--) callback.call(context, tuples[length][0], tuples[length][1]);
69 function request_jit_tree(nodeId, level, depth, onComplete){
70 var params = { };//logarea: 0 };
71 jQuery.getJSON('jit_tree/'+nodeId+'/'+depth, params, onComplete);
78 var tm = new $jit.TM.Squarified({
79 //where to inject the visualization
80 injectInto: 'infovis',
81 //show only one tree level
82 levelsToShow: levelsToShow,
83 //parent box title heights
93 family: 'Tahoma, Verdana, Arial'
95 //enable specific canvas styles
96 //when rendering nodes
103 //Attach left and right click events
106 onClick: function(node) {
107 if(node) tm.enter(node);
109 onRightClick: function() {
112 //change node styles and canvas styles
113 //when hovering a node
114 onMouseEnter: function(node, eventInfo) {
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);
123 onMouseLeave: function(node) {
125 node.removeData('color');
126 node.removeCanvasStyle('shadowBlur');
131 //duration of the animations
137 //add positioning offsets
140 //implement the onShow method to
141 //add content to the tooltip when a node
143 onShow: function(tip, node, isLeaf, domElement) {
144 var data = node.data;
145 var html = "<div class=\"tip-title\">"
146 + (data.title ? "\""+data.title+"\"" : "")
148 + "</div><div class=\"tip-text\">";
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));
155 if (data.self_size) {
156 html += sprintf("Own use: %s<br />", bytesToSize(data.self_size,2));
157 html += sprintf("<div style=\"color:grey\">");
158 bySortedValue(data.leaves,
159 function(a, b) { return a[1] - b[1] },
160 function(k, v) { html += sprintf(" %9s: %s<br />", k, bytesToSize(v,2));
162 html += sprintf("</div>");
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);
176 html += sprintf("<div style=\"color:grey\">");
177 if (data.child_count) {
178 //html += sprintf("Children: %d of %d<br />", data.child_count, data.kids_node_count);
179 html += sprintf("Children: %d<br />", data.kids_node_count);
181 html += sprintf("Id: %s%s<br />", node.id, data._ids_merged ? data._ids_merged : "");
182 html += sprintf("Depth: %d<br />", data.depth);
183 html += sprintf("Parent: %d<br />", data.parent_id);
185 //html += JSON.stringify(data.attr, undefined, 4);
186 //html += JSON.stringify(data, undefined, 4);
187 html += sprintf("</div>");
189 tip.innerHTML = html;
192 //Implement this method for retrieving a requested
193 //subtree that has as root a node with id = nodeId,
194 //and level as depth. This method could also make a server-side
195 //call for the requested subtree. When completed, the onComplete
196 //callback method should be called.
197 request: function(nodeId, level, onComplete){
198 request_jit_tree(nodeId, level, levelsToShow, function(data) {
199 console.log("Fetched node "+nodeId);
201 onComplete.onComplete(nodeId, data);
203 // XXX workaround jit bug where old tooltip is still shown till the
205 jQuery("#_tooltip").fadeOut("fast");
207 //Add the name of the node in the corresponding label
208 //This method is called once, on label creation and only for DOM labels.
209 onCreateLabel: function(domElement, node){
210 domElement.innerHTML = node.name;
212 // this doesn't work with Label:{} above
213 var style = domElement.style;
215 style.border = '1px solid transparent';
216 domElement.onmouseover = function() {
217 style.border = '1px solid #9FD4FF';
219 domElement.onmouseout = function() {
220 style.border = '1px solid transparent';
224 onPlaceLabel: function(domElement, node){ },
227 request_jit_tree(1, 0, levelsToShow, function(data) {
233 //add event to buttons
234 $jit.util.addEvent($jit.id('back'), 'click', function() { tm.out() });
235 $jit.util.addEvent($jit.id('logarea'), 'onchange', function() { tm.refresh() });