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}