Skip to content
This repository has been archived by the owner on Jul 29, 2019. It is now read-only.

Commit

Permalink
Fix React support for group and item templates and add example (#2206)
Browse files Browse the repository at this point in the history
* Hide vertically hidden ranged items in groups that are not visible
* Add element to templates options
* Fix comment typo
* Add documentation for react mounting
* add react example
* Fix typo
* fix title
* Fix review comments
  • Loading branch information
yotamberk authored and mojoaxel committed Oct 22, 2016
1 parent 25a04fc commit d959843
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 25 deletions.
123 changes: 123 additions & 0 deletions examples/timeline/other/usingReact.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>React Components in templates</title>
</head>
<body>

<div id='root'></div>

<!--
For ease of use, we are including the React, ReactDOM and Babel CDN
builds to make getting started as fast as possible.
In production, you'll want to instead look at using something
like Gulp, Grunt or WebPack (my personal recommendation)
to compile JSX into JavaScript. Also, check out:
http://facebook.github.io/react/docs/tooling-integration.html
-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>

<script src="../../../dist/vis.js"></script>
<link href="../../../dist/vis.css" rel="stylesheet" type="text/css" />

<!--
This is where you link to your React code. Can be .js or .jsx
extension, doesn't really matter.
-->
<script type="text/babel">
var timeline;

// create groups
var numberOfGroups = 25;
var groups = new vis.DataSet()
for (var i = 0; i < numberOfGroups; i++) {
groups.add({
id: i,
content: 'Truck ' + i
})
}

// create items
var numberOfItems = 1000;
var items = new vis.DataSet();
var itemsPerGroup = Math.round(numberOfItems/numberOfGroups);
for (var truck = 0; truck < numberOfGroups; truck++) {
var date = new Date();
for (var order = 0; order < itemsPerGroup; order++) {
date.setHours(date.getHours() + 4 * (Math.random() < 0.2));
var start = new Date(date);
date.setHours(date.getHours() + 2 + Math.floor(Math.random()*4));
var end = new Date(date);
items.add({
id: order + itemsPerGroup * truck,
group: truck,
start: start,
end: end,
content: 'Order ' + order
});
}
}

var GroupTemplate = React.createClass({
render: function() {
var { group } = this.props;
return <div>
<label>{group.content}</label>
</div>
}
})

var ItemTemplate = React.createClass({
render: function() {
var { item } = this.props;
return <div>
<label>{item.content}</label>
</div>
}
})

// specify options
var options = {
orientation: 'top',
maxHeight: 400,
start: new Date(),
end: new Date(1000*60*60*24 + (new Date()).valueOf()),
editable: true,
template: function (item, element) {
ReactDOM.unmountComponentAtNode(element);
return ReactDOM.render(<ItemTemplate item={item} />, element);
},
groupTemplate: function (group, element) {
ReactDOM.unmountComponentAtNode(element);
return ReactDOM.render(<GroupTemplate group={group} />, element);
}
}


var VisTimeline = React.createClass({
componentDidMount: function() {
return initTimeline();
},
render: function() {
return <div>
<h1>Vis timline with React</h1>
<h2>Using react components for items and group templates</h2>

<div id="mytimeline"></div>
</div>
}
});

function initTimeline() {
var container = document.getElementById('mytimeline');
timeline = new vis.Timeline(container, items, groups, options);
}

ReactDOM.render(<VisTimeline />, document.getElementById('root'));
</script>
</body>
</html>
16 changes: 9 additions & 7 deletions lib/timeline/component/Group.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,12 @@ Group.prototype._create = function() {
Group.prototype.setData = function(data) {
// update contents
var content;
var templateFunction;

if (this.itemSet.options && this.itemSet.options.groupTemplate) {
content = this.itemSet.options.groupTemplate(data, this.dom.inner);
}
else {
templateFunction = this.itemSet.options.groupTemplate.bind(this);
content = templateFunction(data, this.dom.inner);
} else {
content = data && data.content;
}

Expand All @@ -100,11 +102,11 @@ Group.prototype.setData = function(data) {
this.dom.inner.removeChild(this.dom.inner.firstChild);
}
this.dom.inner.appendChild(content);
}
else if (content !== undefined && content !== null) {
} else if (content instanceof Object) {
templateFunction(data, this.dom.inner);
} else if (content !== undefined && content !== null) {
this.dom.inner.innerHTML = content;
}
else {
} else {
this.dom.inner.innerHTML = this.groupId || ''; // groupId can be null
}

Expand Down
42 changes: 24 additions & 18 deletions lib/timeline/component/item/Item.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,31 +187,37 @@ Item.prototype._repaintDeleteButton = function (anchor) {
*/
Item.prototype._updateContents = function (element) {
var content;
var templateFunction;

if (this.options.template) {
var itemData = this.parent.itemSet.itemsData.get(this.id); // get a clone of the data from the dataset
content = this.options.template(itemData, element);
}
else {
templateFunction = this.options.template.bind(this);
content = templateFunction(itemData, element);
} else {
content = this.data.content;
}

var changed = this._contentToString(this.content) !== this._contentToString(content);
if (changed) {
// only replace the content when changed
if (content instanceof Element) {
element.innerHTML = '';
element.appendChild(content);
}
else if (content != undefined) {
element.innerHTML = content;
}
else {
if (!(this.data.type == 'background' && this.data.content === undefined)) {
throw new Error('Property "content" missing in item ' + this.id);
if (content instanceof Object) {
templateFunction(itemData, element)
} else {
var changed = this._contentToString(this.content) !== this._contentToString(content);
if (changed) {
// only replace the content when changed
if (content instanceof Element) {
element.innerHTML = '';
element.appendChild(content);
}
else if (content != undefined) {
element.innerHTML = content;
}
else {
if (!(this.data.type == 'background' && this.data.content === undefined)) {
throw new Error('Property "content" missing in item ' + this.id);
}
}
}

this.content = content;
this.content = content;
}
}
};

Expand Down

0 comments on commit d959843

Please sign in to comment.