Browse Source

Implemented creating new range items by dragging in an empty space with the ctrl key down.

v3_develop
jos 9 years ago
parent
commit
f6217d9d5e
7 changed files with 4709 additions and 4570 deletions
  1. +2
    -0
      HISTORY.md
  2. +4588
    -4524
      dist/vis.js
  3. +1
    -1
      dist/vis.map
  4. +11
    -11
      dist/vis.min.js
  5. +9
    -1
      docs/timeline.html
  6. +1
    -0
      examples/timeline/08_edit_items.html
  7. +97
    -33
      lib/timeline/component/ItemSet.js

+ 2
- 0
HISTORY.md View File

@ -20,6 +20,8 @@ http://visjs.org
- Implemented orientation option `'both'`, displaying a time axis both on top
and bottom (#665).
- Implemented creating new range items by dragging in an empty space with the
ctrl key down.
- Fixed not property initializing with a DataView for groups.
- Merged add custom timebar functionality, thanks @aytech!
- Fixed #664: end of item not restored when canceling a move event.

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


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


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


+ 9
- 1
docs/timeline.html View File

@ -1170,8 +1170,16 @@ timeline.off('select', onSelect);
<h2 id="Editing_Items">Editing Items</h2>
<p>
When the Timeline is configured to be editable (both options <code>selectable</code> and <code>editable</code> are <code>true</code>), the user can move items by dragging them, can create a new item by double tapping on an empty space, can update an item by double tapping it, and can delete a selected item by clicking the delete button on the top right.
When the Timeline is configured to be editable (both options <code>selectable</code> and <code>editable</code> are <code>true</code>), the user can:
</p>
<ul>
<li>Select an item by clicking it, and use ctrl+click to or shift+click to select multiple items</li>
<li>Move selected items by dragging them.</li>
<li>Create a new item by double tapping on an empty space.</li>
<li>Create a new range item by dragging on an empty space with the ctrl key down.</li>
<li>Update an item by double tapping it.</li>
<li>Delete a selected item by clicking the delete button on the top right.</li>
</ul>
<p>Option <code>editable</code> accepts a boolean or an object. When <code>editable</code> is a boolean, all manipulation actions will be either enabled or disabled. When <code>editable</code> is an object, one can enable individual manipulation actions:</p>

+ 1
- 0
examples/timeline/08_edit_items.html View File

@ -64,6 +64,7 @@
onMoving: function (item, callback) {
if (item.start < min) item.start = min;
if (item.start > max) item.start = max;
if (item.end > max) item.end = max;
callback(item); // send back the (possibly) changed item
},

+ 97
- 33
lib/timeline/component/ItemSet.js View File

@ -1162,6 +1162,54 @@ ItemSet.prototype._onDragStart = function (event) {
event.stopPropagation();
}
else if (this.options.editable.add && event.gesture.srcEvent.ctrlKey) {
// create a new range item when dragging with ctrl key down
this._onDragStartAddItem(event);
}
};
/**
* Start creating a new range item by dragging.
* @param {Event} event
* @private
*/
ItemSet.prototype._onDragStartAddItem = function (event) {
var snap = this.options.snap || null;
var xAbs = util.getAbsoluteLeft(this.dom.frame);
var x = event.gesture.center.pageX - 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 scale = this.body.util.getScale();
var step = this.body.util.getStep();
var start = snap ? snap(time, scale, step) : start;
var end = start;
var itemData = {
type: 'range',
start: start,
end: end,
content: 'new item'
};
var id = util.randomUUID();
itemData[this.itemsData._fieldId] = id;
var group = this.groupFromTarget(event);
if (group) {
itemData.group = group.groupId;
}
var newItem = new RangeItem(itemData, this.conversion, this.options);
newItem.id = id; // TODO: not so nice setting id afterwards
this._addItem(newItem);
var props = {
item: newItem,
end: end.valueOf(),
initialX: event.gesture.center.clientX
};
this.touchParams.itemProps = [props];
event.stopPropagation();
};
/**
@ -1272,49 +1320,65 @@ ItemSet.prototype._onDragEnd = function (event) {
if (this.touchParams.itemProps) {
// prepare a change set for the changed items
var changes = [],
me = this,
dataset = this.itemsData.getDataSet();
var changes = [];
var me = this;
var dataset = this.itemsData.getDataSet();
var itemProps = this.touchParams.itemProps ;
this.touchParams.itemProps = null;
itemProps.forEach(function (props) {
var id = props.item.id,
itemData = me.itemsData.get(id, me.itemOptions);
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;
}
var id = props.item.id;
var itemData = me.itemsData.get(id, me.itemOptions);
// only apply changes when start or end is actually changed
if (changed) {
me.options.onMove(itemData, function (itemData) {
if (!itemData) {
// add a new item
me.options.onAdd(props.item.data, function (itemData) {
me._removeItem(props.item); // remove temporary item
if (itemData) {
// apply changes
itemData[dataset._fieldId] = id; // ensure the item contains its id (can be undefined)
changes.push(itemData);
me.itemsData.getDataSet().add(itemData);
}
else {
// restore original values
me._updateItemProps(props.item, props);
me.stackDirty = true; // force re-stacking of all items next redraw
me.body.emitter.emit('change');
}
// force re-stacking of all items next redraw
me.stackDirty = true;
me.body.emitter.emit('change');
});
}
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);
me.stackDirty = true; // force re-stacking of all items next redraw
me.body.emitter.emit('change');
}
});
}
}
});
// apply the changes to the data (if there are changes)

Loading…
Cancel
Save