From a042d86783938b1a532134c4ad57f233371a299c Mon Sep 17 00:00:00 2001 From: josdejong Date: Thu, 3 Apr 2014 11:52:41 +0200 Subject: [PATCH] ItemSets in GroupSet are now relative positioned --- src/timeline/Timeline.js | 45 +++++++++--------- src/timeline/component/GroupSet.js | 35 +++++--------- src/timeline/component/ItemSet.js | 63 ++++++++++++------------- src/timeline/component/Panel.js | 7 +-- src/timeline/component/TimeAxis.js | 5 +- src/timeline/component/css/groupset.css | 9 ++-- src/timeline/component/css/itemset.css | 8 ++-- src/timeline/component/css/panel.css | 1 - 8 files changed, 77 insertions(+), 96 deletions(-) diff --git a/src/timeline/Timeline.js b/src/timeline/Timeline.js index 57ec6a92..7e7786bb 100644 --- a/src/timeline/Timeline.js +++ b/src/timeline/Timeline.js @@ -57,17 +57,19 @@ function Timeline (container, items, options) { }; // root panel - var rootOptions = Object.create(this.options); - rootOptions.height = function () { - if (me.options.height) { - // fixed height - return me.options.height; - } - else { - // auto height - return (me.timeAxis.height + me.contentPanel.height) + 'px'; + var rootOptions = util.extend(Object.create(this.options), { + height: function () { + if (me.options.height) { + // fixed height + return me.options.height; + } + else { + // auto height + // TODO: implement a css based solution to automatically have the right hight + return (me.timeAxis.height + me.contentPanel.height) + 'px'; + } } - }; + }); this.rootPanel = new RootPanel(container, rootOptions); // single select (or unselect) when tapping an item @@ -81,10 +83,10 @@ function Timeline (container, items, options) { // label panel var labelOptions = util.extend(Object.create(this.options), { - top: '0', + top: null, bottom: null, left: '0', - rigth: null, + right: null, height: '100%', width: function () { if (me.groupSet) { @@ -93,21 +95,23 @@ function Timeline (container, items, options) { else { return 0; } - } + }, + className: 'labels' }); this.labelPanel = new Panel(labelOptions); this.rootPanel.appendChild(this.labelPanel); // main panel (contains time axis and itemsets) var mainOptions = util.extend(Object.create(this.options), { - top: '0', + top: null, bottom: null, left: null, right: '0', height: '100%', width: function () { return me.rootPanel.width - me.labelPanel.width; - } + }, + className: 'main' }); this.mainPanel = new Panel(mainOptions); this.rootPanel.appendChild(this.mainPanel); @@ -153,7 +157,8 @@ function Timeline (container, items, options) { left: null, right: null, height: null, - width: null + width: null, + className: 'content' }); this.contentPanel = new Panel(contentOptions); this.mainPanel.appendChild(this.contentPanel); @@ -323,12 +328,8 @@ Timeline.prototype.setGroups = function(groups) { // 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'; - }, + top: null, + bottom: null, right: null, left: null, width: null, diff --git a/src/timeline/component/GroupSet.js b/src/timeline/component/GroupSet.js index fa504a1e..4387906a 100644 --- a/src/timeline/component/GroupSet.js +++ b/src/timeline/component/GroupSet.js @@ -205,7 +205,6 @@ GroupSet.prototype.repaint = function repaint() { update = util.updateProperty, asSize = util.option.asSize, asString = util.option.asString, - asElement = util.option.asElement, options = this.options, orientation = this.getOption('orientation'), frame = this.dom.frame, @@ -239,9 +238,6 @@ GroupSet.prototype.repaint = function repaint() { this.dom.labelSet = labelSet; } - // update classname - frame.className = 'groupset' + (options.className ? (' ' + asString(options.className)) : ''); - var me = this, queue = this.queue, groups = this.groups, @@ -291,23 +287,11 @@ GroupSet.prototype.repaint = function repaint() { } }); - // update the top positions of the groups in the correct order + // reorder the groups var orderedGroups = this.groupsData.getIds({ order: this.options.groupOrder }); - for (i = 0; i < orderedGroups.length; i++) { - (function (group, prevGroup) { - var top = 0; - if (prevGroup) { - top = function () { - return prevGroup.top + prevGroup.height; - } - } - group.setOptions({ - top: top - }); - })(groups[orderedGroups[i]], groups[orderedGroups[i - 1]]); - } + // TODO: apply order to the DOM // (re)create the labels while (labelSet.firstChild) { @@ -361,17 +345,22 @@ GroupSet.prototype.repaint = function repaint() { } } + // update classname + frame.className = 'groupset' + (options.className ? (' ' + asString(options.className)) : ''); + // reposition frame - frame.style.height = asSize((options.height != null) ? options.height : height); - frame.style.top = asSize(options.top, '0'); - frame.style.left = asSize(options.left, '0'); - frame.style.width = asSize(options.width, '100%'); + frame.style.top = asSize((orientation == 'top') ? '0' : ''); + frame.style.bottom = asSize((orientation == 'top') ? '' : '0'); + frame.style.left = asSize(options.left, ''); + frame.style.right = asSize(options.right, ''); + frame.style.width = asSize(options.width, '100%'); + frame.style.height = asSize(height); // calculate actual size and position this.top = frame.offsetTop; this.left = frame.offsetLeft; this.width = frame.offsetWidth; - this.height = frame.offsetHeight; + this.height = height; // reposition labels labelSet.style.top = asSize(options.top, '0'); diff --git a/src/timeline/component/ItemSet.js b/src/timeline/component/ItemSet.js index 7a5cd608..e727b036 100644 --- a/src/timeline/component/ItemSet.js +++ b/src/timeline/component/ItemSet.js @@ -175,14 +175,15 @@ ItemSet.prototype.repaint = function repaint() { this._updateConversion(); if (!frame) { - frame = document.createElement('div'); - frame['timeline-itemset'] = this; - 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'); + frame = document.createElement('div'); + frame['timeline-itemset'] = this; + parentContainer.appendChild(frame); + this.frame = frame; + // create background panel var background = document.createElement('div'); background.className = 'background'; @@ -197,12 +198,9 @@ ItemSet.prototype.repaint = function repaint() { // create axis panel var axis = document.createElement('div'); - axis.className = 'itemset-axis'; - //frame.appendChild(axis); + axis.className = 'axis'; this.dom.axis = axis; - - parentContainer.appendChild(frame); - parentContainer.appendChild(this.dom.axis); + frame.appendChild(axis); // attach event listeners // TODO: use event listeners from the rootpanel to improve performance @@ -299,45 +297,44 @@ ItemSet.prototype.repaint = function repaint() { // recalculate the height of the itemset var marginAxis = (options.margin && 'axis' in options.margin) ? options.margin.axis : this.itemOptions.margin.axis, marginItem = (options.margin && 'item' in options.margin) ? options.margin.item : this.itemOptions.margin.item, - fixedHeight = (asSize(options.height) != null), height; - // height is not specified, determine the height from the height and positioned items - if (!fixedHeight) { - var visibleItems = this.visibleItems; - if (visibleItems.length) { - var min = visibleItems[0].top; - var max = visibleItems[0].top + visibleItems[0].height; - util.forEach(visibleItems, function (item) { - min = Math.min(min, item.top); - max = Math.max(max, (item.top + item.height)); - }); - height = (max - min) + marginAxis + marginItem; - } - else { - height = marginAxis + marginItem; - } + // determine the height from the stacked items + var visibleItems = this.visibleItems; + if (visibleItems.length) { + var min = visibleItems[0].top; + var max = visibleItems[0].top + visibleItems[0].height; + util.forEach(visibleItems, function (item) { + min = Math.min(min, item.top); + max = Math.max(max, (item.top + item.height)); + }); + height = (max - min) + marginAxis + marginItem; + } + else { + height = marginAxis + marginItem; } // reposition frame - frame.style.left = asSize(options.left, '0'); - frame.style.top = asSize(options.top, ''); - //frame.style.bottom = asSize(options.bottom, ''); + frame.style.left = asSize(options.left, ''); + frame.style.right = asSize(options.right, ''); + frame.style.top = asSize((orientation == 'top') ? '0' : ''); + frame.style.bottom = asSize((orientation == 'top') ? '' : '0'); frame.style.width = asSize(options.width, '100%'); - frame.style.height = fixedHeight ? asSize(options.height) : height + 'px'; + frame.style.height = asSize(height); // calculate actual size and position this.top = frame.offsetTop; this.left = frame.offsetLeft; this.width = frame.offsetWidth; - this.height = fixedHeight ? frame.offsetHeight : height; + this.height = height; // reposition axis this.dom.axis.style.left = asSize(options.left, '0'); + this.dom.axis.style.right = asSize(options.right, ''); this.dom.axis.style.width = asSize(options.width, '100%'); - this.dom.axis.style.top = (orientation == 'top' ? this.top : this.top + this.height) + 'px'; - //this.dom.axis.style.top = asSize(options.top, ''); - //this.dom.axis.style.bottom = asSize(options.bottom, ''); + this.dom.axis.style.height = asSize(0); + this.dom.axis.style.top = (orientation == 'top') ? '0' : ''; + this.dom.axis.style.bottom = (orientation == 'top') ? '' : '0'; return false; }; diff --git a/src/timeline/component/Panel.js b/src/timeline/component/Panel.js index 4ad2c0c0..12f2cf27 100644 --- a/src/timeline/component/Panel.js +++ b/src/timeline/component/Panel.js @@ -118,18 +118,13 @@ 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); 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, height + 'px'); + this.frame.style.height = util.option.asSize(this.options.height, ''); // get actual size this.top = this.frame.offsetTop; diff --git a/src/timeline/component/TimeAxis.js b/src/timeline/component/TimeAxis.js index 1a84f7d6..89ad28a1 100644 --- a/src/timeline/component/TimeAxis.js +++ b/src/timeline/component/TimeAxis.js @@ -73,9 +73,6 @@ TimeAxis.prototype.repaint = function () { frame.className = 'axis'; // TODO: custom className? - // update its size - this.width = frame.offsetWidth; // TODO: only update the width when the frame is resized - if (!frame.parentNode) { if (!this.parent) { throw new Error('Cannot repaint time axis: no parent attached'); @@ -102,6 +99,8 @@ TimeAxis.prototype.repaint = function () { props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; this.height = props.minorLabelHeight + props.majorLabelHeight; + this.width = frame.offsetWidth; // TODO: only update the width when the frame is resized? + props.minorLineHeight = parentHeight + props.minorLabelHeight; props.minorLineWidth = 1; // TODO: really calculate width props.majorLineHeight = parentHeight + this.height; diff --git a/src/timeline/component/css/groupset.css b/src/timeline/component/css/groupset.css index 310e1596..ae37328f 100644 --- a/src/timeline/component/css/groupset.css +++ b/src/timeline/component/css/groupset.css @@ -1,6 +1,6 @@ .vis.timeline .groupset { - position: absolute; + position: relative; padding: 0; margin: 0; } @@ -21,11 +21,10 @@ } .vis.timeline .labels .label-set { - position: absolute; + position: relative; top: 0; left: 0; width: 100%; - height: 100%; overflow: hidden; @@ -54,13 +53,13 @@ } .vis.timeline.top .labels .label-set .vlabel, -.vis.timeline.top .groupset .itemset-axis { +.vis.timeline.top .groupset .itemset .axis { border-top: 1px solid #bfbfbf; border-bottom: none; } .vis.timeline.bottom .labels .label-set .vlabel, -.vis.timeline.bottom .groupset .itemset-axis { +.vis.timeline.bottom .groupset .itemset .axis { border-top: none; border-bottom: 1px solid #bfbfbf; } diff --git a/src/timeline/component/css/itemset.css b/src/timeline/component/css/itemset.css index c21d8fa1..95b0b678 100644 --- a/src/timeline/component/css/itemset.css +++ b/src/timeline/component/css/itemset.css @@ -1,9 +1,11 @@ .vis.timeline .itemset { - position: absolute; + position: relative; padding: 0; margin: 0; - overflow: hidden; + + -webkit-transition: height .4s ease-in-out; + transition: height .4s ease-in-out; } .vis.timeline .background { @@ -12,6 +14,6 @@ .vis.timeline .foreground { } -.vis.timeline .itemset-axis { +.vis.timeline .axis { position: absolute; } diff --git a/src/timeline/component/css/panel.css b/src/timeline/component/css/panel.css index cef917eb..964f6424 100644 --- a/src/timeline/component/css/panel.css +++ b/src/timeline/component/css/panel.css @@ -14,7 +14,6 @@ .vis.timeline .vpanel { position: absolute; - overflow: hidden; -moz-box-sizing: border-box; box-sizing: border-box;