From a093bc4ac0ce196d1b9fbd768a79ad9811e2ff74 Mon Sep 17 00:00:00 2001 From: yotamberk Date: Sat, 17 Dec 2016 00:37:36 +0200 Subject: [PATCH] Add visibleFrameTemplate option for higher item dom content (#2437) * Fix redraw order * Add initial itemVisibleFrame * Add visibleFrameTemplate option * Improve example * Rename and fix example * Fix comments from PR * Fix example --- docs/timeline/index.html | 14 +++- .../items/visibleFrameTemplateContent.html | 67 +++++++++++++++++++ lib/timeline/component/ItemSet.js | 4 +- lib/timeline/component/css/item.css | 4 ++ lib/timeline/component/item/Item.js | 39 ++++++++++- lib/timeline/component/item/RangeItem.js | 7 +- lib/timeline/optionsTimeline.js | 1 + 7 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 examples/timeline/items/visibleFrameTemplateContent.html diff --git a/docs/timeline/index.html b/docs/timeline/index.html index 321ef258..e0d3291c 100644 --- a/docs/timeline/index.html +++ b/docs/timeline/index.html @@ -679,7 +679,7 @@ 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 the first argument and the group element as the second, 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. + A template function used to generate the contents of the groups. The function is called by the Timeline with a groups data as the first argument and the group element as the second, and must return HTML code, a string or a template 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. @@ -1025,7 +1025,15 @@ function (option, path) { template function none - A template function used to generate the contents of the items. The function is called by the Timeline with an items data as the first argument and the item element as the second, and must return HTML code as result. When the option template is specified, the items do not need to have a field content. See section Templates for a detailed explanation. + A template function used to generate the contents of the items. The function is called by the Timeline with an items' data as the first argument and the item element as the second, and must return HTML code, a string or a template as result. When the option template is specified, the items do not need to have a field content. See section Templates for a detailed explanation. + + + + visibleFrameTemplate + function + none + A template function used to generate the visible frame of the items. The function is called by the Timeline with an items' data as the first argument and the item frame element as the second, and must return HTML code, a string or a template as result. When the option template is specified, the items do not need to have a field content. See section Templates for a detailed explanation. + This would be used as an additional way to add content that is constant in size with the visible frame of the item and does not get visibly hidden with the item's internal container: vis-item-overflow which is overflow:hidden. @@ -1072,7 +1080,7 @@ function (option, path) { template Function none - A template function used to generate the contents of the tooltip. The function is called by the Timeline with an item data as the first argument, and must return HTML code as result. See section Templates for a detailed explanation. + A template function used to generate the contents of the tooltip. The function is called by the Timeline with an item data as the first argument, and must return HTML code, a string or a template as result. See section Templates for a detailed explanation. diff --git a/examples/timeline/items/visibleFrameTemplateContent.html b/examples/timeline/items/visibleFrameTemplateContent.html new file mode 100644 index 00000000..67715766 --- /dev/null +++ b/examples/timeline/items/visibleFrameTemplateContent.html @@ -0,0 +1,67 @@ + + + + Timeline | Dynamic Content + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/lib/timeline/component/ItemSet.js b/lib/timeline/component/ItemSet.js index 5ae07ade..53de50af 100644 --- a/lib/timeline/component/ItemSet.js +++ b/lib/timeline/component/ItemSet.js @@ -321,8 +321,8 @@ ItemSet.prototype.setOptions = function(options) { // copy all options that we know var fields = [ 'type', 'rtl', 'align', 'order', 'stack', 'selectable', 'multiselect', 'itemsAlwaysDraggable', - 'multiselectPerGroup', 'groupOrder', 'dataAttributes', 'template', 'groupTemplate', 'hide', 'snap', - 'groupOrderSwap', 'tooltipOnItemUpdateTime' + 'multiselectPerGroup', 'groupOrder', 'dataAttributes', 'template', 'groupTemplate', 'visibleFrameTemplate', + 'hide', 'snap', 'groupOrderSwap', 'tooltipOnItemUpdateTime' ]; util.selectiveExtend(fields, this.options, options); diff --git a/lib/timeline/component/css/item.css b/lib/timeline/component/css/item.css index 37f05533..67221d23 100644 --- a/lib/timeline/component/css/item.css +++ b/lib/timeline/component/css/item.css @@ -66,6 +66,10 @@ overflow: hidden; } +.vis-item-visible-frame { + white-space: nowrap; +} + .vis-item.vis-range .vis-item-content { position: relative; display: inline-block; diff --git a/lib/timeline/component/item/Item.js b/lib/timeline/component/item/Item.js index 9057dd66..a7522921 100644 --- a/lib/timeline/component/item/Item.js +++ b/lib/timeline/component/item/Item.js @@ -325,9 +325,46 @@ Item.prototype._repaintOnItemUpdateTimeTooltip = function (anchor) { Item.prototype._updateContents = function (element) { var content; var templateFunction; + var itemVisibleFrameContent; + var visibleFrameTemplateFunction; + var itemData = this.parent.itemSet.itemsData.get(this.id); // get a clone of the data from the dataset + + var frameElement = this.dom.box || this.dom.point; + var itemVisibleFrameContentElement = frameElement.getElementsByClassName('vis-item-visible-frame')[0] + + if (this.options.visibleFrameTemplate) { + visibleFrameTemplateFunction = this.options.visibleFrameTemplate.bind(this); + itemVisibleFrameContent = visibleFrameTemplateFunction(itemData, frameElement); + } else { + itemVisibleFrameContent = ''; + } + + if (itemVisibleFrameContentElement) { + if ((itemVisibleFrameContent instanceof Object) && !(itemVisibleFrameContent instanceof Element)) { + visibleFrameTemplateFunction(itemData, itemVisibleFrameContentElement) + } else { + var changed = this._contentToString(this.itemVisibleFrameContent) !== this._contentToString(itemVisibleFrameContent); + if (changed) { + // only replace the content when changed + if (itemVisibleFrameContent instanceof Element) { + itemVisibleFrameContentElement.innerHTML = ''; + itemVisibleFrameContentElement.appendChild(itemVisibleFrameContent); + } + else if (itemVisibleFrameContent != undefined) { + itemVisibleFrameContentElement.innerHTML = itemVisibleFrameContent; + } + else { + if (!(this.data.type == 'background' && this.data.content === undefined)) { + throw new Error('Property "content" missing in item ' + this.id); + } + } + + this.itemVisibleFrameContent = itemVisibleFrameContent; + } + } + } if (this.options.template) { - var itemData = this.parent.itemSet.itemsData.get(this.id); // get a clone of the data from the dataset templateFunction = this.options.template.bind(this); content = templateFunction(itemData, element); } else { diff --git a/lib/timeline/component/item/RangeItem.js b/lib/timeline/component/item/RangeItem.js index a840b529..bc586e8f 100644 --- a/lib/timeline/component/item/RangeItem.js +++ b/lib/timeline/component/item/RangeItem.js @@ -60,10 +60,15 @@ RangeItem.prototype.redraw = function() { dom.box = document.createElement('div'); // className is updated in redraw() - // frame box (to prevent the item contents from overflowing + // frame box (to prevent the item contents from overflowing) dom.frame = document.createElement('div'); dom.frame.className = 'vis-item-overflow'; dom.box.appendChild(dom.frame); + + // visible frame box (showing the frame that is always visible) + dom.visibleFrame = document.createElement('div'); + dom.visibleFrame.className = 'vis-item-visible-frame'; + dom.box.appendChild(dom.visibleFrame); // contents box dom.content = document.createElement('div'); diff --git a/lib/timeline/optionsTimeline.js b/lib/timeline/optionsTimeline.js index 4354a213..5ef426b4 100644 --- a/lib/timeline/optionsTimeline.js +++ b/lib/timeline/optionsTimeline.js @@ -128,6 +128,7 @@ let allOptions = { start: {date, number, string, moment}, template: {'function': 'function'}, groupTemplate: {'function': 'function'}, + visibleFrameTemplate: {string, 'function': 'function'}, tooltipOnItemUpdateTime: { template: {'function': 'function'}, __type__: {boolean, object}