Browse Source

Hammer2 mostly working in the Timeline

flowchartTest
jos 10 years ago
parent
commit
a56f8eb2dc
7 changed files with 65 additions and 111 deletions
  1. +3
    -1
      lib/module/hammer.js
  2. +12
    -68
      lib/timeline/Core.js
  3. +35
    -31
      lib/timeline/Range.js
  4. +7
    -4
      lib/timeline/component/CustomTime.js
  5. +5
    -6
      lib/timeline/component/ItemSet.js
  6. +2
    -1
      package.json
  7. +1
    -0
      test/timeline.html

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

@ -1,7 +1,9 @@
// Only load hammer.js when in a browser environment
// (loading hammer.js in a node.js environment gives errors)
if (typeof window !== 'undefined') {
module.exports = window['Hammer'] || require('hammerjs');
var Hammer = window['Hammer'] || require('hammerjs');
var propagating = require('propagating-hammerjs');
module.exports = propagating(Hammer);
}
else {
module.exports = function () {

+ 12
- 68
lib/timeline/Core.js View File

@ -89,10 +89,6 @@ Core.prototype._create = function (container) {
this.dom.rightContainer.appendChild(this.dom.shadowBottomRight);
this.on('rangechange', this.redraw.bind(this));
this.on('touch', this._onTouch.bind(this));
this.on('pinch', this._onPinch.bind(this));
this.on('dragstart', this._onDragStart.bind(this));
this.on('drag', this._onDrag.bind(this));
var me = this;
this.on('change', function (properties) {
@ -113,44 +109,42 @@ Core.prototype._create = function (container) {
// create event listeners for all interesting events, these events will be
// emitted via emitter
this.hammer = new Hammer(this.dom.root);
this.hammer = new Hammer(this.dom.root, {touchAction: 'pan-y'});
this.hammer.get('pinch').set({enable: true});
this.listeners = {};
var events = [
'tap', 'doubletap', 'press',
'pinch',
'panstart', 'panmove', 'panend'
// TODO: mouse wheel?
'pan', 'panstart', 'panmove', 'panend'
// TODO: cleanup
//'touch', 'pinch',
//'tap', 'doubletap', 'hold',
//'dragstart', 'drag', 'dragend',
//'mousewheel', 'DOMMouseScroll' // DOMMouseScroll is needed for Firefox
];
events.forEach(function (event) {
var listener = function () {
var args = [event].concat(Array.prototype.slice.call(arguments, 0));
events.forEach(function (type) {
var listener = function (event) {
if (me.isActive()) {
me.emit.apply(me, args);
me.emit(type, event);
}
};
me.hammer.on(event, listener);
me.listeners[event] = listener;
me.hammer.on(type, listener);
me.listeners[type] = listener;
});
// emulate a touch event (emitted before the start of a pan, pinch, tap, or press)
this.hammer.on('hammer.input', function (event) {
if (event.isFirst) {
var args = ['touch'].concat(Array.prototype.slice.call(arguments, 0));
if (me.isActive()) {
me.emit.apply(me, args);
me.emit('touch', event);
}
}
}.bind(this));
function onMouseWheel() {
var args = ['mousewheel'].concat(Array.prototype.slice.call(arguments, 0));
function onMouseWheel(event) {
if (me.isActive()) {
me.emit.apply(me, args);
me.emit('mousewheel', event);
}
}
this.dom.root.addEventListener('mousewheel', onMouseWheel);
@ -172,7 +166,6 @@ Core.prototype._create = function (container) {
scrollTop: 0,
scrollTopMin: 0
};
this.touch = {}; // store state information needed for touch events
this.redrawCount = 0;
@ -794,55 +787,6 @@ Core.prototype._stopAutoResize = function () {
this._onResize = null;
};
/**
* Start moving the timeline vertically
* @param {Event} event
* @private
*/
Core.prototype._onTouch = function (event) {
this.touch.allowDragging = true;
};
/**
* Start moving the timeline vertically
* @param {Event} event
* @private
*/
Core.prototype._onPinch = function (event) {
this.touch.allowDragging = false;
};
/**
* Start moving the timeline vertically
* @param {Event} event
* @private
*/
Core.prototype._onDragStart = function (event) {
this.touch.initialScrollTop = this.props.scrollTop;
};
/**
* Move the timeline vertically
* @param {Event} event
* @private
*/
Core.prototype._onDrag = function (event) {
// refuse to drag when we where pinching to prevent the timeline make a jump
// when releasing the fingers in opposite order from the touch screen
if (!this.touch.allowDragging) return;
var delta = event.deltaY;
var oldScrollTop = this._getScrollTop();
var newScrollTop = this._setScrollTop(this.touch.initialScrollTop + delta);
if (newScrollTop != oldScrollTop) {
this.redraw(); // TODO: this causes two redraws when dragging, the other is triggered by rangechange already
this.emit("verticalDrag");
}
};
/**
* Apply a scrollTop
* @param {Number} scrollTop

+ 35
- 31
lib/timeline/Range.js View File

@ -363,6 +363,8 @@ Range.prototype._onDragStart = function(event) {
if (this.body.dom.root) {
this.body.dom.root.style.cursor = 'move';
}
event.preventDefault();
};
/**
@ -413,6 +415,8 @@ Range.prototype._onDrag = function (event) {
start: new Date(this.start),
end: new Date(this.end)
});
event.preventDefault();
};
/**
@ -521,41 +525,41 @@ Range.prototype._onPinch = function (event) {
this.props.touch.allowDragging = false;
if (event.touches.length > 1) {
if (!this.props.touch.center) {
this.props.touch.center = getPointer(event.center, this.body.dom.center);
}
if (!this.props.touch.center) {
this.props.touch.center = getPointer(event.center, this.body.dom.center);
}
var scale = 1 / (event.scale + this.scaleOffset);
var centerDate = this._pointerToDate(this.props.touch.center);
var hiddenDuration = DateUtil.getHiddenDurationBetween(this.body.hiddenDates, this.start, this.end);
var hiddenDurationBefore = DateUtil.getHiddenDurationBefore(this.body.hiddenDates, this, centerDate);
var hiddenDurationAfter = hiddenDuration - hiddenDurationBefore;
// calculate new start and end
var newStart = (centerDate - hiddenDurationBefore) + (this.props.touch.start - (centerDate - hiddenDurationBefore)) * scale;
var newEnd = (centerDate + hiddenDurationAfter) + (this.props.touch.end - (centerDate + hiddenDurationAfter)) * scale;
// snapping times away from hidden zones
this.startToFront = 1 - scale > 0 ? false : true; // used to do the right autocorrection with periodic hidden times
this.endToFront = scale - 1 > 0 ? false : true; // used to do the right autocorrection with periodic hidden times
var safeStart = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newStart, 1 - scale, true);
var safeEnd = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newEnd, scale - 1, true);
if (safeStart != newStart || safeEnd != newEnd) {
this.props.touch.start = safeStart;
this.props.touch.end = safeEnd;
this.scaleOffset = 1 - event.scale;
newStart = safeStart;
newEnd = safeEnd;
}
var scale = 1 / (event.scale + this.scaleOffset);
var centerDate = this._pointerToDate(this.props.touch.center);
this.setRange(newStart, newEnd);
var hiddenDuration = DateUtil.getHiddenDurationBetween(this.body.hiddenDates, this.start, this.end);
var hiddenDurationBefore = DateUtil.getHiddenDurationBefore(this.body.hiddenDates, this, centerDate);
var hiddenDurationAfter = hiddenDuration - hiddenDurationBefore;
// calculate new start and end
var newStart = (centerDate - hiddenDurationBefore) + (this.props.touch.start - (centerDate - hiddenDurationBefore)) * scale;
var newEnd = (centerDate + hiddenDurationAfter) + (this.props.touch.end - (centerDate + hiddenDurationAfter)) * scale;
// snapping times away from hidden zones
this.startToFront = 1 - scale <= 0; // used to do the right auto correction with periodic hidden times
this.endToFront = scale - 1 <= 0; // used to do the right auto correction with periodic hidden times
this.startToFront = false; // revert to default
this.endToFront = true; // revert to default
var safeStart = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newStart, 1 - scale, true);
var safeEnd = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newEnd, scale - 1, true);
if (safeStart != newStart || safeEnd != newEnd) {
this.props.touch.start = safeStart;
this.props.touch.end = safeEnd;
this.scaleOffset = 1 - event.scale;
newStart = safeStart;
newEnd = safeEnd;
}
this.setRange(newStart, newEnd);
this.startToFront = false; // revert to default
this.endToFront = true; // revert to default
event.preventDefault();
};
/**

+ 7
- 4
lib/timeline/component/CustomTime.js View File

@ -70,8 +70,11 @@ CustomTime.prototype._create = function() {
// attach event listeners
this.hammer = new Hammer(drag);
this.hammer.on('panstart', this._onDragStart.bind(this));
this.hammer.on('panmove', this._onDrag.bind(this));
this.hammer.on('panmove', this._onDrag.bind(this));
this.hammer.on('panend', this._onDragEnd.bind(this));
this.hammer.on('pan', function (event) {
event.preventDefault();
});
};
/**
@ -147,7 +150,7 @@ CustomTime.prototype._onDragStart = function(event) {
this.eventParams.dragging = true;
this.eventParams.customTime = this.customTime;
//event.stopPropagation();
event.stopPropagation();
event.preventDefault();
};
@ -169,7 +172,7 @@ CustomTime.prototype._onDrag = function (event) {
time: new Date(this.customTime.valueOf())
});
//event.stopPropagation();
event.stopPropagation();
event.preventDefault();
};
@ -186,7 +189,7 @@ CustomTime.prototype._onDragEnd = function (event) {
time: new Date(this.customTime.valueOf())
});
//event.stopPropagation();
event.stopPropagation();
event.preventDefault();
};

+ 5
- 6
lib/timeline/component/ItemSet.js View File

@ -184,7 +184,6 @@ ItemSet.prototype._create = function(){
this.hammer = new Hammer(this.body.dom.centerContainer);
// drag items when selected
//this.hammer.on('pandown', this._onTouch.bind(this)); // TODO
this.hammer.on('hammer.input', function (event) {
if (event.isFirst) {
this._onTouch(event);
@ -1077,6 +1076,7 @@ ItemSet.prototype._onTouch = function (event) {
this.touchParams.item = ItemSet.itemFromTarget(event);
this.touchParams.dragLeftItem = event.target.dragLeftItem || false;
this.touchParams.dragRightItem = event.target.dragRightItem || false;
this.touchParams.itemProps = null;
};
/**
@ -1147,7 +1147,8 @@ ItemSet.prototype._onDragStart = function (event) {
});
}
//event.stopPropagation();
event.stopPropagation();
event.preventDefault();
}
};
@ -1199,7 +1200,7 @@ ItemSet.prototype._onDrag = function (event) {
this.stackDirty = true; // force re-stacking of all items next redraw
this.body.emitter.emit('change');
//event.stopPropagation();
event.stopPropagation();
}
};
@ -1243,8 +1244,6 @@ ItemSet.prototype._moveToGroup = function(item, groupId) {
* @private
*/
ItemSet.prototype._onDragEnd = function (event) {
event.preventDefault()
if (this.touchParams.itemProps) {
// prepare a change set for the changed items
var changes = [],
@ -1297,7 +1296,7 @@ ItemSet.prototype._onDragEnd = function (event) {
dataset.update(changes);
}
//event.stopPropagation();
event.stopPropagation();
}
};

+ 2
- 1
package.json View File

@ -30,8 +30,9 @@
"dependencies": {
"emitter-component": "^1.1.1",
"hammerjs": "^2.0.4",
"keycharm": "^0.1.6",
"moment": "^2.7.0",
"keycharm": "^0.1.6"
"propagating-hammerjs": "^1.2.0"
},
"devDependencies": {
"clean-css": "latest",

+ 1
- 0
test/timeline.html View File

@ -61,6 +61,7 @@
<br>
<div id="visualization"></div>
<div style="height: 1000px;"></div><!-- for testing vertical scroll on touch devices-->
<script>
console.time('create dataset');

Loading…
Cancel
Save