Browse Source

Merge branch 'develop' of https://github.com/almende/vis into develop

Conflicts:
	dist/vis.js
v3_develop
Alex de Mulder 10 years ago
parent
commit
93056303f7
25 changed files with 49888 additions and 23507 deletions
  1. +5
    -1
      HISTORY.md
  2. +16
    -0
      README.md
  3. +26564
    -0
      dist/vis-light.js
  4. +1
    -0
      dist/vis-light.map
  5. +36
    -0
      dist/vis-light.min.js
  6. +22608
    -22768
      dist/vis.js
  7. +1
    -1
      dist/vis.map
  8. +16
    -16
      dist/vis.min.js
  9. +55
    -0
      examples/timeline/19_vis_light_bundle.html
  10. +1
    -0
      examples/timeline/index.html
  11. +41
    -6
      gulpfile.js
  12. +9
    -1
      index.js
  13. +135
    -0
      lib/graph3d/Camera.js
  14. +23
    -609
      lib/graph3d/Graph3d.js
  15. +346
    -0
      lib/graph3d/Slider.js
  16. +0
    -1
      lib/module/hammer.js
  17. +1
    -1
      lib/network/Network.js
  18. +8
    -23
      lib/network/mixins/NavigationMixin.js
  19. +1
    -1
      lib/timeline/Graph2d.js
  20. +1
    -1
      lib/timeline/Timeline.js
  21. +1
    -1
      lib/timeline/component/CustomTime.js
  22. +1
    -1
      lib/timeline/component/ItemSet.js
  23. +1
    -1
      lib/timeline/component/item/Item.js
  24. +1
    -1
      lib/timeline/component/item/ItemRange.js
  25. +16
    -74
      lib/util.js

+ 5
- 1
HISTORY.md View File

@ -12,9 +12,12 @@ http://visjs.org
allows to specify different margins horizontally/vertically.
- Removed check for number of arguments in callbacks `onAdd`, `onUpdate`,
`onRemove`, and `onMove`.
- Refactored the code to commonjs modules, which are browserifyable. This allows
to create custom bundles.
- Fixed items in groups sometimes being displayed but not positioned correctly.
- Fixed range where the `end` of the first is equal to the `start` of the second
sometimes being stacked instead of put besides each other when `item.margin=0`.
sometimes being stacked instead of put besides each other when `item.margin=0`
due to round-off errors.
### Network (formerly named Graph)
@ -31,6 +34,7 @@ http://visjs.org
- Fixed recursively constructing of hierarchical layouts.
- Added borderWidth option for nodes.
- Implemented new Hierarchical view solver.
- Fixed an issue with selecting nodes when the web page is scrolled down.

+ 16
- 0
README.md View File

@ -76,6 +76,22 @@ Where `container` is an HTML element, `data` is an Array with data or a DataSet,
and `options` is an optional object with configuration options for the
component.
### Bundles
The folder `dist` contains bundled versions of vis.js for direct use in the browser. In general, to use vis, load the files `vis.js` and `vis.css`.
vis.js offers various bundled files: default or light version, and minified or non-minified. The source code of vis.js consists of commonjs modules, which makes it possible to create custom bundles using tools like [Browserify](http://browserify.org/) or [Webpack](http://webpack.github.io/). This can be bundling just one visualization like the Timeline, or bundling vis.js as part of your own browserified web application.
Bundle | Files | Description
------ | ----- | -----------
default | vis.js, vis.css | The default bundle, fully standalone. Code is not minified, use this version for development.
default minified | vis.min.js, vis.min.css | The default bundle, fully standalone. Code is minified, use this version for production.
light | vis-light.js, vis.css | The light bundle. External libraries [moment.js](http://momentjs.com/) and [hammer.js](http://hammerjs.github.io/) are excluded and need to be loaded before loading vis. Code is not minified, use this version for development.
light minified | vis-light.min.js, vis.min.css | The light bundle. External libraries [moment.js](http://momentjs.com/) and [hammer.js](http://hammerjs.github.io/) are excluded and need to be loaded before loading vis. Codee is minified, use this version for production.
## Example

+ 26564
- 0
dist/vis-light.js
File diff suppressed because it is too large
View File


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


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


+ 22608
- 22768
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


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


+ 55
- 0
examples/timeline/19_vis_light_bundle.html View File

@ -0,0 +1,55 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Timeline | Light bundle</title>
<style type="text/css">
body, html {
font-family: arial;
}
p {
max-width: 600px;
}
</style>
<!--
load external libraries
-->
<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.7.0/moment.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/hammer.js/1.0.5/hammer.min.js"></script>
<script src="../../dist/vis-light.min.js"></script>
<link href="../../dist/vis.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<p>
The light bundle of vis.js (<code>vis-light.js</code> or <code>vis-light.min.js</code>) don't have the external dependencies of moment.js and hammer.js bundled. You have to load these yourself before loading vis-light.js. This is useful in the case that your application is using moment.js and/or hammer.js itself too, in order not to load these libraries twice. Note that it is possible too to create your own vis.js bundle: the source code consists of common.js modules which is browserifiable.
</p>
<div id="visualization"></div>
<script type="text/javascript">
// 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([
{id: 1, content: 'item 1', start: '2014-04-20'},
{id: 2, content: 'item 2', start: '2014-04-14'},
{id: 3, content: 'item 3', start: '2014-04-18'},
{id: 4, content: 'item 4', start: '2014-04-16', end: '2014-04-19'},
{id: 5, content: 'item 5', start: '2014-04-25'},
{id: 6, content: 'item 6', start: '2014-04-27', type: 'point'}
]);
// Configuration for the Timeline
var options = {
editable: true
};
// Create a Timeline
var timeline = new vis.Timeline(container, items, options);
</script>
</body>
</html>

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

@ -30,6 +30,7 @@
<p><a href="16_navigation_menu.html">16_navigation_menu.html</a></p>
<p><a href="17_data_serialization.html">17_data_serialization.html</a></p>
<p><a href="18_range_overflow.html">18_range_overflow.html</a></p>
<p><a href="19_vis_light_bundle.html">19_vis_light_bundle.html</a></p>
<p><a href="requirejs/requirejs_example.html">requirejs_example.html</a></p>

+ 41
- 6
gulpfile.js View File

@ -15,10 +15,12 @@ var HEADER = './lib/header.js';
var DIST = './dist';
var VIS_JS = 'vis.js';
var VIS_MAP = 'vis.map';
var VIS_MIN_JS = 'vis.min.js';
var VIS_LIGHT_JS = 'vis-light.js';
var VIS_LIGHT_MAP = 'vis-light.map';
var VIS_LIGHT_MIN_JS = 'vis-light.min.js';
var VIS_CSS = 'vis.css';
var VIS_MIN_CSS = 'vis.min.css';
var DIST_VIS_MIN_JS = DIST + '/vis.min.js';
var DIST_VIS_MAP = DIST + '/' + VIS_MAP;
// generate banner with today's date and correct version
function createBanner() {
@ -49,6 +51,23 @@ var webpackConfig = {
cache: true
};
var webpackConfigLight = {
entry: ENTRY,
output: {
library: 'vis',
libraryTarget: 'umd',
path: DIST,
filename: VIS_LIGHT_JS,
sourcePrefix: ' '
},
externals: [
'hammerjs',
'moment'
],
plugins: [ bannerPlugin ],
cache: true
};
var uglifyConfig = {
outSourceMap: VIS_MAP,
output: {
@ -58,6 +77,7 @@ var uglifyConfig = {
// create a single instance of the compiler to allow caching
var compiler = webpack(webpackConfig);
var compilerLight = webpack(webpackConfigLight);
// clean the dist/img directory
gulp.task('clean', function (cb) {
@ -74,6 +94,16 @@ gulp.task('bundle-js', ['clean'], function (cb) {
});
});
gulp.task('bundle-js-light', ['clean'], function (cb) {
// update the banner contents (has a date in it which should stay up to date)
bannerPlugin.banner = createBanner();
compilerLight.run(function (err, stats) {
if (err) gutil.log(err);
cb();
});
});
// bundle and minify css
gulp.task('bundle-css', ['clean'], function () {
var files = [
@ -104,7 +134,7 @@ gulp.task('bundle-css', ['clean'], function () {
.pipe(gulp.dest(DIST));
});
gulp.task('copy-img', ['clean'], function () {
gulp.task('copy', ['clean'], function () {
var network = gulp.src('./lib/network/img/**/*')
.pipe(gulp.dest(DIST + '/img/network'));
@ -115,15 +145,20 @@ gulp.task('copy-img', ['clean'], function () {
});
gulp.task('minify', ['bundle-js'], function (cb) {
// minify full version of vis.js
var result = uglify.minify([DIST + '/' + VIS_JS], uglifyConfig);
fs.writeFileSync(DIST + '/' + VIS_MIN_JS, result.code);
fs.writeFileSync(DIST + '/' + VIS_MAP, result.map);
fs.writeFileSync(DIST_VIS_MIN_JS, result.code);
fs.writeFileSync(DIST_VIS_MAP, result.map);
// minify light version of vis.js (external dependencies excluded)
var result = uglify.minify([DIST + '/' + VIS_LIGHT_JS], uglifyConfig);
fs.writeFileSync(DIST + '/' + VIS_LIGHT_MIN_JS, result.code);
fs.writeFileSync(DIST + '/' + VIS_LIGHT_MAP, result.map);
cb();
});
gulp.task('bundle', ['bundle-js', 'bundle-css', 'copy-img']);
gulp.task('bundle', ['bundle-js', 'bundle-js-light', 'bundle-css', 'copy']);
// read command line arguments --bundle and --minify
var bundle = 'bundle' in argv;

+ 9
- 1
index.js View File

@ -8,11 +8,19 @@ exports.DataView = require('./lib/DataView');
// Graph3d
exports.Graph3d = require('./lib/graph3d/Graph3d');
exports.graph3d = {
Camera: require('./lib/graph3d/Camera'),
Filter: require('./lib/graph3d/Filter'),
Point2d: require('./lib/graph3d/Point2d'),
Point3d: require('./lib/graph3d/Point3d'),
Slider: require('./lib/graph3d/Slider'),
StepNumber: require('./lib/graph3d/StepNumber')
};
// Timeline
exports.Timeline = require('./lib/timeline/Timeline');
exports.Graph2d = require('./lib/timeline/Graph2d');
exports.timeline= {
exports.timeline = {
DataStep: require('./lib/timeline/DataStep'),
Range: require('./lib/timeline/Range'),
stack: require('./lib/timeline/Stack'),

+ 135
- 0
lib/graph3d/Camera.js View File

@ -0,0 +1,135 @@
var Point3d = require('./Point3d');
/**
* @class Camera
* The camera is mounted on a (virtual) camera arm. The camera arm can rotate
* The camera is always looking in the direction of the origin of the arm.
* This way, the camera always rotates around one fixed point, the location
* of the camera arm.
*
* Documentation:
* http://en.wikipedia.org/wiki/3D_projection
*/
Camera = function () {
this.armLocation = new Point3d();
this.armRotation = {};
this.armRotation.horizontal = 0;
this.armRotation.vertical = 0;
this.armLength = 1.7;
this.cameraLocation = new Point3d();
this.cameraRotation = new Point3d(0.5*Math.PI, 0, 0);
this.calculateCameraOrientation();
};
/**
* Set the location (origin) of the arm
* @param {Number} x Normalized value of x
* @param {Number} y Normalized value of y
* @param {Number} z Normalized value of z
*/
Camera.prototype.setArmLocation = function(x, y, z) {
this.armLocation.x = x;
this.armLocation.y = y;
this.armLocation.z = z;
this.calculateCameraOrientation();
};
/**
* Set the rotation of the camera arm
* @param {Number} horizontal The horizontal rotation, between 0 and 2*PI.
* Optional, can be left undefined.
* @param {Number} vertical The vertical rotation, between 0 and 0.5*PI
* if vertical=0.5*PI, the graph is shown from the
* top. Optional, can be left undefined.
*/
Camera.prototype.setArmRotation = function(horizontal, vertical) {
if (horizontal !== undefined) {
this.armRotation.horizontal = horizontal;
}
if (vertical !== undefined) {
this.armRotation.vertical = vertical;
if (this.armRotation.vertical < 0) this.armRotation.vertical = 0;
if (this.armRotation.vertical > 0.5*Math.PI) this.armRotation.vertical = 0.5*Math.PI;
}
if (horizontal !== undefined || vertical !== undefined) {
this.calculateCameraOrientation();
}
};
/**
* Retrieve the current arm rotation
* @return {object} An object with parameters horizontal and vertical
*/
Camera.prototype.getArmRotation = function() {
var rot = {};
rot.horizontal = this.armRotation.horizontal;
rot.vertical = this.armRotation.vertical;
return rot;
};
/**
* Set the (normalized) length of the camera arm.
* @param {Number} length A length between 0.71 and 5.0
*/
Camera.prototype.setArmLength = function(length) {
if (length === undefined)
return;
this.armLength = length;
// Radius must be larger than the corner of the graph,
// which has a distance of sqrt(0.5^2+0.5^2) = 0.71 from the center of the
// graph
if (this.armLength < 0.71) this.armLength = 0.71;
if (this.armLength > 5.0) this.armLength = 5.0;
this.calculateCameraOrientation();
};
/**
* Retrieve the arm length
* @return {Number} length
*/
Camera.prototype.getArmLength = function() {
return this.armLength;
};
/**
* Retrieve the camera location
* @return {Point3d} cameraLocation
*/
Camera.prototype.getCameraLocation = function() {
return this.cameraLocation;
};
/**
* Retrieve the camera rotation
* @return {Point3d} cameraRotation
*/
Camera.prototype.getCameraRotation = function() {
return this.cameraRotation;
};
/**
* Calculate the location and rotation of the camera based on the
* position and orientation of the camera arm
*/
Camera.prototype.calculateCameraOrientation = function() {
// calculate location of the camera
this.cameraLocation.x = this.armLocation.x - this.armLength * Math.sin(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical);
this.cameraLocation.y = this.armLocation.y - this.armLength * Math.cos(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical);
this.cameraLocation.z = this.armLocation.z + this.armLength * Math.sin(this.armRotation.vertical);
// calculate rotation of the camera
this.cameraRotation.x = Math.PI/2 - this.armRotation.vertical;
this.cameraRotation.y = 0;
this.cameraRotation.z = -this.armRotation.horizontal;
};
module.exports = Camera;

+ 23
- 609
lib/graph3d/Graph3d.js View File

@ -1,9 +1,12 @@
var Emitter = require('emitter-component');
var DataSet = require('../DataSet');
var DataView = require('../DataView');
var util = require('../util');
var Point3d = require('./Point3d');
var Point2d = require('./Point2d');
var Camera = require('./Camera');
var Filter = require('./Filter');
var Slider = require('./Slider');
var StepNumber = require('./StepNumber');
/**
@ -48,7 +51,7 @@ function Graph3d(container, data, options) {
this.animationInterval = 1000; // milliseconds
this.animationPreload = false;
this.camera = new Graph3d.Camera();
this.camera = new Camera();
this.eye = new Point3d(0, 0, -1); // TODO: set eye.z about 3/4 of the width of the window?
this.dataTable = null; // The original data table
@ -97,138 +100,6 @@ function Graph3d(container, data, options) {
// Extend Graph3d with an Emitter mixin
Emitter(Graph3d.prototype);
/**
* @class Camera
* The camera is mounted on a (virtual) camera arm. The camera arm can rotate
* The camera is always looking in the direction of the origin of the arm.
* This way, the camera always rotates around one fixed point, the location
* of the camera arm.
*
* Documentation:
* http://en.wikipedia.org/wiki/3D_projection
*/
Graph3d.Camera = function () {
this.armLocation = new Point3d();
this.armRotation = {};
this.armRotation.horizontal = 0;
this.armRotation.vertical = 0;
this.armLength = 1.7;
this.cameraLocation = new Point3d();
this.cameraRotation = new Point3d(0.5*Math.PI, 0, 0);
this.calculateCameraOrientation();
};
/**
* Set the location (origin) of the arm
* @param {Number} x Normalized value of x
* @param {Number} y Normalized value of y
* @param {Number} z Normalized value of z
*/
Graph3d.Camera.prototype.setArmLocation = function(x, y, z) {
this.armLocation.x = x;
this.armLocation.y = y;
this.armLocation.z = z;
this.calculateCameraOrientation();
};
/**
* Set the rotation of the camera arm
* @param {Number} horizontal The horizontal rotation, between 0 and 2*PI.
* Optional, can be left undefined.
* @param {Number} vertical The vertical rotation, between 0 and 0.5*PI
* if vertical=0.5*PI, the graph is shown from the
* top. Optional, can be left undefined.
*/
Graph3d.Camera.prototype.setArmRotation = function(horizontal, vertical) {
if (horizontal !== undefined) {
this.armRotation.horizontal = horizontal;
}
if (vertical !== undefined) {
this.armRotation.vertical = vertical;
if (this.armRotation.vertical < 0) this.armRotation.vertical = 0;
if (this.armRotation.vertical > 0.5*Math.PI) this.armRotation.vertical = 0.5*Math.PI;
}
if (horizontal !== undefined || vertical !== undefined) {
this.calculateCameraOrientation();
}
};
/**
* Retrieve the current arm rotation
* @return {object} An object with parameters horizontal and vertical
*/
Graph3d.Camera.prototype.getArmRotation = function() {
var rot = {};
rot.horizontal = this.armRotation.horizontal;
rot.vertical = this.armRotation.vertical;
return rot;
};
/**
* Set the (normalized) length of the camera arm.
* @param {Number} length A length between 0.71 and 5.0
*/
Graph3d.Camera.prototype.setArmLength = function(length) {
if (length === undefined)
return;
this.armLength = length;
// Radius must be larger than the corner of the graph,
// which has a distance of sqrt(0.5^2+0.5^2) = 0.71 from the center of the
// graph
if (this.armLength < 0.71) this.armLength = 0.71;
if (this.armLength > 5.0) this.armLength = 5.0;
this.calculateCameraOrientation();
};
/**
* Retrieve the arm length
* @return {Number} length
*/
Graph3d.Camera.prototype.getArmLength = function() {
return this.armLength;
};
/**
* Retrieve the camera location
* @return {Point3d} cameraLocation
*/
Graph3d.Camera.prototype.getCameraLocation = function() {
return this.cameraLocation;
};
/**
* Retrieve the camera rotation
* @return {Point3d} cameraRotation
*/
Graph3d.Camera.prototype.getCameraRotation = function() {
return this.cameraRotation;
};
/**
* Calculate the location and rotation of the camera based on the
* position and orientation of the camera arm
*/
Graph3d.Camera.prototype.calculateCameraOrientation = function() {
// calculate location of the camera
this.cameraLocation.x = this.armLocation.x - this.armLength * Math.sin(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical);
this.cameraLocation.y = this.armLocation.y - this.armLength * Math.cos(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical);
this.cameraLocation.z = this.armLocation.z + this.armLength * Math.sin(this.armRotation.vertical);
// calculate rotation of the camera
this.cameraRotation.x = Math.PI/2 - this.armRotation.vertical;
this.cameraRotation.y = 0;
this.cameraRotation.z = -this.armRotation.horizontal;
};
/**
* Calculate the scaling values, dependent on the range in x, y, and z direction
*/
@ -768,11 +639,11 @@ Graph3d.prototype.create = function () {
var ontooltip = function (event) {me._onTooltip(event);};
// TODO: these events are never cleaned up... can give a 'memory leakage'
G3DaddEventListener(this.frame.canvas, 'keydown', onkeydown);
G3DaddEventListener(this.frame.canvas, 'mousedown', onmousedown);
G3DaddEventListener(this.frame.canvas, 'touchstart', ontouchstart);
G3DaddEventListener(this.frame.canvas, 'mousewheel', onmousewheel);
G3DaddEventListener(this.frame.canvas, 'mousemove', ontooltip);
util.addEventListener(this.frame.canvas, 'keydown', onkeydown);
util.addEventListener(this.frame.canvas, 'mousedown', onmousedown);
util.addEventListener(this.frame.canvas, 'touchstart', ontouchstart);
util.addEventListener(this.frame.canvas, 'mousewheel', onmousewheel);
util.addEventListener(this.frame.canvas, 'mousemove', ontooltip);
// add the new graph to the container element
this.containerElement.appendChild(this.frame);
@ -1987,9 +1858,9 @@ Graph3d.prototype._onMouseDown = function(event) {
var me = this;
this.onmousemove = function (event) {me._onMouseMove(event);};
this.onmouseup = function (event) {me._onMouseUp(event);};
G3DaddEventListener(document, 'mousemove', me.onmousemove);
G3DaddEventListener(document, 'mouseup', me.onmouseup);
G3DpreventDefault(event);
util.addEventListener(document, 'mousemove', me.onmousemove);
util.addEventListener(document, 'mouseup', me.onmouseup);
util.preventDefault(event);
};
@ -2035,7 +1906,7 @@ Graph3d.prototype._onMouseMove = function (event) {
var parameters = this.getCameraPosition();
this.emit('cameraPositionChange', parameters);
G3DpreventDefault(event);
util.preventDefault(event);
};
@ -2049,9 +1920,9 @@ Graph3d.prototype._onMouseUp = function (event) {
this.leftButtonDown = false;
// remove event listeners here
G3DremoveEventListener(document, 'mousemove', this.onmousemove);
G3DremoveEventListener(document, 'mouseup', this.onmouseup);
G3DpreventDefault(event);
util.removeEventListener(document, 'mousemove', this.onmousemove);
util.removeEventListener(document, 'mouseup', this.onmouseup);
util.preventDefault(event);
};
/**
@ -2060,8 +1931,8 @@ Graph3d.prototype._onMouseUp = function (event) {
*/
Graph3d.prototype._onTooltip = function (event) {
var delay = 300; // ms
var mouseX = getMouseX(event) - getAbsoluteLeft(this.frame);
var mouseY = getMouseY(event) - getAbsoluteTop(this.frame);
var mouseX = getMouseX(event) - util.getAbsoluteLeft(this.frame);
var mouseY = getMouseY(event) - util.getAbsoluteTop(this.frame);
if (!this.showTooltip) {
return;
@ -2114,8 +1985,8 @@ Graph3d.prototype._onTouchStart = function(event) {
var me = this;
this.ontouchmove = function (event) {me._onTouchMove(event);};
this.ontouchend = function (event) {me._onTouchEnd(event);};
G3DaddEventListener(document, 'touchmove', me.ontouchmove);
G3DaddEventListener(document, 'touchend', me.ontouchend);
util.addEventListener(document, 'touchmove', me.ontouchmove);
util.addEventListener(document, 'touchend', me.ontouchend);
this._onMouseDown(event);
};
@ -2133,8 +2004,8 @@ Graph3d.prototype._onTouchMove = function(event) {
Graph3d.prototype._onTouchEnd = function(event) {
this.touchDown = false;
G3DremoveEventListener(document, 'touchmove', this.ontouchmove);
G3DremoveEventListener(document, 'touchend', this.ontouchend);
util.removeEventListener(document, 'touchmove', this.ontouchmove);
util.removeEventListener(document, 'touchend', this.ontouchend);
this._onMouseUp(event);
};
@ -2179,7 +2050,7 @@ Graph3d.prototype._onWheel = function(event) {
// Prevent default actions caused by mouse wheel.
// That might be ugly, but we handle scrolls somehow
// anyway, so don't bother here..
G3DpreventDefault(event);
util.preventDefault(event);
};
/**
@ -2371,466 +2242,9 @@ Graph3d.prototype._hideTooltip = function () {
}
};
/**
* Add and event listener. Works for all browsers
* @param {Element} element An html element
* @param {string} action The action, for example 'click',
* without the prefix 'on'
* @param {function} listener The callback function to be executed
* @param {boolean} useCapture
*/
G3DaddEventListener = function(element, action, listener, useCapture) {
if (element.addEventListener) {
if (useCapture === undefined)
useCapture = false;
if (action === 'mousewheel' && navigator.userAgent.indexOf('Firefox') >= 0) {
action = 'DOMMouseScroll'; // For Firefox
}
element.addEventListener(action, listener, useCapture);
} else {
element.attachEvent('on' + action, listener); // IE browsers
}
};
/**
* Remove an event listener from an element
* @param {Element} element An html dom element
* @param {string} action The name of the event, for example 'mousedown'
* @param {function} listener The listener function
* @param {boolean} useCapture
*/
G3DremoveEventListener = function(element, action, listener, useCapture) {
if (element.removeEventListener) {
// non-IE browsers
if (useCapture === undefined)
useCapture = false;
if (action === 'mousewheel' && navigator.userAgent.indexOf('Firefox') >= 0) {
action = 'DOMMouseScroll'; // For Firefox
}
element.removeEventListener(action, listener, useCapture);
} else {
// IE browsers
element.detachEvent('on' + action, listener);
}
};
/**
* Stop event propagation
*/
G3DstopPropagation = function(event) {
if (!event)
event = window.event;
if (event.stopPropagation) {
event.stopPropagation(); // non-IE browsers
}
else {
event.cancelBubble = true; // IE browsers
}
};
/**
* Cancels the event if it is cancelable, without stopping further propagation of the event.
*/
G3DpreventDefault = function (event) {
if (!event)
event = window.event;
if (event.preventDefault) {
event.preventDefault(); // non-IE browsers
}
else {
event.returnValue = false; // IE browsers
}
};
/**
* @constructor Slider
*
* An html slider control with start/stop/prev/next buttons
* @param {Element} container The element where the slider will be created
* @param {Object} options Available options:
* {boolean} visible If true (default) the
* slider is visible.
*/
function Slider(container, options) {
if (container === undefined) {
throw 'Error: No container element defined';
}
this.container = container;
this.visible = (options && options.visible != undefined) ? options.visible : true;
if (this.visible) {
this.frame = document.createElement('DIV');
//this.frame.style.backgroundColor = '#E5E5E5';
this.frame.style.width = '100%';
this.frame.style.position = 'relative';
this.container.appendChild(this.frame);
this.frame.prev = document.createElement('INPUT');
this.frame.prev.type = 'BUTTON';
this.frame.prev.value = 'Prev';
this.frame.appendChild(this.frame.prev);
this.frame.play = document.createElement('INPUT');
this.frame.play.type = 'BUTTON';
this.frame.play.value = 'Play';
this.frame.appendChild(this.frame.play);
this.frame.next = document.createElement('INPUT');
this.frame.next.type = 'BUTTON';
this.frame.next.value = 'Next';
this.frame.appendChild(this.frame.next);
this.frame.bar = document.createElement('INPUT');
this.frame.bar.type = 'BUTTON';
this.frame.bar.style.position = 'absolute';
this.frame.bar.style.border = '1px solid red';
this.frame.bar.style.width = '100px';
this.frame.bar.style.height = '6px';
this.frame.bar.style.borderRadius = '2px';
this.frame.bar.style.MozBorderRadius = '2px';
this.frame.bar.style.border = '1px solid #7F7F7F';
this.frame.bar.style.backgroundColor = '#E5E5E5';
this.frame.appendChild(this.frame.bar);
this.frame.slide = document.createElement('INPUT');
this.frame.slide.type = 'BUTTON';
this.frame.slide.style.margin = '0px';
this.frame.slide.value = ' ';
this.frame.slide.style.position = 'relative';
this.frame.slide.style.left = '-100px';
this.frame.appendChild(this.frame.slide);
// create events
var me = this;
this.frame.slide.onmousedown = function (event) {me._onMouseDown(event);};
this.frame.prev.onclick = function (event) {me.prev(event);};
this.frame.play.onclick = function (event) {me.togglePlay(event);};
this.frame.next.onclick = function (event) {me.next(event);};
}
this.onChangeCallback = undefined;
this.values = [];
this.index = undefined;
this.playTimeout = undefined;
this.playInterval = 1000; // milliseconds
this.playLoop = true;
}
/**
* Select the previous index
*/
Slider.prototype.prev = function() {
var index = this.getIndex();
if (index > 0) {
index--;
this.setIndex(index);
}
};
/**
* Select the next index
*/
Slider.prototype.next = function() {
var index = this.getIndex();
if (index < this.values.length - 1) {
index++;
this.setIndex(index);
}
};
/**
* Select the next index
*/
Slider.prototype.playNext = function() {
var start = new Date();
var index = this.getIndex();
if (index < this.values.length - 1) {
index++;
this.setIndex(index);
}
else if (this.playLoop) {
// jump to the start
index = 0;
this.setIndex(index);
}
var end = new Date();
var diff = (end - start);
// calculate how much time it to to set the index and to execute the callback
// function.
var interval = Math.max(this.playInterval - diff, 0);
// document.title = diff // TODO: cleanup
var me = this;
this.playTimeout = setTimeout(function() {me.playNext();}, interval);
};
/**
* Toggle start or stop playing
*/
Slider.prototype.togglePlay = function() {
if (this.playTimeout === undefined) {
this.play();
} else {
this.stop();
}
};
/**
* Start playing
*/
Slider.prototype.play = function() {
// Test whether already playing
if (this.playTimeout) return;
this.playNext();
if (this.frame) {
this.frame.play.value = 'Stop';
}
};
/**
* Stop playing
*/
Slider.prototype.stop = function() {
clearInterval(this.playTimeout);
this.playTimeout = undefined;
if (this.frame) {
this.frame.play.value = 'Play';
}
};
/**
* Set a callback function which will be triggered when the value of the
* slider bar has changed.
*/
Slider.prototype.setOnChangeCallback = function(callback) {
this.onChangeCallback = callback;
};
/**
* Set the interval for playing the list
* @param {Number} interval The interval in milliseconds
*/
Slider.prototype.setPlayInterval = function(interval) {
this.playInterval = interval;
};
/**
* Retrieve the current play interval
* @return {Number} interval The interval in milliseconds
*/
Slider.prototype.getPlayInterval = function(interval) {
return this.playInterval;
};
/**
* Set looping on or off
* @pararm {boolean} doLoop If true, the slider will jump to the start when
* the end is passed, and will jump to the end
* when the start is passed.
*/
Slider.prototype.setPlayLoop = function(doLoop) {
this.playLoop = doLoop;
};
/**
* Execute the onchange callback function
*/
Slider.prototype.onChange = function() {
if (this.onChangeCallback !== undefined) {
this.onChangeCallback();
}
};
/**
* redraw the slider on the correct place
*/
Slider.prototype.redraw = function() {
if (this.frame) {
// resize the bar
this.frame.bar.style.top = (this.frame.clientHeight/2 -
this.frame.bar.offsetHeight/2) + 'px';
this.frame.bar.style.width = (this.frame.clientWidth -
this.frame.prev.clientWidth -
this.frame.play.clientWidth -
this.frame.next.clientWidth - 30) + 'px';
// position the slider button
var left = this.indexToLeft(this.index);
this.frame.slide.style.left = (left) + 'px';
}
};
/**
* Set the list with values for the slider
* @param {Array} values A javascript array with values (any type)
*/
Slider.prototype.setValues = function(values) {
this.values = values;
if (this.values.length > 0)
this.setIndex(0);
else
this.index = undefined;
};
/**
* Select a value by its index
* @param {Number} index
*/
Slider.prototype.setIndex = function(index) {
if (index < this.values.length) {
this.index = index;
this.redraw();
this.onChange();
}
else {
throw 'Error: index out of range';
}
};
/**
* retrieve the index of the currently selected vaue
* @return {Number} index
*/
Slider.prototype.getIndex = function() {
return this.index;
};
/**
* retrieve the currently selected value
* @return {*} value
*/
Slider.prototype.get = function() {
return this.values[this.index];
};
Slider.prototype._onMouseDown = function(event) {
// only react on left mouse button down
var leftButtonDown = event.which ? (event.which === 1) : (event.button === 1);
if (!leftButtonDown) return;
this.startClientX = event.clientX;
this.startSlideX = parseFloat(this.frame.slide.style.left);
this.frame.style.cursor = 'move';
// add event listeners to handle moving the contents
// we store the function onmousemove and onmouseup in the graph, so we can
// remove the eventlisteners lateron in the function mouseUp()
var me = this;
this.onmousemove = function (event) {me._onMouseMove(event);};
this.onmouseup = function (event) {me._onMouseUp(event);};
G3DaddEventListener(document, 'mousemove', this.onmousemove);
G3DaddEventListener(document, 'mouseup', this.onmouseup);
G3DpreventDefault(event);
};
Slider.prototype.leftToIndex = function (left) {
var width = parseFloat(this.frame.bar.style.width) -
this.frame.slide.clientWidth - 10;
var x = left - 3;
var index = Math.round(x / width * (this.values.length-1));
if (index < 0) index = 0;
if (index > this.values.length-1) index = this.values.length-1;
return index;
};
Slider.prototype.indexToLeft = function (index) {
var width = parseFloat(this.frame.bar.style.width) -
this.frame.slide.clientWidth - 10;
var x = index / (this.values.length-1) * width;
var left = x + 3;
return left;
};
Slider.prototype._onMouseMove = function (event) {
var diff = event.clientX - this.startClientX;
var x = this.startSlideX + diff;
var index = this.leftToIndex(x);
this.setIndex(index);
G3DpreventDefault();
};
Slider.prototype._onMouseUp = function (event) {
this.frame.style.cursor = 'auto';
// remove event listeners
G3DremoveEventListener(document, 'mousemove', this.onmousemove);
G3DremoveEventListener(document, 'mouseup', this.onmouseup);
G3DpreventDefault();
};
/**--------------------------------------------------------------------------**/
/**
* Retrieve the absolute left value of a DOM element
* @param {Element} elem A dom element, for example a div
* @return {Number} left The absolute left position of this element
* in the browser page.
*/
getAbsoluteLeft = function(elem) {
var left = 0;
while( elem !== null ) {
left += elem.offsetLeft;
left -= elem.scrollLeft;
elem = elem.offsetParent;
}
return left;
};
/**
* Retrieve the absolute top value of a DOM element
* @param {Element} elem A dom element, for example a div
* @return {Number} top The absolute top position of this element
* in the browser page.
*/
getAbsoluteTop = function(elem) {
var top = 0;
while( elem !== null ) {
top += elem.offsetTop;
top -= elem.scrollTop;
elem = elem.offsetParent;
}
return top;
};
/**
* Get the horizontal mouse position from a mouse event
* @param {Event} event

+ 346
- 0
lib/graph3d/Slider.js View File

@ -0,0 +1,346 @@
var util = require('../util');
/**
* @constructor Slider
*
* An html slider control with start/stop/prev/next buttons
* @param {Element} container The element where the slider will be created
* @param {Object} options Available options:
* {boolean} visible If true (default) the
* slider is visible.
*/
function Slider(container, options) {
if (container === undefined) {
throw 'Error: No container element defined';
}
this.container = container;
this.visible = (options && options.visible != undefined) ? options.visible : true;
if (this.visible) {
this.frame = document.createElement('DIV');
//this.frame.style.backgroundColor = '#E5E5E5';
this.frame.style.width = '100%';
this.frame.style.position = 'relative';
this.container.appendChild(this.frame);
this.frame.prev = document.createElement('INPUT');
this.frame.prev.type = 'BUTTON';
this.frame.prev.value = 'Prev';
this.frame.appendChild(this.frame.prev);
this.frame.play = document.createElement('INPUT');
this.frame.play.type = 'BUTTON';
this.frame.play.value = 'Play';
this.frame.appendChild(this.frame.play);
this.frame.next = document.createElement('INPUT');
this.frame.next.type = 'BUTTON';
this.frame.next.value = 'Next';
this.frame.appendChild(this.frame.next);
this.frame.bar = document.createElement('INPUT');
this.frame.bar.type = 'BUTTON';
this.frame.bar.style.position = 'absolute';
this.frame.bar.style.border = '1px solid red';
this.frame.bar.style.width = '100px';
this.frame.bar.style.height = '6px';
this.frame.bar.style.borderRadius = '2px';
this.frame.bar.style.MozBorderRadius = '2px';
this.frame.bar.style.border = '1px solid #7F7F7F';
this.frame.bar.style.backgroundColor = '#E5E5E5';
this.frame.appendChild(this.frame.bar);
this.frame.slide = document.createElement('INPUT');
this.frame.slide.type = 'BUTTON';
this.frame.slide.style.margin = '0px';
this.frame.slide.value = ' ';
this.frame.slide.style.position = 'relative';
this.frame.slide.style.left = '-100px';
this.frame.appendChild(this.frame.slide);
// create events
var me = this;
this.frame.slide.onmousedown = function (event) {me._onMouseDown(event);};
this.frame.prev.onclick = function (event) {me.prev(event);};
this.frame.play.onclick = function (event) {me.togglePlay(event);};
this.frame.next.onclick = function (event) {me.next(event);};
}
this.onChangeCallback = undefined;
this.values = [];
this.index = undefined;
this.playTimeout = undefined;
this.playInterval = 1000; // milliseconds
this.playLoop = true;
}
/**
* Select the previous index
*/
Slider.prototype.prev = function() {
var index = this.getIndex();
if (index > 0) {
index--;
this.setIndex(index);
}
};
/**
* Select the next index
*/
Slider.prototype.next = function() {
var index = this.getIndex();
if (index < this.values.length - 1) {
index++;
this.setIndex(index);
}
};
/**
* Select the next index
*/
Slider.prototype.playNext = function() {
var start = new Date();
var index = this.getIndex();
if (index < this.values.length - 1) {
index++;
this.setIndex(index);
}
else if (this.playLoop) {
// jump to the start
index = 0;
this.setIndex(index);
}
var end = new Date();
var diff = (end - start);
// calculate how much time it to to set the index and to execute the callback
// function.
var interval = Math.max(this.playInterval - diff, 0);
// document.title = diff // TODO: cleanup
var me = this;
this.playTimeout = setTimeout(function() {me.playNext();}, interval);
};
/**
* Toggle start or stop playing
*/
Slider.prototype.togglePlay = function() {
if (this.playTimeout === undefined) {
this.play();
} else {
this.stop();
}
};
/**
* Start playing
*/
Slider.prototype.play = function() {
// Test whether already playing
if (this.playTimeout) return;
this.playNext();
if (this.frame) {
this.frame.play.value = 'Stop';
}
};
/**
* Stop playing
*/
Slider.prototype.stop = function() {
clearInterval(this.playTimeout);
this.playTimeout = undefined;
if (this.frame) {
this.frame.play.value = 'Play';
}
};
/**
* Set a callback function which will be triggered when the value of the
* slider bar has changed.
*/
Slider.prototype.setOnChangeCallback = function(callback) {
this.onChangeCallback = callback;
};
/**
* Set the interval for playing the list
* @param {Number} interval The interval in milliseconds
*/
Slider.prototype.setPlayInterval = function(interval) {
this.playInterval = interval;
};
/**
* Retrieve the current play interval
* @return {Number} interval The interval in milliseconds
*/
Slider.prototype.getPlayInterval = function(interval) {
return this.playInterval;
};
/**
* Set looping on or off
* @pararm {boolean} doLoop If true, the slider will jump to the start when
* the end is passed, and will jump to the end
* when the start is passed.
*/
Slider.prototype.setPlayLoop = function(doLoop) {
this.playLoop = doLoop;
};
/**
* Execute the onchange callback function
*/
Slider.prototype.onChange = function() {
if (this.onChangeCallback !== undefined) {
this.onChangeCallback();
}
};
/**
* redraw the slider on the correct place
*/
Slider.prototype.redraw = function() {
if (this.frame) {
// resize the bar
this.frame.bar.style.top = (this.frame.clientHeight/2 -
this.frame.bar.offsetHeight/2) + 'px';
this.frame.bar.style.width = (this.frame.clientWidth -
this.frame.prev.clientWidth -
this.frame.play.clientWidth -
this.frame.next.clientWidth - 30) + 'px';
// position the slider button
var left = this.indexToLeft(this.index);
this.frame.slide.style.left = (left) + 'px';
}
};
/**
* Set the list with values for the slider
* @param {Array} values A javascript array with values (any type)
*/
Slider.prototype.setValues = function(values) {
this.values = values;
if (this.values.length > 0)
this.setIndex(0);
else
this.index = undefined;
};
/**
* Select a value by its index
* @param {Number} index
*/
Slider.prototype.setIndex = function(index) {
if (index < this.values.length) {
this.index = index;
this.redraw();
this.onChange();
}
else {
throw 'Error: index out of range';
}
};
/**
* retrieve the index of the currently selected vaue
* @return {Number} index
*/
Slider.prototype.getIndex = function() {
return this.index;
};
/**
* retrieve the currently selected value
* @return {*} value
*/
Slider.prototype.get = function() {
return this.values[this.index];
};
Slider.prototype._onMouseDown = function(event) {
// only react on left mouse button down
var leftButtonDown = event.which ? (event.which === 1) : (event.button === 1);
if (!leftButtonDown) return;
this.startClientX = event.clientX;
this.startSlideX = parseFloat(this.frame.slide.style.left);
this.frame.style.cursor = 'move';
// add event listeners to handle moving the contents
// we store the function onmousemove and onmouseup in the graph, so we can
// remove the eventlisteners lateron in the function mouseUp()
var me = this;
this.onmousemove = function (event) {me._onMouseMove(event);};
this.onmouseup = function (event) {me._onMouseUp(event);};
util.addEventListener(document, 'mousemove', this.onmousemove);
util.addEventListener(document, 'mouseup', this.onmouseup);
util.preventDefault(event);
};
Slider.prototype.leftToIndex = function (left) {
var width = parseFloat(this.frame.bar.style.width) -
this.frame.slide.clientWidth - 10;
var x = left - 3;
var index = Math.round(x / width * (this.values.length-1));
if (index < 0) index = 0;
if (index > this.values.length-1) index = this.values.length-1;
return index;
};
Slider.prototype.indexToLeft = function (index) {
var width = parseFloat(this.frame.bar.style.width) -
this.frame.slide.clientWidth - 10;
var x = index / (this.values.length-1) * width;
var left = x + 3;
return left;
};
Slider.prototype._onMouseMove = function (event) {
var diff = event.clientX - this.startClientX;
var x = this.startSlideX + diff;
var index = this.leftToIndex(x);
this.setIndex(index);
util.preventDefault();
};
Slider.prototype._onMouseUp = function (event) {
this.frame.style.cursor = 'auto';
// remove event listeners
util.removeEventListener(document, 'mousemove', this.onmousemove);
util.removeEventListener(document, 'mouseup', this.onmouseup);
util.preventDefault();
};
module.exports = Slider;

+ 0
- 1
lib/module/hammer.js View File

@ -2,7 +2,6 @@
// (loading hammer.js in a node.js environment gives errors)
if (typeof window !== 'undefined') {
module.exports = window['Hammer'] || require('hammerjs');
// TODO: throw an error when hammerjs is not available?
}
else {
module.exports = function () {

+ 1
- 1
lib/network/Network.js View File

@ -1,5 +1,5 @@
var Emitter = require('emitter-component');
var Hammer = require('hammerjs');
var Hammer = require('../module/hammer');
var mousetrap = require('mousetrap');
var util = require('../util');
var DataSet = require('../DataSet');

+ 8
- 23
lib/network/mixins/NavigationMixin.js View File

@ -1,3 +1,5 @@
var util = require('../../util');
exports._cleanNavigation = function() {
// clean up previous navigation items
var wrapper = document.getElementById('network-navigation_wrapper');
@ -52,23 +54,6 @@ exports._stopMovement = function() {
};
/**
* stops the actions performed by page up and down etc.
*
* @param event
* @private
*/
exports._preventDefault = function(event) {
if (event !== undefined) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
}
};
/**
* move the screen up
* By using the increments, instead of adding a fixed number to the translation, we keep fluent and
@ -80,7 +65,7 @@ exports._preventDefault = function(event) {
exports._moveUp = function(event) {
this.yIncrement = this.constants.keyboard.speed.y;
this.start(); // if there is no node movement, the calculation wont be done
this._preventDefault(event);
util.preventDefault(event);
if (this.navigationDivs) {
this.navigationDivs['up'].className += " active";
}
@ -94,7 +79,7 @@ exports._moveUp = function(event) {
exports._moveDown = function(event) {
this.yIncrement = -this.constants.keyboard.speed.y;
this.start(); // if there is no node movement, the calculation wont be done
this._preventDefault(event);
util.preventDefault(event);
if (this.navigationDivs) {
this.navigationDivs['down'].className += " active";
}
@ -108,7 +93,7 @@ exports._moveDown = function(event) {
exports._moveLeft = function(event) {
this.xIncrement = this.constants.keyboard.speed.x;
this.start(); // if there is no node movement, the calculation wont be done
this._preventDefault(event);
util.preventDefault(event);
if (this.navigationDivs) {
this.navigationDivs['left'].className += " active";
}
@ -122,7 +107,7 @@ exports._moveLeft = function(event) {
exports._moveRight = function(event) {
this.xIncrement = -this.constants.keyboard.speed.y;
this.start(); // if there is no node movement, the calculation wont be done
this._preventDefault(event);
util.preventDefault(event);
if (this.navigationDivs) {
this.navigationDivs['right'].className += " active";
}
@ -136,7 +121,7 @@ exports._moveRight = function(event) {
exports._zoomIn = function(event) {
this.zoomIncrement = this.constants.keyboard.speed.zoom;
this.start(); // if there is no node movement, the calculation wont be done
this._preventDefault(event);
util.preventDefault(event);
if (this.navigationDivs) {
this.navigationDivs['zoomIn'].className += " active";
}
@ -150,7 +135,7 @@ exports._zoomIn = function(event) {
exports._zoomOut = function() {
this.zoomIncrement = -this.constants.keyboard.speed.zoom;
this.start(); // if there is no node movement, the calculation wont be done
this._preventDefault(event);
util.preventDefault(event);
if (this.navigationDivs) {
this.navigationDivs['zoomOut'].className += " active";
}

+ 1
- 1
lib/timeline/Graph2d.js View File

@ -1,5 +1,5 @@
var Emitter = require('emitter-component');
var Hammer = require('hammerjs');
var Hammer = require('../module/hammer');
var util = require('../util');
var DataSet = require('../DataSet');
var DataView = require('../DataView');

+ 1
- 1
lib/timeline/Timeline.js View File

@ -1,5 +1,5 @@
var Emitter = require('emitter-component');
var Hammer = require('hammerjs');
var Hammer = require('../module/hammer');
var util = require('../util');
var DataSet = require('../DataSet');
var DataView = require('../DataView');

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

@ -1,4 +1,4 @@
var Hammer = require('hammerjs');
var Hammer = require('../../module/hammer');
var util = require('../../util');
var Component = require('./Component');

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

@ -1,4 +1,4 @@
var Hammer = require('hammerjs');
var Hammer = require('../../module/hammer');
var util = require('../../util');
var DataSet = require('../../DataSet');
var DataView = require('../../DataView');

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

@ -1,4 +1,4 @@
var Hammer = require('hammerjs');
var Hammer = require('../../../module/hammer');
/**
* @constructor Item

+ 1
- 1
lib/timeline/component/item/ItemRange.js View File

@ -1,4 +1,4 @@
var Hammer = require('hammerjs');
var Hammer = require('../../../module/hammer');
var Item = require('./Item');
/**

+ 16
- 74
lib/util.js View File

@ -418,17 +418,7 @@ exports.getType = function(object) {
* in the browser page.
*/
exports.getAbsoluteLeft = function(elem) {
var doc = document.documentElement;
var body = document.body;
var left = elem.offsetLeft;
var e = elem.offsetParent;
while (e != null && e != body && e != doc) {
left += e.offsetLeft;
left -= e.scrollLeft;
e = e.offsetParent;
}
return left;
return elem.getBoundingClientRect().left + window.pageXOffset;
};
/**
@ -438,69 +428,7 @@ exports.getAbsoluteLeft = function(elem) {
* in the browser page.
*/
exports.getAbsoluteTop = function(elem) {
var doc = document.documentElement;
var body = document.body;
var top = elem.offsetTop;
var e = elem.offsetParent;
while (e != null && e != body && e != doc) {
top += e.offsetTop;
top -= e.scrollTop;
e = e.offsetParent;
}
return top;
};
/**
* Get the absolute, vertical mouse position from an event.
* @param {Event} event
* @return {Number} pageY
*/
exports.getPageY = function(event) {
if ('pageY' in event) {
return event.pageY;
}
else {
var clientY;
if (('targetTouches' in event) && event.targetTouches.length) {
clientY = event.targetTouches[0].clientY;
}
else {
clientY = event.clientY;
}
var doc = document.documentElement;
var body = document.body;
return clientY +
( doc && doc.scrollTop || body && body.scrollTop || 0 ) -
( doc && doc.clientTop || body && body.clientTop || 0 );
}
};
/**
* Get the absolute, horizontal mouse position from an event.
* @param {Event} event
* @return {Number} pageX
*/
exports.getPageX = function(event) {
if ('pageY' in event) {
return event.pageX;
}
else {
var clientX;
if (('targetTouches' in event) && event.targetTouches.length) {
clientX = event.targetTouches[0].clientX;
}
else {
clientX = event.clientX;
}
var doc = document.documentElement;
var body = document.body;
return clientX +
( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
( doc && doc.clientLeft || body && body.clientLeft || 0 );
}
return elem.getBoundingClientRect().top + window.pageYOffset;
};
/**
@ -638,6 +566,20 @@ exports.removeEventListener = function(element, action, listener, useCapture) {
}
};
/**
* Cancels the event if it is cancelable, without stopping further propagation of the event.
*/
exports.preventDefault = function (event) {
if (!event)
event = window.event;
if (event.preventDefault) {
event.preventDefault(); // non-IE browsers
}
else {
event.returnValue = false; // IE browsers
}
};
/**
* Get HTML element which is the target of the event

Loading…
Cancel
Save