Browse Source

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

codeClimate
Yotam Berkowitz 8 years ago
parent
commit
16cfa8c112
25 changed files with 825 additions and 245 deletions
  1. +16
    -0
      dist/vis.css
  2. +350
    -119
      dist/vis.js
  3. +1
    -1
      dist/vis.min.css
  4. +1
    -1
      docs/data/dataset.html
  5. +1
    -0
      examples/timeline/groups/groupsEditable.html
  6. +1
    -1
      examples/timeline/interaction/animateWindow.html
  7. +77
    -0
      examples/timeline/other/rtl.html
  8. +6
    -1
      lib/network/modules/ManipulationSystem.js
  9. +10
    -2
      lib/timeline/Core.js
  10. +28
    -11
      lib/timeline/Range.js
  11. +16
    -8
      lib/timeline/Stack.js
  12. +31
    -12
      lib/timeline/Timeline.js
  13. +7
    -2
      lib/timeline/component/CurrentTime.js
  14. +2
    -2
      lib/timeline/component/DataAxis.js
  15. +2
    -3
      lib/timeline/component/Group.js
  16. +99
    -29
      lib/timeline/component/ItemSet.js
  17. +34
    -9
      lib/timeline/component/TimeAxis.js
  18. +11
    -0
      lib/timeline/component/css/item.css
  19. +5
    -0
      lib/timeline/component/css/timeaxis.css
  20. +46
    -19
      lib/timeline/component/item/BoxItem.js
  21. +7
    -1
      lib/timeline/component/item/Item.js
  22. +24
    -9
      lib/timeline/component/item/PointItem.js
  23. +44
    -14
      lib/timeline/component/item/RangeItem.js
  24. +2
    -1
      lib/timeline/optionsTimeline.js
  25. +4
    -0
      lib/util.js

+ 16
- 0
dist/vis.css View File

@ -565,6 +565,17 @@ input.vis-configuration.vis-config-range:focus::-ms-fill-upper {
cursor: pointer; cursor: pointer;
} }
.vis-item .vis-delete-rtl {
background: url('img/timeline/delete.png') no-repeat center;
position: absolute;
width: 24px;
height: 24px;
top: -4px;
left: -24px;
cursor: pointer;
}
.vis-item.vis-range .vis-drag-left { .vis-item.vis-range .vis-drag-left {
position: absolute; position: absolute;
width: 24px; width: 24px;
@ -637,6 +648,11 @@ input.vis-configuration.vis-config-range:focus::-ms-fill-upper {
border-left: 1px solid; border-left: 1px solid;
} }
.vis-time-axis .vis-grid.vis-vertical-rtl {
position: absolute;
border-right: 1px solid;
}
.vis-time-axis .vis-grid.vis-minor { .vis-time-axis .vis-grid.vis-minor {
border-color: #e5e5e5; border-color: #e5e5e5;
} }

+ 350
- 119
dist/vis.js View File

@ -5,7 +5,7 @@
* A dynamic, browser-based visualization library. * A dynamic, browser-based visualization library.
* *
* @version 4.15.1 * @version 4.15.1
* @date 2016-03-08
* @date 2016-03-13
* *
* @license * @license
* Copyright (C) 2011-2016 Almende B.V, http://almende.com * Copyright (C) 2011-2016 Almende B.V, http://almende.com
@ -723,6 +723,10 @@ return /******/ (function(modules) { // webpackBootstrap
return elem.getBoundingClientRect().left; return elem.getBoundingClientRect().left;
}; };
exports.getAbsoluteRight = function (elem) {
return elem.getBoundingClientRect().right;
};
/** /**
* Retrieve the absolute top value of a DOM element * Retrieve the absolute top value of a DOM element
* @param {Element} elem A dom element, for example a div * @param {Element} elem A dom element, for example a div
@ -10661,6 +10665,7 @@ return /******/ (function(modules) { // webpackBootstrap
* @extends Core * @extends Core
*/ */
function Timeline(container, items, groups, options) { function Timeline(container, items, groups, options) {
if (!(this instanceof Timeline)) { if (!(this instanceof Timeline)) {
throw new SyntaxError('Constructor must be called with the new operator'); throw new SyntaxError('Constructor must be called with the new operator');
} }
@ -10684,7 +10689,7 @@ return /******/ (function(modules) { // webpackBootstrap
axis: 'bottom', // axis orientation: 'bottom', 'top', or 'both' axis: 'bottom', // axis orientation: 'bottom', 'top', or 'both'
item: 'bottom' // not relevant item: 'bottom' // not relevant
}, },
rtl: false,
moment: moment, moment: moment,
width: null, width: null,
@ -10739,7 +10744,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.components.push(this.currentTime); this.components.push(this.currentTime);
// item set // item set
this.itemSet = new ItemSet(this.body);
this.itemSet = new ItemSet(this.body, this.options);
this.components.push(this.itemSet); this.components.push(this.itemSet);
this.itemsData = null; // DataSet this.itemsData = null; // DataSet
@ -10822,6 +10827,7 @@ return /******/ (function(modules) { // webpackBootstrap
Timeline.prototype.setOptions = function (options) { Timeline.prototype.setOptions = function (options) {
// validate options // validate options
var errorFound = _Validator2.default.validate(options, allOptions); var errorFound = _Validator2.default.validate(options, allOptions);
if (errorFound === true) { if (errorFound === true) {
console.log('%cErrors have been found in the supplied options object.', printStyle); console.log('%cErrors have been found in the supplied options object.', printStyle);
} }
@ -11051,16 +11057,23 @@ return /******/ (function(modules) { // webpackBootstrap
var start = getStart(item); var start = getStart(item);
var end = getEnd(item); var end = getEnd(item);
console.log(start, end);
console.log(this.options);
var left = start - (item.getWidthLeft() + 10) * factor;
var right = end + (item.getWidthRight() + 10) * factor;
if (this.options.rtl) {
var startSide = start - (item.getWidthRight() + 10) * factor;
var endSide = end + (item.getWidthLeft() + 10) * factor;
} else {
var startSide = start - (item.getWidthLeft() + 10) * factor;
var endSide = end + (item.getWidthRight() + 10) * factor;
}
if (left < min) {
min = left;
if (startSide < min) {
min = startSide;
minItem = item; minItem = item;
} }
if (right > max) {
max = right;
if (endSide > max) {
max = endSide;
maxItem = item; maxItem = item;
} }
}.bind(_this)); }.bind(_this));
@ -11071,8 +11084,13 @@ return /******/ (function(modules) { // webpackBootstrap
delta = _this.props.center.width - lhs - rhs; // px delta = _this.props.center.width - lhs - rhs; // px
if (delta > 0) { if (delta > 0) {
min = getStart(minItem) - lhs * interval / delta; // ms
max = getEnd(maxItem) + rhs * interval / delta; // ms
if (_this.options.rtl) {
min = getStart(minItem) - rhs * interval / delta; // ms
max = getEnd(maxItem) + lhs * interval / delta; // ms
} else {
min = getStart(minItem) - lhs * interval / delta; // ms
max = getEnd(maxItem) + rhs * interval / delta; // ms
}
} }
} }
})(); })();
@ -11121,7 +11139,11 @@ return /******/ (function(modules) { // webpackBootstrap
Timeline.prototype.getEventProperties = function (event) { Timeline.prototype.getEventProperties = function (event) {
var clientX = event.center ? event.center.x : event.clientX; var clientX = event.center ? event.center.x : event.clientX;
var clientY = event.center ? event.center.y : event.clientY; var clientY = event.center ? event.center.y : event.clientY;
var x = clientX - util.getAbsoluteLeft(this.dom.centerContainer);
if (this.options.rtl) {
var x = util.getAbsoluteRight(this.dom.centerContainer) - clientX;
} else {
var x = clientX - util.getAbsoluteLeft(this.dom.centerContainer);
}
var y = clientY - util.getAbsoluteTop(this.dom.centerContainer); var y = clientY - util.getAbsoluteTop(this.dom.centerContainer);
var item = this.itemSet.itemFromTarget(event); var item = this.itemSet.itemFromTarget(event);
@ -15804,9 +15826,9 @@ return /******/ (function(modules) { // webpackBootstrap
// http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript // http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
/* /*
Copyright (c) 2011 Andrei Mackenzie Copyright (c) 2011 Andrei Mackenzie
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
}, { }, {
@ -15887,6 +15909,7 @@ return /******/ (function(modules) { // webpackBootstrap
// default options // default options
this.defaultOptions = { this.defaultOptions = {
rtl: false,
start: null, start: null,
end: null, end: null,
moment: moment, moment: moment,
@ -15899,7 +15922,6 @@ return /******/ (function(modules) { // webpackBootstrap
zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000 // milliseconds zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000 // milliseconds
}; };
this.options = util.extend({}, this.defaultOptions); this.options = util.extend({}, this.defaultOptions);
this.props = { this.props = {
touch: {} touch: {}
}; };
@ -15941,7 +15963,7 @@ return /******/ (function(modules) { // webpackBootstrap
Range.prototype.setOptions = function (options) { Range.prototype.setOptions = function (options) {
if (options) { if (options) {
// copy the options that we know // copy the options that we know
var fields = ['direction', 'min', 'max', 'zoomMin', 'zoomMax', 'moveable', 'zoomable', 'moment', 'activate', 'hiddenDates', 'zoomKey'];
var fields = ['direction', 'min', 'max', 'zoomMin', 'zoomMax', 'moveable', 'zoomable', 'moment', 'activate', 'hiddenDates', 'zoomKey', 'rtl'];
util.selectiveExtend(fields, this.options, options); util.selectiveExtend(fields, this.options, options);
if ('start' in options || 'end' in options) { if ('start' in options || 'end' in options) {
@ -16263,7 +16285,13 @@ return /******/ (function(modules) { // webpackBootstrap
interval -= duration; interval -= duration;
var width = direction == 'horizontal' ? this.body.domProps.center.width : this.body.domProps.center.height; var width = direction == 'horizontal' ? this.body.domProps.center.width : this.body.domProps.center.height;
var diffRange = -delta / width * interval;
if (this.options.rtl) {
var diffRange = delta / width * interval;
} else {
var diffRange = -delta / width * interval;
}
var newStart = this.props.touch.start + diffRange; var newStart = this.props.touch.start + diffRange;
var newEnd = this.props.touch.end + diffRange; var newEnd = this.props.touch.end + diffRange;
@ -16365,7 +16393,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
// calculate center, the date to zoom around // calculate center, the date to zoom around
var pointer = getPointer({ x: event.clientX, y: event.clientY }, this.body.dom.center);
var pointer = this.getPointer({ x: event.clientX, y: event.clientY }, this.body.dom.center);
var pointerDate = this._pointerToDate(pointer); var pointerDate = this._pointerToDate(pointer);
this.zoom(scale, pointerDate, delta); this.zoom(scale, pointerDate, delta);
@ -16401,7 +16429,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.props.touch.allowDragging = false; this.props.touch.allowDragging = false;
if (!this.props.touch.center) { if (!this.props.touch.center) {
this.props.touch.center = getPointer(event.center, this.body.dom.center);
this.props.touch.center = this.getPointer(event.center, this.body.dom.center);
} }
var scale = 1 / (event.scale + this.scaleOffset); var scale = 1 / (event.scale + this.scaleOffset);
@ -16446,7 +16474,11 @@ return /******/ (function(modules) { // webpackBootstrap
// calculate the time where the mouse is, check whether inside // calculate the time where the mouse is, check whether inside
// and no scroll action should happen. // and no scroll action should happen.
var clientX = event.center ? event.center.x : event.clientX; var clientX = event.center ? event.center.x : event.clientX;
var x = clientX - util.getAbsoluteLeft(this.body.dom.centerContainer);
if (this.options.rtl) {
var x = clientX - util.getAbsoluteLeft(this.body.dom.centerContainer);
} else {
var x = util.getAbsoluteRight(this.body.dom.centerContainer) - clientX;
}
var time = this.body.util.toTime(x); var time = this.body.util.toTime(x);
return time >= this.start && time <= this.end; return time >= this.start && time <= this.end;
@ -16480,12 +16512,19 @@ return /******/ (function(modules) { // webpackBootstrap
* @return {{x: Number, y: Number}} pointer * @return {{x: Number, y: Number}} pointer
* @private * @private
*/ */
function getPointer(touch, element) {
return {
x: touch.x - util.getAbsoluteLeft(element),
y: touch.y - util.getAbsoluteTop(element)
};
}
Range.prototype.getPointer = function (touch, element) {
if (this.options.rtl) {
return {
x: util.getAbsoluteRight(element) - touch.x,
y: touch.y - util.getAbsoluteTop(element)
};
} else {
return {
x: touch.x - util.getAbsoluteLeft(element),
y: touch.y - util.getAbsoluteTop(element)
};
}
};
/** /**
* Zoom the range the given scale in or out. Start and end date will * Zoom the range the given scale in or out. Start and end date will
@ -17321,9 +17360,17 @@ return /******/ (function(modules) { // webpackBootstrap
Core.prototype.setOptions = function (options) { Core.prototype.setOptions = function (options) {
if (options) { if (options) {
// copy the known options // copy the known options
var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'clickToUse', 'dataAttributes', 'hiddenDates', 'locale', 'locales', 'moment', 'throttleRedraw'];
var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'clickToUse', 'dataAttributes', 'hiddenDates', 'locale', 'locales', 'moment', 'rtl', 'throttleRedraw'];
util.selectiveExtend(fields, this.options, options); util.selectiveExtend(fields, this.options, options);
if (this.options.rtl) {
var contentContainer = this.dom.leftContainer;
this.dom.leftContainer = this.dom.rightContainer;
this.dom.rightContainer = contentContainer;
this.dom.container.style.direction = "rtl";
this.dom.backgroundVertical.className = 'vis-panel vis-background vis-vertical-rtl';
}
this.options.orientation = { item: undefined, axis: undefined }; this.options.orientation = { item: undefined, axis: undefined };
if ('orientation' in options) { if ('orientation' in options) {
if (typeof options.orientation === 'string') { if (typeof options.orientation === 'string') {
@ -17622,7 +17669,7 @@ return /******/ (function(modules) { // webpackBootstrap
var interval = range.max - range.min; var interval = range.max - range.min;
var min = new Date(range.min.valueOf() - interval * 0.01); var min = new Date(range.min.valueOf() - interval * 0.01);
var max = new Date(range.max.valueOf() + interval * 0.01); var max = new Date(range.max.valueOf() + interval * 0.01);
console.log(min, max);
var animation = options && options.animation !== undefined ? options.animation : true; var animation = options && options.animation !== undefined ? options.animation : true;
this.range.setRange(min, max, animation); this.range.setRange(min, max, animation);
}; };
@ -18170,8 +18217,8 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
function ItemSet(body, options) { function ItemSet(body, options) {
this.body = body; this.body = body;
this.defaultOptions = { this.defaultOptions = {
rtl: false,
type: null, // 'box', 'point', 'range', 'background' type: null, // 'box', 'point', 'range', 'background'
orientation: { orientation: {
item: 'bottom' // item orientation: 'top' or 'bottom' item: 'bottom' // item orientation: 'top' or 'bottom'
@ -18374,8 +18421,8 @@ return /******/ (function(modules) { // webpackBootstrap
// add item on doubletap // add item on doubletap
this.hammer.on('doubletap', this._onAddItem.bind(this)); this.hammer.on('doubletap', this._onAddItem.bind(this));
this.groupHammer = new Hammer(this.body.dom.leftContainer); this.groupHammer = new Hammer(this.body.dom.leftContainer);
this.groupHammer.on('panstart', this._onGroupDragStart.bind(this)); this.groupHammer.on('panstart', this._onGroupDragStart.bind(this));
this.groupHammer.on('panmove', this._onGroupDrag.bind(this)); this.groupHammer.on('panmove', this._onGroupDrag.bind(this));
this.groupHammer.on('panend', this._onGroupDragEnd.bind(this)); this.groupHammer.on('panend', this._onGroupDragEnd.bind(this));
@ -18452,7 +18499,7 @@ return /******/ (function(modules) { // webpackBootstrap
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', 'order', 'stack', 'selectable', 'multiselect', 'itemsAlwaysDraggable', 'multiselectPerGroup', 'groupOrder', 'dataAttributes', 'template', 'groupTemplate', 'hide', 'snap', 'groupOrderSwap'];
var fields = ['type', 'rtl', 'align', 'order', 'stack', 'selectable', 'multiselect', 'itemsAlwaysDraggable', 'multiselectPerGroup', 'groupOrder', 'dataAttributes', 'template', 'groupTemplate', 'hide', 'snap', 'groupOrderSwap'];
util.selectiveExtend(fields, this.options, options); util.selectiveExtend(fields, this.options, options);
if ('orientation' in options) { if ('orientation' in options) {
@ -18637,8 +18684,14 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
ItemSet.prototype.getVisibleItems = function () { ItemSet.prototype.getVisibleItems = function () {
var range = this.body.range.getRange(); var range = this.body.range.getRange();
var left = this.body.util.toScreen(range.start);
var right = this.body.util.toScreen(range.end);
if (this.options.rtl) {
var right = this.body.util.toScreen(range.start);
var left = this.body.util.toScreen(range.end);
} else {
var left = this.body.util.toScreen(range.start);
var right = this.body.util.toScreen(range.end);
}
var ids = []; var ids = [];
for (var groupId in this.groups) { for (var groupId in this.groups) {
@ -18651,8 +18704,14 @@ return /******/ (function(modules) { // webpackBootstrap
for (var i = 0; i < rawVisibleItems.length; i++) { for (var i = 0; i < rawVisibleItems.length; i++) {
var item = rawVisibleItems[i]; var item = rawVisibleItems[i];
// TODO: also check whether visible vertically // TODO: also check whether visible vertically
if (item.left < right && item.left + item.width > left) {
ids.push(item.id);
if (this.options.rtl) {
if (item.right < left && item.right + item.width > right) {
ids.push(item.id);
}
} else {
if (item.left < right && item.left + item.width > left) {
ids.push(item.id);
}
} }
} }
} }
@ -18692,7 +18751,12 @@ return /******/ (function(modules) { // webpackBootstrap
// recalculate absolute position (before redrawing groups) // recalculate absolute position (before redrawing groups)
this.props.top = this.body.domProps.top.height + this.body.domProps.border.top; this.props.top = this.body.domProps.top.height + this.body.domProps.border.top;
this.props.left = this.body.domProps.left.width + this.body.domProps.border.left;
if (this.options.rtl) {
this.props.right = this.body.domProps.right.width + this.body.domProps.border.right;
} else {
this.props.left = this.body.domProps.left.width + this.body.domProps.border.left;
}
// update class name // update class name
frame.className = 'vis-itemset'; frame.className = 'vis-itemset';
@ -18743,7 +18807,11 @@ return /******/ (function(modules) { // webpackBootstrap
// reposition axis // reposition axis
this.dom.axis.style.top = asSize(orientation == 'top' ? this.body.domProps.top.height + this.body.domProps.border.top : this.body.domProps.top.height + this.body.domProps.centerContainer.height); this.dom.axis.style.top = asSize(orientation == 'top' ? this.body.domProps.top.height + this.body.domProps.border.top : this.body.domProps.top.height + this.body.domProps.centerContainer.height);
this.dom.axis.style.left = '0';
if (this.options.rtl) {
this.dom.axis.style.right = '0';
} else {
this.dom.axis.style.left = '0';
}
// check if this component is resized // check if this component is resized
resized = this._isResized() || resized; resized = this._isResized() || resized;
@ -19363,8 +19431,15 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
ItemSet.prototype._onDragStartAddItem = function (event) { ItemSet.prototype._onDragStartAddItem = function (event) {
var snap = this.options.snap || null; var snap = this.options.snap || null;
var xAbs = util.getAbsoluteLeft(this.dom.frame);
var x = event.center.x - xAbs - 10; // minus 10 to compensate for the drag starting as soon as you've moved 10px
if (this.options.rtl) {
var xAbs = util.getAbsoluteRight(this.dom.frame);
var x = xAbs - event.center.x + 10; // plus 10 to compensate for the drag starting as soon as you've moved 10px
} else {
var xAbs = util.getAbsoluteLeft(this.dom.frame);
var x = event.center.x - xAbs - 10; // minus 10 to compensate for the drag starting as soon as you've moved 10px
}
var time = this.body.util.toTime(x); var time = this.body.util.toTime(x);
var scale = this.body.util.getScale(); var scale = this.body.util.getScale();
var step = this.body.util.getStep(); var step = this.body.util.getStep();
@ -19385,7 +19460,6 @@ return /******/ (function(modules) { // webpackBootstrap
if (group) { if (group) {
itemData.group = group.groupId; itemData.group = group.groupId;
} }
var newItem = new RangeItem(itemData, this.conversion, this.options); var newItem = new RangeItem(itemData, this.conversion, this.options);
newItem.id = id; // TODO: not so nice setting id afterwards newItem.id = id; // TODO: not so nice setting id afterwards
newItem.data = this._cloneItemData(itemData); newItem.data = this._cloneItemData(itemData);
@ -19393,10 +19467,15 @@ return /******/ (function(modules) { // webpackBootstrap
var props = { var props = {
item: newItem, item: newItem,
dragRight: true,
initialX: event.center.x, initialX: event.center.x,
data: newItem.data data: newItem.data
}; };
if (this.options.rtl) {
props.dragLeft = true;
} else {
props.dragRight = true;
}
this.touchParams.itemProps = [props]; this.touchParams.itemProps = [props];
event.stopPropagation(); event.stopPropagation();
@ -19413,7 +19492,13 @@ return /******/ (function(modules) { // webpackBootstrap
var me = this; var me = this;
var snap = this.options.snap || null; var snap = this.options.snap || null;
var xOffset = this.body.dom.root.offsetLeft + this.body.domProps.left.width;
if (this.options.rtl) {
var xOffset = this.body.dom.root.offsetLeft + this.body.domProps.right.width;
} else {
var xOffset = this.body.dom.root.offsetLeft + this.body.domProps.left.width;
}
var scale = this.body.util.getScale(); var scale = this.body.util.getScale();
var step = this.body.util.getStep(); var step = this.body.util.getStep();
@ -19437,7 +19522,12 @@ return /******/ (function(modules) { // webpackBootstrap
this.touchParams.itemProps.forEach(function (props) { this.touchParams.itemProps.forEach(function (props) {
var current = me.body.util.toTime(event.center.x - xOffset); var current = me.body.util.toTime(event.center.x - xOffset);
var initial = me.body.util.toTime(props.initialX - xOffset); var initial = me.body.util.toTime(props.initialX - xOffset);
var offset = current - initial; // ms
if (this.options.rtl) {
var offset = -(current - initial); // ms
} else {
var offset = current - initial; // ms
}
var itemData = this._cloneItemData(props.item.data); // clone the data var itemData = this._cloneItemData(props.item.data); // clone the data
if (props.item.editable === false) { if (props.item.editable === false) {
@ -19445,27 +19535,45 @@ return /******/ (function(modules) { // webpackBootstrap
} }
var updateTimeAllowed = me.options.editable.updateTime || props.item.editable === true; var updateTimeAllowed = me.options.editable.updateTime || props.item.editable === true;
if (updateTimeAllowed) { if (updateTimeAllowed) {
if (props.dragLeft) { if (props.dragLeft) {
// drag left side of a range item // drag left side of a range item
if (itemData.start != undefined) {
var initialStart = util.convert(props.data.start, 'Date');
var start = new Date(initialStart.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.start = snap ? snap(start, scale, step) : start;
if (this.options.rtl) {
if (itemData.end != undefined) {
var initialEnd = util.convert(props.data.end, 'Date');
var end = new Date(initialEnd.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.end = snap ? snap(end, scale, step) : end;
}
} else {
if (itemData.start != undefined) {
var initialStart = util.convert(props.data.start, 'Date');
var start = new Date(initialStart.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.start = snap ? snap(start, scale, step) : start;
}
} }
} else if (props.dragRight) { } else if (props.dragRight) {
// drag right side of a range item // drag right side of a range item
if (itemData.end != undefined) {
var initialEnd = util.convert(props.data.end, 'Date');
var end = new Date(initialEnd.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.end = snap ? snap(end, scale, step) : end;
if (this.options.rtl) {
if (itemData.start != undefined) {
var initialStart = util.convert(props.data.start, 'Date');
var start = new Date(initialStart.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.start = snap ? snap(start, scale, step) : start;
}
} else {
if (itemData.end != undefined) {
var initialEnd = util.convert(props.data.end, 'Date');
var end = new Date(initialEnd.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.end = snap ? snap(end, scale, step) : end;
}
} }
} else { } else {
// drag both start and end // drag both start and end
if (itemData.start != undefined) { if (itemData.start != undefined) {
var initialStart = util.convert(props.data.start, 'Date').valueOf(); var initialStart = util.convert(props.data.start, 'Date').valueOf();
var start = new Date(initialStart + offset); var start = new Date(initialStart + offset);
@ -19811,8 +19919,15 @@ return /******/ (function(modules) { // webpackBootstrap
}); });
} else { } else {
// add item // add item
var xAbs = util.getAbsoluteLeft(this.dom.frame);
var x = event.center.x - xAbs;
if (this.options.rtl) {
var xAbs = util.getAbsoluteRight(this.dom.frame);
var x = xAbs - event.center.x;
} else {
var xAbs = util.getAbsoluteLeft(this.dom.frame);
var x = event.center.x - xAbs;
}
// var xAbs = util.getAbsoluteLeft(this.dom.frame);
// var x = event.center.x - xAbs;
var start = this.body.util.toTime(x); var start = this.body.util.toTime(x);
var scale = this.body.util.getScale(); var scale = this.body.util.getScale();
var step = this.body.util.getStep(); var step = this.body.util.getStep();
@ -20967,8 +21082,8 @@ return /******/ (function(modules) { // webpackBootstrap
this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range); this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range);
} else { } else {
// no custom order function, lazy stacking // no custom order function, lazy stacking
this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range);
this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range);
if (this.itemSet.options.stack) { if (this.itemSet.options.stack) {
// TODO: ugly way to access options... // TODO: ugly way to access options...
stack.stack(this.visibleItems, margin, restack); stack.stack(this.visibleItems, margin, restack);
@ -20984,10 +21099,9 @@ return /******/ (function(modules) { // webpackBootstrap
// calculate actual size and position // calculate actual size and position
var foreground = this.dom.foreground; var foreground = this.dom.foreground;
this.top = foreground.offsetTop; this.top = foreground.offsetTop;
this.left = foreground.offsetLeft;
this.right = foreground.offsetLeft;
this.width = foreground.offsetWidth; this.width = foreground.offsetWidth;
resized = util.updateProperty(this, 'height', height) || resized; resized = util.updateProperty(this, 'height', height) || resized;
// recalculate size of label // recalculate size of label
resized = util.updateProperty(this.props.label, 'width', this.dom.inner.clientWidth) || resized; resized = util.updateProperty(this.props.label, 'width', this.dom.inner.clientWidth) || resized;
resized = util.updateProperty(this.props.label, 'height', this.dom.inner.clientHeight) || resized; resized = util.updateProperty(this.props.label, 'height', this.dom.inner.clientHeight) || resized;
@ -21427,7 +21541,6 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
exports.stack = function (items, margin, force) { exports.stack = function (items, margin, force) {
var i, iMax; var i, iMax;
if (force) { if (force) {
// reset top position of all items // reset top position of all items
for (i = 0, iMax = items.length; i < iMax; i++) { for (i = 0, iMax = items.length; i < iMax; i++) {
@ -21448,7 +21561,7 @@ return /******/ (function(modules) { // webpackBootstrap
var collidingItem = null; var collidingItem = null;
for (var j = 0, jj = items.length; j < jj; j++) { for (var j = 0, jj = items.length; j < jj; j++) {
var other = items[j]; var other = items[j];
if (other.top !== null && other !== item && other.stack && exports.collision(item, other, margin.item)) {
if (other.top !== null && other !== item && other.stack && exports.collision(item, other, margin.item, other.options.rtl)) {
collidingItem = other; collidingItem = other;
break; break;
} }
@ -21501,8 +21614,14 @@ return /******/ (function(modules) { // webpackBootstrap
* minimum required margin. * minimum required margin.
* @return {boolean} true if a and b collide, else false * @return {boolean} true if a and b collide, else false
*/ */
exports.collision = function (a, b, margin) {
return a.left - margin.horizontal + EPSILON < b.left + b.width && a.left + a.width + margin.horizontal - EPSILON > b.left && a.top - margin.vertical + EPSILON < b.top + b.height && a.top + a.height + margin.vertical - EPSILON > b.top;
exports.collision = function (a, b, margin, rtl) {
var isCollision = null;
if (rtl) {
isCollision = a.right - margin.horizontal + EPSILON < b.right + b.width && a.right + a.width + margin.horizontal - EPSILON > b.right && a.top - margin.vertical + EPSILON < b.top + b.height && a.top + a.height + margin.vertical - EPSILON > b.top;
} else {
a.left - margin.horizontal + EPSILON < b.left + b.width && a.left + a.width + margin.horizontal - EPSILON > b.left && a.top - margin.vertical + EPSILON < b.top + b.height && a.top + a.height + margin.vertical - EPSILON > b.top;
}
return isCollision;
}; };
/***/ }, /***/ },
@ -21531,7 +21650,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
}; };
this.overflow = false; // if contents can overflow (css styling), this flag is set to true this.overflow = false; // if contents can overflow (css styling), this flag is set to true
this.options = options;
// validate data // validate data
if (data) { if (data) {
if (data.start == undefined) { if (data.start == undefined) {
@ -21631,7 +21750,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.dirty = false; this.dirty = false;
} }
console.log("redrawing range");
this._repaintDeleteButton(dom.box); this._repaintDeleteButton(dom.box);
this._repaintDragLeft(); this._repaintDragLeft();
this._repaintDragRight(); this._repaintDragRight();
@ -21676,7 +21795,7 @@ return /******/ (function(modules) { // webpackBootstrap
var parentWidth = this.parent.width; var parentWidth = this.parent.width;
var start = this.conversion.toScreen(this.data.start); var start = this.conversion.toScreen(this.data.start);
var end = this.conversion.toScreen(this.data.end); var end = this.conversion.toScreen(this.data.end);
var contentLeft;
var contentStartPosition;
var contentWidth; var contentWidth;
// limit the width of the range, as browsers cannot draw very wide divs // limit the width of the range, as browsers cannot draw very wide divs
@ -21691,7 +21810,11 @@ return /******/ (function(modules) { // webpackBootstrap
var boxWidth = Math.max(end - start, 1); var boxWidth = Math.max(end - start, 1);
if (this.overflow) { if (this.overflow) {
this.left = start;
if (this.options.rtl) {
this.right = start;
} else {
this.left = start;
}
this.width = boxWidth + this.props.content.width; this.width = boxWidth + this.props.content.width;
contentWidth = this.props.content.width; contentWidth = this.props.content.width;
@ -21699,25 +21822,46 @@ return /******/ (function(modules) { // webpackBootstrap
// a width which will not change when moving the Timeline // a width which will not change when moving the Timeline
// So no re-stacking needed, which is nicer for the eye; // So no re-stacking needed, which is nicer for the eye;
} else { } else {
this.left = start;
if (this.options.rtl) {
this.right = start;
} else {
this.left = start;
}
this.width = boxWidth; this.width = boxWidth;
contentWidth = Math.min(end - start, this.props.content.width); contentWidth = Math.min(end - start, this.props.content.width);
} }
this.dom.box.style.left = this.left + 'px';
if (this.options.rtl) {
this.dom.box.style.right = this.right + 'px';
} else {
this.dom.box.style.left = this.left + 'px';
}
this.dom.box.style.width = boxWidth + 'px'; this.dom.box.style.width = boxWidth + 'px';
switch (this.options.align) { switch (this.options.align) {
case 'left': case 'left':
this.dom.content.style.left = '0';
if (this.options.rtl) {
this.dom.content.style.right = '0';
} else {
this.dom.content.style.left = '0';
}
break; break;
case 'right': case 'right':
this.dom.content.style.left = Math.max(boxWidth - contentWidth, 0) + 'px';
if (this.options.rtl) {
this.dom.content.style.right = Math.max(boxWidth - contentWidth, 0) + 'px';
} else {
this.dom.content.style.left = Math.max(boxWidth - contentWidth, 0) + 'px';
}
break; break;
case 'center': case 'center':
this.dom.content.style.left = Math.max((boxWidth - contentWidth) / 2, 0) + 'px';
if (this.options.rtl) {
this.dom.content.style.right = Math.max((boxWidth - contentWidth) / 2, 0) + 'px';
} else {
this.dom.content.style.left = Math.max((boxWidth - contentWidth) / 2, 0) + 'px';
}
break; break;
default: default:
@ -21725,18 +21869,22 @@ return /******/ (function(modules) { // webpackBootstrap
// when range exceeds left of the window, position the contents at the left of the visible area // when range exceeds left of the window, position the contents at the left of the visible area
if (this.overflow) { if (this.overflow) {
if (end > 0) { if (end > 0) {
contentLeft = Math.max(-start, 0);
contentStartPosition = Math.max(-start, 0);
} else { } else {
contentLeft = -contentWidth; // ensure it's not visible anymore
contentStartPosition = -contentWidth; // ensure it's not visible anymore
} }
} else { } else {
if (start < 0) { if (start < 0) {
contentLeft = -start;
contentStartPosition = -start;
} else { } else {
contentLeft = 0;
contentStartPosition = 0;
} }
} }
this.dom.content.style.left = contentLeft + 'px';
if (this.options.rtl) {
this.dom.content.style.right = contentStartPosition + 'px';
} else {
this.dom.content.style.left = contentStartPosition + 'px';
}
} }
}; };
@ -21782,6 +21930,7 @@ return /******/ (function(modules) { // webpackBootstrap
* @protected * @protected
*/ */
RangeItem.prototype._repaintDragRight = function () { RangeItem.prototype._repaintDragRight = function () {
console.log("repainting!!!!");
if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) { if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) {
// create and show drag area // create and show drag area
var dragRight = document.createElement('div'); var dragRight = document.createElement('div');
@ -21832,6 +21981,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.dirty = true; this.dirty = true;
this.top = null; this.top = null;
this.right = null;
this.left = null; this.left = null;
this.width = null; this.width = null;
this.height = null; this.height = null;
@ -21958,7 +22108,12 @@ return /******/ (function(modules) { // webpackBootstrap
var me = this; var me = this;
var deleteButton = document.createElement('div'); var deleteButton = document.createElement('div');
deleteButton.className = 'vis-delete';
if (this.options.rtl) {
deleteButton.className = 'vis-delete-rtl';
} else {
deleteButton.className = 'vis-delete';
}
deleteButton.title = 'Delete this item'; deleteButton.title = 'Delete this item';
// TODO: be able to destroy the delete button // TODO: be able to destroy the delete button
@ -22196,7 +22351,7 @@ return /******/ (function(modules) { // webpackBootstrap
height: 0 height: 0
} }
}; };
this.options = options;
// validate data // validate data
if (data) { if (data) {
if (data.start == undefined) { if (data.start == undefined) {
@ -22340,27 +22495,54 @@ return /******/ (function(modules) { // webpackBootstrap
// calculate left position of the box // calculate left position of the box
if (align == 'right') { if (align == 'right') {
this.left = start - this.width;
if (this.options.rtl) {
this.right = start - this.width;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = start - this.props.line.width + 'px';
this.dom.dot.style.left = start - this.props.line.width / 2 - this.props.dot.width / 2 + 'px';
// reposition box, line, and dot
this.dom.box.style.right = this.right + 'px';
this.dom.line.style.right = start - this.props.line.width + 'px';
this.dom.dot.style.right = start - this.props.line.width / 2 - this.props.dot.width / 2 + 'px';
} else {
this.left = start - this.width;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = start - this.props.line.width + 'px';
this.dom.dot.style.left = start - this.props.line.width / 2 - this.props.dot.width / 2 + 'px';
}
} else if (align == 'left') { } else if (align == 'left') {
this.left = start;
if (this.options.rtl) {
this.right = start;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = start + 'px';
this.dom.dot.style.left = start + this.props.line.width / 2 - this.props.dot.width / 2 + 'px';
// reposition box, line, and dot
this.dom.box.style.right = this.right + 'px';
this.dom.line.style.right = start + 'px';
this.dom.dot.style.right = start + this.props.line.width / 2 - this.props.dot.width / 2 + 'px';
} else {
this.left = start;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = start + 'px';
this.dom.dot.style.left = start + this.props.line.width / 2 - this.props.dot.width / 2 + 'px';
}
} else { } else {
// default or 'center' // default or 'center'
this.left = start - this.width / 2;
if (this.options.rtl) {
this.right = start - this.width / 2;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = start - this.props.line.width / 2 + 'px';
this.dom.dot.style.left = start - this.props.dot.width / 2 + 'px';
// reposition box, line, and dot
this.dom.box.style.right = this.right + 'px';
this.dom.line.style.right = start - this.props.line.width + 'px';
this.dom.dot.style.right = start - this.props.dot.width / 2 + 'px';
} else {
this.left = start - this.width / 2;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = start - this.props.line.width / 2 + 'px';
this.dom.dot.style.left = start - this.props.dot.width / 2 + 'px';
}
} }
}; };
@ -22438,10 +22620,11 @@ return /******/ (function(modules) { // webpackBootstrap
}, },
content: { content: {
height: 0, height: 0,
marginLeft: 0
marginLeft: 0,
marginRight: 0
} }
}; };
this.options = options;
// validate data // validate data
if (data) { if (data) {
if (data.start == undefined) { if (data.start == undefined) {
@ -22531,7 +22714,11 @@ return /******/ (function(modules) { // webpackBootstrap
this.props.content.height = dom.content.offsetHeight; this.props.content.height = dom.content.offsetHeight;
// resize contents // resize contents
dom.content.style.marginLeft = 2 * this.props.dot.width + 'px';
if (this.options.rtl) {
dom.content.style.marginRight = 2 * this.props.dot.width + 'px';
} else {
dom.content.style.marginLeft = 2 * this.props.dot.width + 'px';
}
//dom.content.style.marginRight = ... + 'px'; // TODO: margin right //dom.content.style.marginRight = ... + 'px'; // TODO: margin right
// recalculate size // recalculate size
@ -22540,7 +22727,11 @@ return /******/ (function(modules) { // webpackBootstrap
// reposition the dot // reposition the dot
dom.dot.style.top = (this.height - this.props.dot.height) / 2 + 'px'; dom.dot.style.top = (this.height - this.props.dot.height) / 2 + 'px';
dom.dot.style.left = this.props.dot.width / 2 + 'px';
if (this.options.rtl) {
dom.dot.style.right = this.props.dot.width / 2 + 'px';
} else {
dom.dot.style.left = this.props.dot.width / 2 + 'px';
}
this.dirty = false; this.dirty = false;
} }
@ -22578,10 +22769,17 @@ return /******/ (function(modules) { // webpackBootstrap
PointItem.prototype.repositionX = function () { PointItem.prototype.repositionX = function () {
var start = this.conversion.toScreen(this.data.start); var start = this.conversion.toScreen(this.data.start);
this.left = start - this.props.dot.width;
if (this.options.rtl) {
this.right = start - this.props.dot.width;
// reposition point
this.dom.point.style.left = this.left + 'px';
// reposition point
this.dom.point.style.right = this.right + 'px';
} else {
this.left = start - this.props.dot.width;
// reposition point
this.dom.point.style.left = this.left + 'px';
}
}; };
/** /**
@ -22591,7 +22789,6 @@ return /******/ (function(modules) { // webpackBootstrap
PointItem.prototype.repositionY = function () { PointItem.prototype.repositionY = function () {
var orientation = this.options.orientation.item; var orientation = this.options.orientation.item;
var point = this.dom.point; var point = this.dom.point;
if (orientation == 'top') { if (orientation == 'top') {
point.style.top = this.top + 'px'; point.style.top = this.top + 'px';
} else { } else {
@ -22612,7 +22809,7 @@ return /******/ (function(modules) { // webpackBootstrap
* @return {number} * @return {number}
*/ */
PointItem.prototype.getWidthRight = function () { PointItem.prototype.getWidthRight = function () {
return this.width - this.props.dot.width;
return this.props.dot.width;
}; };
module.exports = PointItem; module.exports = PointItem;
@ -22915,7 +23112,7 @@ return /******/ (function(modules) { // webpackBootstrap
TimeAxis.prototype.setOptions = function (options) { TimeAxis.prototype.setOptions = function (options) {
if (options) { if (options) {
// copy all options that we know // copy all options that we know
util.selectiveExtend(['showMinorLabels', 'showMajorLabels', 'maxMinorChars', 'hiddenDates', 'timeAxis', 'moment'], this.options, options);
util.selectiveExtend(['showMinorLabels', 'showMajorLabels', 'maxMinorChars', 'hiddenDates', 'timeAxis', 'moment', 'rtl'], this.options, options);
// deep copy the format options // deep copy the format options
util.selectiveDeepExtend(['format'], this.options, options); util.selectiveDeepExtend(['format'], this.options, options);
@ -23019,7 +23216,6 @@ return /******/ (function(modules) { // webpackBootstrap
} else { } else {
this.body.dom.backgroundVertical.appendChild(background); this.body.dom.backgroundVertical.appendChild(background);
} }
return this._isResized() || parentChanged; return this._isResized() || parentChanged;
}; };
@ -23172,7 +23368,13 @@ return /******/ (function(modules) { // webpackBootstrap
label.childNodes[0].nodeValue = text; label.childNodes[0].nodeValue = text;
label.style.top = orientation == 'top' ? this.props.majorLabelHeight + 'px' : '0'; label.style.top = orientation == 'top' ? this.props.majorLabelHeight + 'px' : '0';
label.style.left = x + 'px';
if (this.options.rtl) {
label.style.left = "";
label.style.right = x + 'px';
} else {
label.style.left = x + 'px';
};
label.className = 'vis-text vis-minor ' + className; label.className = 'vis-text vis-minor ' + className;
//label.title = title; // TODO: this is a heavy operation //label.title = title; // TODO: this is a heavy operation
@ -23206,7 +23408,12 @@ return /******/ (function(modules) { // webpackBootstrap
//label.title = title; // TODO: this is a heavy operation //label.title = title; // TODO: this is a heavy operation
label.style.top = orientation == 'top' ? '0' : this.props.minorLabelHeight + 'px'; label.style.top = orientation == 'top' ? '0' : this.props.minorLabelHeight + 'px';
label.style.left = x + 'px';
if (this.options.rtl) {
label.style.left = "";
label.style.right = x + 'px';
} else {
label.style.left = x + 'px';
};
return label; return label;
}; };
@ -23237,11 +23444,16 @@ return /******/ (function(modules) { // webpackBootstrap
line.style.top = this.body.domProps.top.height + 'px'; line.style.top = this.body.domProps.top.height + 'px';
} }
line.style.height = props.minorLineHeight + 'px'; line.style.height = props.minorLineHeight + 'px';
line.style.left = x - props.minorLineWidth / 2 + 'px';
if (this.options.rtl) {
line.style.left = "";
line.style.right = x - props.minorLineWidth / 2 + 'px';
line.className = 'vis-grid vis-vertical-rtl vis-minor ' + className;
} else {
line.style.left = x - props.minorLineWidth / 2 + 'px';
line.className = 'vis-grid vis-vertical vis-minor ' + className;
};
line.style.width = width + 'px'; line.style.width = width + 'px';
line.className = 'vis-grid vis-vertical vis-minor ' + className;
return line; return line;
}; };
@ -23270,12 +23482,19 @@ return /******/ (function(modules) { // webpackBootstrap
} else { } else {
line.style.top = this.body.domProps.top.height + 'px'; line.style.top = this.body.domProps.top.height + 'px';
} }
line.style.left = x - props.majorLineWidth / 2 + 'px';
if (this.options.rtl) {
line.style.left = "";
line.style.right = x - props.majorLineWidth / 2 + 'px';
line.className = 'vis-grid vis-vertical-rtl vis-major ' + className;
} else {
line.style.left = x - props.majorLineWidth / 2 + 'px';
line.className = 'vis-grid vis-vertical vis-major ' + className;
}
line.style.height = props.majorLineHeight + 'px'; line.style.height = props.majorLineHeight + 'px';
line.style.width = width + 'px'; line.style.width = width + 'px';
line.className = 'vis-grid vis-vertical vis-major ' + className;
return line; return line;
}; };
@ -23972,6 +24191,7 @@ return /******/ (function(modules) { // webpackBootstrap
// default options // default options
this.defaultOptions = { this.defaultOptions = {
rtl: false,
showCurrentTime: true, showCurrentTime: true,
moment: moment, moment: moment,
@ -24020,7 +24240,7 @@ return /******/ (function(modules) { // webpackBootstrap
CurrentTime.prototype.setOptions = function (options) { CurrentTime.prototype.setOptions = function (options) {
if (options) { if (options) {
// copy all options that we know // copy all options that we know
util.selectiveExtend(['showCurrentTime', 'moment', 'locale', 'locales'], this.options, options);
util.selectiveExtend(['rtl', 'showCurrentTime', 'moment', 'locale', 'locales'], this.options, options);
} }
}; };
@ -24055,7 +24275,11 @@ return /******/ (function(modules) { // webpackBootstrap
var title = locale.current + ' ' + locale.time + ': ' + now.format('dddd, MMMM Do YYYY, H:mm:ss'); var title = locale.current + ' ' + locale.time + ': ' + now.format('dddd, MMMM Do YYYY, H:mm:ss');
title = title.charAt(0).toUpperCase() + title.substring(1); title = title.charAt(0).toUpperCase() + title.substring(1);
this.bar.style.left = x + 'px';
if (this.options.rtl) {
this.bar.style.right = x + 'px';
} else {
this.bar.style.left = x + 'px';
}
this.bar.title = title; this.bar.title = title;
} else { } else {
// remove the line from the DOM // remove the line from the DOM
@ -24162,6 +24386,7 @@ return /******/ (function(modules) { // webpackBootstrap
//globals : //globals :
align: { string: string }, align: { string: string },
rtl: { boolean: boolean, 'undefined': 'undefined' },
autoResize: { boolean: boolean }, autoResize: { boolean: boolean },
throttleRedraw: { number: number }, throttleRedraw: { number: number },
clickToUse: { boolean: boolean }, clickToUse: { boolean: boolean },
@ -24279,6 +24504,7 @@ return /******/ (function(modules) { // webpackBootstrap
var configureOptions = { var configureOptions = {
global: { global: {
align: ['center', 'left', 'right'], align: ['center', 'left', 'right'],
direction: false,
autoResize: true, autoResize: true,
throttleRedraw: [10, 0, 1000, 10], throttleRedraw: [10, 0, 1000, 10],
clickToUse: false, clickToUse: false,
@ -25952,10 +26178,10 @@ return /******/ (function(modules) { // webpackBootstrap
DataAxis.prototype.show = function () { DataAxis.prototype.show = function () {
this.hidden = false; this.hidden = false;
if (!this.dom.frame.parentNode) { if (!this.dom.frame.parentNode) {
if (this.options.orientation === 'left') {
if (this.options.rtl) {
this.body.dom.left.appendChild(this.dom.frame); this.body.dom.left.appendChild(this.dom.frame);
} else { } else {
this.body.dom.right.appendChild(this.dom.frame);
this.body.dom.left.appendChild(this.dom.frame);
} }
} }
@ -42865,7 +43091,12 @@ return /******/ (function(modules) { // webpackBootstrap
}, { }, {
key: '_createDeleteButton', key: '_createDeleteButton',
value: function _createDeleteButton(locale) { value: function _createDeleteButton(locale) {
var button = this._createButton('delete', 'vis-button vis-delete', locale['del'] || this.options.locales['en']['del']);
if (this.options.rtl) {
var deleteBtnClass = 'vis-button vis-delete-rtl';
} else {
var deleteBtnClass = 'vis-button vis-delete';
}
var button = this._createButton('delete', deleteBtnClass, locale['del'] || this.options.locales['en']['del']);
this.manipulationDiv.appendChild(button); this.manipulationDiv.appendChild(button);
this._bindHammerToDiv(button, this.deleteSelected.bind(this)); this._bindHammerToDiv(button, this.deleteSelected.bind(this));
} }

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


+ 1
- 1
docs/data/dataset.html View File

@ -431,7 +431,7 @@ var data = new vis.DataSet([data] [, options])
</td> </td>
<td>Number[]</td> <td>Number[]</td>
<td> <td>
Update on ore multiple existing items. <code>data</code> can be a single item or an array with items. When an item doesn't exist, it will be created. Returns an array with the ids of the removed items. See section <a href="#Data_Manipulation">Data Manipulation</a>.
Update one or multiple existing items. <code>data</code> can be a single item or an array with items. When an item doesn't exist, it will be created. Returns an array with the ids of the removed items. See section <a href="#Data_Manipulation">Data Manipulation</a>.
</td> </td>
</tr> </tr>

+ 1
- 0
examples/timeline/groups/groupsEditable.html View File

@ -299,6 +299,7 @@
a.value = b.value; a.value = b.value;
b.value = v; b.value = v;
}, },
orientation: 'both',
editable: true, editable: true,
groupEditable: true, groupEditable: true,
start: new Date(2015, 6, 1), start: new Date(2015, 6, 1),

+ 1
- 1
examples/timeline/interaction/animateWindow.html View File

@ -58,7 +58,7 @@
start: '2014-01-10', start: '2014-01-10',
end: '2014-02-10', end: '2014-02-10',
editable: true, editable: true,
showCurrentTime: true
showCurrentTime: true,
}; };
var timeline = new vis.Timeline(container, items, options); var timeline = new vis.Timeline(container, items, options);

+ 77
- 0
examples/timeline/other/rtl.html View File

@ -0,0 +1,77 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Timeline | RTL example</title>
<style>
body, html {
font-family: arial, sans-serif;
font-size: 11pt;
}
</style>
<script src="../../../dist/vis.js"></script>
<link href="../../../dist/vis.css" rel="stylesheet" type="text/css" />
<script src="../../googleAnalytics.js"></script>
</head>
<body>
<p>An editable timeline allows to drag items around, create new items, and remove items. Changes are logged in the browser console.</p>
<div id="visualization"></div>
<script>
// create a dataset with items
// we specify the type of the fields `start` and `end` here to be strings
// containing an ISO date. The fields will be outputted as ISO dates
// automatically getting data from the DataSet via items.get().
var items = new vis.DataSet({
type: { start: 'ISODate', end: 'ISODate' }
});
// add items to the DataSet
items.add([
{id: 1, content: '2014-01-23 <br>start', start: '2014-01-23'},
{id: 2, content: '2014-01-18', start: '2014-01-18'},
{id: 3, content: '2014-01-21', start: '2014-01-21'},
{id: 4, content: '2014-01-19 - 2014-01-24', start: '2014-01-19', end: '2014-01-24'},
{id: 5, content: '2014-01-28', start: '2014-01-28', type:'point'},
{id: 6, content: '2014-01-26', start: '2014-01-26'}
]);
// log changes to the console
items.on('*', function (event, properties) {
console.log(event, properties.items);
});
var container = document.getElementById('visualization');
var options = {
start: '2014-01-10',
end: '2014-02-10',
height: '300px',
rtl: true,
// allow selecting multiple items using ctrl+click, shift+click, or hold.
multiselect: true,
// allow manipulation of items
editable: true,
/* alternatively, enable/disable individual actions:
editable: {
add: true,
updateTime: true,
updateGroup: true,
remove: true
},
*/
showCurrentTime: true
};
var timeline = new vis.Timeline(container, items, options);
</script>
</body>
</html>

+ 6
- 1
lib/network/modules/ManipulationSystem.js View File

@ -690,7 +690,12 @@ class ManipulationSystem {
} }
_createDeleteButton(locale) { _createDeleteButton(locale) {
let button = this._createButton('delete', 'vis-button vis-delete', locale['del'] || this.options.locales['en']['del']);
if (this.options.rtl) {
var deleteBtnClass = 'vis-button vis-delete-rtl';
} else {
var deleteBtnClass = 'vis-button vis-delete';
}
let button = this._createButton('delete', deleteBtnClass, locale['del'] || this.options.locales['en']['del']);
this.manipulationDiv.appendChild(button); this.manipulationDiv.appendChild(button);
this._bindHammerToDiv(button, this.deleteSelected.bind(this)); this._bindHammerToDiv(button, this.deleteSelected.bind(this));
} }

+ 10
- 2
lib/timeline/Core.js View File

@ -222,11 +222,19 @@ Core.prototype.setOptions = function (options) {
var fields = [ var fields = [
'width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'width', 'height', 'minHeight', 'maxHeight', 'autoResize',
'start', 'end', 'clickToUse', 'dataAttributes', 'hiddenDates', 'start', 'end', 'clickToUse', 'dataAttributes', 'hiddenDates',
'locale', 'locales', 'moment',
'locale', 'locales', 'moment', 'rtl',
'throttleRedraw' 'throttleRedraw'
]; ];
util.selectiveExtend(fields, this.options, options); util.selectiveExtend(fields, this.options, options);
if (this.options.rtl) {
var contentContainer = this.dom.leftContainer;
this.dom.leftContainer = this.dom.rightContainer;
this.dom.rightContainer = contentContainer;
this.dom.container.style.direction = "rtl";
this.dom.backgroundVertical.className = 'vis-panel vis-background vis-vertical-rtl'; }
this.options.orientation = {item:undefined,axis:undefined}; this.options.orientation = {item:undefined,axis:undefined};
if ('orientation' in options) { if ('orientation' in options) {
if (typeof options.orientation === 'string') { if (typeof options.orientation === 'string') {
@ -529,7 +537,7 @@ Core.prototype.fit = function(options) {
var interval = range.max - range.min; var interval = range.max - range.min;
var min = new Date(range.min.valueOf() - interval * 0.01); var min = new Date(range.min.valueOf() - interval * 0.01);
var max = new Date(range.max.valueOf() + interval * 0.01); var max = new Date(range.max.valueOf() + interval * 0.01);
console.log(min, max);
var animation = (options && options.animation !== undefined) ? options.animation : true; var animation = (options && options.animation !== undefined) ? options.animation : true;
this.range.setRange(min, max, animation); this.range.setRange(min, max, animation);
}; };

+ 28
- 11
lib/timeline/Range.js View File

@ -25,6 +25,7 @@ function Range(body, options) {
// default options // default options
this.defaultOptions = { this.defaultOptions = {
rtl: false,
start: null, start: null,
end: null, end: null,
moment: moment, moment: moment,
@ -37,7 +38,6 @@ function Range(body, options) {
zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000 // milliseconds zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000 // milliseconds
}; };
this.options = util.extend({}, this.defaultOptions); this.options = util.extend({}, this.defaultOptions);
this.props = { this.props = {
touch: {} touch: {}
}; };
@ -81,7 +81,7 @@ Range.prototype.setOptions = function (options) {
// copy the options that we know // copy the options that we know
var fields = [ var fields = [
'direction', 'min', 'max', 'zoomMin', 'zoomMax', 'moveable', 'zoomable', 'direction', 'min', 'max', 'zoomMin', 'zoomMax', 'moveable', 'zoomable',
'moment', 'activate', 'hiddenDates', 'zoomKey'
'moment', 'activate', 'hiddenDates', 'zoomKey', 'rtl'
]; ];
util.selectiveExtend(fields, this.options, options); util.selectiveExtend(fields, this.options, options);
@ -411,7 +411,13 @@ Range.prototype._onDrag = function (event) {
interval -= duration; interval -= duration;
var width = (direction == 'horizontal') ? this.body.domProps.center.width : this.body.domProps.center.height; var width = (direction == 'horizontal') ? this.body.domProps.center.width : this.body.domProps.center.height;
var diffRange = -delta / width * interval;
if (this.options.rtl) {
var diffRange = delta / width * interval;
} else {
var diffRange = -delta / width * interval;
}
var newStart = this.props.touch.start + diffRange; var newStart = this.props.touch.start + diffRange;
var newEnd = this.props.touch.end + diffRange; var newEnd = this.props.touch.end + diffRange;
@ -513,7 +519,7 @@ Range.prototype._onMouseWheel = function(event) {
} }
// calculate center, the date to zoom around // calculate center, the date to zoom around
var pointer = getPointer({x: event.clientX, y: event.clientY}, this.body.dom.center);
var pointer = this.getPointer({x: event.clientX, y: event.clientY}, this.body.dom.center);
var pointerDate = this._pointerToDate(pointer); var pointerDate = this._pointerToDate(pointer);
this.zoom(scale, pointerDate, delta); this.zoom(scale, pointerDate, delta);
@ -549,7 +555,7 @@ Range.prototype._onPinch = function (event) {
this.props.touch.allowDragging = false; this.props.touch.allowDragging = false;
if (!this.props.touch.center) { if (!this.props.touch.center) {
this.props.touch.center = getPointer(event.center, this.body.dom.center);
this.props.touch.center = this.getPointer(event.center, this.body.dom.center);
} }
var scale = 1 / (event.scale + this.scaleOffset); var scale = 1 / (event.scale + this.scaleOffset);
@ -594,7 +600,11 @@ Range.prototype._isInsideRange = function(event) {
// calculate the time where the mouse is, check whether inside // calculate the time where the mouse is, check whether inside
// and no scroll action should happen. // and no scroll action should happen.
var clientX = event.center ? event.center.x : event.clientX; var clientX = event.center ? event.center.x : event.clientX;
var x = clientX - util.getAbsoluteLeft(this.body.dom.centerContainer);
if (this.options.rtl) {
var x = clientX - util.getAbsoluteLeft(this.body.dom.centerContainer);
} else {
var x = util.getAbsoluteRight(this.body.dom.centerContainer) - clientX;
}
var time = this.body.util.toTime(x); var time = this.body.util.toTime(x);
return time >= this.start && time <= this.end; return time >= this.start && time <= this.end;
@ -629,11 +639,18 @@ Range.prototype._pointerToDate = function (pointer) {
* @return {{x: Number, y: Number}} pointer * @return {{x: Number, y: Number}} pointer
* @private * @private
*/ */
function getPointer (touch, element) {
return {
x: touch.x - util.getAbsoluteLeft(element),
y: touch.y - util.getAbsoluteTop(element)
};
Range.prototype.getPointer = function (touch, element) {
if (this.options.rtl) {
return {
x: util.getAbsoluteRight(element) - touch.x,
y: touch.y - util.getAbsoluteTop(element)
};
} else {
return {
x: touch.x - util.getAbsoluteLeft(element),
y: touch.y - util.getAbsoluteTop(element)
};
}
} }
/** /**

+ 16
- 8
lib/timeline/Stack.js View File

@ -37,8 +37,7 @@ exports.orderByEnd = function(items) {
* items having a top===null will be re-stacked * items having a top===null will be re-stacked
*/ */
exports.stack = function(items, margin, force) { exports.stack = function(items, margin, force) {
var i, iMax;
var i, iMax;
if (force) { if (force) {
// reset top position of all items // reset top position of all items
for (i = 0, iMax = items.length; i < iMax; i++) { for (i = 0, iMax = items.length; i < iMax; i++) {
@ -59,7 +58,7 @@ exports.stack = function(items, margin, force) {
var collidingItem = null; var collidingItem = null;
for (var j = 0, jj = items.length; j < jj; j++) { for (var j = 0, jj = items.length; j < jj; j++) {
var other = items[j]; var other = items[j];
if (other.top !== null && other !== item && other.stack && exports.collision(item, other, margin.item)) {
if (other.top !== null && other !== item && other.stack && exports.collision(item, other, margin.item, other.options.rtl)) {
collidingItem = other; collidingItem = other;
break; break;
} }
@ -114,9 +113,18 @@ exports.nostack = function(items, margin, subgroups) {
* minimum required margin. * minimum required margin.
* @return {boolean} true if a and b collide, else false * @return {boolean} true if a and b collide, else false
*/ */
exports.collision = function(a, b, margin) {
return ((a.left - margin.horizontal + EPSILON) < (b.left + b.width) &&
(a.left + a.width + margin.horizontal - EPSILON) > b.left &&
(a.top - margin.vertical + EPSILON) < (b.top + b.height) &&
(a.top + a.height + margin.vertical - EPSILON) > b.top);
exports.collision = function(a, b, margin, rtl) {
var isCollision = null;
if (rtl) {
isCollision = ((a.right - margin.horizontal + EPSILON) < (b.right + b.width) &&
(a.right + a.width + margin.horizontal - EPSILON) > b.right &&
(a.top - margin.vertical + EPSILON) < (b.top + b.height) &&
(a.top + a.height + margin.vertical - EPSILON) > b.top);
} else {
((a.left - margin.horizontal + EPSILON) < (b.left + b.width) &&
(a.left + a.width + margin.horizontal - EPSILON) > b.left &&
(a.top - margin.vertical + EPSILON) < (b.top + b.height) &&
(a.top + a.height + margin.vertical - EPSILON) > b.top);
}
return isCollision;
}; };

+ 31
- 12
lib/timeline/Timeline.js View File

@ -29,6 +29,7 @@ import Validator from '../shared/Validator';
* @extends Core * @extends Core
*/ */
function Timeline (container, items, groups, options) { function Timeline (container, items, groups, options) {
if (!(this instanceof Timeline)) { if (!(this instanceof Timeline)) {
throw new SyntaxError('Constructor must be called with the new operator'); throw new SyntaxError('Constructor must be called with the new operator');
} }
@ -52,7 +53,7 @@ function Timeline (container, items, groups, options) {
axis: 'bottom', // axis orientation: 'bottom', 'top', or 'both' axis: 'bottom', // axis orientation: 'bottom', 'top', or 'both'
item: 'bottom' // not relevant item: 'bottom' // not relevant
}, },
rtl: false,
moment: moment, moment: moment,
width: null, width: null,
@ -107,7 +108,7 @@ function Timeline (container, items, groups, options) {
this.components.push(this.currentTime); this.components.push(this.currentTime);
// item set // item set
this.itemSet = new ItemSet(this.body);
this.itemSet = new ItemSet(this.body, this.options);
this.components.push(this.itemSet); this.components.push(this.itemSet);
this.itemsData = null; // DataSet this.itemsData = null; // DataSet
@ -191,6 +192,7 @@ Timeline.prototype.redraw = function() {
Timeline.prototype.setOptions = function (options) { Timeline.prototype.setOptions = function (options) {
// validate options // validate options
let errorFound = Validator.validate(options, allOptions); let errorFound = Validator.validate(options, allOptions);
if (errorFound === true) { if (errorFound === true) {
console.log('%cErrors have been found in the supplied options object.', printStyle); console.log('%cErrors have been found in the supplied options object.', printStyle);
} }
@ -413,16 +415,24 @@ Timeline.prototype.getItemRange = function () {
var start = getStart(item); var start = getStart(item);
var end = getEnd(item); var end = getEnd(item);
console.log(start, end)
console.log(this.options);
if (this.options.rtl) {
var startSide = start - (item.getWidthRight() + 10) * factor;
var endSide = end + (item.getWidthLeft() + 10) * factor;
} else {
var startSide = start - (item.getWidthLeft() + 10) * factor;
var endSide = end + (item.getWidthRight() + 10) * factor;
}
var left = start - (item.getWidthLeft() + 10) * factor;
var right = end + (item.getWidthRight() + 10) * factor;
if (left < min) {
min = left;
if (startSide < min) {
min = startSide;
minItem = item; minItem = item;
} }
if (right > max) {
max = right;
if (endSide > max) {
max = endSide;
maxItem = item; maxItem = item;
} }
}.bind(this)); }.bind(this));
@ -433,8 +443,13 @@ Timeline.prototype.getItemRange = function () {
var delta = this.props.center.width - lhs - rhs; // px var delta = this.props.center.width - lhs - rhs; // px
if (delta > 0) { if (delta > 0) {
min = getStart(minItem) - lhs * interval / delta; // ms
max = getEnd(maxItem) + rhs * interval / delta; // ms
if (this.options.rtl) {
min = getStart(minItem) - rhs * interval / delta; // ms
max = getEnd(maxItem) + lhs * interval / delta; // ms
} else {
min = getStart(minItem) - lhs * interval / delta; // ms
max = getEnd(maxItem) + rhs * interval / delta; // ms
}
} }
} }
} }
@ -482,7 +497,11 @@ Timeline.prototype.getDataRange = function() {
Timeline.prototype.getEventProperties = function (event) { Timeline.prototype.getEventProperties = function (event) {
var clientX = event.center ? event.center.x : event.clientX; var clientX = event.center ? event.center.x : event.clientX;
var clientY = event.center ? event.center.y : event.clientY; var clientY = event.center ? event.center.y : event.clientY;
var x = clientX - util.getAbsoluteLeft(this.dom.centerContainer);
if (this.options.rtl) {
var x = util.getAbsoluteRight(this.dom.centerContainer) - clientX;
} else {
var x = clientX - util.getAbsoluteLeft(this.dom.centerContainer);
}
var y = clientY - util.getAbsoluteTop(this.dom.centerContainer); var y = clientY - util.getAbsoluteTop(this.dom.centerContainer);
var item = this.itemSet.itemFromTarget(event); var item = this.itemSet.itemFromTarget(event);

+ 7
- 2
lib/timeline/component/CurrentTime.js View File

@ -16,6 +16,7 @@ function CurrentTime (body, options) {
// default options // default options
this.defaultOptions = { this.defaultOptions = {
rtl: false,
showCurrentTime: true, showCurrentTime: true,
moment: moment, moment: moment,
@ -64,7 +65,7 @@ CurrentTime.prototype.destroy = function () {
CurrentTime.prototype.setOptions = function(options) { CurrentTime.prototype.setOptions = function(options) {
if (options) { if (options) {
// copy all options that we know // copy all options that we know
util.selectiveExtend(['showCurrentTime', 'moment', 'locale', 'locales'], this.options, options);
util.selectiveExtend(['rtl', 'showCurrentTime', 'moment', 'locale', 'locales'], this.options, options);
} }
}; };
@ -99,7 +100,11 @@ CurrentTime.prototype.redraw = function() {
var title = locale.current + ' ' + locale.time + ': ' + now.format('dddd, MMMM Do YYYY, H:mm:ss'); var title = locale.current + ' ' + locale.time + ': ' + now.format('dddd, MMMM Do YYYY, H:mm:ss');
title = title.charAt(0).toUpperCase() + title.substring(1); title = title.charAt(0).toUpperCase() + title.substring(1);
this.bar.style.left = x + 'px';
if (this.options.rtl) {
this.bar.style.right = x + 'px';
} else {
this.bar.style.left = x + 'px';
}
this.bar.title = title; this.bar.title = title;
} }
else { else {

+ 2
- 2
lib/timeline/component/DataAxis.js View File

@ -212,11 +212,11 @@ DataAxis.prototype._cleanupIcons = function() {
DataAxis.prototype.show = function() { DataAxis.prototype.show = function() {
this.hidden = false; this.hidden = false;
if (!this.dom.frame.parentNode) { if (!this.dom.frame.parentNode) {
if (this.options.orientation === 'left') {
if (this.options.rtl) {
this.body.dom.left.appendChild(this.dom.frame); this.body.dom.left.appendChild(this.dom.frame);
} }
else { else {
this.body.dom.right.appendChild(this.dom.frame);
this.body.dom.left.appendChild(this.dom.frame);
} }
} }

+ 2
- 3
lib/timeline/component/Group.js View File

@ -209,8 +209,8 @@ Group.prototype.redraw = function(range, margin, restack) {
} }
else { else {
// no custom order function, lazy stacking // no custom order function, lazy stacking
this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range);
this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range);
if (this.itemSet.options.stack) { // TODO: ugly way to access options... if (this.itemSet.options.stack) { // TODO: ugly way to access options...
stack.stack(this.visibleItems, margin, restack); stack.stack(this.visibleItems, margin, restack);
} }
@ -225,10 +225,9 @@ Group.prototype.redraw = function(range, margin, restack) {
// calculate actual size and position // calculate actual size and position
var foreground = this.dom.foreground; var foreground = this.dom.foreground;
this.top = foreground.offsetTop; this.top = foreground.offsetTop;
this.left = foreground.offsetLeft;
this.right = foreground.offsetLeft;
this.width = foreground.offsetWidth; this.width = foreground.offsetWidth;
resized = util.updateProperty(this, 'height', height) || resized; resized = util.updateProperty(this, 'height', height) || resized;
// recalculate size of label // recalculate size of label
resized = util.updateProperty(this.props.label, 'width', this.dom.inner.clientWidth) || resized; resized = util.updateProperty(this.props.label, 'width', this.dom.inner.clientWidth) || resized;
resized = util.updateProperty(this.props.label, 'height', this.dom.inner.clientHeight) || resized; resized = util.updateProperty(this.props.label, 'height', this.dom.inner.clientHeight) || resized;

+ 99
- 29
lib/timeline/component/ItemSet.js View File

@ -26,8 +26,8 @@ var BACKGROUND = '__background__'; // reserved group id for background items wit
*/ */
function ItemSet(body, options) { function ItemSet(body, options) {
this.body = body; this.body = body;
this.defaultOptions = { this.defaultOptions = {
rtl: false,
type: null, // 'box', 'point', 'range', 'background' type: null, // 'box', 'point', 'range', 'background'
orientation: { orientation: {
item: 'bottom' // item orientation: 'top' or 'bottom' item: 'bottom' // item orientation: 'top' or 'bottom'
@ -96,7 +96,7 @@ function ItemSet(body, options) {
// options is shared by this ItemSet and all its items // options is shared by this ItemSet and all its items
this.options = util.extend({}, this.defaultOptions); this.options = util.extend({}, this.defaultOptions);
// options for getting items from the DataSet with the correct type // options for getting items from the DataSet with the correct type
this.itemOptions = { this.itemOptions = {
type: {start: 'Date', end: 'Date'} type: {start: 'Date', end: 'Date'}
@ -230,8 +230,8 @@ ItemSet.prototype._create = function(){
// add item on doubletap // add item on doubletap
this.hammer.on('doubletap', this._onAddItem.bind(this)); this.hammer.on('doubletap', this._onAddItem.bind(this));
this.groupHammer = new Hammer(this.body.dom.leftContainer); this.groupHammer = new Hammer(this.body.dom.leftContainer);
this.groupHammer.on('panstart', this._onGroupDragStart.bind(this)); this.groupHammer.on('panstart', this._onGroupDragStart.bind(this));
this.groupHammer.on('panmove', this._onGroupDrag.bind(this)); this.groupHammer.on('panmove', this._onGroupDrag.bind(this));
this.groupHammer.on('panend', this._onGroupDragEnd.bind(this)); this.groupHammer.on('panend', this._onGroupDragEnd.bind(this));
@ -308,7 +308,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', 'order', 'stack', 'selectable', 'multiselect', 'itemsAlwaysDraggable', 'multiselectPerGroup', 'groupOrder', 'dataAttributes', 'template', 'groupTemplate', 'hide', 'snap', 'groupOrderSwap'];
var fields = ['type', 'rtl', 'align', 'order', 'stack', 'selectable', 'multiselect', 'itemsAlwaysDraggable', 'multiselectPerGroup', 'groupOrder', 'dataAttributes', 'template', 'groupTemplate', 'hide', 'snap', 'groupOrderSwap'];
util.selectiveExtend(fields, this.options, options); util.selectiveExtend(fields, this.options, options);
if ('orientation' in options) { if ('orientation' in options) {
@ -498,8 +498,14 @@ ItemSet.prototype.getSelection = function() {
*/ */
ItemSet.prototype.getVisibleItems = function() { ItemSet.prototype.getVisibleItems = function() {
var range = this.body.range.getRange(); var range = this.body.range.getRange();
var left = this.body.util.toScreen(range.start);
var right = this.body.util.toScreen(range.end);
if (this.options.rtl) {
var right = this.body.util.toScreen(range.start);
var left = this.body.util.toScreen(range.end);
} else {
var left = this.body.util.toScreen(range.start);
var right = this.body.util.toScreen(range.end);
}
var ids = []; var ids = [];
for (var groupId in this.groups) { for (var groupId in this.groups) {
@ -512,8 +518,14 @@ ItemSet.prototype.getVisibleItems = function() {
for (var i = 0; i < rawVisibleItems.length; i++) { for (var i = 0; i < rawVisibleItems.length; i++) {
var item = rawVisibleItems[i]; var item = rawVisibleItems[i];
// TODO: also check whether visible vertically // TODO: also check whether visible vertically
if ((item.left < right) && (item.left + item.width > left)) {
ids.push(item.id);
if (this.options.rtl) {
if ((item.right < left) && (item.right + item.width > right)) {
ids.push(item.id);
}
} else {
if ((item.left < right) && (item.left + item.width > left)) {
ids.push(item.id);
}
} }
} }
} }
@ -552,7 +564,12 @@ ItemSet.prototype.redraw = function() {
// recalculate absolute position (before redrawing groups) // recalculate absolute position (before redrawing groups)
this.props.top = this.body.domProps.top.height + this.body.domProps.border.top; this.props.top = this.body.domProps.top.height + this.body.domProps.border.top;
this.props.left = this.body.domProps.left.width + this.body.domProps.border.left;
if (this.options.rtl) {
this.props.right = this.body.domProps.right.width + this.body.domProps.border.right;
} else {
this.props.left = this.body.domProps.left.width + this.body.domProps.border.left;
}
// update class name // update class name
frame.className = 'vis-itemset'; frame.className = 'vis-itemset';
@ -605,7 +622,11 @@ ItemSet.prototype.redraw = function() {
this.dom.axis.style.top = asSize((orientation == 'top') ? this.dom.axis.style.top = asSize((orientation == 'top') ?
(this.body.domProps.top.height + this.body.domProps.border.top) : (this.body.domProps.top.height + this.body.domProps.border.top) :
(this.body.domProps.top.height + this.body.domProps.centerContainer.height)); (this.body.domProps.top.height + this.body.domProps.centerContainer.height));
this.dom.axis.style.left = '0';
if (this.options.rtl) {
this.dom.axis.style.right = '0';
} else {
this.dom.axis.style.left = '0';
}
// check if this component is resized // check if this component is resized
resized = this._isResized() || resized; resized = this._isResized() || resized;
@ -1245,8 +1266,15 @@ ItemSet.prototype._onDragStart = function (event) {
*/ */
ItemSet.prototype._onDragStartAddItem = function (event) { ItemSet.prototype._onDragStartAddItem = function (event) {
var snap = this.options.snap || null; var snap = this.options.snap || null;
var xAbs = util.getAbsoluteLeft(this.dom.frame);
var x = event.center.x - xAbs - 10; // minus 10 to compensate for the drag starting as soon as you've moved 10px
if (this.options.rtl) {
var xAbs = util.getAbsoluteRight(this.dom.frame);
var x = xAbs - event.center.x + 10; // plus 10 to compensate for the drag starting as soon as you've moved 10px
} else {
var xAbs = util.getAbsoluteLeft(this.dom.frame);
var x = event.center.x - xAbs - 10; // minus 10 to compensate for the drag starting as soon as you've moved 10px
}
var time = this.body.util.toTime(x); var time = this.body.util.toTime(x);
var scale = this.body.util.getScale(); var scale = this.body.util.getScale();
var step = this.body.util.getStep(); var step = this.body.util.getStep();
@ -1267,7 +1295,6 @@ ItemSet.prototype._onDragStartAddItem = function (event) {
if (group) { if (group) {
itemData.group = group.groupId; itemData.group = group.groupId;
} }
var newItem = new RangeItem(itemData, this.conversion, this.options); var newItem = new RangeItem(itemData, this.conversion, this.options);
newItem.id = id; // TODO: not so nice setting id afterwards newItem.id = id; // TODO: not so nice setting id afterwards
newItem.data = this._cloneItemData(itemData); newItem.data = this._cloneItemData(itemData);
@ -1275,10 +1302,15 @@ ItemSet.prototype._onDragStartAddItem = function (event) {
var props = { var props = {
item: newItem, item: newItem,
dragRight: true,
initialX: event.center.x, initialX: event.center.x,
data: newItem.data data: newItem.data
}; };
if (this.options.rtl) {
props.dragLeft = true;
} else {
props.dragRight = true;
}
this.touchParams.itemProps = [props]; this.touchParams.itemProps = [props];
event.stopPropagation(); event.stopPropagation();
@ -1295,7 +1327,13 @@ ItemSet.prototype._onDrag = function (event) {
var me = this; var me = this;
var snap = this.options.snap || null; var snap = this.options.snap || null;
var xOffset = this.body.dom.root.offsetLeft + this.body.domProps.left.width;
if (this.options.rtl) {
var xOffset = this.body.dom.root.offsetLeft + this.body.domProps.right.width;
} else {
var xOffset = this.body.dom.root.offsetLeft + this.body.domProps.left.width;
}
var scale = this.body.util.getScale(); var scale = this.body.util.getScale();
var step = this.body.util.getStep(); var step = this.body.util.getStep();
@ -1319,7 +1357,12 @@ ItemSet.prototype._onDrag = function (event) {
this.touchParams.itemProps.forEach(function (props) { this.touchParams.itemProps.forEach(function (props) {
var current = me.body.util.toTime(event.center.x - xOffset); var current = me.body.util.toTime(event.center.x - xOffset);
var initial = me.body.util.toTime(props.initialX - xOffset); var initial = me.body.util.toTime(props.initialX - xOffset);
var offset = current - initial; // ms
if (this.options.rtl) {
var offset = -(current - initial); // ms
} else {
var offset = (current - initial); // ms
}
var itemData = this._cloneItemData(props.item.data); // clone the data var itemData = this._cloneItemData(props.item.data); // clone the data
if (props.item.editable === false) { if (props.item.editable === false) {
@ -1328,29 +1371,47 @@ ItemSet.prototype._onDrag = function (event) {
var updateTimeAllowed = me.options.editable.updateTime || var updateTimeAllowed = me.options.editable.updateTime ||
props.item.editable === true; props.item.editable === true;
if (updateTimeAllowed) { if (updateTimeAllowed) {
if (props.dragLeft) { if (props.dragLeft) {
// drag left side of a range item // drag left side of a range item
if (itemData.start != undefined) {
var initialStart = util.convert(props.data.start, 'Date');
var start = new Date(initialStart.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.start = snap ? snap(start, scale, step) : start;
if (this.options.rtl) {
if (itemData.end != undefined) {
var initialEnd = util.convert(props.data.end, 'Date');
var end = new Date(initialEnd.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.end = snap ? snap(end, scale, step) : end;
}
} else {
if (itemData.start != undefined) {
var initialStart = util.convert(props.data.start, 'Date');
var start = new Date(initialStart.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.start = snap ? snap(start, scale, step) : start;
}
} }
} }
else if (props.dragRight) { else if (props.dragRight) {
// drag right side of a range item // drag right side of a range item
if (itemData.end != undefined) {
var initialEnd = util.convert(props.data.end, 'Date');
var end = new Date(initialEnd.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.end = snap ? snap(end, scale, step) : end;
if (this.options.rtl) {
if (itemData.start != undefined) {
var initialStart = util.convert(props.data.start, 'Date');
var start = new Date(initialStart.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.start = snap ? snap(start, scale, step) : start;
}
} else {
if (itemData.end != undefined) {
var initialEnd = util.convert(props.data.end, 'Date');
var end = new Date(initialEnd.valueOf() + offset);
// TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.end = snap ? snap(end, scale, step) : end;
}
} }
} }
else { else {
// drag both start and end // drag both start and end
if (itemData.start != undefined) { if (itemData.start != undefined) {
var initialStart = util.convert(props.data.start, 'Date').valueOf(); var initialStart = util.convert(props.data.start, 'Date').valueOf();
var start = new Date(initialStart + offset); var start = new Date(initialStart + offset);
@ -1366,6 +1427,8 @@ ItemSet.prototype._onDrag = function (event) {
// TODO: pass a Moment instead of a Date to snap(). (Breaking change) // TODO: pass a Moment instead of a Date to snap(). (Breaking change)
itemData.start = snap ? snap(start, scale, step) : start; itemData.start = snap ? snap(start, scale, step) : start;
} }
} }
} }
} }
@ -1706,8 +1769,15 @@ ItemSet.prototype._onAddItem = function (event) {
} }
else { else {
// add item // add item
var xAbs = util.getAbsoluteLeft(this.dom.frame);
var x = event.center.x - xAbs;
if (this.options.rtl) {
var xAbs = util.getAbsoluteRight(this.dom.frame);
var x = xAbs - event.center.x;
} else {
var xAbs = util.getAbsoluteLeft(this.dom.frame);
var x = event.center.x - xAbs;
}
// var xAbs = util.getAbsoluteLeft(this.dom.frame);
// var x = event.center.x - xAbs;
var start = this.body.util.toTime(x); var start = this.body.util.toTime(x);
var scale = this.body.util.getScale(); var scale = this.body.util.getScale();
var step = this.body.util.getStep(); var step = this.body.util.getStep();

+ 34
- 9
lib/timeline/component/TimeAxis.js View File

@ -73,7 +73,8 @@ TimeAxis.prototype.setOptions = function(options) {
'maxMinorChars', 'maxMinorChars',
'hiddenDates', 'hiddenDates',
'timeAxis', 'timeAxis',
'moment'
'moment',
'rtl'
], this.options, options); ], this.options, options);
// deep copy the format options // deep copy the format options
@ -183,7 +184,6 @@ TimeAxis.prototype.redraw = function () {
else { else {
this.body.dom.backgroundVertical.appendChild(background) this.body.dom.backgroundVertical.appendChild(background)
} }
return this._isResized() || parentChanged; return this._isResized() || parentChanged;
}; };
@ -336,7 +336,13 @@ TimeAxis.prototype._repaintMinorText = function (x, text, orientation, className
label.childNodes[0].nodeValue = text; label.childNodes[0].nodeValue = text;
label.style.top = (orientation == 'top') ? (this.props.majorLabelHeight + 'px') : '0'; label.style.top = (orientation == 'top') ? (this.props.majorLabelHeight + 'px') : '0';
label.style.left = x + 'px';
if (this.options.rtl) {
label.style.left = "";
label.style.right = x + 'px';
} else {
label.style.left = x + 'px';
};
label.className = 'vis-text vis-minor ' + className; label.className = 'vis-text vis-minor ' + className;
//label.title = title; // TODO: this is a heavy operation //label.title = title; // TODO: this is a heavy operation
@ -370,7 +376,12 @@ TimeAxis.prototype._repaintMajorText = function (x, text, orientation, className
//label.title = title; // TODO: this is a heavy operation //label.title = title; // TODO: this is a heavy operation
label.style.top = (orientation == 'top') ? '0' : (this.props.minorLabelHeight + 'px'); label.style.top = (orientation == 'top') ? '0' : (this.props.minorLabelHeight + 'px');
label.style.left = x + 'px';
if (this.options.rtl) {
label.style.left = "";
label.style.right = x + 'px';
} else {
label.style.left = x + 'px';
};
return label; return label;
}; };
@ -402,10 +413,17 @@ TimeAxis.prototype._repaintMinorLine = function (x, width, orientation, classNam
line.style.top = this.body.domProps.top.height + 'px'; line.style.top = this.body.domProps.top.height + 'px';
} }
line.style.height = props.minorLineHeight + 'px'; line.style.height = props.minorLineHeight + 'px';
line.style.left = (x - props.minorLineWidth / 2) + 'px';
if (this.options.rtl) {
line.style.left = "";
line.style.right = (x - props.minorLineWidth / 2) + 'px';
line.className = 'vis-grid vis-vertical-rtl vis-minor ' + className;
} else {
line.style.left = (x - props.minorLineWidth / 2) + 'px';
line.className = 'vis-grid vis-vertical vis-minor ' + className;
};
line.style.width = width + 'px'; line.style.width = width + 'px';
line.className = 'vis-grid vis-vertical vis-minor ' + className;
return line; return line;
}; };
@ -436,12 +454,19 @@ TimeAxis.prototype._repaintMajorLine = function (x, width, orientation, classNam
else { else {
line.style.top = this.body.domProps.top.height + 'px'; line.style.top = this.body.domProps.top.height + 'px';
} }
line.style.left = (x - props.majorLineWidth / 2) + 'px';
if (this.options.rtl) {
line.style.left = "";
line.style.right = (x - props.majorLineWidth / 2) + 'px';
line.className = 'vis-grid vis-vertical-rtl vis-major ' + className;
} else {
line.style.left = (x - props.majorLineWidth / 2) + 'px';
line.className = 'vis-grid vis-vertical vis-major ' + className;
}
line.style.height = props.majorLineHeight + 'px'; line.style.height = props.majorLineHeight + 'px';
line.style.width = width + 'px'; line.style.width = width + 'px';
line.className = 'vis-grid vis-vertical vis-major ' + className;
return line; return line;
}; };

+ 11
- 0
lib/timeline/component/css/item.css View File

@ -100,6 +100,17 @@
cursor: pointer; cursor: pointer;
} }
.vis-item .vis-delete-rtl {
background: url('img/timeline/delete.png') no-repeat center;
position: absolute;
width: 24px;
height: 24px;
top: -4px;
left: -24px;
cursor: pointer;
}
.vis-item.vis-range .vis-drag-left { .vis-item.vis-range .vis-drag-left {
position: absolute; position: absolute;
width: 24px; width: 24px;

+ 5
- 0
lib/timeline/component/css/timeaxis.css View File

@ -41,6 +41,11 @@
border-left: 1px solid; border-left: 1px solid;
} }
.vis-time-axis .vis-grid.vis-vertical-rtl {
position: absolute;
border-right: 1px solid;
}
.vis-time-axis .vis-grid.vis-minor { .vis-time-axis .vis-grid.vis-minor {
border-color: #e5e5e5; border-color: #e5e5e5;
} }

+ 46
- 19
lib/timeline/component/item/BoxItem.js View File

@ -22,7 +22,7 @@ function BoxItem (data, conversion, options) {
height: 0 height: 0
} }
}; };
this.options = options;
// validate data // validate data
if (data) { if (data) {
if (data.start == undefined) { if (data.start == undefined) {
@ -171,29 +171,56 @@ BoxItem.prototype.repositionX = function() {
// calculate left position of the box // calculate left position of the box
if (align == 'right') { if (align == 'right') {
this.left = start - this.width;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = (start - this.props.line.width) + 'px';
this.dom.dot.style.left = (start - this.props.line.width / 2 - this.props.dot.width / 2) + 'px';
if (this.options.rtl) {
this.right = start - this.width;
// reposition box, line, and dot
this.dom.box.style.right = this.right + 'px';
this.dom.line.style.right = (start - this.props.line.width) + 'px';
this.dom.dot.style.right = (start - this.props.line.width / 2 - this.props.dot.width / 2) + 'px';
} else {
this.left = start - this.width;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = (start - this.props.line.width) + 'px';
this.dom.dot.style.left = (start - this.props.line.width / 2 - this.props.dot.width / 2) + 'px';
}
} }
else if (align == 'left') { else if (align == 'left') {
this.left = start;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = start + 'px';
this.dom.dot.style.left = (start + this.props.line.width / 2 - this.props.dot.width / 2) + 'px';
if (this.options.rtl) {
this.right = start;
// reposition box, line, and dot
this.dom.box.style.right = this.right + 'px';
this.dom.line.style.right = start + 'px';
this.dom.dot.style.right = (start + this.props.line.width / 2 - this.props.dot.width / 2) + 'px';
} else {
this.left = start;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = start + 'px';
this.dom.dot.style.left = (start + this.props.line.width / 2 - this.props.dot.width / 2) + 'px';
}
} }
else { else {
// default or 'center' // default or 'center'
this.left = start - this.width / 2;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = (start - this.props.line.width / 2) + 'px';
this.dom.dot.style.left = (start - this.props.dot.width / 2) + 'px';
if (this.options.rtl) {
this.right = start - this.width / 2;
// reposition box, line, and dot
this.dom.box.style.right = this.right + 'px';
this.dom.line.style.right = (start - this.props.line.width) + 'px';
this.dom.dot.style.right = (start - this.props.dot.width / 2) + 'px';
} else {
this.left = start - this.width / 2;
// reposition box, line, and dot
this.dom.box.style.left = this.left + 'px';
this.dom.line.style.left = (start - this.props.line.width / 2) + 'px';
this.dom.dot.style.left = (start - this.props.dot.width / 2) + 'px';
}
} }
}; };

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

@ -23,6 +23,7 @@ function Item (data, conversion, options) {
this.dirty = true; this.dirty = true;
this.top = null; this.top = null;
this.right = null;
this.left = null; this.left = null;
this.width = null; this.width = null;
this.height = null; this.height = null;
@ -154,7 +155,12 @@ Item.prototype._repaintDeleteButton = function (anchor) {
var me = this; var me = this;
var deleteButton = document.createElement('div'); var deleteButton = document.createElement('div');
deleteButton.className = 'vis-delete';
if (this.options.rtl) {
deleteButton.className = 'vis-delete-rtl';
} else {
deleteButton.className = 'vis-delete';
}
deleteButton.title = 'Delete this item'; deleteButton.title = 'Delete this item';
// TODO: be able to destroy the delete button // TODO: be able to destroy the delete button

+ 24
- 9
lib/timeline/component/item/PointItem.js View File

@ -19,10 +19,11 @@ function PointItem (data, conversion, options) {
}, },
content: { content: {
height: 0, height: 0,
marginLeft: 0
marginLeft: 0,
marginRight: 0
} }
}; };
this.options = options;
// validate data // validate data
if (data) { if (data) {
if (data.start == undefined) { if (data.start == undefined) {
@ -117,7 +118,11 @@ PointItem.prototype.redraw = function() {
this.props.content.height = dom.content.offsetHeight; this.props.content.height = dom.content.offsetHeight;
// resize contents // resize contents
dom.content.style.marginLeft = 2 * this.props.dot.width + 'px';
if (this.options.rtl) {
dom.content.style.marginRight = 2 * this.props.dot.width + 'px';
} else {
dom.content.style.marginLeft = 2 * this.props.dot.width + 'px';
}
//dom.content.style.marginRight = ... + 'px'; // TODO: margin right //dom.content.style.marginRight = ... + 'px'; // TODO: margin right
// recalculate size // recalculate size
@ -126,7 +131,11 @@ PointItem.prototype.redraw = function() {
// reposition the dot // reposition the dot
dom.dot.style.top = ((this.height - this.props.dot.height) / 2) + 'px'; dom.dot.style.top = ((this.height - this.props.dot.height) / 2) + 'px';
dom.dot.style.left = (this.props.dot.width / 2) + 'px';
if (this.options.rtl) {
dom.dot.style.right = (this.props.dot.width / 2) + 'px';
} else {
dom.dot.style.left = (this.props.dot.width / 2) + 'px';
}
this.dirty = false; this.dirty = false;
} }
@ -164,10 +173,17 @@ PointItem.prototype.hide = function() {
PointItem.prototype.repositionX = function() { PointItem.prototype.repositionX = function() {
var start = this.conversion.toScreen(this.data.start); var start = this.conversion.toScreen(this.data.start);
this.left = start - this.props.dot.width;
if (this.options.rtl) {
this.right = start - this.props.dot.width;
// reposition point
this.dom.point.style.right = this.right + 'px';
} else {
this.left = start - this.props.dot.width;
// reposition point
this.dom.point.style.left = this.left + 'px';
// reposition point
this.dom.point.style.left = this.left + 'px';
}
}; };
/** /**
@ -177,7 +193,6 @@ PointItem.prototype.repositionX = function() {
PointItem.prototype.repositionY = function() { PointItem.prototype.repositionY = function() {
var orientation = this.options.orientation.item; var orientation = this.options.orientation.item;
var point = this.dom.point; var point = this.dom.point;
if (orientation == 'top') { if (orientation == 'top') {
point.style.top = this.top + 'px'; point.style.top = this.top + 'px';
} }
@ -199,7 +214,7 @@ PointItem.prototype.getWidthLeft = function () {
* @return {number} * @return {number}
*/ */
PointItem.prototype.getWidthRight = function () { PointItem.prototype.getWidthRight = function () {
return this.width - this.props.dot.width;
return this.props.dot.width;
}; };
module.exports = PointItem; module.exports = PointItem;

+ 44
- 14
lib/timeline/component/item/RangeItem.js View File

@ -18,7 +18,7 @@ function RangeItem (data, conversion, options) {
} }
}; };
this.overflow = false; // if contents can overflow (css styling), this flag is set to true this.overflow = false; // if contents can overflow (css styling), this flag is set to true
this.options = options;
// validate data // validate data
if (data) { if (data) {
if (data.start == undefined) { if (data.start == undefined) {
@ -123,7 +123,7 @@ RangeItem.prototype.redraw = function() {
this.dirty = false; this.dirty = false;
} }
console.log("redrawing range");
this._repaintDeleteButton(dom.box); this._repaintDeleteButton(dom.box);
this._repaintDragLeft(); this._repaintDragLeft();
this._repaintDragRight(); this._repaintDragRight();
@ -168,7 +168,7 @@ RangeItem.prototype.repositionX = function(limitSize) {
var parentWidth = this.parent.width; var parentWidth = this.parent.width;
var start = this.conversion.toScreen(this.data.start); var start = this.conversion.toScreen(this.data.start);
var end = this.conversion.toScreen(this.data.end); var end = this.conversion.toScreen(this.data.end);
var contentLeft;
var contentStartPosition;
var contentWidth; var contentWidth;
// limit the width of the range, as browsers cannot draw very wide divs // limit the width of the range, as browsers cannot draw very wide divs
@ -183,7 +183,11 @@ RangeItem.prototype.repositionX = function(limitSize) {
var boxWidth = Math.max(end - start, 1); var boxWidth = Math.max(end - start, 1);
if (this.overflow) { if (this.overflow) {
this.left = start;
if (this.options.rtl) {
this.right = start;
} else {
this.left = start;
}
this.width = boxWidth + this.props.content.width; this.width = boxWidth + this.props.content.width;
contentWidth = this.props.content.width; contentWidth = this.props.content.width;
@ -192,46 +196,71 @@ RangeItem.prototype.repositionX = function(limitSize) {
// So no re-stacking needed, which is nicer for the eye; // So no re-stacking needed, which is nicer for the eye;
} }
else { else {
this.left = start;
if (this.options.rtl) {
this.right = start;
} else {
this.left = start;
}
this.width = boxWidth; this.width = boxWidth;
contentWidth = Math.min(end - start, this.props.content.width); contentWidth = Math.min(end - start, this.props.content.width);
} }
this.dom.box.style.left = this.left + 'px';
if (this.options.rtl) {
this.dom.box.style.right = this.right + 'px';
} else {
this.dom.box.style.left = this.left + 'px';
}
this.dom.box.style.width = boxWidth + 'px'; this.dom.box.style.width = boxWidth + 'px';
switch (this.options.align) { switch (this.options.align) {
case 'left': case 'left':
this.dom.content.style.left = '0';
if (this.options.rtl) {
this.dom.content.style.right = '0';
} else {
this.dom.content.style.left = '0';
}
break; break;
case 'right': case 'right':
this.dom.content.style.left = Math.max((boxWidth - contentWidth), 0) + 'px';
if (this.options.rtl) {
this.dom.content.style.right = Math.max((boxWidth - contentWidth), 0) + 'px';
} else {
this.dom.content.style.left = Math.max((boxWidth - contentWidth), 0) + 'px';
}
break; break;
case 'center': case 'center':
this.dom.content.style.left = Math.max((boxWidth - contentWidth) / 2, 0) + 'px';
if (this.options.rtl) {
this.dom.content.style.right = Math.max((boxWidth - contentWidth) / 2, 0) + 'px';
} else {
this.dom.content.style.left = Math.max((boxWidth - contentWidth) / 2, 0) + 'px';
}
break; break;
default: // 'auto' default: // 'auto'
// when range exceeds left of the window, position the contents at the left of the visible area // when range exceeds left of the window, position the contents at the left of the visible area
if (this.overflow) { if (this.overflow) {
if (end > 0) { if (end > 0) {
contentLeft = Math.max(-start, 0);
contentStartPosition = Math.max(-start, 0);
} }
else { else {
contentLeft = -contentWidth; // ensure it's not visible anymore
contentStartPosition = -contentWidth; // ensure it's not visible anymore
} }
} }
else { else {
if (start < 0) { if (start < 0) {
contentLeft = -start;
contentStartPosition = -start;
} }
else { else {
contentLeft = 0;
contentStartPosition = 0;
} }
} }
this.dom.content.style.left = contentLeft + 'px';
if (this.options.rtl) {
this.dom.content.style.right = contentStartPosition + 'px';
} else {
this.dom.content.style.left = contentStartPosition + 'px';
}
} }
}; };
@ -279,6 +308,7 @@ RangeItem.prototype._repaintDragLeft = function () {
* @protected * @protected
*/ */
RangeItem.prototype._repaintDragRight = function () { RangeItem.prototype._repaintDragRight = function () {
console.log("repainting!!!!");
if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) { if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) {
// create and show drag area // create and show drag area
var dragRight = document.createElement('div'); var dragRight = document.createElement('div');

+ 2
- 1
lib/timeline/optionsTimeline.js View File

@ -15,7 +15,6 @@ let dom = 'dom';
let moment = 'moment'; let moment = 'moment';
let any = 'any'; let any = 'any';
let allOptions = { let allOptions = {
configure: { configure: {
enabled: {boolean}, enabled: {boolean},
@ -26,6 +25,7 @@ let allOptions = {
//globals : //globals :
align: {string}, align: {string},
rtl: {boolean, 'undefined': 'undefined'},
autoResize: {boolean}, autoResize: {boolean},
throttleRedraw: {number}, throttleRedraw: {number},
clickToUse: {boolean}, clickToUse: {boolean},
@ -143,6 +143,7 @@ let allOptions = {
let configureOptions = { let configureOptions = {
global: { global: {
align: ['center', 'left', 'right'], align: ['center', 'left', 'right'],
direction: false,
autoResize: true, autoResize: true,
throttleRedraw: [10, 0, 1000, 10], throttleRedraw: [10, 0, 1000, 10],
clickToUse: false, clickToUse: false,

+ 4
- 0
lib/util.js View File

@ -599,6 +599,10 @@ exports.getAbsoluteLeft = function (elem) {
return elem.getBoundingClientRect().left; return elem.getBoundingClientRect().left;
}; };
exports.getAbsoluteRight = function (elem) {
return elem.getBoundingClientRect().right;
};
/** /**
* Retrieve the absolute top value of a DOM element * Retrieve the absolute top value of a DOM element
* @param {Element} elem A dom element, for example a div * @param {Element} elem A dom element, for example a div

Loading…
Cancel
Save