Browse Source

Consistently using Emitter instead of home-baked event emitter everywhere

css_transitions
josdejong 10 years ago
parent
commit
568ac65686
5 changed files with 142 additions and 96 deletions
  1. +65
    -0
      examples/timeline/07_custom_time_bar.html
  2. +1
    -0
      examples/timeline/index.html
  3. +32
    -8
      src/timeline/Timeline.js
  4. +44
    -82
      src/timeline/component/CustomTime.js
  5. +0
    -6
      src/timeline/component/ItemSet.js

+ 65
- 0
examples/timeline/07_custom_time_bar.html View File

@ -0,0 +1,65 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Timeline | Show current and custom time bars</title>
<style type="text/css">
body, html {
font-family: sans-serif;
font-size: 11pt;
}
</style>
<script src="../../dist/vis.js"></script>
<link href="../../dist/vis.css" rel="stylesheet" type="text/css" />
</head>
<body>
<p>
<input type="text" id="setTime" value="2014-02-07" />
<input type="button" id="set" value="Set custom time" />
</p>
<p>
<input type="button" id="get" value="Get custom time" />
<span id="getTime"></span>
</p>
<p>
<code>timechange</code> event: <span id="timechangeEvent"></span>
</p>
<p>
<code>timechanged</code> event: <span id="timechangedEvent"></span>
</p>
<div id="visualization"></div>
<script type="text/javascript">
var container = document.getElementById('visualization');
var items = [];
var options = {
showCurrentTime: true,
showCustomTime: true,
start: new Date(Date.now() - 1000 * 60 * 60 * 24),
end: new Date(Date.now() + 1000 * 60 * 60 * 24 * 6)
};
var timeline = new vis.Timeline(container, items, options);
document.getElementById('set').onclick = function () {
var time = document.getElementById('setTime').value;
timeline.setCustomTime(time);
};
document.getElementById('setTime').value = new Date().toISOString().substring(0, 10);
document.getElementById('get').onclick = function () {
document.getElementById('getTime').innerHTML = timeline.getCustomTime();
};
timeline.on('timechange', function (properties) {
document.getElementById('timechangeEvent').innerHTML = properties.time;
});
timeline.on('timechanged', function (properties) {
document.getElementById('timechangedEvent').innerHTML = properties.time;
});
</script>
</body>
</html>

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

@ -18,6 +18,7 @@
<p><a href="04_html_data.html">04_html_data.html</a></p> <p><a href="04_html_data.html">04_html_data.html</a></p>
<p><a href="05_groups.html">05_groups.html</a></p> <p><a href="05_groups.html">05_groups.html</a></p>
<p><a href="06_event_listeners.html">06_event_listeners.html</a></p> <p><a href="06_event_listeners.html">06_event_listeners.html</a></p>
<p><a href="07_custom_time_bar.html">07_custom_time_bar.html</a></p>
</div> </div>
</body> </body>

+ 32
- 8
src/timeline/Timeline.js View File

@ -96,13 +96,13 @@ function Timeline (container, items, options) {
this.range.subscribe(this.controller, this.rootPanel, 'zoom', 'horizontal'); this.range.subscribe(this.controller, this.rootPanel, 'zoom', 'horizontal');
this.range.on('rangechange', function (properties) { this.range.on('rangechange', function (properties) {
var force = true; var force = true;
me.controller.emit('rangechange', properties);
me.controller.emit('request-reflow', force); me.controller.emit('request-reflow', force);
me.emit('rangechange', properties);
}); });
this.range.on('rangechanged', function (properties) { this.range.on('rangechanged', function (properties) {
var force = true; var force = true;
me.controller.emit('rangechanged', properties);
me.controller.emit('request-reflow', force); me.controller.emit('request-reflow', force);
me.emit('rangechanged', properties);
}); });
// time axis // time axis
@ -141,8 +141,24 @@ function Timeline (container, items, options) {
} }
} }
// extend Timeline with the Emitter mixin
Emitter(Timeline.prototype);
/**
* Add an event listener to the timeline
* @param {String} event Available events: select, rangechange, rangechanged,
* timechange, timechanged
* @param {function} callback
*/
Timeline.prototype.on = function on (event, callback) {
this.controller.on(event, callback);
};
/**
* Add an event listener from the timeline
* @param {String} event
* @param {function} callback
*/
Timeline.prototype.off = function off (event, callback) {
this.controller.off(event, callback);
};
/** /**
* Set options * Set options
@ -164,7 +180,11 @@ Timeline.prototype.setOptions = function (options) {
* @param {Date} time * @param {Date} time
*/ */
Timeline.prototype.setCustomTime = function (time) { Timeline.prototype.setCustomTime = function (time) {
this.customtime._setCustomTime(time);
if (!this.customtime) {
throw new Error('Cannot get custom time: Custom time bar is not enabled');
}
this.customtime.setCustomTime(time);
}; };
/** /**
@ -172,7 +192,11 @@ Timeline.prototype.setCustomTime = function (time) {
* @return {Date} customTime * @return {Date} customTime
*/ */
Timeline.prototype.getCustomTime = function() { Timeline.prototype.getCustomTime = function() {
return new Date(this.customtime.customTime.valueOf());
if (!this.customtime) {
throw new Error('Cannot get custom time: Custom time bar is not enabled');
}
return this.customtime.getCustomTime();
}; };
/** /**
@ -383,7 +407,7 @@ Timeline.prototype._onSelectItem = function (event) {
var selection = item ? [item.id] : []; var selection = item ? [item.id] : [];
this.setSelection(selection); this.setSelection(selection);
this.emit('select', {
this.controller.emit('select', {
items: this.getSelection() items: this.getSelection()
}); });
@ -417,7 +441,7 @@ Timeline.prototype._onMultiSelectItem = function (event) {
} }
this.setSelection(selection); this.setSelection(selection);
this.emit('select', {
this.controller.emit('select', {
items: this.getSelection() items: this.getSelection()
}); });

+ 44
- 82
src/timeline/component/CustomTime.js View File

@ -19,12 +19,14 @@ function CustomTime (parent, depends, options) {
showCustomTime: false showCustomTime: false
}; };
this.listeners = [];
this.customTime = new Date(); this.customTime = new Date();
this.eventParams = {}; // stores state parameters while dragging the bar
} }
CustomTime.prototype = new Component(); CustomTime.prototype = new Component();
Emitter(CustomTime.prototype);
CustomTime.prototype.setOptions = Component.prototype.setOptions; CustomTime.prototype.setOptions = Component.prototype.setOptions;
/** /**
@ -59,7 +61,7 @@ CustomTime.prototype.repaint = function () {
delete this.frame; delete this.frame;
} }
return;
return false;
} }
if (!bar) { if (!bar) {
@ -81,7 +83,8 @@ CustomTime.prototype.repaint = function () {
this.frame = bar; this.frame = bar;
this.subscribe(this, 'movetime');
var me = this;
util.addEventListener(bar, 'mousedown', me._onMouseDown.bind(me));
} }
if (!parent.conversion) { if (!parent.conversion) {
@ -100,7 +103,7 @@ CustomTime.prototype.repaint = function () {
* Set custom time. * Set custom time.
* @param {Date} time * @param {Date} time
*/ */
CustomTime.prototype._setCustomTime = function(time) {
CustomTime.prototype.setCustomTime = function(time) {
this.customTime = new Date(time.valueOf()); this.customTime = new Date(time.valueOf());
this.repaint(); this.repaint();
}; };
@ -109,55 +112,17 @@ CustomTime.prototype._setCustomTime = function(time) {
* Retrieve the current custom time. * Retrieve the current custom time.
* @return {Date} customTime * @return {Date} customTime
*/ */
CustomTime.prototype._getCustomTime = function() {
CustomTime.prototype.getCustomTime = function() {
return new Date(this.customTime.valueOf()); return new Date(this.customTime.valueOf());
}; };
/**
* Add listeners for mouse and touch events to the component
* @param {Component} component
*/
CustomTime.prototype.subscribe = function (component, event) {
var me = this;
var listener = {
component: component,
event: event,
callback: function (event) {
me._onMouseDown(event, listener);
},
params: {}
};
component.on('mousedown', listener.callback);
me.listeners.push(listener);
};
/**
* Event handler
* @param {String} event name of the event, for example 'click', 'mousemove'
* @param {function} callback callback handler, invoked with the raw HTML Event
* as parameter.
*/
CustomTime.prototype.on = function (event, callback) {
var bar = this.frame;
if (!bar) {
throw new Error('Cannot add event listener: no parent attached');
}
events.addListener(this, event, callback);
util.addEventListener(bar, event, callback);
};
/** /**
* Start moving horizontally * Start moving horizontally
* @param {Event} event * @param {Event} event
* @param {Object} listener Listener containing the component and params
* @private * @private
*/ */
CustomTime.prototype._onMouseDown = function(event, listener) {
CustomTime.prototype._onMouseDown = function(event) {
event = event || window.event; event = event || window.event;
var params = listener.params;
// only react on left mouse button down // only react on left mouse button down
var leftButtonDown = event.which ? (event.which == 1) : (event.button == 1); var leftButtonDown = event.which ? (event.which == 1) : (event.button == 1);
@ -166,24 +131,20 @@ CustomTime.prototype._onMouseDown = function(event, listener) {
} }
// get mouse position // get mouse position
params.mouseX = util.getPageX(event);
params.moved = false;
this.eventParams.mouseX = util.getPageX(event);
this.eventParams.moved = false;
params.customTime = this.customTime;
this.eventParams.customTime = this.customTime;
// add event listeners to handle moving the custom time bar // add event listeners to handle moving the custom time bar
var me = this; var me = this;
if (!params.onMouseMove) {
params.onMouseMove = function (event) {
me._onMouseMove(event, listener);
};
util.addEventListener(document, 'mousemove', params.onMouseMove);
if (!this.eventParams.onMouseMove) {
this.eventParams.onMouseMove = me._onMouseMove.bind(me);
util.addEventListener(document, 'mousemove', this.eventParams.onMouseMove);
} }
if (!params.onMouseUp) {
params.onMouseUp = function (event) {
me._onMouseUp(event, listener);
};
util.addEventListener(document, 'mouseup', params.onMouseUp);
if (!this.eventParams.onMouseUp) {
this.eventParams.onMouseUp = me._onMouseUp.bind(me);
util.addEventListener(document, 'mouseup', this.eventParams.onMouseUp);
} }
util.stopPropagation(event); util.stopPropagation(event);
@ -192,37 +153,38 @@ CustomTime.prototype._onMouseDown = function(event, listener) {
/** /**
* Perform moving operating. * Perform moving operating.
* This function activated from within the funcion CustomTime._onMouseDown().
* This function activated from within the function CustomTime._onMouseDown().
* @param {Event} event * @param {Event} event
* @param {Object} listener
* @private * @private
*/ */
CustomTime.prototype._onMouseMove = function (event, listener) {
CustomTime.prototype._onMouseMove = function (event) {
event = event || window.event; event = event || window.event;
var params = listener.params;
var parent = this.parent; var parent = this.parent;
// calculate change in mouse position // calculate change in mouse position
var mouseX = util.getPageX(event); var mouseX = util.getPageX(event);
if (params.mouseX === undefined) {
params.mouseX = mouseX;
if (this.eventParams.mouseX === undefined) {
this.eventParams.mouseX = mouseX;
} }
var diff = mouseX - params.mouseX;
var diff = mouseX - this.eventParams.mouseX;
// if mouse movement is big enough, register it as a "moved" event // if mouse movement is big enough, register it as a "moved" event
if (Math.abs(diff) >= 1) { if (Math.abs(diff) >= 1) {
params.moved = true;
this.eventParams.moved = true;
} }
var x = parent.toScreen(params.customTime);
var x = parent.toScreen(this.eventParams.customTime);
var xnew = x + diff; var xnew = x + diff;
var time = parent.toTime(xnew);
this._setCustomTime(time);
this.setCustomTime(parent.toTime(xnew));
// fire a timechange event // fire a timechange event
events.trigger(this, 'timechange', {customTime: this.customTime});
if (this.controller) {
this.controller.emit('timechange', {
time: this.customTime
})
}
util.preventDefault(event); util.preventDefault(event);
}; };
@ -231,25 +193,25 @@ CustomTime.prototype._onMouseMove = function (event, listener) {
* Stop moving operating. * Stop moving operating.
* This function activated from within the function CustomTime._onMouseDown(). * This function activated from within the function CustomTime._onMouseDown().
* @param {event} event * @param {event} event
* @param {Object} listener
* @private * @private
*/ */
CustomTime.prototype._onMouseUp = function (event, listener) {
event = event || window.event;
var params = listener.params;
CustomTime.prototype._onMouseUp = function (event) {
// remove event listeners here, important for Safari // remove event listeners here, important for Safari
if (params.onMouseMove) {
util.removeEventListener(document, 'mousemove', params.onMouseMove);
params.onMouseMove = null;
if (this.eventParams.onMouseMove) {
util.removeEventListener(document, 'mousemove', this.eventParams.onMouseMove);
this.eventParams.onMouseMove = null;
} }
if (params.onMouseUp) {
util.removeEventListener(document, 'mouseup', params.onMouseUp);
params.onMouseUp = null;
if (this.eventParams.onMouseUp) {
util.removeEventListener(document, 'mouseup', this.eventParams.onMouseUp);
this.eventParams.onMouseUp = null;
} }
if (params.moved) {
if (this.eventParams.moved) {
// fire a timechanged event // fire a timechanged event
events.trigger(this, 'timechanged', {customTime: this.customTime});
if (this.controller) {
this.controller.emit('timechanged', {
time: this.customTime
})
}
} }
}; };

+ 0
- 6
src/timeline/component/ItemSet.js View File

@ -203,12 +203,6 @@ ItemSet.prototype.setSelection = function setSelection(ids) {
} }
} }
// trigger a select event
selection = this.selection.concat([]);
events.trigger(this, 'select', {
ids: selection
});
if (this.controller) { if (this.controller) {
this.requestRepaint(); this.requestRepaint();
} }

Loading…
Cancel
Save