Sequential Layout
Open in a new window.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../build/ogma.min.js"></script>
<style>
#graph-container { top: 0; bottom: 0; left: 0; right: 0; position: absolute; margin: 0; overflow: hidden; }
#wrapper {
position: absolute;
top: 10px;
right: 10px;
z-index: 400;
background: white;
padding: 10px;
}
.control-bar {
font-family: Helvetica, Arial, sans-serif;
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.control-bar label { display: block; }
.concept {
height: 10px;
width: 10px;
background-color: #2ca02c;
border-radius: 50%;
display: inline-block;
}
.table {
height: 10px;
width: 10px;
background-color: #ff9896;
border-radius: 50%;
display: inline-block;
}
</style>
</head>
<body>
<div id="graph-container"></div>
<form id="wrapper" class="control-bar">
<p>How to order the sequence:</p>
<label><input type="radio" name="layering" checked value="0" /> Auto</label>
<label><input type="radio" name="layering" value="2" /> One color per layer</label>
<label><input type="radio" name="layering" value="1" /> <span class="concept"></span> Concept → <span class="table"></span> Table</label>
</form>
<script>
'use strict';
var ogma = new Ogma({
container: 'graph-container',
});
var defaultLayoutOptions = {
direction: 'TB', // Direction of the layout. Can be TB, BT, LR, or RL,
// where T = top, B = bottom, L = left, and R = right.
duration: 300, // Duration of the animation
nodeDistance: 15, // Number of pixels that separate nodes horizontally in the layout.
levelDistance: 50, // Number of pixels between each layer in the layout.
};
ogma.parse.jsonFromUrl('files/data-flow.json')
.then(function (graph) { return ogma.setGraph(graph); })
.then(function () { return ogma.view.locateGraph(); })
.then(function () {
return runLayout(defaultLayoutOptions)
});
function runLayout (options) {
ogma.layouts.sequential(options)
.then(function () {
ogma.view.locateGraph({
easing: 'linear',
duration: 300
});
});
}
var form = document.getElementById('wrapper');
form.addEventListener('change', function () { setTimeout(onChange); });
function onChange () {
var mode = Number(Array.prototype.filter.call(form['layering'], function(input) {
return input.checked;
})[0].value);
var modes = {
// you can mix layering and roots/sinks definitions
1: {'Concept': 0, 'Table': 'sink'},
// or control the layer by layer as well
2: {'Concept': 0, 'Subject': 1, 'Area': 2, 'DataElement': 3, 'DataOwner': 4, 'DataSteward': 5, 'Column': 6, 'Table': 7, 'DQMetric': 8, 'Database': 9, 'DQDimension': 10, 'DataPolicy': 11, 'DataPrinciple': 12}
};
ogma.getNodes().fillData('layer', null);
var sinks = [];
// check if it's a supported mode
if(mode in modes){
var customLogic = modes[mode];
// pick the sinks first
sinks = ogma.getNodes().filter(function(node){
var category = node.getData('categories')[0];
return customLogic[category] === 'sink';
});
// now set the custom layering
ogma.getNodes().forEach(function(node){
var category = node.getData('categories')[0];
var layer = customLogic[category];
if(typeof layer === 'number'){
// save the layer in the node data
node.setData('layer', layer);
}
});
}
// create fresh new options
var newOptions = {};
for( var prop in defaultLayoutOptions){
newOptions[prop] = defaultLayoutOptions[prop];
}
// save the sinks in the layout options
newOptions.sinks = sinks;
runLayout(newOptions);
}
</script>
</body>
</html>