Browse Source

Fixed #248: Implemented support for templates

v3_develop
jos 10 years ago
parent
commit
8ba08c5a8b
9 changed files with 25138 additions and 24788 deletions
  1. +1
    -0
      HISTORY.md
  2. +24780
    -24771
      dist/vis.js
  3. +1
    -1
      dist/vis.map
  4. +11
    -11
      dist/vis.min.js
  5. +82
    -0
      docs/timeline.html
  6. +248
    -0
      examples/timeline/25_templates.html
  7. +1
    -0
      examples/timeline/index.html
  8. +1
    -1
      lib/timeline/component/ItemSet.js
  9. +13
    -4
      lib/timeline/component/item/Item.js

+ 1
- 0
HISTORY.md View File

@ -18,6 +18,7 @@ http://visjs.org
### Timeline ### Timeline
- Implemented support for templates.
- Implemented a new item type: `'background'`. This can be used to mark periods - Implemented a new item type: `'background'`. This can be used to mark periods
with a background color and label. with a background color and label.
- Implemented support for attaching HTML attributes to items. Thanks @dturkenk. - Implemented support for attaching HTML attributes to items. Thanks @dturkenk.

+ 24780
- 24771
dist/vis.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/vis.map
File diff suppressed because it is too large
View File


+ 11
- 11
dist/vis.min.js
File diff suppressed because it is too large
View File


+ 82
- 0
docs/timeline.html View File

@ -43,6 +43,7 @@
<li><a href="#Methods">Methods</a></li> <li><a href="#Methods">Methods</a></li>
<li><a href="#Events">Events</a></li> <li><a href="#Events">Events</a></li>
<li><a href="#Editing_Items">Editing Items</a></li> <li><a href="#Editing_Items">Editing Items</a></li>
<li><a href="#Templates">Templates</a></li>
<li><a href="#Localization">Localization</a></li> <li><a href="#Localization">Localization</a></li>
<li><a href="#Styles">Styles</a></li> <li><a href="#Styles">Styles</a></li>
<li><a href="#Data_Policy">Data Policy</a></li> <li><a href="#Data_Policy">Data Policy</a></li>
@ -664,6 +665,13 @@ var options = {
If not provided, the earliest date present in the events is taken as start date.</td> If not provided, the earliest date present in the events is taken as start date.</td>
</tr> </tr>
<tr>
<td>template</td>
<td>Function</td>
<td>none</td>
<td>A template function used to generate the contents of the items. The function is called by the Timeline with an items data as argument, and must return HTML code as result. When the option template is specified, the items do not need to have a field <code>content</code>. See section <a href="#Templates">Templates</a> for a detailed explanation.</td>
</tr>
<tr> <tr>
<td>type</td> <td>type</td>
<td>String</td> <td>String</td>
@ -1068,6 +1076,80 @@ var options = {
A full example is available here: <a href="../examples/timeline/08_edit_items.html">08_edit_items.html</a>. A full example is available here: <a href="../examples/timeline/08_edit_items.html">08_edit_items.html</a>.
<h2 id="Templates">Templates</h2>
<p>
Timeline supports templates to format item contents. Any template engine (such as <a href="http://handlebarsjs.com/">handlebars</a> or <a href="http://mustache.github.io/">mustache</a>) can be used, and one can also manually build HTML. In the options, one can provide a template handler. This handler is a function accepting an items data as argument, and outputs formatted HTML:
</p>
<pre class="prettyprint lang-js">var options = {
template: function (item) {
var html = ... // generate HTML markup for this item
return html;
}
};
</pre>
<h3>Create HTML manually</h3>
The HTML for an item can be created manually:
<pre class="prettyprint lang-js">var options = {
template: function (item) {
return '&lt;h1&gt;' + item.header + '&lt;/h1&gt;&lt;p&gt;' + item.description + '&lt;/p&gt;';
}
};
</pre>
<h3>Using a template engine</h3>
Using <a href="http://handlebarsjs.com/">handlebars</a>, one can write the template in HTML:
<pre class="prettyprint lang-html">
&lt;script id="item-template" type="text/x-handlebars-template"&gt;
&lt;h1&gt;{{header}}&lt;/h1&gt;
&lt;p&gt;{{description}}&lt;/p&gt;
&lt;/script&gt;
</pre>
Compile the template:
<pre class="prettyprint lang-js">
var source = document.getElementById('item-template').innerHTML;
var template = Handlebars.compile(source);
</pre>
And then specify the template in the Timeline options
<pre class="prettyprint lang-js">var options = {
template: template
};
</pre>
<h3>Multiple templates</h3>
In order to support multiple templates, the template handler can be extended to switch between different templates, depending on a specific item property:
<pre class="prettyprint lang-js">
var templates = {
template1: Handlebars.compile(...),
template2: Handlebars.compile(...),
template2: Handlebars.compile(...),
...
};
var options = {
template: function (item) {
var template = templates[item.template]; // choose the right template
return template(item); // execute the template
}
};
</pre>
Now the items can be extended with a property <code>template</code>, specifying which template to use for the item.
<h2 id="Localization">Localization</h2> <h2 id="Localization">Localization</h2>
<p> <p>
Timeline can be localized. For localization, Timeline depends largely on the localization of <a href="http://momentjs.com">moment.js</a>. Locales are not included in vis.js by default. To enable localization, moment.js must be loaded with locales. Moment.js offers a bundle named "moment-with-locales.min.js" for this and there are various alternative ways to load locales. Timeline can be localized. For localization, Timeline depends largely on the localization of <a href="http://momentjs.com">moment.js</a>. Locales are not included in vis.js by default. To enable localization, moment.js must be loaded with locales. Moment.js offers a bundle named "moment-with-locales.min.js" for this and there are various alternative ways to load locales.

+ 248
- 0
examples/timeline/25_templates.html View File

@ -0,0 +1,248 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Timeline | Basic demo</title>
<!-- load handlebars for templating, and create a template -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0-alpha.4/handlebars.min.js"></script>
<script id="item-template" type="text/x-handlebars-template">
<table class="score">
<tr>
<td colspan="3" class="description">{{description}}</td>
</tr>
<tr>
<td>{{player1}}</td>
<th>{{score1}} - {{score2}}</th>
<td>{{player2}}</td>
</tr>
<tr>
<td><img src="http://flagpedia.net/data/flags/mini/{{abbr1}}.png" width="31" height="20" alt="{{abbr1}}"></td>
<th></th>
<td><img src="http://flagpedia.net/data/flags/mini/{{abbr2}}.png" width="31" height="20" alt="{{abbr2}}"></td>
</tr>
</table>
</script>
<script src="../../dist/vis.js"></script>
<link href="../../dist/vis.css" rel="stylesheet" type="text/css" />
<style type="text/css">
body, html {
font-family: sans-serif;
font-size: 10pt;
}
.vis.timeline .item {
border-color: #acacac;
background-color: #efefef;
box-shadow: 5px 5px 10px rgba(128,128,128, 0.3);
}
table .description {
font-style: italic;
}
#visualization {
position: relative;
}
.logo {
position: absolute;
right: 10px;
top: 10px;
}
.logo img {
width: 120px;
}
</style>
</head>
<body>
<h1>WK 2014</h1>
<p>
This example demonstrates using templates to format item contents.
</p>
<div id="visualization">
<div class="logo"><img src="http://upload.wikimedia.org/wikipedia/en/e/e8/WC-2014-Brasil.svg"></div>
</div>
<script type="text/javascript">
// create a handlebars template
var source = document.getElementById('item-template').innerHTML;
var template = Handlebars.compile(document.getElementById('item-template').innerHTML);
// DOM element where the Timeline will be attached
var container = document.getElementById('visualization');
// Create a DataSet (allows two way data-binding)
var items = new vis.DataSet([
{
player1: 'Brazil',
abbr1: 'br',
score1: '1 (3)',
player2: 'Chile',
abbr2: 'cl',
score2: '1 (2)',
description: 'round of 16',
start: '2014-06-28 13:00'
},
{
player1: 'Colombia',
abbr1: 'co',
score1: 2,
player2: 'Uruguay',
abbr2: 'uy',
score2: 0,
description: 'round of 16',
start: '2014-06-28 17:00'
},
{
player1: 'Netherlands',
abbr1: 'nl',
score1: 2,
player2: 'Mexico',
abbr2: 'mx',
score2: 1,
description: 'round of 16',
start: '2014-06-29 13:00'
},
{
player1: 'Costa Rica',
abbr1: 'cr',
score1: '1 (5)',
player2: 'Greece',
abbr2: 'gr',
score2: '1 (3)',
description: 'round of 16',
start: '2014-06-29 17:00'
},
{
player1: 'France',
abbr1: 'fr',
score1: 2,
player2: 'Nigeria',
abbr2: 'ng',
score2: 0,
description: 'round of 16',
start: '2014-06-30 13:00'
},
{
player1: 'Germany',
abbr1: 'de',
score1: 2,
player2: 'Algeria',
abbr2: 'dz',
score2: 1,
description: 'round of 16',
start: '2014-06-30 17:00'
},
{
player1: 'Argentina',
abbr1: 'ar',
score1: 1,
player2: 'Switzerland',
abbr2: 'ch',
score2: 0,
description: 'round of 16',
start: '2014-07-01 13:00'
},
{
player1: 'Belgium',
abbr1: 'be',
score1: 2,
player2: 'USA',
abbr2: 'us',
score2: 1,
description: 'round of 16',
start: '2014-07-01 17:00'
},
// quarter-finals
{
player1: 'France',
abbr1: 'fr',
score1: 0,
player2: 'Germany',
abbr2: 'de',
score2: 1,
description: 'quarter-finals',
start: '2014-07-04 13:00'
},
{
player1: 'Brazil',
abbr1: 'br',
score1: 2,
player2: 'Colombia',
abbr2: 'co',
score2: 1,
description: 'quarter-finals',
start: '2014-07-04 17:00'
},
{
player1: 'Argentina',
abbr1: 'ar',
score1: 1,
player2: 'Belgium',
abbr2: 'be',
score2: 0,
description: 'quarter-finals',
start: '2014-07-05 13:00'
},
{
player1: 'Netherlands',
abbr1: 'nl',
score1: '0 (4)',
player2: 'Costa Rica',
abbr2: 'cr',
score2: '0 (3)',
description: 'quarter-finals',
start: '2014-07-05 17:00'
},
// semi-finals
{
player1: 'Brazil',
abbr1: 'br',
score1: 1,
player2: 'Germany',
abbr2: 'de',
score2: 7,
description: 'semi-finals',
start: '2014-07-08 17:00'
},
{
player1: 'Netherlands',
abbr1: 'nl',
score1: '0 (2)',
player2: 'Argentina',
abbr2: 'ar',
score2: '0 (4)',
description: 'semi-finals',
start: '2014-07-09 17:00'
},
// final
{
player1: 'Germany',
score1: 1,
abbr1: 'de',
player2: 'Argentina',
abbr2: 'ar',
score2: 0,
description: 'final',
start: '2014-07-13 16:00'
}
]);
// Configuration for the Timeline
var options = {
// specify a template for the items
template: template
};
// Create a Timeline
var timeline = new vis.Timeline(container, items, options);
</script>
</body>
</html>

+ 1
- 0
examples/timeline/index.html View File

@ -36,6 +36,7 @@
<p><a href="22_window_adjustment.html">22_window_adjustment.html</a></p> <p><a href="22_window_adjustment.html">22_window_adjustment.html</a></p>
<p><a href="23_data_attributes.html">23_data_attributes.html</a></p> <p><a href="23_data_attributes.html">23_data_attributes.html</a></p>
<p><a href="24_background_areas.html">24_background_areas.html</a></p> <p><a href="24_background_areas.html">24_background_areas.html</a></p>
<p><a href="25_templates.html">25_templates.html</a></p>
<p><a href="requirejs/requirejs_example.html">requirejs_example.html</a></p> <p><a href="requirejs/requirejs_example.html">requirejs_example.html</a></p>

+ 1
- 1
lib/timeline/component/ItemSet.js View File

@ -262,7 +262,7 @@ ItemSet.prototype._create = function(){
ItemSet.prototype.setOptions = function(options) { ItemSet.prototype.setOptions = function(options) {
if (options) { if (options) {
// copy all options that we know // copy all options that we know
var fields = ['type', 'align', 'orientation', 'padding', 'stack', 'selectable', 'groupOrder', 'dataAttributes'];
var fields = ['type', 'align', 'orientation', 'padding', 'stack', 'selectable', 'groupOrder', 'dataAttributes', 'template'];
util.selectiveExtend(fields, this.options, options); util.selectiveExtend(fields, this.options, options);
if ('margin' in options) { if ('margin' in options) {

+ 13
- 4
lib/timeline/component/item/Item.js View File

@ -159,12 +159,21 @@ Item.prototype._repaintDeleteButton = function (anchor) {
* @private * @private
*/ */
Item.prototype._updateContents = function (element) { Item.prototype._updateContents = function (element) {
if (this.data.content instanceof Element) {
var content;
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);
}
else {
content = this.data.content;
}
if (content instanceof Element) {
element.innerHTML = ''; element.innerHTML = '';
element.appendChild(this.data.content);
element.appendChild(content);
} }
else if (this.data.content != undefined) {
element.innerHTML = this.data.content;
else if (content != undefined) {
element.innerHTML = content;
} }
else { else {
throw new Error('Property "content" missing in item ' + this.data.id); throw new Error('Property "content" missing in item ' + this.data.id);

Loading…
Cancel
Save