DiaColloDB-WWW
view release on metacpan or search on metacpan
share/htdocs/diacollo.js view on Meta::CPAN
}
}
},
marker: {
lineWidth: 1
}
}
},
series: []
};
//-- create hicharts series
var item, di, score;
items.forEach(function(item) {
item.hiseries = { name:item.label, data:[] };
for (var di in dlabels) {
score = item.score[di];
item.hiseries.data.push({x:Number(String(dlabels[di]).replace(/-/g,".")), y:(score==null ? null : score), label:dlabels[di]});
}
cdata.series.push(item.hiseries);
});
//-- setup plot area
$(".rawURL").hide();
$("#profileDataChart").addClass("hcParent").show();
//-- plot the chart
$("#profileDataChart").addClass("hcChart").highcharts(cdata).show();
dcpClearMsg();
}
//----------------------------------------------------------------------
// str = chartTitleString(prefix,parens)
function chartTitleString(prefix,parens) {
if (prefix==null) { prefix = ''; }
var q = user_query[prefix+'query'];
var title = q;
/*
var d = user_query[prefix+'date'];
if (d != null && d != '') {
title += ' ['+d.replace(/:/,'-')+']';
}
var s = user_query[prefix+'slice'];
if (s != null && s != '') {
title += ' /'+s;
}
*/
return Boolean(parens) ? ('('+title+')') : title;
}
//----------------------------------------------------------------------
// d3: common variables & utilities
var dforce, dcloud, dcur, dsnapto, dkeys, dlabels, itemid, items;
var dcpScoreRange; //-- [minScore,maxScore]
var dcpValueNull; //-- null value
var dcpSizeRange; //-- [minSize,maxSize]
var dcpItemSize; //-- interpolating accessor for item size (cloud:font-size, bubble:radius)
var d3InfoCur; //-- currently selected info-popup data
var brushInterp; //-- function variable for brush interpolation
var brushSnap; //-- function variable for brush snap
// data = dcpParseFlat(dataStr,opts)
// + parses profile data into flat d3-friendly format
// + returns true on success; sets $("#status .msg").text() and returns false on error
// + sets globals:
// qinfo = data.qinfo
// dkeys = [$date0,...] (slice key-strings, raw, e.g. "1900-1900" or "0-1750")
// dlabels = [$date0,...] (slice key-strings, trimmed, e.g. "1900" or "1750")
// items = [$itemData0,...]
// itemid = {$itemKey0:$itemId0, ...}
// dcur = $currentSliceIndex //-- may be fractional if inbetween slices
// dcpScoreRange = [min,max]
// dcpSizeRange = [min,max]
// dcpItemSize = function(d,dcur) { ... }
// dcpDateInterp = function(dcur) { ... }
// + where items[itemId] =
// item = {id:$itemId, item:$itemKey, label:$itemLabel, score:[...], value:[...], avalue:[...], sizes:[...], opacity:[...], maxSize:maxSize?}
// + array-valued item data keys are indexed by dlabels[] index
// + calls setupDebugTable() after parsing qinfo()
// + options:
// mode: MODE, //-- parse mode (known values: "bubble", "cloud")
var d3data = null;
function dcpParseFlat(data,opts) {
//-- status message
dcpStatusMsg("loading","Parsing...");
//-- parse JSON data
if (!(data instanceof Object)) { data = $.parseJSON(data); }
d3data = data;
qinfo = data.qinfo;
setupDebugTable(qinfo);
if (data.profiles.length == 0) {
dcpErrorMsg("Error: no data to display!");
return null;
}
//-- options
if (opts==null) { opts={}; }
if (opts.mode==null) { opts.mode="bubble"; }
var isBubble = opts.mode == "bubble";
var isCloud = opts.mode == "cloud";
//-- initialize
dkeys = [];
dlabels = [];
itemid = {};
items = [];
dcur = 0; //-- current subprofile index
//-- get data range
data.profiles.forEach(function (p) { p.range = d3.extent(d3.values(p[p.score])); });
var smin = d3.min(data.profiles, function(p) { return p.range[0]; });
var smax = d3.max(data.profiles, function(p) { return p.range[1]; });
if (smin > 0) { smin = 0; }
if (smax < smin) { smax = smin; }
if (smin==smax) { smin -= 1e-5; smax += 1e-5; }
var amax = Math.max(Math.abs(smin),Math.abs(smax));
dcpScoreRange = [smin,smax];
dcpValueNull = dcpScoreValue(0);
//-- setup scales: size/radius ("sizes" key)
dcpSizeRange = (isBubble
? [8,56] //-- bubble: radius range
: [12,78] //-- cloud: font-size range (in pixels)
);
dcpItemSize = (isAbsDiff
? function(item,pos) { return dcpSizeRange[0] + linterp(item.avalue,pos)*(dcpSizeRange[1]-dcpSizeRange[0]); }
: function(item,pos) { return dcpSizeRange[0] + linterp(item.value,pos) *(dcpSizeRange[1]-dcpSizeRange[0]); }
);
//-- setup formatters (for details popup)
var ffmt = d3.format(",r");
var sfmt = d3.format(user_query.score=="ld" ? ".4r"
: (user_query.score=="f" ? ",r"
: ".4s"));
//-- parse data
var pi, p, pscores, iid, idata, iscore, ivalue, avalue;
for (pi=0; pi < data.profiles.length; ++pi) {
p = data.profiles[pi];
p.label = String(p.label);
dkeys.push(p.label);
//-- simplify label
p.label = p.label.replace(/^([0-9]+)-\1/,'$1').replace(/^0-/,'').replace(/-0$/,'');
dlabels.push(p.label);
pscores = p[p.score];
for (var item in pscores) {
if ((iid=itemid[item]) != null) {
//-- existing item
idata = items[iid];
} else {
//-- new item
itemid[item] = iid = items.length;
items.push(idata={"id":iid,
"item":item,
"label":item.replace(/\t/g, '/'),
"text":item.replace(/\t.*$/,''),
score:[], value:[], avalue:[], sizes:[], opacity:[]
});
if (isDiff) {
idata.N1 = []; //ffmt(p.prf1.N);
idata.N2 = []; //ffmt(p.prf2.N);
idata.af1 = [];
idata.bf1 = [];
idata.af2 = [];
idata.bf2 = [];
idata.af12 = [];
idata.bf12 = [];
idata.ascore=[];
idata.bscore=[];
} else {
idata.N = []; //ffmt(p.N);
idata.f1 = [];
idata.f2 = [];
idata.f12 = [];
}
}
idata.score[pi] = iscore = pscores[item];
idata.value[pi] = ivalue = dcpScoreValue(iscore);
idata.avalue[pi] = avalue = Math.abs(iscore)/amax;
idata.sizes[pi] = dcpItemSize(idata,pi);
idata.opacity[pi] = 1;
if (isDiff) {
idata.N1[pi] = ffmt(p.prf1.N);
idata.N2[pi] = ffmt(p.prf2.N);
idata.af1[pi] = ffmt(p.prf1.f1);
idata.bf1[pi] = ffmt(p.prf2.f1);
share/htdocs/diacollo.js view on Meta::CPAN
dcur = 0;
}
return data;
}
//----------------------------------------------------------------------
// d3: common: interpolating accessors
function vinterp(frac, x0,x1, missing) {
if (missing==null) missing=0;
return ((1.0-frac)*(x0==null ? missing : x0)) + (frac*(x1==null ? missing : x1));
}
function linterp(l,pos,missing) {
return vinterp(pos-Math.floor(pos), l[Math.floor(pos)], l[Math.ceil(pos)], missing);
}
function dcpItemScore(item,pos) { return linterp(item.score, pos); }
function dcpItemValue(item,pos) { return linterp(item.value, pos, dcpValueNull); }
function dcpItemAbsValue(item,pos) { return linterp(item.avalue, pos); }
//dcpItemSize : function variable
function dcpItemScale(item,pos) { return dcpItemSize(item,pos) / item.maxSize; }
function dcpScoreValue(score) {
return (score-dcpScoreRange[0]) / (dcpScoreRange[1]-dcpScoreRange[0]);
}
//-- dcpItemSat, dcpItemVal: for "old" rainbow-style colors
// + green takes up too much space in these for some reason (~ 4 score points on for diff [-8..8])
// + better differentiation using colorbrewer colors and d3 scale, not as pretty for html though
var dcpItemSat = 1;
var dcpItemVal = 1;
function dcpItemColor(item,pos) { return heatcolorf(dcpItemValue(item,pos), dcpItemSat, dcpItemVal); }
function dcpMinColor() { return heatcolorf(0, dcpItemSat, dcpItemVal); }
function dcpMaxColor() { return heatcolorf(1, dcpItemSat, dcpItemVal); }
function dcpItemOpacity(item,pos,max) {
return (max==null ? 1 : max)*linterp(item.opacity,pos);
}
// interpolator = dcpDateInterpolator(dlabel0,dlabel1)
// + returned function is called as "interpolatedDateLabel = interpolator(t)" with 0 <= t <= 1
function dcpDateInterpolator(dlabel0,dlabel1) {
var d0 = dlabel0.split("-");
var d1 = dlabel1.split("-");
if (d0.length==1) {
return d3.interpolateRound(Number(d0[0]),Number(d1[0]));
} else {
var interp = d0.map(function(e,i){ return d3.interpolateRound(Number(d0[i]),Number(d1[i])); });
return function(t) { return interp.map(function(i) { return i(t) }).join("-"); };
}
}
//--------------------------------------------------------------
// d3: common: node titles (bubble,cloud)
function d3NodeTitleText(d) {
return (d.label + " ~ " + dcpItemScore(d,dcur)
+ (user_query.debug ? (": " + JSON.stringify({id:d.id, value:dcpItemValue(d,dcur), avalue:dcpItemAbsValue(d,dcur), size:dcpItemSize(d,dcur)})) : '')
);
}
//--------------------------------------------------------------
// d3: info popup
function d3InfoPopup(d,opts) {
var dsnap = Math.round(dcur);
var dlabel = dlabels[dsnap];
//-- save current info item
d3InfoCur = {data:d};
var dopts = {
title: d.label,
autoOpen: true,
modal: false,
minHeight: 64,
minWidth: 300,
height: "auto",
width: "auto",
show: {effect:"scale",percent:100, duration:150},
hide: {effect:"scale",percent:0, duration:150},
close: function(e,ui) {
d3InfoCur = null;
d3.selectAll(".node").classed("selected",false);
$(".content").focus();
}
};
if (!$("#profileDataPopup").is(":visible")) {
dopts.position = {at:"center",of:this};
}
for (var o in opts) {
if (o == null) {
delete dopts[o];
} else {
dopts[o] = opts[o];
}
}
var content = (''
+'<span class="ui-helper-hidden-accessible"><input type="text"/></span>' //-- disable ugly jquery-ui autofocus
+'<table class="dcslide">'
+'<tr><th>slice:</th><td class="slice">' + dlabel +'</td></tr>'
+ '<th>score:</th><td class="score">' + d.score[dsnap] + '</td></tr>'
);
var tr = [dkeys[dsnap]].concat(d.item.split("\t"));
if (isDiff) {
d3InfoCur.kwic = {"tr":tr,"ilabel":0,
"qtemplate":qinfo.aqtemplate,"text":"KWIC:A","dtrim":/[^0-9].*$/,"dslice":user_query.slice,
title:"DDC KWIC search for point pairs (QUERY)",
classes:"textButtonSmall kwic"
};
d3InfoCur.bkwic = {"tr":tr,"ilabel":0,
"qtemplate":qinfo.bqtemplate,"text":"KWIC:B","dtrim":/^.*[^0-9]/,"dslice":user_query.bslice,
title:"DDC KWIC search for point pairs (~QUERY)",
classes:"textButtonSmall bkwic"
};
content += (''
+'<tr><th>search:</th><td>'
+ kwiclink(d3InfoCur.kwic)
+ ' '
+ kwiclink(d3InfoCur.bkwic)
+ '</td></tr>'
+'<tr><th>details:</th><td class="diff details">'+(
'<table>'
+'<tr><th>N(a/b):</th><td class="num N1">'+d.N1[dsnap]+'</td><td>/</td><td class="num N2">'+d.N2[dsnap]+'</tr>'
+'<tr><th>f1(a/b):</th><td class="num af1">'+d.af1[dsnap]+'</td><td>/</td><td class="num bf1">'+d.bf1[dsnap]+'</tr>'
+'<tr><th>f2(a/b):</th><td class="num af2">'+d.af2[dsnap]+'</td><td>/</td><td class="num bf2">'+d.bf2[dsnap]+'</tr>'
+'<tr><th>f12(a/b):</th><td class="num af12">'+d.af12[dsnap]+'</td><td>/</td><td class="num bf12">'+d.bf12[dsnap]+'</tr>'
+'<tr><th>score(a/b):</th><td class="num ascore">'+d.ascore[dsnap]+'</td><td>/</td><td class="num bscore">'+d.bscore[dsnap]+'</tr>'
+'</table>'
)
);
} else {
d3InfoCur.kwic = {"tr":tr,"ilabel":0,"qtemplate":qinfo.qtemplate,"text":"KWIC",
title:"DDC KWIC search for point pairs",
classes:"textButtonSmall kwic"
};
content += (''
+'<tr><th>search:</th><td>'
+ kwiclink(d3InfoCur.kwic)
+ '</td></tr>'
+'<tr><th>details:</th><td class="details">'+(
'<table>'
+'<tr><th>N:</th><td class="num N">'+d.N[dsnap]+'</td></tr>'
+'<tr><th>f1:</th><td class="num f1">'+d.f1[dsnap]+'</td></tr>'
+'<tr><th>f2:</th><td class="num f2">'+d.f2[dsnap]+'</td></tr>'
+'<tr><th>f12:</th><td class="num f12">'+d.f12[dsnap]+'</td></tr>'
+'</table>'
)
);
}
var dlg = $("#profileDataPopup").html(content).dialog(dopts);
//-- add node-class
d3.selectAll(".node").classed("selected",false);
d3.select("#g"+d.id).classed("selected",true);
return false;
}
//--------------------------------------------------------------
// d3: info popup: update
function d3InfoPopupUpdate(snapto) {
//-- maybe update info box
if (d3InfoCur != null && snapto != dsnapto) {
var dlg = $("#profileDataPopup");
var d = d3InfoCur.data;
dlg.find(".slice").text(String(dlabels[snapto]));
dlg.find(".score").text(String(d.score[snapto]));
if (d3InfoCur.kwic != null) { d3InfoCur.kwic.tr[0] = dkeys[snapto]; dlg.find(".kwic").prop('href',kwicurl(d3InfoCur.kwic)); }
if (d3InfoCur.bkwic != null) { d3InfoCur.bkwic.tr[0] = dkeys[snapto]; dlg.find(".bkwic").prop('href',kwicurl(d3InfoCur.bkwic)); }
if (isDiff) {
dlg.find(".N1").text(String(d.N1[snapto]));
dlg.find(".N2").text(String(d.N2[snapto]));
dlg.find(".af1").text(String(d.af1[snapto]));
dlg.find(".bf1").text(String(d.bf1[snapto]));
dlg.find(".af2").text(String(d.af2[snapto]));
dlg.find(".bf2").text(String(d.bf2[snapto]));
dlg.find(".af12").text(String(d.af12[snapto]));
dlg.find(".bf12").text(String(d.bf12[snapto]));
dlg.find(".ascore").text(String(d.ascore[snapto]));
dlg.find(".bscore").text(String(d.bscore[snapto]));
} else {
dlg.find(".N").text(String(d.N[snapto]));
dlg.find(".f1").text(String(d.f1[snapto]));
dlg.find(".f2").text(String(d.f2[snapto]));
dlg.find(".f12").text(String(d.f12[snapto]));
}
//dlg.parent().stop(true,true).effect("highlight");
d3.select("#g"+d.id).classed("selected",true);
}
}
//--------------------------------------------------------------
// d3: brush-slider (date-slice selector)
// + see http://bl.ocks.org/mbostock/6452972
// dbrush = d3brush(dlabels, selector, opts)
// + sets global dbrush=brush, bhandle=handle, bsvg=brush-svg
var dbrush, bhandle, bsvg;
function dcpTransportSlider(dlabels, parent_selector, opts) {
//-- setup defaults
if (opts.id==null) opts.id = "d3slider";
if (opts.width==null) opts.width = 800;
if (opts.height==null) opts.height = 50;
var margin = opts.margin==null ? {} : opts.margin;
if (margin.left==null) margin.left = 0;
if (margin.right==null) margin.right = 0;
if (margin.top==null) margin.top = 0;
if (margin.bottom==null) margin.bottom = 0;
if (opts.translate==null) opts.translate = {x:0,y:0};
//debug_log("dcpTransportSlider(dlabels="+JSON.stringify(dlabels)+", parent_selector="+JSON.stringify(parent_selector)+", opts="+JSON.stringify(opts)+")");
//-- common variables
var width = opts.width - margin.left - margin.right;
var height = opts.height - margin.top - margin.bottom;
var xscale = d3.scale.linear() //d3.v4: d3.scaleLinear()
.domain([0,dlabels.length-1])
.range([0,width])
.clamp(true);
share/htdocs/diacollo.js view on Meta::CPAN
var snapto = Math.round(dcur);
var dcur0 = Math.floor(dcur);
var dcur1 = Math.ceil(dcur);
var dfrac = dcur-dcur0;
var ditems = items.filter(function(i) { return i.value[dcur0] != null || i.value[dcur1] != null; });
ditems.forEach(function(i) { i.gravity = linterp(i.value,dcur); });
dforce.nodes(ditems);
var psvg = d3.select(d3BodySelector);
var nodes = psvg.selectAll(".node")
.data(ditems, function(d) { return d.id; });
//-- UPDATE: update existing elements
//var updated = nodes;
//-- ENTER: append new elements
var entered = nodes.enter()
.append("g")
.attr("class", "node")
.attr("id", function(d) { return "g"+d.id; })
.attr("opacity",0)
.on("dblclick", d3InfoPopup)
.call(dforce.drag);
entered
.append("title");
entered
.append("circle")
.attr("opacity",bubbleOpacity)
.attr("r",dcpSizeRange[0]);
entered
//.filter(function(d) { return d.avalue >= 0.25 }) //-- only annotate nodes with 75%+ absolute score-quantiles
.append("text")
.text(function(d) { return d.text; });
//-- ENTER+UPDATE: update old or new nodes
nodes.selectAll("title").text(d3NodeTitleText);
var updated = nodes.transition()
.duration(dur)
.ease(easeby);
updated
.attr("opacity",function(d) { return dcpItemOpacity(d,dcur); })
.selectAll("circle")
.attr("r", function(d) { return d.r = dcpItemSize(d,dcur); })
.style("fill", function(d) { return dcpItemColor(d,dcur); })
;
//-- EXIT: remove old elements as needed
var exited = nodes.exit()
.transition()
.duration(dur)
.ease(easeby)
.remove();
exited
.attr("opacity",0)
.selectAll("circle")
.attr("r",dcpSizeRange[0]);
//-- (re-)start the force layout
dforce.start();
//-- update info popup and current snap-to value
d3InfoPopupUpdate(snapto);
dsnapto = snapto;
}
//--------------------------------------------------------------
// d3: bubble: collision detection: text "radius" (really horizontal only)
function itemTextRadius(item) {
if (Number(item.textRadius) > 0) return item.textRadius;
return item.textRadius = d3.select("#g"+item.id+" text").node().getBBox().width/2;
}
//--------------------------------------------------------------
// d3: bubble: collision detection
// + see https://gist.github.com/mbostock/3231298 (orig, circles only)
// + see http://stackoverflow.com/questions/29844823/force-layout-collision-detection-with-group-nodes (for group nodes)
// + using canvas-constraints from http://bl.ocks.org/mbostock/1129492
function collide(node, canvasWidth, canvasHeight) {
var nodeElt = d3.select("#g"+node.id).node();
var bbox = nodeElt.getBBox();
var pad = 2;
//-- fit to canvas hack from http://bl.ocks.org/mbostock/1129492
node.x = Math.max(node.r, Math.min(canvasWidth - bbox.width/2, node.x));
node.y = Math.max(node.r, Math.min(canvasHeight - bbox.height/2, node.y));
var
rx = bbox.width/2 + pad,
ry = bbox.height/2 + pad,
r = Math.max(rx,ry),
//r = ry,
nx1 = node.x - rx, //rx
nx2 = node.x + rx, //rx
ny1 = node.y - ry, //ry
ny2 = node.y + ry; //ry
return function(quad, x1, y1, x2, y2) {
if (quad.point && (quad.point !== node)) {
//-- collision detection: circles
var x = node.x - quad.point.x,
y = node.y - quad.point.y,
dl = Math.sqrt(x * x + y * y),
dr = r + Math.max(quad.point.r, itemTextRadius(quad.point));
//dr = r + quad.point.r;
if (dl < dr) {
dl = (dl - dr) / dl * .5;
node.x -= x *= dl;
node.y -= y *= dl;
quad.point.x += x;
quad.point.y += y;
}
}
//return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
};
}
//----------------------------------------------------------------------
// d3: cloud: tag-cloud layout
// + see https://github.com/jasondavies/d3-cloud
var dcpCloudFont = {family:"Impact",weight:"normal",style:"normal"};
share/htdocs/diacollo.js view on Meta::CPAN
};
};
var nodes = d3.select(d3BodySelector+" > g")
.selectAll(".node")
.data(ditems, function(d) { return d.id; });
//-- UPDATE: update existing elements
//var updated = nodes;
//-- ENTER: append new elements
var entered = nodes.enter()
.append("g")
.attr("id", function(d) { return "g"+d.id; })
.attr("class","node")
.attr("transform", function(d) { return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; })
.on("click", d3InfoPopup);
//-- enter: title
entered.append("title");
//-- enter: text
entered.append("text")
//-- enter: text: constant attributes
.text(function(d) { return d.text; })
//-- these get set by css [but we might need them for svg export?]
.attr("text-anchor","middle")
.style("font-family",dcpCloudFont.family)
.style("font-weight",dcpCloudFont.weight)
.style("font-style",dcpCloudFont.style)
.style("fill",dcpMinColor())
.attr("opacity",0)
.style("font-size",function(d) { (d.curSize=dcpSizeRange[0])+"px"; }) //-- use dcpSizeRange[0] rather than 0 minimum size; 0 --> collisions!
;
//-- ENTER+UPDATE: update old or new nodes
nodes.selectAll("title").text(d3NodeTitleText);
nodes.transition()
.duration(dur)
.ease(easeby)
.selectAll("text")
.attr("opacity", function(d) { return dcpItemOpacity(d,dcur) })
.style("fill", function(d) { return dcpItemColor(d,dcur) })
//.style("font-size", function(d) { return ~~dcpItemSize(d,dcur)+"px"; })
.tween("font-size",tween_font_size)
;
//-- EXIT: remove old elements as needed
var exited = nodes.exit()
.transition()
.duration(dur)
.ease(easeby)
.remove();
exited.selectAll("text")
.attr("opacity", 0)
.style("fill", dcpMinColor())
.tween("font-size", tween_font_size)
;
//-- maybe update info popup
d3InfoPopupUpdate(snapto);
dsnapto = snapto;
}
//--------------------------------------------------------------
// d3: cloud: debug (show all at max size)
function dcpCloudDebug(dur,easeby,opacity,doInterp) {
if (dcloud==null) return; //-- not defined yet
if (dur==null) { dur = 1000; }
if (easeby==null) { easeby = "linear"; }
if (opacity==null) { opacity = 1; }
if (doInterp==null) { doInterp = false; }
debug_log("dcpCloudDebug("+dur+","+","+easeby+","+opacity+","+doInterp+")");
var ditems = items;
function tween_font_size(d) {
var interp = d3.interpolateRound(d.curSize, d.maxSize);
return function(t) {
$(this).css("font-size",(d.curSize=interp(t))+"px");
};
};
var nodes = d3.select(d3BodySelector+" > g")
.selectAll(".node")
.data(ditems, function(d) { return d.id; });
//-- UPDATE: update existing elements
//var updated = nodes;
//-- ENTER: append new elements
var entered = nodes.enter()
.append("g")
.attr("id", function(d) { return "g"+d.id; })
.attr("class","node")
.attr("transform", function(d) { return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; })
.on("click", d3InfoPopup);
entered
.append("title")
;
//-- enter: text
entered.append("text")
//-- enter: text: constant attributes
.text(function(d) { return d.text; })
//-- these get set by css [but we might need them for svg export?]
.attr("text-anchor","middle")
.style("font-family",dcpCloudFont.family)
.style("font-weight",dcpCloudFont.weight)
.style("font-style",dcpCloudFont.style)
.style("fill",dcpMinColor())
.attr("opacity",0)
.style("font-size",function(d) { (d.curSize=dcpSizeRange[0])+"px"; })
;
//-- ENTER+UPDATE: update old or new nodes
var ntrans=0;
nodes.selectAll("text")
.transition()
.duration(dur)
( run in 1.188 second using v1.01-cache-2.11-cpan-364913b4093 )