timeline = function() {
const o = {
padding: 0,
accessor: identity,
flat: false,
compact: -1
};
const treeOptions = {
update: (value, T) => {
T.value._m.set(value.id, value);
},
remove: (value, T) => {
if (value._m) return true;
T.value._m.delete(value.id);
return T.value._m.size === 0;
},
compare: (a, b) => o.compact * (a.max - b.max),
create: value => {
return node({
max: value.max,
_m: new Map([[value.id, value]])
});
}
};
const Row = (id, item) => {
const r = [item];
r.id = id;
r.max = item[1];
return r;
};
Row.add = (row, item) => (row.push(item), (row.max = item[1]));
Row.check = (row, [min]) => row.length === 0 || row.max + o.padding <= min;
const timeline = function(items) {
let counter = 0;
let T = new Tree(treeOptions);
items.forEach(item => {
const interval = o.accessor(item);
interval.data = item;
let finished = T.forEach(holder =>
each(holder._m.values(), function(row) {
if (Row.check(row, interval)) {
T.remove(row);
Row.add(row, interval);
T.insert(row);
return false;
}
})
);
if (finished !== false) T.insert(Row(counter++, interval));
});
let rows = [];
T.forEach(v => [].push.apply(rows, Array.from(v._m.values())));
rows.sort((a, b) => a.id - b.id);
if (o.flat) {
const flat = flatten(rows);
flat.rows = rows.length;
return flat;
}
return rows;
};
timeline.padding = function(v) {
if (v === undefined || v === null) return o.padding;
o.padding = v;
return timeline;
};
timeline.accessor = function(v) {
if (v === undefined || v === null) return o.accessor;
o.accessor = v;
return timeline;
};
timeline.flat = function(fl) {
if (fl === undefined || fl === null) return o.flat;
o.flat = fl;
return timeline;
};
timeline.compact = function(fl) {
if (fl === undefined || fl === null) return o.compact;
o.compact = fl ? -1 : 1;
return timeline;
};
return timeline;
}