From 6cf519175c3a8afbfd1f691fbc4e87eebca120e9 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Fri, 19 Jun 2015 17:02:16 +0200 Subject: [PATCH 1/6] added templating for groups --- docs/timeline/index.html | 9 ++++++++- lib/timeline/component/Group.js | 11 +++++++++-- lib/timeline/component/ItemSet.js | 2 +- lib/timeline/optionsTimeline.js | 1 + 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/docs/timeline/index.html b/docs/timeline/index.html index eaa79b60..9961039e 100644 --- a/docs/timeline/index.html +++ b/docs/timeline/index.html @@ -580,6 +580,13 @@ function (option, path) { + + groupTemplate + function + none + A template function used to generate the contents of the groups. The function is called by the Timeline with a groups data as argument, and must return HTML code as result. When the option groupTemplate is specified, the groups do not need to have a field content. See section Templates for a detailed explanation. + + height number or String @@ -1591,4 +1598,4 @@ var options = { - \ No newline at end of file + diff --git a/lib/timeline/component/Group.js b/lib/timeline/component/Group.js index 226ebab6..b125773a 100644 --- a/lib/timeline/component/Group.js +++ b/lib/timeline/component/Group.js @@ -81,9 +81,16 @@ Group.prototype._create = function() { */ Group.prototype.setData = function(data) { // update contents - var content = data && data.content; + var content; + if (this.itemSet.options && this.itemSet.options.groupTemplate) { + content = this.itemSet.options.groupTemplate(data); + } + else { + content = data && data.content; + } + if (content instanceof Element) { - this.dom.inner.appendChild(content); + this.dom.inner.appendChild(content); } else if (content !== undefined && content !== null) { this.dom.inner.innerHTML = content; diff --git a/lib/timeline/component/ItemSet.js b/lib/timeline/component/ItemSet.js index 43c27871..f6a498ea 100644 --- a/lib/timeline/component/ItemSet.js +++ b/lib/timeline/component/ItemSet.js @@ -279,7 +279,7 @@ ItemSet.prototype._create = function(){ ItemSet.prototype.setOptions = function(options) { if (options) { // copy all options that we know - var fields = ['type', 'align', 'order', 'stack', 'selectable', 'multiselect', 'groupOrder', 'dataAttributes', 'template','hide', 'snap']; + var fields = ['type', 'align', 'order', 'stack', 'selectable', 'multiselect', 'groupOrder', 'dataAttributes', 'template','groupTemplate','hide', 'snap']; util.selectiveExtend(fields, this.options, options); if ('orientation' in options) { diff --git a/lib/timeline/optionsTimeline.js b/lib/timeline/optionsTimeline.js index 7082e8a5..d05bfc0c 100644 --- a/lib/timeline/optionsTimeline.js +++ b/lib/timeline/optionsTimeline.js @@ -104,6 +104,7 @@ let allOptions = { snap: {'function': 'function', 'null': 'null'}, start: {date, number, string, moment}, template: {'function': 'function'}, + groupTemplate: {'function': 'function'}, timeAxis: { scale: {string,'undefined': 'undefined'}, step: {number,'undefined': 'undefined'}, From 4fd843edd033be6eccc8a5b9fe0bf141584e6662 Mon Sep 17 00:00:00 2001 From: jos Date: Thu, 9 Jul 2015 15:07:53 +0200 Subject: [PATCH 2/6] Fixed #1033: Moved item data not updated in DataSet when using an asynchronous `onMove` handler --- HISTORY.md | 2 ++ lib/timeline/component/ItemSet.js | 13 +++---------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 7456d461..bd3424f8 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -16,6 +16,8 @@ http://visjs.org - Fixed #1001: First element of group style being cut. - Fixed #1071: HTML contents of a group not cleared when the contents is updated. +- Fixed #1033: Moved item data not updated in DataSet when using an asynchronous + `onMove` handler. ## 2015-07-03, version 4.4.0 diff --git a/lib/timeline/component/ItemSet.js b/lib/timeline/component/ItemSet.js index 8509c021..cd763249 100644 --- a/lib/timeline/component/ItemSet.js +++ b/lib/timeline/component/ItemSet.js @@ -46,7 +46,7 @@ function ItemSet(body, options) { remove: false }, - snap: TimeStep.snap, + snap: TimeStep.snap, onAdd: function (item, callback) { callback(item); @@ -1345,13 +1345,11 @@ ItemSet.prototype._onDragEnd = function (event) { if (this.touchParams.itemProps) { event.stopPropagation(); - // prepare a change set for the changed items - var changes = []; var me = this; var dataset = this.itemsData.getDataSet(); - var itemProps = this.touchParams.itemProps ; this.touchParams.itemProps = null; + itemProps.forEach(function (props) { var id = props.item.id; var exists = me.itemsData.get(id, me.itemOptions) != null; @@ -1376,7 +1374,7 @@ ItemSet.prototype._onDragEnd = function (event) { if (itemData) { // apply changes itemData[dataset._fieldId] = id; // ensure the item contains its id (can be undefined) - changes.push(itemData); + dataset.update(itemData); } else { // restore original values @@ -1388,11 +1386,6 @@ ItemSet.prototype._onDragEnd = function (event) { }); } }); - - // apply the changes to the data (if there are changes) - if (changes.length) { - dataset.update(changes); - } } }; From 20af47e85937e3e095e47be9469b0b5b0dc25d8a Mon Sep 17 00:00:00 2001 From: jos Date: Thu, 9 Jul 2015 15:46:53 +0200 Subject: [PATCH 3/6] Fixed #239: Do not zoom/move the window when the mouse is on the left panel with group labels --- HISTORY.md | 2 ++ lib/timeline/Range.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index aad678ec..f007ac32 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -19,6 +19,8 @@ http://visjs.org - Fixed #1071: HTML contents of a group not cleared when the contents is updated. - Fixed #1033: Moved item data not updated in DataSet when using an asynchronous `onMove` handler. +- Fixed #239: Do not zoom/move the window when the mouse is on the left panel + with group labels. ## 2015-07-03, version 4.4.0 diff --git a/lib/timeline/Range.js b/lib/timeline/Range.js index 2fc5ef73..11c33093 100644 --- a/lib/timeline/Range.js +++ b/lib/timeline/Range.js @@ -360,9 +360,13 @@ Range.conversion = function (start, end, width, totalHidden) { Range.prototype._onDragStart = function(event) { this.deltaDifference = 0; this.previousDelta = 0; + // only allow dragging when configured as movable if (!this.options.moveable) return; + // only start dragging when the mouse is inside the current range + if (!this._isInsideRange(event)) return; + // refuse to drag when we where pinching to prevent the timeline make a jump // when releasing the fingers in opposite order from the touch screen if (!this.props.touch.allowDragging) return; @@ -382,6 +386,8 @@ Range.prototype._onDragStart = function(event) { * @private */ Range.prototype._onDrag = function (event) { + if (!this.props.touch.dragging) return; + // only allow dragging when configured as movable if (!this.options.moveable) return; @@ -433,6 +439,8 @@ Range.prototype._onDrag = function (event) { * @private */ Range.prototype._onDragEnd = function (event) { + if (!this.props.touch.dragging) return; + // only allow dragging when configured as movable if (!this.options.moveable) return; @@ -464,6 +472,9 @@ Range.prototype._onMouseWheel = function(event) { // only allow zooming when configured as zoomable and moveable if (!(this.options.zoomable && this.options.moveable)) return; + // only zoom when the mouse is inside the current range + if (!this._isInsideRange(event)) return; + // retrieve delta var delta = 0; if (event.wheelDelta) { /* IE/Opera. */ @@ -561,6 +572,23 @@ Range.prototype._onPinch = function (event) { this.endToFront = true; // revert to default }; +/** + * Test whether the mouse from a mouse event is inside the visible window, + * between the current start and end date + * @param {Object} event + * @return {boolean} Returns true when inside the visible window + * @private + */ +Range.prototype._isInsideRange = function(event) { + // calculate the time where the mouse is, check whether inside + // and no scroll action should happen. + var clientX = event.center ? event.center.x : event.clientX; + var x = clientX - util.getAbsoluteLeft(this.body.dom.centerContainer); + var time = this.body.util.toTime(x); + + return time >= this.start && time <= this.end; +}; + /** * Helper function to calculate the center date for zooming * @param {{x: Number, y: Number}} pointer From 89660a3d318fe183e5b3ce395299bf2ca473efa0 Mon Sep 17 00:00:00 2001 From: jos Date: Thu, 9 Jul 2015 15:53:58 +0200 Subject: [PATCH 4/6] Added missing method getEventProperties in Core --- lib/timeline/Core.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/timeline/Core.js b/lib/timeline/Core.js index 545039c3..060dffce 100644 --- a/lib/timeline/Core.js +++ b/lib/timeline/Core.js @@ -396,6 +396,16 @@ Core.prototype.getCustomTime = function(id) { return customTimes[0].getCustomTime(); }; +/** + * Retrieve meta information from an event. + * Should be overridden by classes extending Core + * @param {Event} event + * @return {Object} An object with related information. + */ +Core.prototype.getEventProperties = function (event) { + return { event: event }; +}; + /** * Add custom vertical bar * @param {Date | String | Number} [time] A Date, unix timestamp, or From 25706fb4ed9da45be8d8f959838b6d408584c917 Mon Sep 17 00:00:00 2001 From: jos Date: Thu, 9 Jul 2015 15:59:07 +0200 Subject: [PATCH 5/6] Updated history --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index f007ac32..4874b1a1 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -15,6 +15,7 @@ http://visjs.org ### Timeline +- Implemented support for group templates (#996). Thanks @hansmaulwurf23. - Fixed #1001: First element of group style being cut. - Fixed #1071: HTML contents of a group not cleared when the contents is updated. - Fixed #1033: Moved item data not updated in DataSet when using an asynchronous From b175068b2a46ba4eb42cf92967d5cb87711da2a8 Mon Sep 17 00:00:00 2001 From: jos Date: Thu, 9 Jul 2015 16:27:45 +0200 Subject: [PATCH 6/6] Fixed #1076: Fixed possible overlap of minor labels text on the TimeAxis --- HISTORY.md | 1 + lib/timeline/component/TimeAxis.js | 12 +++++++++++- lib/timeline/component/css/timeaxis.css | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 4874b1a1..56385cf2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -16,6 +16,7 @@ http://visjs.org ### Timeline - Implemented support for group templates (#996). Thanks @hansmaulwurf23. +- Fixed #1076: Fixed possible overlap of minor labels text on the TimeAxis. - Fixed #1001: First element of group style being cut. - Fixed #1071: HTML contents of a group not cleared when the contents is updated. - Fixed #1033: Moved item data not updated in DataSet when using an asynchronous diff --git a/lib/timeline/component/TimeAxis.js b/lib/timeline/component/TimeAxis.js index 750eb54a..4c35ad4e 100644 --- a/lib/timeline/component/TimeAxis.js +++ b/lib/timeline/component/TimeAxis.js @@ -223,6 +223,7 @@ TimeAxis.prototype._repaintLabels = function () { var xPrev = 0; var width = 0; var prevLine; + var prevText; var xFirstMajorLabel = undefined; var max = 0; var className; @@ -241,9 +242,12 @@ TimeAxis.prototype._repaintLabels = function () { if (prevLine) { prevLine.style.width = width + 'px'; } + if (prevText) { + prevText.style.width = width + 'px'; + } if (this.options.showMinorLabels) { - this._repaintMinorText(x, step.getLabelMinor(), orientation, className); + prevText = this._repaintMinorText(x, step.getLabelMinor(), orientation, className); } if (isMajor && this.options.showMajorLabels) { @@ -290,6 +294,7 @@ TimeAxis.prototype._repaintLabels = function () { * @param {String} text * @param {String} orientation "top" or "bottom" (default) * @param {String} className + * @return {Element} Returns the HTML element of the created label * @private */ TimeAxis.prototype._repaintMinorText = function (x, text, orientation, className) { @@ -311,6 +316,8 @@ TimeAxis.prototype._repaintMinorText = function (x, text, orientation, className label.style.left = x + 'px'; label.className = 'vis-text vis-minor ' + className; //label.title = title; // TODO: this is a heavy operation + + return label; }; /** @@ -319,6 +326,7 @@ TimeAxis.prototype._repaintMinorText = function (x, text, orientation, className * @param {String} text * @param {String} orientation "top" or "bottom" (default) * @param {String} className + * @return {Element} Returns the HTML element of the created label * @private */ TimeAxis.prototype._repaintMajorText = function (x, text, orientation, className) { @@ -340,6 +348,8 @@ TimeAxis.prototype._repaintMajorText = function (x, text, orientation, className label.style.top = (orientation == 'top') ? '0' : (this.props.minorLabelHeight + 'px'); label.style.left = x + 'px'; + + return label; }; /** diff --git a/lib/timeline/component/css/timeaxis.css b/lib/timeline/component/css/timeaxis.css index efe8e90f..a9c72aa2 100644 --- a/lib/timeline/component/css/timeaxis.css +++ b/lib/timeline/component/css/timeaxis.css @@ -21,6 +21,9 @@ position: absolute; color: #4d4d4d; padding: 3px; + overflow: hidden; + box-sizing: border-box; + white-space: nowrap; }