Browse Source

Attached ItemSet again

css_transitions
josdejong 10 years ago
parent
commit
f64b2fac95
8 changed files with 136 additions and 189 deletions
  1. +11
    -31
      src/timeline/Range.js
  2. +97
    -111
      src/timeline/Timeline.js
  3. +2
    -2
      src/timeline/component/ContentPanel.js
  4. +1
    -8
      src/timeline/component/GroupSet.js
  5. +9
    -30
      src/timeline/component/ItemSet.js
  6. +12
    -7
      src/timeline/component/Panel.js
  7. +1
    -0
      src/timeline/component/RootPanel.js
  8. +3
    -0
      src/timeline/component/css/panel.css

+ 11
- 31
src/timeline/Range.js View File

@ -16,41 +16,21 @@ function Range(root, parent, options) {
this.parent = parent;
this.options = options || {};
// drag start listener
var me = this;
this.root.on('dragstart', function (event) {
me._onDragStart(event, parent);
});
// drag listener
this.root.on('drag', function (event) {
me._onDrag(event, parent);
});
// drag end listener
this.root.on('dragend', function (event) {
me._onDragEnd(event);
});
// drag listeners for draggign
this.root.on('dragstart', this._onDragStart.bind(this));
this.root.on('drag', this._onDrag.bind(this));
this.root.on('dragend', this._onDragEnd.bind(this));
// ignore dragging when holding
this.root.on('hold', function (event) {
me._onHold();
});
this.root.on('hold', this._onHold.bind(this));
// mouse wheel
function mousewheel (event) {
me._onMouseWheel(event, parent);
}
this.root.on('mousewheel', mousewheel);
this.root.on('DOMMouseScroll', mousewheel); // For FF
// mouse wheel for zooming
this.root.on('mousewheel', this._onMouseWheel.bind(this));
this.root.on('DOMMouseScroll', this._onMouseWheel.bind(this)); // For FF
// pinch
this.root.on('touch', function (event) {
me._onTouch(event);
});
this.root.on('pinch', function (event) {
me._onPinch(event);
});
// pinch to zoom
this.root.on('touch', this._onTouch.bind(this));
this.root.on('pinch', this._onPinch.bind(this));
this.setOptions(options);
}

+ 97
- 111
src/timeline/Timeline.js View File

@ -65,8 +65,7 @@ function Timeline (container, items, options) {
}
else {
// auto height
// return (me.timeaxis.height + me.content.height) + 'px';
// TODO: return the sum of the height of the childs
return (me.timeAxis.height + me.contentPanel.height) + 'px';
}
};
this.rootPanel = new RootPanel(container, rootOptions);
@ -81,36 +80,38 @@ function Timeline (container, items, options) {
this.rootPanel.on('doubletap', this._onAddItem.bind(this));
// label panel
var labelOptions = Object.create(this.options);
labelOptions.top = '0';
labelOptions.bottom = null;
labelOptions.left = '0';
labelOptions.right = null;
labelOptions.height = '100%';
labelOptions.width = function () {
/* TODO: dynamically determine the width of the label panel
if (me.content && typeof me.content.getLabelsWidth === 'function') {
return me.content.getLabelsWidth();
var labelOptions = util.extend(Object.create(this.options), {
top: '0',
bottom: null,
left: '0',
rigth: null,
height: null,
width: function () {
/* TODO: dynamically determine the width of the label panel
if (me.content && typeof me.content.getLabelsWidth === 'function') {
return me.content.getLabelsWidth();
}
else {
return 0;
}
*/
return 200;
}
else {
return 0;
}
*/
return 200;
};
});
this.labelPanel = new Panel(labelOptions);
this.rootPanel.appendChild(this.labelPanel);
// main panel (contains time axis and itemsets)
var mainOptions = Object.create(this.options);
mainOptions.top = '0';
mainOptions.bottom = null;
mainOptions.left = null;
mainOptions.right = '0';
mainOptions.height = '100%';
mainOptions.width = function () {
return me.rootPanel.width - me.labelPanel.width;
};
var mainOptions = util.extend(Object.create(this.options), {
top: '0',
bottom: null,
left: null,
right: '0',
height: '100%',
width: function () {
return me.rootPanel.width - me.labelPanel.width;
}
});
this.mainPanel = new Panel(mainOptions);
this.rootPanel.appendChild(this.mainPanel);
@ -132,27 +133,31 @@ function Timeline (container, items, options) {
});
// panel with time axis
var timeAxisOptions = Object.create(rootOptions);
timeAxisOptions.range = this.range;
timeAxisOptions.left = null;
timeAxisOptions.top = null;
timeAxisOptions.width = null;
timeAxisOptions.height = null; // height is determined by the
var timeAxisOptions = util.extend(Object.create(rootOptions), {
range: this.range,
left: null,
top: null,
width: null,
height: null
});
this.timeAxis = new TimeAxis(timeAxisOptions);
this.timeAxis.setRange(this.range);
this.options.snap = this.timeAxis.snap.bind(this.timeAxis);
this.mainPanel.appendChild(this.timeAxis);
// content panel (contains itemset(s))
var contentOptions = Object.create(this.options);
contentOptions.top = '0';
contentOptions.bottom = null;
contentOptions.left = '0';
contentOptions.right = null;
contentOptions.height = function () {
return me.mainPanel.height - me.timeAxis.height;
};
contentOptions.width = null;
var contentOptions = util.extend(Object.create(this.options), {
top: function () {
return (me.options.orientation == 'top') ? (me.timeAxis.height + 'px') : '';
},
bottom: function () {
return (me.options.orientation == 'top') ? '' : (me.timeAxis.height + 'px');
},
left: null,
right: null,
height: null,
width: null
});
this.contentPanel = new Panel(contentOptions);
this.mainPanel.appendChild(this.contentPanel);
@ -170,6 +175,9 @@ function Timeline (container, items, options) {
me.emit('timechanged', time);
});
this.itemSet = null;
this.groupSet = null;
// create groupset
this.setGroups(null);
@ -220,7 +228,6 @@ Timeline.prototype.setOptions = function (options) {
}).bind(this);
['onAdd', 'onUpdate', 'onRemove', 'onMove'].forEach(validateCallback);
//this.controller.reflow(); // TODO: remove
this.rootPanel.repaint();
};
@ -275,9 +282,7 @@ Timeline.prototype.setItems = function(items) {
// set items
this.itemsData = newDataSet;
/* TODO
this.content.setItems(newDataSet);
*/
(this.itemSet || this.groupSet).setItems(newDataSet);
if (initialLoad && (this.options.start == undefined || this.options.end == undefined)) {
// apply the data range as range
@ -319,71 +324,48 @@ Timeline.prototype.setGroups = function(groups) {
var me = this;
this.groupsData = groups;
// switch content type between ItemSet or GroupSet when needed
var Type = this.groupsData ? GroupSet : ItemSet;
if (!(this.content instanceof Type)) {
// remove old content set
if (this.content) {
this.content.hide();
if (this.content.setItems) {
this.content.setItems(); // disconnect from items
}
if (this.content.setGroups) {
this.content.setGroups(); // disconnect from groups
}
//this.controller.remove(this.content); // TODO: cleanup
}
// create new content set
var options = Object.create(this.options);
util.extend(options, {
top: function () {
return (me.options.orientation == 'top') ? (me.timeaxis.height + 'px') : '';
},
bottom: function () {
return (me.options.orientation == 'top') ? '' : (me.timeaxis.height + 'px');
},
left: null,
width: '100%',
height: function () {
if (me.options.height) {
// fixed height
return me.itemPanel.height - me.timeaxis.height;
}
else {
// auto height
return null;
}
},
maxHeight: function () {
// TODO: change maxHeight to be a css string like '100%' or '300px'
if (me.options.maxHeight) {
if (!util.isNumber(me.options.maxHeight)) {
throw new TypeError('Number expected for property maxHeight');
}
return me.options.maxHeight - me.timeaxis.height;
}
else {
return null;
}
},
labelContainer: function () {
return me.labelPanel.getContainer();
}
});
// create options for the itemset or groupset
var options = util.extend(Object.create(this.options), {
top: function () {
return (me.options.orientation == 'top') ? '0' : '';
},
bottom: function () {
return (me.options.orientation == 'top') ? '' : '0px';
},
right: null,
left: null,
width: null,
height: null
});
/* TODO
this.content = new Type(this.itemPanel, [this.timeaxis], options);
if (this.content.setRange) {
this.content.setRange(this.range);
if (this.groupsData) {
// GroupSet
if (this.itemSet) {
this.itemSet.hide(); // TODO: not so nice having to hide here
this.contentPanel.removeChild(this.itemSet);
this.itemSet.setItems(); // disconnect from items
}
if (this.content.setItems) {
this.content.setItems(this.itemsData);
}
if (this.content.setGroups) {
this.content.setGroups(this.groupsData);
// create new GroupSet
this.groupSet = new GroupSet(this.labelPanel, options);
this.groupSet.setRange(this.range);
this.groupSet.setItems(this.itemsData);
this.groupSet.setGroups(this.groupsData);
this.contentPanel.appendChild(this.groupSet);
}
else {
// ItemSet
if (this.groupSet) {
this.groupSet.hide(); // TODO: not so nice having to hide here
this.contentPanel.removeChild(this.groupSet);
this.groupSet.setItems(); // disconnect from items
}
*/
// create new items
this.itemSet = new ItemSet(options);
this.itemSet.setRange(this.range);
this.itemSet.setItems(this.itemsData);
this.contentPanel.appendChild(this.itemSet);
}
};
@ -434,7 +416,9 @@ Timeline.prototype.getItemRange = function getItemRange() {
* unselected.
*/
Timeline.prototype.setSelection = function setSelection (ids) {
if (this.content) this.content.setSelection(ids);
var itemOrGroupSet = (this.itemSet || this.groupSet);
if (itemOrGroupSet) itemOrGroupSet.setSelection(ids);
};
/**
@ -442,7 +426,9 @@ Timeline.prototype.setSelection = function setSelection (ids) {
* @return {Array} ids The ids of the selected items
*/
Timeline.prototype.getSelection = function getSelection() {
return this.content ? this.content.getSelection() : [];
var itemOrGroupSet = (this.itemSet || this.groupSet);
if (itemOrGroupSet) itemOrGroupSet.getSelection() || [];
};
/**
@ -523,7 +509,7 @@ Timeline.prototype._onAddItem = function (event) {
var xAbs = vis.util.getAbsoluteLeft(this.rootPanel.frame);
var x = event.gesture.center.pageX - xAbs;
var newItem = {
start: this.timeaxis.snap(this._toTime(x)),
start: this.timeAxis.snap(this._toTime(x)),
content: 'new item'
};

+ 2
- 2
src/timeline/component/ContentPanel.js View File

@ -47,7 +47,7 @@ ContentPanel.prototype.getContainer = function () {
* Repaint the component
*/
ContentPanel.prototype.repaint = function () {
var asSize = util.option.asSize,
var asString = util.option.asString,
options = this.options,
frame = this.frame;
@ -63,7 +63,7 @@ ContentPanel.prototype.repaint = function () {
}
// update className
frame.className = 'content-panel' + (options.className ? (' ' + asSize(options.className)) : '');
frame.className = 'content-panel' + (options.className ? (' ' + asString(options.className)) : '');
// update frame size
this._updateSize();

+ 1
- 8
src/timeline/component/GroupSet.js View File

@ -263,8 +263,7 @@ GroupSet.prototype.repaint = function repaint() {
if (!group) {
var groupOptions = Object.create(me.options);
util.extend(groupOptions, {
height: null,
maxHeight: null
height: null
});
group = new Group(me, id, groupOptions);
@ -364,12 +363,6 @@ GroupSet.prototype.repaint = function repaint() {
}
}
// FIXME: right now maxHeight is only usable when fixedHeight == false
var maxHeight = util.option.asNumber(options.maxHeight);
if (maxHeight != null) {
height = Math.min(height, maxHeight);
}
// reposition frame
frame.style.height = fixedHeight ? asSize(options.height) : this.height + 'px';
frame.style.top = asSize(options.top, '0');

+ 9
- 30
src/timeline/component/ItemSet.js View File

@ -2,19 +2,14 @@
* An ItemSet holds a set of items and ranges which can be displayed in a
* range. The width is determined by the parent of the ItemSet, and the height
* is determined by the size of the items.
* @param {Component} parent
* @param {Component[]} [depends] Components on which this components depends
* (except for the parent)
* @param {Object} [options] See ItemSet.setOptions for the available
* options.
* @constructor ItemSet
* @extends Panel
*/
// TODO: improve performance by replacing all Array.forEach with a for loop
function ItemSet(parent, depends, options) {
function ItemSet(options) {
this.id = util.randomUUID();
this.parent = parent;
this.depends = depends;
// event listeners
this.eventListeners = {
@ -208,6 +203,7 @@ ItemSet.prototype._deselect = function _deselect(id) {
*/
ItemSet.prototype.repaint = function repaint() {
var asSize = util.option.asSize,
asString = util.option.asString,
asNumber = util.option.asNumber,
options = this.options,
orientation = this.getOption('orientation'),
@ -217,13 +213,12 @@ ItemSet.prototype.repaint = function repaint() {
if (!frame) {
frame = document.createElement('div');
frame.className = 'itemset';
frame['timeline-itemset'] = this;
this.frame = frame;
var className = options.className;
if (className) {
util.addClassName(frame, util.option.asString(className));
}
if (!this.parent) throw new Error('Cannot repaint itemset: no parent attached');
var parentContainer = this.parent.getContainer();
if (!parentContainer) throw new Error('Cannot repaint itemset: parent has no container element');
// create background panel
var background = document.createElement('div');
@ -243,23 +238,13 @@ ItemSet.prototype.repaint = function repaint() {
//frame.appendChild(axis);
this.dom.axis = axis;
this.frame = frame;
}
if (!this.parent) {
throw new Error('Cannot repaint itemset: no parent attached');
}
var parentContainer = this.parent.getContainer();
if (!parentContainer) {
throw new Error('Cannot repaint itemset: parent has no container element');
}
if (!frame.parentNode) {
parentContainer.appendChild(frame);
}
if (!this.dom.axis.parentNode) {
parentContainer.appendChild(this.dom.axis);
}
// update className
frame.className = 'itemset' + (options.className ? (' ' + asString(options.className)) : '');
// check whether zoomed (in that case we need to re-stack everything)
var visibleInterval = this.range.end - this.range.start;
var zoomed = this.visibleInterval != visibleInterval;
@ -362,12 +347,6 @@ ItemSet.prototype.repaint = function repaint() {
}
}
// FIXME: right now maxHeight is only usable when fixedHeight == false
var maxHeight = asNumber(options.maxHeight);
if (maxHeight != null) {
height = Math.min(height, maxHeight);
}
// reposition frame
frame.style.left = asSize(options.left, '0');
frame.style.top = asSize(options.top, '');

+ 12
- 7
src/timeline/component/Panel.js View File

@ -77,7 +77,7 @@ Panel.prototype.removeChild = function (child) {
* Repaint the component
*/
Panel.prototype.repaint = function () {
var asSize = util.option.asSize,
var asString = util.option.asString,
options = this.options,
frame = this.frame;
@ -94,7 +94,7 @@ Panel.prototype.repaint = function () {
}
// update className
frame.className = 'vpanel' + (options.className ? (' ' + asSize(options.className)) : '');
frame.className = 'vpanel' + (options.className ? (' ' + asString(options.className)) : '');
// repaint the child components
this._repaintChilds();
@ -118,13 +118,18 @@ Panel.prototype._repaintChilds = function () {
* @private
*/
Panel.prototype._updateSize = function () {
var height = 0;
for (var i = 0, ii = this.childs.length; i < ii; i++) {
height += this.childs[i].height;
}
// apply size
this.frame.style.top = util.option.asSize(this.options.top, null);
this.frame.style.bottom = util.option.asSize(this.options.bottom, null);
this.frame.style.left = util.option.asSize(this.options.left, null);
this.frame.style.right = util.option.asSize(this.options.right, null);
this.frame.style.top = util.option.asSize(this.options.top);
this.frame.style.bottom = util.option.asSize(this.options.bottom);
this.frame.style.left = util.option.asSize(this.options.left);
this.frame.style.right = util.option.asSize(this.options.right);
this.frame.style.width = util.option.asSize(this.options.width, '100%');
this.frame.style.height = util.option.asSize(this.options.height, '100%');
this.frame.style.height = util.option.asSize(this.options.height, height + 'px');
// get actual size
this.top = this.frame.offsetTop;

+ 1
- 0
src/timeline/component/RootPanel.js View File

@ -90,6 +90,7 @@ RootPanel.prototype.repaint = function () {
this._repaintChilds();
// update frame size
this.frame.style.maxHeight = util.option.asSize(this.options.maxHeight, '');
this._updateSize();
};

+ 3
- 0
src/timeline/component/css/panel.css View File

@ -6,6 +6,9 @@
border: 1px solid #bfbfbf;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-transition: height .4s ease-in-out;
transition: height .4s ease-in-out;
}
.vis.timeline .vpanel {

Loading…
Cancel
Save