303 lines
9.8 KiB
JavaScript
303 lines
9.8 KiB
JavaScript
var labelType, useGradients, nativeTextSupport, animate;
|
|
|
|
(function() {
|
|
var ua = navigator.userAgent,
|
|
iStuff = ua.match(/iPhone/i) || ua.match(/iPad/i),
|
|
typeOfCanvas = typeof HTMLCanvasElement,
|
|
nativeCanvasSupport = (typeOfCanvas == 'object' || typeOfCanvas == 'function'),
|
|
textSupport = nativeCanvasSupport
|
|
&& (typeof document.createElement('canvas').getContext('2d').fillText == 'function');
|
|
//I'm setting this based on the fact that ExCanvas provides text support for IE
|
|
//and that as of today iPhone/iPad current text support is lame
|
|
labelType = (!nativeCanvasSupport || (textSupport && !iStuff))? 'Native' : 'HTML';
|
|
nativeTextSupport = labelType == 'Native';
|
|
useGradients = nativeCanvasSupport;
|
|
animate = !(iStuff || !nativeCanvasSupport);
|
|
})();
|
|
|
|
var Log = {
|
|
elem: false,
|
|
write: function(text){
|
|
if (!this.elem)
|
|
this.elem = document.getElementById('log');
|
|
this.elem.innerHTML = text;
|
|
this.elem.style.left = (500 - this.elem.offsetWidth / 2) + 'px';
|
|
}
|
|
};
|
|
|
|
|
|
function init(){
|
|
//init data
|
|
var json = {
|
|
id: "node02",
|
|
name: "0.2",
|
|
children: [{
|
|
id: "node13",
|
|
name: "1.3",
|
|
children: [{
|
|
id: "node24",
|
|
name: "2.4"
|
|
}, {
|
|
id: "node222",
|
|
name: "2.22"
|
|
}]
|
|
}, {
|
|
id: "node125",
|
|
name: "1.25",
|
|
children: [{
|
|
id: "node226",
|
|
name: "2.26"
|
|
}, {
|
|
id: "node237",
|
|
name: "2.37"
|
|
}, {
|
|
id: "node258",
|
|
name: "2.58"
|
|
}]
|
|
}, {
|
|
id: "node165",
|
|
name: "1.65",
|
|
children: [{
|
|
id: "node266",
|
|
name: "2.66"
|
|
}, {
|
|
id: "node283",
|
|
name: "2.83"
|
|
}, {
|
|
id: "node2104",
|
|
name: "2.104"
|
|
}, {
|
|
id: "node2109",
|
|
name: "2.109"
|
|
}, {
|
|
id: "node2125",
|
|
name: "2.125"
|
|
}]
|
|
}, {
|
|
id: "node1130",
|
|
name: "1.130",
|
|
children: [{
|
|
id: "node2131",
|
|
name: "2.131"
|
|
}, {
|
|
id: "node2138",
|
|
name: "2.138"
|
|
}]
|
|
}]
|
|
};
|
|
//end
|
|
//init Node Types
|
|
//Create a node rendering function that plots a fill
|
|
//rectangle and a stroke rectangle for borders
|
|
$jit.ST.Plot.NodeTypes.implement({
|
|
'stroke-rect': {
|
|
'render': function(node, canvas) {
|
|
var width = node.getData('width'),
|
|
height = node.getData('height'),
|
|
pos = this.getAlignedPos(node.pos.getc(true), width, height),
|
|
posX = pos.x + width/2,
|
|
posY = pos.y + height/2;
|
|
this.nodeHelper.rectangle.render('fill', {x: posX, y: posY}, width, height, canvas);
|
|
this.nodeHelper.rectangle.render('stroke', {x: posX, y: posY}, width, height, canvas);
|
|
}
|
|
}
|
|
});
|
|
//end
|
|
//init Spacetree
|
|
//Create a new ST instance
|
|
var st = new $jit.ST({
|
|
//id of viz container element
|
|
injectInto: 'infovis',
|
|
//set distance between node and its children
|
|
levelDistance: 50,
|
|
//set an X offset
|
|
offsetX: 130,
|
|
//set node, edge and label styles
|
|
//set overridable=true for styling individual
|
|
//nodes or edges
|
|
Node: {
|
|
overridable: true,
|
|
type: 'stroke-rect',
|
|
height: 20,
|
|
width: 60,
|
|
//canvas specific styles
|
|
CanvasStyles: {
|
|
fillStyle: '#daa',
|
|
strokeStyle: '#ffc',
|
|
lineWidth: 2
|
|
}
|
|
},
|
|
Edge: {
|
|
overridable: true,
|
|
type: 'line',
|
|
color: '#ffc',
|
|
lineWidth: 1
|
|
},
|
|
Label: {
|
|
type: labelType,
|
|
style: 'bold',
|
|
size: 10,
|
|
color: '#333'
|
|
},
|
|
//This method is called on DOM label creation.
|
|
//Use this method to add event handlers and styles to
|
|
//your node.
|
|
onCreateLabel: function(label, node){
|
|
label.innerHTML = node.name;
|
|
//set label styles
|
|
var style = label.style;
|
|
style.width = 60 + 'px';
|
|
style.height = 17 + 'px';
|
|
style.color = '#333';
|
|
style.fontSize = '0.8em';
|
|
style.textAlign= 'center';
|
|
style.paddingTop = '3px';
|
|
},
|
|
onPlaceLabel: function(label, node) {
|
|
var style = label.style;
|
|
style.width = node.getData('width') + 'px';
|
|
style.height = node.getData('height') + 'px';
|
|
style.color = node.getLabelData('color');
|
|
style.fontSize = node.getLabelData('size') + 'px';
|
|
style.textAlign= 'center';
|
|
style.paddingTop = '3px';
|
|
}
|
|
});
|
|
//load json data
|
|
st.loadJSON(json);
|
|
//compute node positions and layout
|
|
st.compute();
|
|
//emulate a click on the root node.
|
|
st.onClick(st.root);
|
|
//end
|
|
|
|
//Add Select All/None actions
|
|
var nodeAll = $jit.id('select-all-nodes'),
|
|
nodeNone = $jit.id('select-none-nodes'),
|
|
edgeAll = $jit.id('select-all-edges'),
|
|
edgeNone = $jit.id('select-none-edges'),
|
|
labelAll = $jit.id('select-all-labels'),
|
|
labelNone = $jit.id('select-none-labels');
|
|
$jit.util.each([nodeAll, edgeAll, labelAll], function(elem) {
|
|
elem.onclick = function() {
|
|
var pn = elem.parentNode.parentNode.parentNode; //table
|
|
var inputs = pn.getElementsByTagName('input');
|
|
for(var i=0, l=inputs.length; i<l; i++) {
|
|
if(inputs[i].type == 'checkbox') {
|
|
inputs[i].checked = true;
|
|
}
|
|
}
|
|
};
|
|
});
|
|
$jit.util.each([nodeNone, edgeNone, labelNone], function(elem) {
|
|
elem.onclick = function() {
|
|
var pn = elem.parentNode.parentNode.parentNode; //table
|
|
var inputs = pn.getElementsByTagName('input');
|
|
for(var i=0, l=inputs.length; i<l; i++) {
|
|
if(inputs[i].type == 'checkbox') {
|
|
inputs[i].checked = false;
|
|
}
|
|
}
|
|
};
|
|
});
|
|
//get checkboxes
|
|
var nWidth = $jit.id('n-width'),
|
|
nHeight = $jit.id('n-height'),
|
|
nColor = $jit.id('n-color'),
|
|
nBorderColor = $jit.id('n-border-color'),
|
|
nBorderWidth = $jit.id('n-border-width'),
|
|
eLineWidth = $jit.id('e-line-width'),
|
|
eLineColor = $jit.id('e-line-color'),
|
|
lFontSize = $jit.id('l-font-size'),
|
|
lFontColor = $jit.id('l-font-color');
|
|
|
|
//init Morphing Animations
|
|
var button = $jit.id('update'),
|
|
restore = $jit.id('restore'),
|
|
rand = Math.random,
|
|
floor = Math.floor,
|
|
colors = ['#33a', '#55b', '#77c', '#99d', '#aae', '#bf0', '#cf5',
|
|
'#dfa', '#faccff', '#ffccff', '#CCC', '#C37'],
|
|
colorLength = colors.length;
|
|
//add click event for restore
|
|
$jit.util.addEvent(restore, 'click', function() {
|
|
if(init.busy) return;
|
|
init.busy = true;
|
|
|
|
st.graph.eachNode(function(n) {
|
|
//restore width and height node styles
|
|
n.setDataset('end', {
|
|
width: 60,
|
|
height: 20
|
|
});
|
|
//restore canvas specific styles
|
|
n.setCanvasStyles('end', {
|
|
fillStyle: '#daa',
|
|
strokeStyle: '#ffc',
|
|
lineWidth: 2
|
|
});
|
|
//restore font styles
|
|
n.setLabelDataset('end', {
|
|
size: 10,
|
|
color: '#333'
|
|
});
|
|
//set adjacencies styles
|
|
n.eachAdjacency(function(adj) {
|
|
adj.setDataset('end', {
|
|
lineWidth: 1,
|
|
color: '#ffc'
|
|
});
|
|
});
|
|
});
|
|
st.compute('end');
|
|
st.geom.translate({x:-130, y:0}, 'end');
|
|
st.fx.animate({
|
|
modes: ['linear',
|
|
'node-property:width:height',
|
|
'edge-property:lineWidth:color',
|
|
'label-property:size:color',
|
|
'node-style:fillStyle:strokeStyle:lineWidth'],
|
|
duration: 1500,
|
|
onComplete: function() {
|
|
init.busy = false;
|
|
}
|
|
});
|
|
});
|
|
//add click event for updating styles
|
|
$jit.util.addEvent(button, 'click', function() {
|
|
if(init.busy) return;
|
|
init.busy = true;
|
|
|
|
st.graph.eachNode(function(n) {
|
|
//set random width and height node styles
|
|
nWidth.checked && n.setData('width', floor(rand() * 40 + 20), 'end');
|
|
nHeight.checked && n.setData('height', floor(rand() * 40 + 20), 'end');
|
|
//set random canvas specific styles
|
|
nColor.checked && n.setCanvasStyle('fillStyle', colors[floor(colorLength * rand())], 'end');
|
|
nBorderColor.checked && n.setCanvasStyle('strokeStyle', colors[floor(colorLength * rand())], 'end');
|
|
nBorderWidth.checked && n.setCanvasStyle('lineWidth', 10 * rand() + 1, 'end');
|
|
//set label styles
|
|
lFontSize.checked && n.setLabelData('size', 20 * rand() + 1, 'end');
|
|
lFontColor.checked && n.setLabelData('color', colors[floor(colorLength * rand())], 'end');
|
|
//set adjacency styles
|
|
n.eachAdjacency(function(adj) {
|
|
eLineWidth.checked && adj.setData('lineWidth', 10 * rand() + 1, 'end');
|
|
eLineColor.checked && adj.setData('color', colors[floor(colorLength * rand())], 'end');
|
|
});
|
|
});
|
|
st.compute('end');
|
|
st.geom.translate({x:-130, y:0}, 'end');
|
|
st.fx.animate({
|
|
modes: ['linear',
|
|
'node-property:width:height',
|
|
'edge-property:lineWidth:color',
|
|
'label-property:size:color',
|
|
'node-style:fillStyle:strokeStyle:lineWidth'],
|
|
duration: 1500,
|
|
onComplete: function() {
|
|
init.busy = false;
|
|
}
|
|
});
|
|
});
|
|
//end
|
|
}
|