From: Tim Bunce Date: Tue, 18 Sep 2012 21:29:20 +0000 (+0100) Subject: drill down with basic tooltip X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=bb66f8a106436d62b6815aa4d353f54d97a07d87;p=p5sagit%2FDevel-Size.git drill down with basic tooltip --- diff --git a/static/MemView.pl b/static/MemView.pl index bd4889f..b4bb73e 100755 --- a/static/MemView.pl +++ b/static/MemView.pl @@ -27,21 +27,35 @@ get '/jit_tree/:id/:depth' => sub { my $depth = $self->stash('depth'); warn "jit_tree $id $depth"; my $jit_tree = _fetch_node($id, $depth, sub { - my $node=shift; $node->{data}{'$area'} = $node->{self_size}+$node->{kids_size} + my ($node, $children) = @_; + $node->{'$area'} = $node->{self_size}+$node->{kids_size}; + $node->{child_count} = @$children if $children; + my $jit_node = { + id => $node->{id}, + name => $node->{name}, + data => $node, + }; + $jit_node->{children} = $children if $children; + return $jit_node; }); - use Devel::Dwarn; Dwarn($jit_tree); +if(1){ + use Devel::Dwarn; + use Data::Dump qw(pp); + local $jit_tree->{children}; + pp($jit_tree); +} $self->render_json($jit_tree); }; sub _fetch_node { my ($id, $depth, $transform) = @_; my $node = MemView->selectrow_hashref("select * from node where id = ?", undef, $id); + my $children; if ($depth && $node->{child_seqns}) { my @child_seqns = split /,/, $node->{child_seqns}; - my @children = map { _fetch_node($_, $depth-1, $transform) } @child_seqns; - $node->{children} = \@children; + $children = [ map { _fetch_node($_, $depth-1, $transform) } @child_seqns ]; } - $transform->($node) if $transform; + $node = $transform->($node, $children) if $transform; return $node; } @@ -57,7 +71,7 @@ Welcome to the Mojolicious real-time web framework! -Treemap - TreeMap with on-demand nodes +Perl Memory Treemap @@ -70,7 +84,7 @@ Welcome to the Mojolicious real-time web framework! - + @@ -79,52 +93,14 @@ Welcome to the Mojolicious real-time web framework!
- -

-TreeMap with on-demand nodes +Perl Memory TreeMap

- - This example shows how you can use the request controller method to create a TreeMap with on demand nodes

- This example makes use of native Canvas text and shadows, but can be easily adapted to use HTML like the other examples.

- There should be only one level shown at a time.

- Clicking on a band should show a new TreeMap with its most listened albums.

- -
- -
- - - - - - - - - - - - -
- - - -
- - - -
- - - -
+ Clicking on a node will show a new TreeMap with the contents of that node.

Go to Parent - - -
See the Example Code
diff --git a/static/public/.tm.js.swp b/static/public/.tm.js.swp index 24a0da4..1974839 100644 Binary files a/static/public/.tm.js.swp and b/static/public/.tm.js.swp differ diff --git a/static/public/sprintf.js b/static/public/sprintf.js new file mode 100644 index 0000000..78509f4 --- /dev/null +++ b/static/public/sprintf.js @@ -0,0 +1,183 @@ +// from https://raw.github.com/kvz/phpjs/master/functions/strings/sprintf.js +function sprintf () { + // http://kevin.vanzonneveld.net + // + original by: Ash Searle (http://hexmen.com/blog/) + // + namespaced by: Michael White (http://getsprink.com) + // + tweaked by: Jack + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + input by: Paulo Freitas + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + input by: Brett Zamir (http://brett-zamir.me) + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + improved by: Dj + // * example 1: sprintf("%01.2f", 123.1); + // * returns 1: 123.10 + // * example 2: sprintf("[%10s]", 'monkey'); + // * returns 2: '[ monkey]' + // * example 3: sprintf("[%'#10s]", 'monkey'); + // * returns 3: '[####monkey]' + var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuideEfFgG])/g; + var a = arguments, + i = 0, + format = a[i++]; + + // pad() + var pad = function (str, len, chr, leftJustify) { + if (!chr) { + chr = ' '; + } + var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr); + return leftJustify ? str + padding : padding + str; + }; + + // justify() + var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) { + var diff = minWidth - value.length; + if (diff > 0) { + if (leftJustify || !zeroPad) { + value = pad(value, minWidth, customPadChar, leftJustify); + } else { + value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length); + } + } + return value; + }; + + // formatBaseX() + var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) { + // Note: casts negative numbers to positive ones + var number = value >>> 0; + prefix = prefix && number && { + '2': '0b', + '8': '0', + '16': '0x' + }[base] || ''; + value = prefix + pad(number.toString(base), precision || 0, '0', false); + return justify(value, prefix, leftJustify, minWidth, zeroPad); + }; + + // formatString() + var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) { + if (precision != null) { + value = value.slice(0, precision); + } + return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar); + }; + + // doFormat() + var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) { + var number; + var prefix; + var method; + var textTransform; + var value; + + if (substring == '%%') { + return '%'; + } + + // parse flags + var leftJustify = false, + positivePrefix = '', + zeroPad = false, + prefixBaseX = false, + customPadChar = ' '; + var flagsl = flags.length; + for (var j = 0; flags && j < flagsl; j++) { + switch (flags.charAt(j)) { + case ' ': + positivePrefix = ' '; + break; + case '+': + positivePrefix = '+'; + break; + case '-': + leftJustify = true; + break; + case "'": + customPadChar = flags.charAt(j + 1); + break; + case '0': + zeroPad = true; + break; + case '#': + prefixBaseX = true; + break; + } + } + + // parameters may be null, undefined, empty-string or real valued + // we want to ignore null, undefined and empty-string values + if (!minWidth) { + minWidth = 0; + } else if (minWidth == '*') { + minWidth = +a[i++]; + } else if (minWidth.charAt(0) == '*') { + minWidth = +a[minWidth.slice(1, -1)]; + } else { + minWidth = +minWidth; + } + + // Note: undocumented perl feature: + if (minWidth < 0) { + minWidth = -minWidth; + leftJustify = true; + } + + if (!isFinite(minWidth)) { + throw new Error('sprintf: (minimum-)width must be finite'); + } + + if (!precision) { + precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : undefined; + } else if (precision == '*') { + precision = +a[i++]; + } else if (precision.charAt(0) == '*') { + precision = +a[precision.slice(1, -1)]; + } else { + precision = +precision; + } + + // grab value using valueIndex if required? + value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++]; + + switch (type) { + case 's': + return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar); + case 'c': + return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad); + case 'b': + return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad); + case 'o': + return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad); + case 'x': + return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad); + case 'X': + return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase(); + case 'u': + return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad); + case 'i': + case 'd': + number = (+value) | 0; + prefix = number < 0 ? '-' : positivePrefix; + value = prefix + pad(String(Math.abs(number)), precision, '0', false); + return justify(value, prefix, leftJustify, minWidth, zeroPad); + case 'e': + case 'E': + case 'f': // Should handle locales (as per setlocale) + case 'F': + case 'g': + case 'G': + number = +value; + prefix = number < 0 ? '-' : positivePrefix; + method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())]; + textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2]; + value = prefix + Math.abs(number)[method](precision); + return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform](); + default: + return substring; + } + }; + + return format.replace(regex, doFormat); +} diff --git a/static/public/tm.js b/static/public/tm.js index 89b0fb6..5f5b36d 100644 --- a/static/public/tm.js +++ b/static/public/tm.js @@ -99,15 +99,22 @@ function init(){ var html = "
" + node.name + "
"; var data = node.data; - if(data.artist) { - html += "Artist: " + data.artist + "
"; - } - if(data.playcount) { - html += "Play count: " + data.playcount; - } - if(data.image) { - html += ""; + + //"child_seqns" => 4, + //"depth" => 2, + //"id" => 3, + //"kids_node_count" => 4426, + //"kids_size" => 560058, + //"name" => "SV(PVHV)", + //"parent_seqn" => 2, + //"self_size" => 1080, + + html += sprintf("Name: %s
\n", data.name); + html += sprintf("Size: %d (%d + %d)
", data.self_size+data.kids_size, data.self_size, data.kids_size); + if (data.child_count) { + html += sprintf("Children: %d of %d
", data.child_count, data.kids_node_count); } + tip.innerHTML = html; } }, @@ -152,27 +159,6 @@ else { tm.refresh(); } - var sq = $jit.id('r-sq'), - st = $jit.id('r-st'), - sd = $jit.id('r-sd'); - var util = $jit.util; - util.addEvent(sq, 'change', function() { - if(!sq.checked) return; - util.extend(tm, new $jit.Layouts.TM.Squarified); - tm.refresh(); - }); - util.addEvent(st, 'change', function() { - if(!st.checked) return; - util.extend(tm, new $jit.Layouts.TM.Strip); - tm.layout.orientation = "v"; - tm.refresh(); - }); - util.addEvent(sd, 'change', function() { - if(!sd.checked) return; - util.extend(tm, new $jit.Layouts.TM.SliceAndDice); - tm.layout.orientation = "v"; - tm.refresh(); - }); //add event to the back button var back = $jit.id('back'); $jit.util.addEvent(back, 'click', function() {