Browse Source

The event handlers `onMove` and `onMoving` are now invoked with all item properties as argument, and can be used to update all properties (like content, className, etc) and add new properties as well

v3_develop
jos 9 years ago
parent
commit
34a576761c
8 changed files with 4711 additions and 4742 deletions
  1. +3
    -0
      HISTORY.md
  2. +4596
    -4621
      dist/vis.js
  3. +1
    -1
      dist/vis.map
  4. +9
    -9
      dist/vis.min.js
  5. +73
    -107
      lib/timeline/component/ItemSet.js
  6. +5
    -0
      lib/timeline/component/item/Item.js
  7. +2
    -1
      test/timeline.html
  8. +22
    -3
      test/timeline_groups.html

+ 3
- 0
HISTORY.md View File

@ -11,6 +11,9 @@ http://visjs.org
### Timeline
- Orientation can now be configured separately for axis and items.
- The event handlers `onMove` and `onMoving` are now invoked with all item
properties as argument, and can be used to update all properties (like
content, className, etc) and add new properties as well.
- Fixed #654: removed unnecessary minimum height for groups, takes the
height of the group label as minimum height now.
- Fixed #708: detecting wrong group when page is scrolled.

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


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


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


+ 73
- 107
lib/timeline/component/ItemSet.js View File

@ -1115,31 +1115,21 @@ ItemSet.prototype._onDragStart = function (event) {
if (dragLeftItem) {
props = {
item: dragLeftItem,
initialX: event.gesture.center.clientX
initialX: event.gesture.center.clientX,
dragLeft: true,
data: util.extend({}, item.data) // clone the items data
};
if (me.options.editable.updateTime) {
props.start = item.data.start.valueOf();
}
if (me.options.editable.updateGroup) {
if ('group' in item.data) props.group = item.data.group;
}
this.touchParams.itemProps = [props];
}
else if (dragRightItem) {
props = {
item: dragRightItem,
initialX: event.gesture.center.clientX
initialX: event.gesture.center.clientX,
dragRight: true,
data: util.extend({}, item.data) // clone the items data
};
if (me.options.editable.updateTime) {
props.end = item.data.end.valueOf();
}
if (me.options.editable.updateGroup) {
if ('group' in item.data) props.group = item.data.group;
}
this.touchParams.itemProps = [props];
}
else {
@ -1147,24 +1137,10 @@ ItemSet.prototype._onDragStart = function (event) {
var item = me.items[id];
var props = {
item: item,
initialX: event.gesture.center.clientX
initialX: event.gesture.center.clientX,
data: util.extend({}, item.data) // clone the items data
};
if (me.options.editable.updateTime) {
if ('start' in item.data) {
props.start = item.data.start.valueOf();
if ('end' in item.data) {
// we store a duration here in order not to change the width
// of the item when moving it.
props.duration = item.data.end.valueOf() - props.start;
}
}
}
if (me.options.editable.updateGroup) {
if ('group' in item.data) props.group = item.data.group;
}
return props;
});
}
@ -1209,12 +1185,14 @@ ItemSet.prototype._onDragStartAddItem = function (event) {
var newItem = new RangeItem(itemData, this.conversion, this.options);
newItem.id = id; // TODO: not so nice setting id afterwards
newItem.data = itemData;
this._addItem(newItem);
var props = {
item: newItem,
end: end.valueOf(),
initialX: event.gesture.center.clientX
dragRight: true,
initialX: event.gesture.center.clientX,
data: util.extend({}, itemData)
};
this.touchParams.itemProps = [props];
@ -1240,35 +1218,63 @@ ItemSet.prototype._onDrag = function (event) {
// move
this.touchParams.itemProps.forEach(function (props) {
var newProps = {};
var current = me.body.util.toTime(event.gesture.center.clientX - xOffset);
var initial = me.body.util.toTime(props.initialX - xOffset);
var offset = current - initial;
if ('start' in props) {
var start = new Date(props.start + offset);
newProps.start = snap ? snap(start, scale, step) : start;
}
var itemData = util.extend({}, props.item.data); // clone the data
if ('end' in props) {
var end = new Date(props.end + offset);
newProps.end = snap ? snap(end, scale, step) : end;
}
else if ('duration' in props) {
newProps.end = new Date(newProps.start.valueOf() + props.duration);
if (me.options.editable.updateTime) {
if (props.dragLeft) {
// 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);
itemData.start = snap ? snap(start, scale, step) : start;
}
}
else if (props.dragRight) {
// 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);
itemData.end = snap ? snap(end, scale, step) : end;
}
}
else {
// drag both start and end
if (itemData.start != undefined) {
var initialStart = util.convert(props.data.start, 'Date').valueOf();
var start = new Date(initialStart + offset);
if (itemData.end != undefined) {
var initialEnd = util.convert(props.data.end, 'Date');
var duration = initialEnd.valueOf() - initialStart.valueOf();
itemData.start = snap ? snap(start, scale, step) : start;
itemData.end = new Date(itemData.start.valueOf() + duration);
}
else {
itemData.start = snap ? snap(start, scale, step) : start;
}
}
}
}
if ('group' in props) {
// drag from one group to another
var group = me.groupFromTarget(event);
newProps.group = group && group.groupId;
if (me.options.editable.updateGroup && (!props.dragLeft && !props.dragRight)) {
if (itemData.group != undefined) {
// drag from one group to another
var group = me.groupFromTarget(event);
if (group) {
itemData.group = group.groupId;
}
}
}
// confirm moving the item
var itemData = util.extend({}, props.item.data, newProps);
me.options.onMoving(itemData, function (itemData) {
if (itemData) {
me._updateItemProps(props.item, itemData);
props.item.setData(itemData);
}
});
});
@ -1278,28 +1284,6 @@ ItemSet.prototype._onDrag = function (event) {
}
};
/**
* Update an items properties
* @param {Item} item
* @param {Object} props Can contain properties start, end, and group.
* @private
*/
ItemSet.prototype._updateItemProps = function(item, props) {
// TODO: copy all properties from props to item? (also new ones)
if ('start' in props) {
item.data.start = props.start;
}
if ('end' in props) {
item.data.end = props.end;
}
else if ('duration' in props) {
item.data.end = new Date(props.start.valueOf() + props.duration);
}
if ('group' in props && item.data.group != props.group) {
this._moveToGroup(item, props.group)
}
};
/**
* Move an item to another group
* @param {Item} item
@ -1339,9 +1323,9 @@ ItemSet.prototype._onDragEnd = function (event) {
this.touchParams.itemProps = null;
itemProps.forEach(function (props) {
var id = props.item.id;
var itemData = me.itemsData.get(id, me.itemOptions);
var exists = me.itemsData.get(id, me.itemOptions) != null;
if (!itemData) {
if (!exists) {
// add a new item
me.options.onAdd(props.item.data, function (itemData) {
me._removeItem(props.item); // remove temporary item
@ -1356,39 +1340,21 @@ ItemSet.prototype._onDragEnd = function (event) {
}
else {
// update existing item
var changed = false;
if ('start' in props.item.data) {
changed = (props.start != props.item.data.start.valueOf());
itemData.start = util.convert(props.item.data.start,
dataset._options.type && dataset._options.type.start || 'Date');
}
if ('end' in props.item.data) {
changed = changed || (props.end != props.item.data.end.valueOf());
itemData.end = util.convert(props.item.data.end,
dataset._options.type && dataset._options.type.end || 'Date');
}
if ('group' in props.item.data) {
changed = changed || (props.group != props.item.data.group);
itemData.group = props.item.data.group;
}
// only apply changes when start or end is actually changed
if (changed) {
me.options.onMove(itemData, function (itemData) {
if (itemData) {
// apply changes
itemData[dataset._fieldId] = id; // ensure the item contains its id (can be undefined)
changes.push(itemData);
}
else {
// restore original values
me._updateItemProps(props.item, props);
var itemData = util.extend({}, props.item.data); // clone the data
me.options.onMove(itemData, function (itemData) {
if (itemData) {
// apply changes
itemData[dataset._fieldId] = id; // ensure the item contains its id (can be undefined)
changes.push(itemData);
}
else {
// restore original values
props.item.setData(props.data);
me.stackDirty = true; // force re-stacking of all items next redraw
me.body.emitter.emit('change');
}
});
}
me.stackDirty = true; // force re-stacking of all items next redraw
me.body.emitter.emit('change');
}
});
}
});

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

@ -54,6 +54,11 @@ Item.prototype.unselect = function() {
* @param {Object} data
*/
Item.prototype.setData = function(data) {
var groupChanged = data.group != undefined && this.data.group != data.group;
if (groupChanged) {
this.parent.itemSet._moveToGroup(this, data.group);
}
this.data = data;
this.dirty = true;
if (this.displayed) this.redraw();

+ 2
- 1
test/timeline.html View File

@ -41,8 +41,9 @@
<div>
<label for="orientation">Orientation</label>
<select id="orientation">
<option value="both" selected>both</option>
<option value="bottom">bottom</option>
<option value="top">top</option>
<option value="bottom" selected>bottom</option>
</select>
</div>
<script>

+ 22
- 3
test/timeline_groups.html View File

@ -13,6 +13,19 @@
box-sizing: border-box;
width: 100%;
}
.vis.timeline .item.red,
.vis.timeline .item.red.selected {
background-color: red;
color: white;
}
.vis.timeline .item.green,
.vis.timeline .item.green.selected {
background-color: green;
color: white;
}
</style>
<script src="../dist/vis.js"></script>
@ -45,7 +58,7 @@
var now = moment().minutes(0).seconds(0).milliseconds(0);
var groupCount = 3;
var itemCount = 20;
var itemCount = 7;
// create a data set with groups
var names = ['John (0)', 'Alston (1)', 'Lee (2)', 'Grant (3)'];
@ -58,6 +71,7 @@
var items = new vis.DataSet();
for (var i = 0; i < itemCount; i++) {
var start = now.clone().add(Math.random() * 200, 'hours');
var end = Math.random() > 0.5 ? start.clone().add(24, 'hours') : undefined;
var group = Math.floor(Math.random() * groupCount);
items.add({
id: i,
@ -65,8 +79,9 @@
content: 'item ' + i +
' <span style="color:#97B0F8;">(' + names[group] + ')</span>',
start: start,
end: end,
title: 'Title for item ' + i,
type: 'box',
//type: 'box',
className: 'myItem'
});
}
@ -109,10 +124,14 @@
},
onMoving: function (item, callback) {
var min = moment().minutes(0).seconds(0).milliseconds(0).add(2, 'day').toDate();
var min = moment().minutes(0).seconds(0).milliseconds(0).add(-2, 'day').toDate();
if (item.start < min) {
item.start = min;
}
//item.className = item.id > 3 ? 'red' : 'green';
//item.group = Math.random() > 0.5 ? 2 : 1;
//item.hasMoved = true;
//item.content = Math.round(Math.random() * 4);
callback(item); // send back item as confirmation (can be changed)
},

Loading…
Cancel
Save