mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-27 03:57:21 +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:
parent
df809bcb87
commit
8bf7dd7172
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
291
plugins/tiddlywiki/hammerjs/files/widgets/pan.js
Normal file
291
plugins/tiddlywiki/hammerjs/files/widgets/pan.js
Normal 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;
|
||||
})();
|
192
plugins/tiddlywiki/hammerjs/files/widgets/pinch.js
Normal file
192
plugins/tiddlywiki/hammerjs/files/widgets/pinch.js
Normal 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;
|
||||
})();
|
173
plugins/tiddlywiki/hammerjs/files/widgets/press.js
Normal file
173
plugins/tiddlywiki/hammerjs/files/widgets/press.js
Normal 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;
|
||||
})();
|
168
plugins/tiddlywiki/hammerjs/files/widgets/swipe.js
Normal file
168
plugins/tiddlywiki/hammerjs/files/widgets/swipe.js
Normal 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;
|
||||
})();
|
142
plugins/tiddlywiki/hammerjs/files/widgets/tap.js
Normal file
142
plugins/tiddlywiki/hammerjs/files/widgets/tap.js
Normal 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;
|
||||
})();
|
@ -3,5 +3,5 @@
|
||||
"description": "HammerJS library by Jorik Tangelder (Eight Media)",
|
||||
"author": "JeremyRuston",
|
||||
"core-version": ">=5.0.0",
|
||||
"list": "readme license"
|
||||
"list": "readme usage license"
|
||||
}
|
||||
|
10
plugins/tiddlywiki/hammerjs/styles.tid
Normal file
10
plugins/tiddlywiki/hammerjs/styles.tid
Normal file
@ -0,0 +1,10 @@
|
||||
title: $:/plugins/tiddlywiki/hammerjs/styles
|
||||
tags: $:/tags/Stylesheet
|
||||
|
||||
<$list filter="[[$:/state/dragging]!is[missing]]">
|
||||
|
||||
iframe {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
</$list>
|
63
plugins/tiddlywiki/hammerjs/usage.tid
Normal file
63
plugins/tiddlywiki/hammerjs/usage.tid
Normal file
@ -0,0 +1,63 @@
|
||||
title: $:/plugins/tiddlywiki/hammerjs/usage
|
||||
|
||||
The ''swipe'', ''press'', ''pan'', ''tap'' and ''pinch'' widgets included in this plugin enable users of creating html elements that trigger user-actions when the corresponding gesture gets executed on the element - or, in case of the pan and pinch widgets, in addition to triggering user-actions, populate a state tiddler with coordinates and values of the element itself and the gesture
|
||||
|
||||
The pan widget stores the coordinates of the element and the relative and absolute coordinates of the pointer in $:/state/pan or a user-defined tiddler
|
||||
|
||||
The pinch widget stores the scale value and the angle of the detected rotation of the pinch gesture in $:/state/pinch or a user-defined tiddler
|
||||
|
||||
With those values users can position elements following the mouse, create custom sliders or create image galleries with pinch-zoomable and rotatable images, in combination with [ext[css calculations|https://www.w3schools.com/cssref/func_calc.asp]] and/or tiddlywiki plugins that allow number-crunching
|
||||
|
||||
|
||||
!!Swipe Widget
|
||||
|
||||
|
||||
|
||||
!!Press Widget
|
||||
|
||||
|
||||
|
||||
!!Pan Widget
|
||||
|
||||
|!Attribute |!Description |!Optional? |h
|
||||
|targets |the css class of the target element(s) |no |
|
||||
|startactions |the actions that should be performed when panning starts |yes |
|
||||
|endactions |the actions that should be performed when panning ends |yes |
|
||||
|repeatactions |actions that are repeatedly performed while panning |yes |
|
||||
|state |optional tiddler where values get stored - default: $:/state/pan |yes |
|
||||
|pointers |the number of pointers needed for the swipe gesture - default: 1 |yes |
|
||||
|threshold |a minimal distance in px required before recognizing the pan gesture - default: 0 |yes |
|
||||
|decimals |the number of decimal points for the stored values in the state tiddler - default: 0 |yes |
|
||||
|
||||
|
||||
As an example, an element with the class `tc-test-class` is made pannable by
|
||||
|
||||
```
|
||||
<$pan targets="tc-test-class">
|
||||
<div class="tc-test-class"/>
|
||||
</$pan>
|
||||
|
||||
```
|
||||
|
||||
When users click this element, hold the mouse and move it, the tiddler $:/state/pan gets populated with the pan-values
|
||||
|
||||
Those values can be used to position that same element using css in a `Stylesheet Tiddler` - note that the values from the state tiddler can be transcluded within the css `calc()` function:
|
||||
|
||||
```css
|
||||
.tc-test-class {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
background-color: #f4f4f4;
|
||||
position: absolute;
|
||||
left: calc({{$:/state/pan!!absolute-x}}px - 35px);
|
||||
top: calc({{$:/state/pan!!absolute-y}}px - 35px)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
!!Tap Widget
|
||||
|
||||
|
||||
|
||||
!!Pinch Widget
|
Loading…
Reference in New Issue
Block a user