1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2025-12-03 23:38:07 +00:00

Add swipe,tap and press widget to hammerjs (#3214)

* Create swipe.js

* add swipe widget

* add popup handling

* velocity mini-tweak

* add press widget

* add tap widget

* remove popup from tap widget - not possible as it seems

* add pan widget + utility css

* correcting field name

* naming and formatting

* add usage

* add pinch widget

* add pinch widget

* various small fixes

* adding absolute coordinates to pan widget

* prevent default dragging for pan widget

* improve pan widget stability
This commit is contained in:
BurningTreeC
2018-04-18 12:33:59 +02:00
committed by Jeremy Ruston
parent df809bcb87
commit 8bf7dd7172
9 changed files with 1076 additions and 2 deletions

View File

@@ -15,6 +15,41 @@
"type": "text/plain",
"title": "$:/plugins/tiddlywiki/hammerjs/license"
}
}
},{
"file": "widgets/swipe.js",
"fields": {
"type": "application/javascript",
"title": "$:/plugins/tiddlywiki/hammerjs/widgets/swipe.js",
"module-type": "widget"
}
},{
"file": "widgets/press.js",
"fields": {
"type": "application/javascript",
"title": "$:/plugins/tiddlywiki/hammerjs/widgets/press.js",
"module-type": "widget"
}
},{
"file": "widgets/tap.js",
"fields": {
"type": "application/javascript",
"title": "$:/plugins/tiddlywiki/hammerjs/widgets/tap.js",
"module-type": "widget"
}
},{
"file": "widgets/pan.js",
"fields": {
"type": "application/javascript",
"title": "$:/plugins/tiddlywiki/hammerjs/widgets/pan.js",
"module-type": "widget"
}
},{
"file": "widgets/pinch.js",
"fields": {
"type": "application/javascript",
"title": "$:/plugins/tiddlywiki/hammerjs/widgets/pinch.js",
"module-type": "widget"
}
}
]
}

View File

@@ -0,0 +1,291 @@
/*\
title: $:/plugins/tiddlywiki/hammerjs/widgets/pan.js
type: application/javascript
module-type: widget
actions triggered on pan gestures + event coordinates
\*/
(function (global) {
"use strict";
/*jslint node: true, browser: true */
/*global $tw: false */
var Widget = require("$:/core/modules/widgets/widget.js").widget;
if (typeof window !== 'undefined') {
var Hammer = require("$:/plugins/tiddlywiki/hammerjs/hammer.js");
}
var PanWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
PanWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
PanWidget.prototype.render = function(parent,nextSibling) {
var self = this;
var parentDomNode = parent;
// Compute attributes and execute state
this.computeAttributes();
this.execute();
if (self === this && parent !== undefined && nextSibling !== undefined && this.children !== undefined) {
self.renderChildren(parent,nextSibling);
} else if (self === this && parent !== undefined && nextSibling !== undefined && nextSibling !== null) {
self.refresh();
parentDomNode = parent;
} else {
if(self.parentWidget !== undefined) {
self.parentWidget.refreshSelf();
parentDomNode = parent;
} else {
return false;
}
}
if(this.panTargets === undefined || this.panTargets === "") {
return false;
}
var panElementClass;
var panMultipleClasses = null;
if(this.panTargets.indexOf(' ') !== -1) {
panMultipleClasses = true;
panElementClass = self.panTargets.split(' ');
} else {
panElementClass = self.panTargets;
}
if(panElementClass === undefined || panElementClass === "" || parentDomNode === undefined) {
return false;
}
var domNodeList = [];
if (panMultipleClasses === true) {
for (var i=0; i < elementClass.length; i++) {
var panElements = parentDomNode.getElementsByClassName(panElementClass[i]);
for (var k=0; k < panElements.length; k++) {
domNodeList[i + k] = panElements[k];
}
}
} else {
domNodeList = parentDomNode.getElementsByClassName(panElementClass);
}
var elementIndex;
var panStartValues = [];
for(i=0; i < domNodeList.length; i++) {
elementIndex = i;
var currentElement = domNodeList[i];
var hammer = new Hammer.Manager(domNodeList[i]);
hammer.add(new Hammer.Pan({
event: 'pan',
pointers: self.panPointers,
threshold: self.panThreshold,
direction: Hammer.DIRECTION_ALL
}));
hammer.get('pan');
var scrollLeft = null,
scrollTop = null;
var startX = null;
var startY = null;
var elementTop = null;
var elementLeft = null;
var elementBottom = null;
var elementRight = null;
var elementWidth = null;
var elementHeight = null;
var startActions = null;
var singleElement = null;
var pointerType = null;
var domNodeRect = null;
var parentDomNodeRect = null;
var elementAbsoluteTop = null;
var elementAbsoluteLeft = null;
var fieldStartNames = [ 'starting-x', 'starting-y', 'element-top', 'element-left', 'element-bottom', 'element-right', 'element-width', 'element-height', 'pointer-type', 'parent-x', 'parent-y' ];
hammer.on('touchmove panstart panmove', function(e) {
// Prevent default behaviour
e.preventDefault && e.preventDefault();
e.stopPropagation && e.stopPropagation();
// Set a "dragging" state tiddler - gets deleted when panning ends
$tw.wiki.setText("$:/state/dragging","text",undefined,"yes",null);
// Get the coordinates of the parent Dom Node
if (parentDomNodeRect === null && parentDomNode !== undefined && parentDomNode.parentElement !== undefined) {
parentDomNodeRect = parentDomNode.parentElement.getBoundingClientRect();
}
// Get the current coordinates of the element
if (domNodeRect === null) {
domNodeRect = currentElement.getBoundingClientRect();
}
if (self.panStartActions && startActions !== "done") {
self.invokeActionString(self.panStartActions,self,e);
startActions = "done";
}
// Absolute coordinates of the pointer
scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
scrollTop = window.pageYOffset || document.documentElement.scrollTop;
elementAbsoluteLeft = (e.center.x + scrollLeft).toFixed(self.userToFixed);
elementAbsoluteTop = (e.center.y + scrollTop).toFixed(self.userToFixed);
// Set values at pan-start only
if (panStartValues.length === 0) {
panStartValues[0] = e.center.x.toFixed(self.userToFixed);
panStartValues[1] = e.center.y.toFixed(self.userToFixed);
panStartValues[2] = domNodeRect.top.toFixed(self.userToFixed);
panStartValues[3] = domNodeRect.left.toFixed(self.userToFixed);
panStartValues[4] = domNodeRect.bottom.toFixed(self.userToFixed);
panStartValues[5] = domNodeRect.right.toFixed(self.userToFixed);
panStartValues[6] = domNodeRect.width.toFixed(self.userToFixed);
panStartValues[7] = domNodeRect.height.toFixed(self.userToFixed);
panStartValues[8] = e.pointerType;
panStartValues[9] = parentDomNodeRect.left.toFixed(self.userToFixed) || "undefined";
panStartValues[10] = parentDomNodeRect.top.toFixed(self.userToFixed) || "undefined";
for(var t = 0; t<panStartValues.length; t++){
if(domNodeList.length === 1) {
singleElement = true;
self.setField(self.panStateTiddler,fieldStartNames[t],panStartValues[t]);
} else {
var fieldName = fieldStartNames[t] + "-" + elementIndex;
self.setField(self.panStateTiddler,fieldName,panStartValues[t]);
}
}
if(singleElement === true) {
self.setField(self.panStateTiddler,'delta-x',e.deltaX.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'delta-y',e.deltaY.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'relative-x',e.center.x.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'relative-y',e.center.y.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'absolute-x',elementAbsoluteLeft);
self.setField(self.panStateTiddler,'absolute-y',elementAbsoluteTop);
} else {
self.setField(self.panStateTiddler,'delta-x-' + elementIndex,e.deltaX.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'delta-y-' + elementIndex,e.deltaY.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'relative-x-' + elementIndex,e.center.x.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'relative-y-' + elementIndex,e.center.y.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'absolute-x-' + elementIndex,elementAbsoluteLeft);
self.setField(self.panStateTiddler,'absolute-y-' + elementIndex,elementAbsoluteTop);
}
}
function panWidgetTimeoutFunction(timestamp) {
// Invoke actions that should be repeated every cycle if specified
if(self.panRepeatActions) {
self.invokeActionString(self.panRepeatActions,self,e);
}
if(singleElement === true) {
self.setField(self.panStateTiddler,'delta-x',e.deltaX.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'delta-y',e.deltaY.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'relative-x',e.center.x.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'relative-y',e.center.y.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'absolute-x',elementAbsoluteLeft);
self.setField(self.panStateTiddler,'absolute-y',elementAbsoluteTop);
} else {
self.setField(self.panStateTiddler,'delta-x-' + elementIndex,e.deltaX.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'delta-y-' + elementIndex,e.deltaY.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'relative-x-' + elementIndex,e.center.x.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'relative-y-' + elementIndex,e.center.y.toFixed(self.userToFixed));
self.setField(self.panStateTiddler,'absolute-x-' + elementIndex,elementAbsoluteLeft);
self.setField(self.panStateTiddler,'absolute-y-' + elementIndex,elementAbsoluteTop);
}
};
window.requestAnimationFrame(panWidgetTimeoutFunction);
})
.on('panend pancancel touchend mouseup', function(e) {
startX = null;
startY = null;
scrollLeft = null;
scrollTop = null;
elementTop = null;
elementLeft = null;
elementBottom = null;
elementRight = null;
elementWidth = null;
elementHeight = null;
startActions = null;
singleElement = null;
pointerType = null;
domNodeRect = null;
parentDomNodeRect = null;
panStartValues = [];
if(self.panEndActions) {
self.invokeActionString(self.panEndActions,self,e);
}
// Delete the "dragging" state tiddler
$tw.wiki.deleteTiddler("$:/state/dragging");
if (self.parentWidget !== undefined) {
self.parentWidget.refreshSelf();
}
return true;
});
}
};
/*
Set the computed values in the state-tiddler fields
*/
PanWidget.prototype.setField = function(tiddler,field,value) {
$tw.wiki.setText(tiddler,field,undefined,value,{ suppressTimestamp: true });
};
/*
Compute the internal state of the widget
*/
PanWidget.prototype.execute = function() {
this.panTargets = this.getAttribute("targets", "");
this.panStateTiddler = this.getAttribute("state","$:/state/pan");
this.panPointers = parseInt(this.getAttribute("pointers","1"));
this.panThreshold = parseInt(this.getAttribute("threshold","0"));
this.userToFixed = parseInt(this.getAttribute("decimals","0"));
this.panStartActions = this.getAttribute("startactions","");
this.panRepeatActions = this.getAttribute("repeatactions","");
this.panEndActions = this.getAttribute("endactions","");
this.makeChildWidgets();
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
PanWidget.prototype.refresh = function(changedTiddlers) {
var self = this;
var changedAttributes = this.computeAttributes();
if(Object.keys(changedAttributes).length) {
self.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
exports.pan = PanWidget;
})();

View File

@@ -0,0 +1,192 @@
/*\
title: $:/plugins/tiddlywiki/hammerjs/widgets/pinch.js
type: application/javascript
module-type: widget
actions triggered on pinch gestures + event values
\*/
(function (global) {
"use strict";
/*jslint node: true, browser: true */
/*global $tw: false */
var Widget = require("$:/core/modules/widgets/widget.js").widget;
if (typeof window !== 'undefined') {
var Hammer = require("$:/plugins/tiddlywiki/hammerjs/hammer.js");
}
var PinchWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
PinchWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
PinchWidget.prototype.render = function(parent,nextSibling) {
var self = this;
var parentDomNode = parent;
// Compute attributes and execute state
this.computeAttributes();
this.execute();
if(self === this && parent !== undefined && nextSibling !== undefined) {
self.renderChildren(parent,nextSibling);
} else if (self === this) {
self.refresh();
parentDomNode = parent;
} else {
return false;
}
if(this.pinchTargets === undefined || this.pinchTargets === "") {
return false;
}
var pinchElementClass;
var pinchMultipleClasses = null;
if(this.pinchTargets.indexOf(' ') !== -1) {
pinchMultipleClasses = true;
pinchElementClass = self.pinchTargets.split(' ');
} else {
pinchElementClass = self.pinchTargets;
}
if(pinchElementClass === undefined || pinchElementClass === "" || parentDomNode === undefined) {
return false;
}
var domNodeList = [];
if (pinchMultipleClasses === true) {
for (var i=0; i < pinchElementClass.length; i++) {
var pinchElements = parentDomNode.getElementsByClassName(pinchElementClass[i]);
for (var k=0; k < pinchElements.length; k++) {
domNodeList[i + k] = pinchElements[k];
}
}
} else {
domNodeList = parentDomNode.getElementsByClassName(pinchElementClass);
}
var elementIndex;
for(i=0; i < domNodeList.length; i++) {
elementIndex = i;
var hammer = new Hammer.Manager(domNodeList[i]);
hammer.add(new Hammer.Pinch({
event: 'pinch',
pointers: 2,
threshold: self.pinchThreshold
}));
hammer.get('pinch').set({ enable: true });
var singleElement = null;
var firstSet = null;
var startActions = null;
hammer.on('pinch pinchstart pinchmove', function(e) {
if(startActions !== "done") {
self.invokeActionString(self.pinchStartActions,self,e);
startActions = "done";
}
if(singleElement === null && domNodeList.length === 1) {
singleElement = true;
}
if(firstSet !== "done") {
var rotationValue = e.rotation.toFixed(self.userToFixed);
var scaleValue = e.scale.toFixed(5);
if(singleElement === true) {
self.setField(self.pinchStateTiddler,'rotation',rotationValue);
self.setField(self.pinchStateTiddler,'scale',scaleValue);
} else {
var fieldNameRot = 'rotation' + "-" + elementIndex;
var fieldNameScale = 'scale' + "-" + elementIndex;
self.setField(self.pinchStateTiddler,fieldNameRot,rotationValue);
self.setField(self.pinchStateTiddler,fieldNameScale,scaleValue);
}
firstSet = "done";
}
function pinchWidgetTimeoutFunction(timestamp) {
var rotationValue = e.rotation.toFixed(self.userToFixed);
var scaleValue = e.scale.toFixed(5);
if(singleElement === true) {
self.setField(self.pinchStateTiddler,'rotation',rotationValue);
self.setField(self.pinchStateTiddler,'scale',scaleValue);
} else {
var fieldNameRot = 'rotation' + "-" + elementIndex;
var fieldNameScale = 'scale' + "-" + elementIndex;
self.setField(self.pinchStateTiddler,fieldNameRot,rotationValue);
self.setField(self.pinchStateTiddler,fieldNameScale,scaleValue);
}
};
window.requestAnimationFrame(pinchWidgetTimeoutFunction);
})
.on('pinchend pinchcancel touchend', function(e) {
e.stopPropagation && e.stopPropagation();
if(self.pinchEndActions) {
self.invokeActionString(self.pinchEndActions,self,e);
}
firstSet = null;
startActions = null;
if(self.parentWidget !== undefined) {
self.parentWidget.refreshSelf();
}
return true; // Action was invoked
});
}
};
/*
Set the computed values in the state-tiddler fields
*/
PinchWidget.prototype.setField = function(tiddler,field,value) {
$tw.wiki.setText(tiddler,field,undefined,value,{ suppressTimestamp: true });
};
/*
Compute the internal state of the widget
*/
PinchWidget.prototype.execute = function() {
this.pinchTargets = this.getAttribute("targets","");
this.userToFixed = parseInt(this.getAttribute("decimals","0"));
this.pinchThreshold = parseInt(this.getAttribute("threshold","0"));
this.pinchStateTiddler = this.getAttribute("statetiddler","$:/state/pinch");
this.pinchStartActions = this.getAttribute("startactions","");
this.pinchEndActions = this.getAttribute("endactions","");
this.makeChildWidgets();
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
PinchWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(Object.keys(changedAttributes).length) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
exports.pinch = PinchWidget;
})();

View File

@@ -0,0 +1,173 @@
/*\
title: $:/plugins/tiddlywiki/hammerjs/widgets/press.js
type: application/javascript
module-type: widget
actions triggered on press gestures
\*/
(function (global) {
"use strict";
/*jslint node: true, browser: true */
/*global $tw: false */
var Widget = require("$:/core/modules/widgets/widget.js").widget;
if (typeof window !== 'undefined') {
var Hammer = require("$:/plugins/tiddlywiki/hammerjs/hammer.js");
}
var PressWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
PressWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
PressWidget.prototype.render = function(parent,nextSibling) {
var self = this;
var parentDomNode = parent;
// Compute attributes and execute state
this.computeAttributes();
this.execute();
if(self === this && parent !== undefined && nextSibling !== undefined ) {
self.renderChildren(parent,nextSibling);
} else if(self === this) {
self.refresh();
parentDomNode = parent;
} else {
return false;
}
if(this.pressTargets === undefined || this.pressTargets === "") {
return false;
}
var pressElementClass;
var pressMultipleClasses = null;
if(this.pressTargets.indexOf(' ') !== -1) {
pressMultipleClasses = true;
pressElementClass = self.pressTargets.split(' ');
} else {
pressElementClass = self.pressTargets;
}
if(pressElementClass === undefined || pressElementClass === "" || parentDomNode === undefined) {
return false;
}
var domNodeList = [];
if (pressMultipleClasses === true) {
for (var i=0; i < pressElementClass.length;i++) {
var pressElements = parentDomNode.getElementsByClassName(pressElementClass[i]);
for (var k=0; k < pressElements.length; k++) {
domNodeList[i + k] = pressElements[k];
self.domNodes.push(pressElements[k]);
}
}
} else {
domNodeList = parentDomNode.getElementsByClassName(pressElementClass);
self.domNodes.push(domNodeList);
}
var isPoppedUp = this.pressPopup && this.isPoppedUp(),
pressElementIndex;
for(i=0; i < domNodeList.length; i++) {
pressElementIndex = i;
var currentElement = domNodeList[i];
var hammer = new Hammer.Manager(domNodeList[i]);
// Event Listener to cancel browser popup menu on long press
currentElement.addEventListener('contextmenu', function(e) {
e.preventDefault && e.preventDefault();
e.stopPropagation && e.stopPropagation();
e.cancelBubble = true;
e.returnValue = false;
return false;
});
hammer.add(new Hammer.Press({
event: 'press',
pointers: self.pressPointers,
threshold: self.pressThreshold,
time: self.pressTime
}));
hammer.get('press');
hammer.on('press', function(e) {
if (self.pressPopup) {
self.triggerPopup(e);
}
if(self.pressStartActions) {
self.invokeActionString(self.pressStartActions,self,e);
}
return true;
})
.on('pressup', function(e) {
if(self.pressEndActions) {
self.invokeActionString(self.pressEndActions,self,e);
}
if (self.pressPopup === undefined && self.parentWidget !== undefined && self.domNodes[0] !== undefined && self.domNodes[0].parentNode !== undefined) {
self.parentWidget.refreshSelf();
}
return true;
});
}
};
PressWidget.prototype.isPoppedUp = function() {
var tiddler = this.wiki.getTiddler(this.pressPopup);
var result = tiddler && tiddler.fields.text ? $tw.popup.readPopupState(tiddler.fields.text) : false;
return result;
};
PressWidget.prototype.triggerPopup = function(event) {
$tw.popup.triggerPopup({
domNode: this.domNodes[0],
title: this.pressPopup,
wiki: this.wiki
});
};
/*
Compute the internal state of the widget
*/
PressWidget.prototype.execute = function() {
this.pressTargets = this.getAttribute("targets");
this.pressPointers = parseInt(this.getAttribute("pointers","1"));
this.pressTime = parseInt(this.getAttribute("time","0"));
this.pressThreshold = parseInt(this.getAttribute("threshold","1000"));
this.pressStartActions = this.getAttribute("startactions","");
this.pressEndActions = this.getAttribute("endactions","");
this.pressPopup = this.getAttribute("popup");
this.makeChildWidgets();
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
PressWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(Object.keys(changedAttributes).length) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
exports.press = PressWidget;
})();

View File

@@ -0,0 +1,168 @@
/*\
title: $:/plugins/tiddlywiki/hammerjs/widgets/swipe.js
type: application/javascript
module-type: widget
actions triggered on swipe gestures
\*/
(function (global) {
"use strict";
/*jslint node: true, browser: true */
/*global $tw: false */
var Widget = require("$:/core/modules/widgets/widget.js").widget;
if (typeof window !== 'undefined') {
var Hammer = require("$:/plugins/tiddlywiki/hammerjs/hammer.js");
}
var SwipeWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
SwipeWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
SwipeWidget.prototype.render = function(parent,nextSibling) {
var self = this;
var parentDomNode = parent;
// Compute attributes and execute state
this.computeAttributes();
this.execute();
if(self === this && parent !== undefined && nextSibling !== undefined) {
self.renderChildren(parent,nextSibling);
} else if (self === this) {
self.refresh();
parentDomNode = parent;
} else {
return false;
}
// Return if no target elements specified
if(this.swipeTargets === undefined || this.swipeTargets === "") {
return false;
}
// Get the Elements with the specified class
var swipeElementClass;
var swipeMultipleClasses = null;
if(this.swipeTargets.indexOf(' ') !== -1) {
swipeMultipleClasses = true;
swipeElementClass = self.swipeTargets.split(' ');
} else {
swipeElementClass = self.swipeTargets;
}
if(swipeElementClass === undefined || swipeElementClass === "" || parentDomNode === undefined) {
return false;
}
// If more than one element with the target class is found, store them in an array and cycle through that
var domNodeList = [];
if (swipeMultipleClasses === true) {
for (var i=0; i < swipeElementClass.length; i++) {
var swipeElements = parentDomNode.getElementsByClassName(swipeElementClass[i]);
for (var k=0; k < swipeElements.length; k++) {
domNodeList[i + k] = swipeElements[k];
self.domNodes.push(swipeElements[k]);
}
}
} else {
domNodeList = parentDomNode.getElementsByClassName(swipeElementClass);
self.domNodes.push(domNodeList);
}
// Create the swipe direction used by Hammer
var swipeDirection = 'swipe' + this.swipeDirection;
// Handle a popup state tiddler
var isPoppedUp = this.swipePopup && this.isPoppedUp();
// Create a new Hammer instance for each found dom node
var swipeElementIndex;
for(i=0; i < domNodeList.length; i++) {
swipeElementIndex = i;
var hammer = new Hammer.Manager(domNodeList[i]);
hammer.add(new Hammer.Swipe({
event: 'swipe',
pointers: self.swipePointers,
threshold: self.swipeThreshold,
velocity: self.swipeVelocity,
direction: Hammer.DIRECTION_ALL
}));
// Tell Hammer it should listen for the swipe event
hammer.get('swipe');
hammer.on(swipeDirection, function(e) {
e.preventDefault && e.preventDefault();
e.stopPropagation && e.stopPropagation();
if (self.swipePopup) {
self.triggerPopup(e);
}
if(self.swipeActions) {
self.invokeActionString(self.swipeActions,self,e);
}
if(self.swipePopup === undefined && self.parentWidget !== undefined && self.domNodes[0] !== undefined && self.domNodes[0].parentNode !== undefined) {
self.parentWidget.refreshSelf();
}
return true; // Action was invoked
});
}
};
SwipeWidget.prototype.isPoppedUp = function() {
var tiddler = this.wiki.getTiddler(this.swipePopup);
var result = tiddler && tiddler.fields.text ? $tw.popup.readPopupState(tiddler.fields.text) : false;
return result;
};
SwipeWidget.prototype.triggerPopup = function(event) {
$tw.popup.triggerPopup({
domNode: this.domNodes[0],
title: this.swipePopup,
wiki: this.wiki
});
};
/*
Compute the internal state of the widget
*/
SwipeWidget.prototype.execute = function() {
this.swipeTargets = this.getAttribute("targets");
this.swipeActions = this.getAttribute("actions","");
this.swipeVelocity = parseFloat(this.getAttribute("velocity", "0.1"));
this.swipeDirection = this.getAttribute("direction","");
this.swipePointers = parseInt(this.getAttribute("pointers","1"));
this.swipeThreshold = parseInt(this.getAttribute("threshold","0"));
this.swipePopup = this.getAttribute("popup");
this.makeChildWidgets();
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
SwipeWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(Object.keys(changedAttributes).length) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
exports.swipe = SwipeWidget;
})();

View File

@@ -0,0 +1,142 @@
/*\
title: $:/plugins/tiddlywiki/hammerjs/widgets/tap.js
type: application/javascript
module-type: widget
actions triggered on taps&clicks
\*/
(function (global) {
"use strict";
/*jslint node: true, browser: true */
/*global $tw: false */
var Widget = require("$:/core/modules/widgets/widget.js").widget;
if (typeof window !== 'undefined') {
var Hammer = require("$:/plugins/tiddlywiki/hammerjs/hammer.js");
}
var TapWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
TapWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
TapWidget.prototype.render = function(parent,nextSibling) {
var self = this;
var parentDomNode = parent;
// Compute attributes and execute state
this.computeAttributes();
this.execute();
if (self === this && parent !== undefined && nextSibling !== undefined) {
self.renderChildren(parent,nextSibling);
} else if (self === this) {
self.refresh();
parentDomNode = parent;
} else {
return false;
}
if(this.tapTargets === undefined || this.tapTargets === "") {
return false;
}
var tapElementClass;
var tapMultipleClasses = null;
if(this.tapTargets.indexOf(' ') !== -1) {
tapMultipleClasses = true;
tapElementClass = self.tapTargets.split(' ');
} else {
tapElementClass = self.tapTargets;
}
if(tapElementClass === undefined || tapElementClass === "" || parentDomNode === undefined) {
return false;
}
var domNodeList = [];
if (tapMultipleClasses === true) {
for (var i=0; i < tapElementClass.length; i++) {
var tapElements = parentDomNode.getElementsByClassName(tapElementClass[i]);
for (var k=0; k < tapElements.length; k++) {
domNodeList[i + k] = tapElements[k];
self.domNodes.push(tapElements[k]);
}
}
} else {
domNodeList = parentDomNode.getElementsByClassName(tapElementClass);
self.domNodes.push(domNodeList);
}
var tapElementIndex;
for(i=0; i < domNodeList.length; i++) {
tapElementIndex = i;
var hammer = new Hammer.Manager(domNodeList[i]);
hammer.add(new Hammer.Tap({
event: 'usertap',
pointers: self.tapPointers,
taps: self.tapCount,
interval: self.tapInterval,
time: self.tapTime,
threshold: self.tapThreshold,
posThreshold: self.tapPosThreshold
}));
hammer.get('usertap');
hammer.on('usertap', function(e) {
if(self.tapActions) {
self.invokeActionString(self.tapActions,self,e);
}
if (self.parentWidget !== undefined && self.domNodes[0] !== undefined && self.domNodes[0].parentNode !== undefined) {
self.parentWidget.refreshSelf();
}
return true; // Action was invoked
});
}
};
/*
Compute the internal state of the widget
*/
TapWidget.prototype.execute = function() {
this.tapTargets = this.getAttribute("targets");
this.tapCount = parseInt(this.getAttribute("taps","1"));
this.tapPointers = parseInt(this.getAttribute("pointers","1"));
this.tapThreshold = parseInt(this.getAttribute("threshold","100"));
this.tapPosThreshold = parseInt(this.getAttribute("posthreshold","200"));
this.tapTime = parseInt(this.getAttribute("time","250"));
this.tapInterval = parseInt(this.getAttribute("interval","300"));
this.tapActions = this.getAttribute("actions","");
this.makeChildWidgets();
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
TapWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(Object.keys(changedAttributes).length) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
exports.tap = TapWidget;
})();