Browse Source

Issues #275, #363 - individual Timeline items editable or readonly

Timeline will check for the property 'editable' on individual items.

  if editable === true
    ignore timeline option 'editable'
    allow item to be edited
  else if editable === false
    ignore timeline option 'editable'
    do not allow item to be edited
  else
    use timeline option 'editable'

If two items are selected and one is not editable, only the editable
item is draggable.

This change required the css class .vis-editable be moved from the
item set to the individual item containers to maintain proper styling.
flowchartTest
bertolds 9 years ago
parent
commit
f43e935bef
7 changed files with 81 additions and 16 deletions
  1. +17
    -2
      docs/timeline/index.html
  2. +26
    -9
      lib/timeline/component/ItemSet.js
  3. +1
    -1
      lib/timeline/component/css/item.css
  4. +7
    -1
      lib/timeline/component/item/BoxItem.js
  5. +16
    -1
      lib/timeline/component/item/Item.js
  6. +7
    -1
      lib/timeline/component/item/PointItem.js
  7. +7
    -1
      lib/timeline/component/item/RangeItem.js

+ 17
- 2
docs/timeline/index.html View File

@ -203,8 +203,8 @@
The Timeline uses regular Arrays and Objects as data format. The Timeline uses regular Arrays and Objects as data format.
Data items can contain the properties <code>start</code>, Data items can contain the properties <code>start</code>,
<code>end</code> (optional), <code>content</code>, <code>end</code> (optional), <code>content</code>,
<code>group</code> (optional), <code>className</code> (optional),
and <code>style</code> (optional).
<code>group</code> (optional), <code>className</code> (optional),
<code>editable</code> (optional), and <code>style</code> (optional).
</p> </p>
<p> <p>
@ -325,6 +325,11 @@ var items = [
Types 'box' and 'point' need a start date, the types 'range' and 'background' needs both a start and end date. Types 'box' and 'point' need a start date, the types 'range' and 'background' needs both a start and end date.
</td> </td>
</tr> </tr>
<tr>
<td>editable</td>
<td>Boolean</td>
<td>no</td>
<td>Override the editable option of the timeline for a specific item.</td>
</table> </table>
<h3 id="groups">Groups</h3> <h3 id="groups">Groups</h3>
@ -1323,6 +1328,16 @@ var options = {
} }
};</pre> };</pre>
<p>
Editing can be enabled/disabled for specific items. Setting the property <code>editable</code> to <code>true</code> or <code>false</code> on a data item will override the timeline option.
</p>
<pre class="prettyprint lang-js">
var items = new vis.DataSet([
{id: 1, content: 'read-only item', start: '2013-04-20', editable: false},
{id: 2, content: 'editable item', start: '2013-04-14'}
]);
</pre>
<p> <p>
One can specify callback functions to validate changes made by the user. There are a number of callback functions for this purpose: One can specify callback functions to validate changes made by the user. There are a number of callback functions for this purpose:

+ 26
- 9
lib/timeline/component/ItemSet.js View File

@ -508,15 +508,14 @@ ItemSet.prototype.redraw = function() {
options = this.options, options = this.options,
orientation = options.orientation.item, orientation = options.orientation.item,
resized = false, resized = false,
frame = this.dom.frame,
editable = options.editable.updateTime || options.editable.updateGroup;
frame = this.dom.frame;
// 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; this.props.left = this.body.domProps.left.width + this.body.domProps.border.left;
// update class name // update class name
frame.className = 'vis-itemset' + (editable ? ' vis-editable' : '');
frame.className = 'vis-itemset';
// reorder the groups (if needed) // reorder the groups (if needed)
resized = this._orderGroups() || resized; resized = this._orderGroups() || resized;
@ -1116,15 +1115,23 @@ ItemSet.prototype._onTouch = function (event) {
* @private * @private
*/ */
ItemSet.prototype._onDragStart = function (event) { ItemSet.prototype._onDragStart = function (event) {
if (!this.options.editable.updateTime && !this.options.editable.updateGroup) {
return;
}
var item = this.touchParams.item || null; var item = this.touchParams.item || null;
var me = this; var me = this;
var props; var props;
if (item && item.selected) { if (item && item.selected) {
if (!this.options.editable.updateTime &&
!this.options.editable.updateGroup &&
!item.editable) {
return;
}
// override options.editable
if (item.editable === false) {
return;
}
var dragLeftItem = this.touchParams.dragLeftItem; var dragLeftItem = this.touchParams.dragLeftItem;
var dragRightItem = this.touchParams.dragRightItem; var dragRightItem = this.touchParams.dragRightItem;
@ -1239,7 +1246,14 @@ ItemSet.prototype._onDrag = function (event) {
var itemData = util.extend({}, props.item.data); // clone the data var itemData = util.extend({}, props.item.data); // clone the data
if (me.options.editable.updateTime) {
if (props.item.editable === false) {
return;
}
var updateTimeAllowed = me.options.editable.updateTime ||
props.item.editable === true;
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) { if (itemData.start != undefined) {
@ -1276,7 +1290,10 @@ ItemSet.prototype._onDrag = function (event) {
} }
} }
if (me.options.editable.updateGroup && (!props.dragLeft && !props.dragRight)) {
var updateGroupAllowed = me.options.editable.updateGroup ||
props.item.editable === true;
if (updateGroupAllowed && (!props.dragLeft && !props.dragRight)) {
if (itemData.group != undefined) { if (itemData.group != undefined) {
// drag from one group to another // drag from one group to another
var group = me.groupFromTarget(event); var group = me.groupFromTarget(event);

+ 1
- 1
lib/timeline/component/css/item.css View File

@ -17,7 +17,7 @@
z-index: 2; z-index: 2;
} }
.vis-editable .vis-item.vis-selected {
.vis-editable.vis-selected {
cursor: move; cursor: move;
} }

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

@ -110,9 +110,15 @@ BoxItem.prototype.redraw = function() {
this._updateDataAttributes(this.dom.box); this._updateDataAttributes(this.dom.box);
this._updateStyle(this.dom.box); this._updateStyle(this.dom.box);
var editable = (this.options.editable.updateTime ||
this.options.editable.updateGroup ||
this.editable === true) &&
this.editable !== false;
// update class // update class
var className = (this.data.className? ' ' + this.data.className : '') + var className = (this.data.className? ' ' + this.data.className : '') +
(this.selected ? ' vis-selected' : '');
(this.selected ? ' vis-selected' : '') +
(editable ? ' vis-editable' : '');
dom.box.className = 'vis-item vis-box' + className; dom.box.className = 'vis-item vis-box' + className;
dom.line.className = 'vis-item vis-line' + className; dom.line.className = 'vis-item vis-line' + className;
dom.dot.className = 'vis-item vis-dot' + className; dom.dot.className = 'vis-item vis-dot' + className;

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

@ -26,6 +26,13 @@ function Item (data, conversion, options) {
this.left = null; this.left = null;
this.width = null; this.width = null;
this.height = null; this.height = null;
this.editable = null;
if (this.data &&
this.data.hasOwnProperty('editable') &&
typeof this.data.editable === 'boolean') {
this.editable = data.editable;
}
} }
Item.prototype.stack = true; Item.prototype.stack = true;
@ -59,6 +66,10 @@ Item.prototype.setData = function(data) {
this.parent.itemSet._moveToGroup(this, data.group); this.parent.itemSet._moveToGroup(this, data.group);
} }
if (data.hasOwnProperty('editable') && typeof data.editable === 'boolean') {
this.editable = data.editable;
}
this.data = data; this.data = data;
this.dirty = true; this.dirty = true;
if (this.displayed) this.redraw(); if (this.displayed) this.redraw();
@ -134,7 +145,11 @@ Item.prototype.repositionY = function() {
* @protected * @protected
*/ */
Item.prototype._repaintDeleteButton = function (anchor) { Item.prototype._repaintDeleteButton = function (anchor) {
if (this.selected && this.options.editable.remove && !this.dom.deleteButton) {
var editable = (this.options.editable.remove ||
this.data.editable === true) &&
this.data.editable !== false;
if (this.selected && editable && !this.dom.deleteButton) {
// create and show button // create and show button
var me = this; var me = this;

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

@ -99,9 +99,15 @@ PointItem.prototype.redraw = function() {
this._updateDataAttributes(this.dom.point); this._updateDataAttributes(this.dom.point);
this._updateStyle(this.dom.point); this._updateStyle(this.dom.point);
var editable = (this.options.editable.updateTime ||
this.options.editable.updateGroup ||
this.editable === true) &&
this.editable !== false;
// update class // update class
var className = (this.data.className ? ' ' + this.data.className : '') + var className = (this.data.className ? ' ' + this.data.className : '') +
(this.selected ? ' vis-selected' : '');
(this.selected ? ' vis-selected' : '') +
(editable ? ' vis-editable' : '');
dom.point.className = 'vis-item vis-point' + className; dom.point.className = 'vis-item vis-point' + className;
dom.dot.className = 'vis-item vis-dot' + className; dom.dot.className = 'vis-item vis-dot' + className;

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

@ -99,9 +99,15 @@ RangeItem.prototype.redraw = function() {
this._updateDataAttributes(this.dom.box); this._updateDataAttributes(this.dom.box);
this._updateStyle(this.dom.box); this._updateStyle(this.dom.box);
var editable = (this.options.editable.updateTime ||
this.options.editable.updateGroup ||
this.editable === true) &&
this.editable !== false;
// update class // update class
var className = (this.data.className ? (' ' + this.data.className) : '') + var className = (this.data.className ? (' ' + this.data.className) : '') +
(this.selected ? ' vis-selected' : '');
(this.selected ? ' vis-selected' : '') +
(editable ? ' vis-editable' : '');
dom.box.className = this.baseClassName + className; dom.box.className = this.baseClassName + className;
// determine from css whether this box has overflow // determine from css whether this box has overflow

Loading…
Cancel
Save