feat: Phase 2.5 - Variant Collections Spreadsheet Editor
Replaces JSON textarea with professional Excel-like spreadsheet interface for managing product variant properties. Features: - Handsontable 14.6.1 spreadsheet component - Property presets (Size, Color, Material, Storage, Custom) - Inline cell editing with Tab/Enter navigation - Context menu for add/remove rows and columns - Keyboard shortcuts (Ctrl+D delete, Ctrl+Enter save, Ctrl+Z undo) - Mobile touch gestures (swipe to delete rows) - Automatic JSON serialization on form submit - Form validation before saving - Comprehensive user guide documentation Files Changed: - LittleShop/package.json: NPM package management setup - LittleShop/wwwroot/js/variant-editor.js: 400-line spreadsheet editor module - LittleShop/wwwroot/lib/handsontable/: Handsontable library (Community Edition) - LittleShop/wwwroot/lib/hammerjs/: Hammer.js touch gesture library - LittleShop/Areas/Admin/Views/VariantCollections/Edit.cshtml: Spreadsheet UI integration - VARIANT_COLLECTIONS_USER_GUIDE.md: Complete user guide (18+ pages) Technical Details: - Excel-like editing experience (no more manual JSON editing) - Mobile-first responsive design - Browser compatibility: Chrome 90+, Firefox 88+, Edge 90+, Safari 14+ - Touch-optimized for mobile administration - Automatic data validation and error handling
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
@import url(http://fonts.googleapis.com/css?family=Open+Sans);
|
||||
|
||||
*, *:after, *:before {
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
background: #eee;
|
||||
font: 13px/1.5em 'Open Sans', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4986e7;
|
||||
}
|
||||
|
||||
.bg1, .green { background: #42d692; }
|
||||
.bg2, .blue { background: #4986e7; }
|
||||
.bg3, .red { background: #d06b64; }
|
||||
.bg4, .purple { background: #cd74e6; }
|
||||
.bg5, .azure { background: #9fe1e7; }
|
||||
|
||||
body {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.clear { clear: both; }
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
Open the inspector and play a bit with the touchAction property.
|
||||
<script src="../../hammer.min.js"></script>
|
||||
<script>
|
||||
var mc = new Hammer(document.body);
|
||||
mc.add(new Hammer.Swipe({ direction: Hammer.DIRECTION_HORIZONTAL }));
|
||||
mc.add(new Hammer.Pan({ direction: Hammer.DIRECTION_HORIZONTAL }));
|
||||
|
||||
console.log(document.body.style.touchAction)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
51
LittleShop/wwwroot/lib/hammerjs/tests/manual/input.html
Normal file
51
LittleShop/wwwroot/lib/hammerjs/tests/manual/input.html
Normal file
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
|
||||
<meta name="msapplication-tap-highlight" content="no"/>
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
<title>Hammer.js</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div id="hit" class="bg1" style="padding: 30px; height: 200px;">
|
||||
</div>
|
||||
|
||||
<pre id="debug" style="overflow:hidden; background: #eee; padding: 15px;"></pre>
|
||||
|
||||
<pre id="log" style="overflow:hidden;"></pre>
|
||||
</div>
|
||||
<script src="../../hammer.js"></script>
|
||||
<script>
|
||||
|
||||
Object.prototype.toDirString = function() {
|
||||
var output = [];
|
||||
for(var key in this) {
|
||||
if(this.hasOwnProperty(key)) {
|
||||
var value = this[key];
|
||||
if(Array.isArray(value)) {
|
||||
value = "Array("+ value.length +"):"+ value;
|
||||
} else if(value instanceof HTMLElement) {
|
||||
value = value +" ("+ value.outerHTML.substring(0, 50) +"...)";
|
||||
}
|
||||
output.push(key +": "+ value);
|
||||
}
|
||||
}
|
||||
return output.join("\n")
|
||||
};
|
||||
|
||||
var el = document.querySelector("#hit");
|
||||
var log = document.querySelector("#log");
|
||||
var debug = document.querySelector("#debug");
|
||||
|
||||
var mc = new Hammer(el);
|
||||
mc.get('pinch').set({ enable: true });
|
||||
|
||||
mc.on("hammer.input", function(ev) {
|
||||
debug.innerHTML = [ev.srcEvent.type, ev.pointers.length, ev.isFinal, ev.deltaX, ev.deltaY].join("<br>");
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
61
LittleShop/wwwroot/lib/hammerjs/tests/manual/log.html
Normal file
61
LittleShop/wwwroot/lib/hammerjs/tests/manual/log.html
Normal file
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
<title>Hammer.js</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<div id="hit" class="bg1" style="padding: 30px;">
|
||||
<span id="target" class="bg5" style="display: block; height: 100px;"></span>
|
||||
</div>
|
||||
|
||||
<pre id="debug" style="overflow:hidden; background: #eee; padding: 15px;"></pre>
|
||||
|
||||
<pre id="log" style="overflow:hidden;"></pre>
|
||||
|
||||
</div>
|
||||
<script src="../../hammer.min.js"></script>
|
||||
<script>
|
||||
|
||||
Object.prototype.toDirString = function() {
|
||||
var output = [];
|
||||
for(var key in this) {
|
||||
if(this.hasOwnProperty(key)) {
|
||||
var value = this[key];
|
||||
if(Array.isArray(value)) {
|
||||
value = "Array("+ value.length +"):"+ value;
|
||||
} else if(value instanceof HTMLElement) {
|
||||
value = value +" ("+ value.outerHTML.substring(0, 50) +"...)";
|
||||
}
|
||||
output.push(key +": "+ value);
|
||||
}
|
||||
}
|
||||
return output.join("\n")
|
||||
};
|
||||
|
||||
|
||||
var el = document.querySelector("#hit");
|
||||
var log = document.querySelector("#log");
|
||||
var debug = document.querySelector("#debug");
|
||||
|
||||
var mc = new Hammer(el);
|
||||
mc.get('pinch').set({ enable: true });
|
||||
mc.get('rotate').set({ enable: true });
|
||||
mc.on("swipe pan panstart panmove panend pancancel multipan press pressup pinch rotate tap doubletap",
|
||||
logGesture);
|
||||
|
||||
function DEBUG(str) {
|
||||
debug.textContent = str;
|
||||
}
|
||||
function logGesture(ev) {
|
||||
console.log(ev.timeStamp, ev.type, ev);
|
||||
log.textContent = ev.toDirString();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
73
LittleShop/wwwroot/lib/hammerjs/tests/manual/multiple.html
Normal file
73
LittleShop/wwwroot/lib/hammerjs/tests/manual/multiple.html
Normal file
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
<title>Hammer.js</title>
|
||||
<style>
|
||||
|
||||
#right,
|
||||
#left {
|
||||
display: block;
|
||||
width: 50%;
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#left { float: left; }
|
||||
#right { float: right; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<pre id="left" class="bg1"></pre>
|
||||
<pre id="right" class="bg5"></pre>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
<h1>Multiple instances the same time</h1>
|
||||
<p>You can run multiple instances of Hammer on your page and they will recognize each completely isolated
|
||||
from each other. This makes it possible to build multi-user interfaces.</p>
|
||||
|
||||
</div>
|
||||
<script src="../../hammer.min.js"></script>
|
||||
<script>
|
||||
|
||||
Object.prototype.toDirString = function() {
|
||||
var output = [];
|
||||
for(var key in this) {
|
||||
if(this.hasOwnProperty(key)) {
|
||||
var value = this[key];
|
||||
if(Array.isArray(value)) {
|
||||
value = "Array("+ value.length +"):"+ value;
|
||||
} else if(value instanceof HTMLElement) {
|
||||
value = value +" ("+ value.outerHTML.substring(0, 50) +"...)";
|
||||
}
|
||||
output.push(key +": "+ value);
|
||||
}
|
||||
}
|
||||
return output.join("\n")
|
||||
};
|
||||
|
||||
|
||||
function addHammer(el) {
|
||||
var mc = new Hammer(el, { multiUser: true });
|
||||
mc.get('pan').set({ direction: Hammer.DIRECTION_ALL });
|
||||
mc.get('swipe').set({ direction: Hammer.DIRECTION_ALL });
|
||||
mc.get('pinch').set({ enable: true });
|
||||
mc.get('rotate').set({ enable: true });
|
||||
|
||||
mc.on("swipe pan press pinch rotate tap doubletap", function (ev) {
|
||||
ev.preventDefault();
|
||||
el.innerText = ev.toDirString();
|
||||
});
|
||||
}
|
||||
|
||||
addHammer(document.querySelector("#left"));
|
||||
addHammer(document.querySelector("#right"));
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
217
LittleShop/wwwroot/lib/hammerjs/tests/manual/nested.html
Normal file
217
LittleShop/wwwroot/lib/hammerjs/tests/manual/nested.html
Normal file
@@ -0,0 +1,217 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
|
||||
<meta name="msapplication-tap-highlight" content="no"/>
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
<title>Hammer.js</title>
|
||||
<style>
|
||||
|
||||
.container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.panes.wrapper {
|
||||
max-height: 400px;
|
||||
max-width: 800px;
|
||||
background: #666;
|
||||
margin: 40px auto;
|
||||
}
|
||||
|
||||
.panes {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pane {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
text-align: center;
|
||||
font: bold 60px/250px 'Open Sans', Helvetica, Arial, sans-serif;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.panes.animate > .pane {
|
||||
transition: all .3s;
|
||||
-webkit-transition: all .3s;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="panes wrapper">
|
||||
<div class="pane bg1">
|
||||
<div class="panes">
|
||||
<div class="pane" style="background: rgba(0,0,0,0);">1.1</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.2);">1.2</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.4);">1.3</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.6);">1.4</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.8);">1.5</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pane bg2">
|
||||
<div class="panes">
|
||||
<div class="pane" style="background: rgba(0,0,0,0);">2.1</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.2);">2.2</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.4);">2.3</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.6);">2.4</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.8);">2.5</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pane bg3">
|
||||
<div class="panes">
|
||||
<div class="pane" style="background: rgba(0,0,0,0);">3.1</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.2);">3.2</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.4);">3.3</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.6);">3.4</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.8);">3.5</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pane bg4">
|
||||
<div class="panes">
|
||||
<div class="pane" style="background: rgba(0,0,0,0);">4.1</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.2);">4.2</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.4);">4.3</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.6);">4.4</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.8);">4.5</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pane bg5">
|
||||
<div class="panes">
|
||||
<div class="pane" style="background: rgba(0,0,0,0);">5.1</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.2);">5.2</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.4);">5.3</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.6);">5.4</div>
|
||||
<div class="pane" style="background: rgba(0,0,0,.8);">5.5</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<h1>Nested Pan recognizers</h1>
|
||||
|
||||
<p>Nested recognizers are possible with some threshold and with use of <code>requireFailure()</code>.</p>
|
||||
</div>
|
||||
|
||||
<script src="../../hammer.js"></script>
|
||||
<script>
|
||||
|
||||
var reqAnimationFrame = (function() {
|
||||
return window[Hammer.prefixed(window, "requestAnimationFrame")] || function(callback) {
|
||||
setTimeout(callback, 1000 / 60);
|
||||
}
|
||||
})();
|
||||
|
||||
function dirProp(direction, hProp, vProp) {
|
||||
return (direction & Hammer.DIRECTION_HORIZONTAL) ? hProp : vProp
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Carousel
|
||||
* @param container
|
||||
* @param direction
|
||||
* @constructor
|
||||
*/
|
||||
function HammerCarousel(container, direction) {
|
||||
this.container = container;
|
||||
this.direction = direction;
|
||||
|
||||
this.panes = Array.prototype.slice.call(this.container.children, 0);
|
||||
this.containerSize = this.container[dirProp(direction, 'offsetWidth', 'offsetHeight')];
|
||||
|
||||
this.currentIndex = 0;
|
||||
|
||||
this.hammer = new Hammer.Manager(this.container);
|
||||
this.hammer.add(new Hammer.Pan({ direction: this.direction, threshold: 10 }));
|
||||
this.hammer.on("panstart panmove panend pancancel", Hammer.bindFn(this.onPan, this));
|
||||
|
||||
this.show(this.currentIndex);
|
||||
}
|
||||
|
||||
|
||||
HammerCarousel.prototype = {
|
||||
/**
|
||||
* show a pane
|
||||
* @param {Number} showIndex
|
||||
* @param {Number} [percent] percentage visible
|
||||
* @param {Boolean} [animate]
|
||||
*/
|
||||
show: function(showIndex, percent, animate){
|
||||
showIndex = Math.max(0, Math.min(showIndex, this.panes.length - 1));
|
||||
percent = percent || 0;
|
||||
|
||||
var className = this.container.className;
|
||||
if(animate) {
|
||||
if(className.indexOf('animate') === -1) {
|
||||
this.container.className += ' animate';
|
||||
}
|
||||
} else {
|
||||
if(className.indexOf('animate') !== -1) {
|
||||
this.container.className = className.replace('animate', '').trim();
|
||||
}
|
||||
}
|
||||
|
||||
var paneIndex, pos, translate;
|
||||
for (paneIndex = 0; paneIndex < this.panes.length; paneIndex++) {
|
||||
pos = (this.containerSize / 100) * (((paneIndex - showIndex) * 100) + percent);
|
||||
if(this.direction & Hammer.DIRECTION_HORIZONTAL) {
|
||||
translate = 'translate3d(' + pos + 'px, 0, 0)';
|
||||
} else {
|
||||
translate = 'translate3d(0, ' + pos + 'px, 0)'
|
||||
}
|
||||
this.panes[paneIndex].style.transform = translate;
|
||||
this.panes[paneIndex].style.mozTransform = translate;
|
||||
this.panes[paneIndex].style.webkitTransform = translate;
|
||||
}
|
||||
|
||||
this.currentIndex = showIndex;
|
||||
},
|
||||
|
||||
/**
|
||||
* handle pan
|
||||
* @param {Object} ev
|
||||
*/
|
||||
onPan : function (ev) {
|
||||
var delta = dirProp(this.direction, ev.deltaX, ev.deltaY);
|
||||
var percent = (100 / this.containerSize) * delta;
|
||||
var animate = false;
|
||||
|
||||
if (ev.type == 'panend' || ev.type == 'pancancel') {
|
||||
if (Math.abs(percent) > 20 && ev.type == 'panend') {
|
||||
this.currentIndex += (percent < 0) ? 1 : -1;
|
||||
}
|
||||
percent = 0;
|
||||
animate = true;
|
||||
}
|
||||
|
||||
this.show(this.currentIndex, percent, animate);
|
||||
}
|
||||
};
|
||||
|
||||
// the horizontal pane scroller
|
||||
var outer = new HammerCarousel(document.querySelector(".panes.wrapper"), Hammer.DIRECTION_HORIZONTAL);
|
||||
|
||||
// each pane should contain a vertical pane scroller
|
||||
Hammer.each(document.querySelectorAll(".pane .panes"), function(container) {
|
||||
// setup the inner scroller
|
||||
var inner = new HammerCarousel(container, Hammer.DIRECTION_VERTICAL);
|
||||
|
||||
// only recognize the inner pan when the outer is failing.
|
||||
// they both have a threshold of some px
|
||||
outer.hammer.get('pan').requireFailure(inner.hammer.get('pan'));
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,100 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
<title>Hammer.js</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<div id="maps" style="height: 500px; margin-bottom: 20px;"></div>
|
||||
|
||||
<h1>Gestures simulator</h1>
|
||||
<p>Used for unit-testing Hammer.js. To test it on the Google Maps view, you should open your
|
||||
<a href="https://developer.chrome.com/devtools/docs/mobile-emulation#emulate-touch-events">
|
||||
Inspector and emulate a touch-screen.</a>
|
||||
Or just open it on your touch-device.</p>
|
||||
<p>Currently, it only triggers touchEvents.</p>
|
||||
</div>
|
||||
|
||||
<script src="../../node_modules/hammer-simulator/index.js"></script>
|
||||
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
|
||||
<script>
|
||||
|
||||
Simulator.events.touch.fakeSupport();
|
||||
|
||||
var el, map;
|
||||
var container = document.getElementById('maps');
|
||||
var program = [
|
||||
['pan', ['deltaX','deltaY']],
|
||||
['pinch', ['scale']],
|
||||
['tap', ['pos']],
|
||||
['swipe', ['deltaX','deltaY']],
|
||||
['pinch', ['pos','scale']],
|
||||
['pan', ['pos']],
|
||||
['rotate', ['pos','rotation']],
|
||||
['doubleTap', ['pos']],
|
||||
['pinchRotate', ['pos','scale','rotation']],
|
||||
];
|
||||
|
||||
function randomRange(min, max) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
||||
function randomRangeInt(min, max) {
|
||||
return Math.round(randomRange(min, max));
|
||||
}
|
||||
|
||||
function gestureOption(name) {
|
||||
var max = map.getDiv().offsetWidth * .9;
|
||||
switch(name) {
|
||||
case 'deltaY':
|
||||
case 'deltaX':
|
||||
return randomRangeInt(10, max * .5);
|
||||
case 'pos':
|
||||
return [randomRangeInt(10, max), randomRangeInt(10, max)];
|
||||
case 'scale':
|
||||
return randomRange(.2, 2);
|
||||
case 'rotation':
|
||||
return randomRange(-180, 180);
|
||||
}
|
||||
}
|
||||
|
||||
function walkProgram(done) {
|
||||
var clone = [].concat(program);
|
||||
(function next() {
|
||||
if(clone.length) {
|
||||
var entry = clone.shift();
|
||||
var options = {};
|
||||
for(var i=0; i<entry[1].length; i++) {
|
||||
options[entry[1][i]] = gestureOption(entry[1][i]);
|
||||
}
|
||||
Simulator.gestures[entry[0]](el, options, next);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
function startSimulator() {
|
||||
walkProgram(startSimulator);
|
||||
}
|
||||
|
||||
(function setupGoogleMaps() {
|
||||
map = new google.maps.Map(container, {
|
||||
zoom: 14,
|
||||
center: new google.maps.LatLng(51.98, 5.91)
|
||||
});
|
||||
|
||||
// collect the target element
|
||||
google.maps.event.addListenerOnce(map, 'idle', function(){
|
||||
el = container.childNodes[0].childNodes[0];
|
||||
startSimulator();
|
||||
});
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
118
LittleShop/wwwroot/lib/hammerjs/tests/manual/simulator.html
Normal file
118
LittleShop/wwwroot/lib/hammerjs/tests/manual/simulator.html
Normal file
@@ -0,0 +1,118 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
<title>Hammer.js</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div id="hit" class="bg4" style="padding: 30px; height: 300px; position: relative;">
|
||||
</div>
|
||||
|
||||
<pre id="debug" style="overflow:hidden; background: #eee; padding: 15px;"></pre>
|
||||
|
||||
<pre id="log" style="overflow:hidden;"></pre>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="../../node_modules/hammer-simulator/index.js"></script>
|
||||
<script src="../../hammer.js"></script>
|
||||
<script>
|
||||
|
||||
var program = [
|
||||
['pan', ['deltaX','deltaY']],
|
||||
['pinch', ['scale']],
|
||||
['tap', ['pos']],
|
||||
['swipe', ['deltaX','deltaY']],
|
||||
['pinch', ['pos','scale']],
|
||||
['pan', ['pos']],
|
||||
['rotate', ['pos','rotation']],
|
||||
['doubleTap', ['pos']],
|
||||
['pinchRotate', ['pos','scale','rotation']],
|
||||
];
|
||||
|
||||
function randomRange(min, max) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
||||
function randomRangeInt(min, max) {
|
||||
return Math.round(randomRange(min, max));
|
||||
}
|
||||
|
||||
function gestureOption(name) {
|
||||
var max = el.offsetWidth * .9;
|
||||
switch(name) {
|
||||
case 'deltaY':
|
||||
case 'deltaX':
|
||||
return randomRangeInt(10, max * .5);
|
||||
case 'pos':
|
||||
return [randomRangeInt(10, max), randomRangeInt(10, max)];
|
||||
case 'scale':
|
||||
return randomRange(.2, 2);
|
||||
case 'rotation':
|
||||
return randomRange(-180, 180);
|
||||
}
|
||||
}
|
||||
|
||||
function walkProgram(done) {
|
||||
var clone = [].concat(program);
|
||||
(function next() {
|
||||
if(clone.length) {
|
||||
var entry = clone.shift();
|
||||
var options = {};
|
||||
for(var i=0; i<entry[1].length; i++) {
|
||||
options[entry[1][i]] = gestureOption(entry[1][i]);
|
||||
}
|
||||
setTimeout(function() {
|
||||
log.innerHTML = '';
|
||||
Simulator.gestures[entry[0]](el, options, next);
|
||||
}, 1000);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
function startSimulator() {
|
||||
walkProgram(startSimulator);
|
||||
}
|
||||
|
||||
|
||||
var el = document.querySelector("#hit");
|
||||
var log = document.querySelector("#log");
|
||||
var debug = document.querySelector("#debug");
|
||||
|
||||
var mc = new Hammer(el);
|
||||
mc.get('pinch').set({ enable: true, threshold:.1 });
|
||||
mc.get('rotate').set({ enable: true });
|
||||
mc.on("swipe pan multipan press pinch rotate tap doubletap", logGesture);
|
||||
|
||||
function logGesture(ev) {
|
||||
log.textContent = ev.toDirString();
|
||||
}
|
||||
|
||||
Object.prototype.toDirString = function() {
|
||||
var output = [];
|
||||
for(var key in this) {
|
||||
if(this.hasOwnProperty(key)) {
|
||||
var value = this[key];
|
||||
if(Array.isArray(value)) {
|
||||
value = "Array("+ value.length +"):"+ value;
|
||||
} else if(value instanceof HTMLElement) {
|
||||
value = value +" ("+ value.outerHTML.substring(0, 50) +"...)";
|
||||
}
|
||||
output.push(key +": "+ value);
|
||||
}
|
||||
}
|
||||
return output.join("\n")
|
||||
};
|
||||
|
||||
startSimulator();
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,91 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
<title>Hammer.js</title>
|
||||
|
||||
<style>
|
||||
.tester {
|
||||
margin: 20px 0;
|
||||
padding: 10px;
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.scroll-space {
|
||||
height: 9000px;
|
||||
}
|
||||
|
||||
#native, #no-native {
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
padding: 10px 20px;
|
||||
display: none;
|
||||
margin: 25px 0;
|
||||
}
|
||||
|
||||
.show {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<p>Hammer provides a <a href="../../src/touchaction.js">kind of polyfill</a>
|
||||
for the browsers that don't support the <a href="http://www.w3.org/TR/pointerevents/#the-touch-action-css-property">touch-action</a> property.</p>
|
||||
|
||||
<div id="native" class="green">Your browser has support for the touch-action property!</div>
|
||||
<div id="no-native" class="red">Your browser doesn't support the touch-action property,
|
||||
so we use the polyfill.</div>
|
||||
|
||||
<h2>touch-action: auto</h2>
|
||||
<p>Should prevent nothing.</p>
|
||||
<div class="tester azure" id="auto"></div>
|
||||
|
||||
<h2>touch-action: pan-y</h2>
|
||||
<p>Should prevent scrolling on horizontal movement. This is set by default when creating a Hammer instance.</p>
|
||||
<div class="tester azure" id="pan-y"></div>
|
||||
|
||||
<h2>touch-action: pan-x</h2>
|
||||
<p>Should prevent scrolling on vertical movement.</p>
|
||||
<div class="tester azure" id="pan-x"></div>
|
||||
|
||||
<h2>touch-action: pan-x pan-y</h2>
|
||||
<p>Should <strong>not</strong> prevent any scrolling on any movement. Horizontal and vertical scrolling handled by the browser directly.</p>
|
||||
<div class="tester azure" id="pan-x-pan-y"></div>
|
||||
|
||||
<h2>touch-action: none</h2>
|
||||
<p>Should prevent all.</p>
|
||||
<div class="tester azure" id="none"></div>
|
||||
</div>
|
||||
<script src="../../hammer.js"></script>
|
||||
<script>
|
||||
var support = Hammer.prefixed(document.body.style, 'touchAction');
|
||||
document.getElementById(support ? 'native' : 'no-native').className += ' show';
|
||||
|
||||
var touchActions = ['auto', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'];
|
||||
Hammer.each(touchActions, function(touchAction) {
|
||||
var el = document.getElementById(touchAction.replace(" ", "-"));
|
||||
|
||||
var mc = Hammer(el, {
|
||||
touchAction: touchAction
|
||||
});
|
||||
mc.get('pan').set({ direction: Hammer.DIRECTION_ALL });
|
||||
mc.get('pinch').set({ enable: true });
|
||||
mc.get('rotate').set({ enable: true });
|
||||
|
||||
mc.on("pan swipe rotate pinch tap doubletap press", function(ev) {
|
||||
el.textContent = ev.type +" "+ el.textContent;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="scroll-space"></div>
|
||||
<p>hi.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
211
LittleShop/wwwroot/lib/hammerjs/tests/manual/visual.html
Normal file
211
LittleShop/wwwroot/lib/hammerjs/tests/manual/visual.html
Normal file
@@ -0,0 +1,211 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
<title>Hammer.js</title>
|
||||
|
||||
<style>
|
||||
|
||||
html, body {
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-perspective: 500;
|
||||
-moz-perspective: 500;
|
||||
perspective: 500;
|
||||
}
|
||||
|
||||
.animate {
|
||||
-webkit-transition: all .3s;
|
||||
-moz-transition: all .3s;
|
||||
transition: all .3s;
|
||||
}
|
||||
|
||||
#hit {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#log {
|
||||
position: absolute;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="log"></div>
|
||||
<div id="hit" style="background: #42d692; width: 150px; height: 150px;"></div>
|
||||
|
||||
|
||||
<script src="../../hammer.js"></script>
|
||||
<script>
|
||||
|
||||
var reqAnimationFrame = (function () {
|
||||
return window[Hammer.prefixed(window, 'requestAnimationFrame')] || function (callback) {
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
})();
|
||||
|
||||
var log = document.querySelector("#log");
|
||||
var el = document.querySelector("#hit");
|
||||
|
||||
var START_X = Math.round((window.innerWidth - el.offsetWidth) / 2);
|
||||
var START_Y = Math.round((window.innerHeight - el.offsetHeight) / 2);
|
||||
|
||||
var ticking = false;
|
||||
var transform;
|
||||
var timer;
|
||||
|
||||
var mc = new Hammer.Manager(el);
|
||||
|
||||
mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
|
||||
|
||||
mc.add(new Hammer.Swipe()).recognizeWith(mc.get('pan'));
|
||||
mc.add(new Hammer.Rotate({ threshold: 0 })).recognizeWith(mc.get('pan'));
|
||||
mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith([mc.get('pan'), mc.get('rotate')]);
|
||||
|
||||
mc.add(new Hammer.Tap({ event: 'doubletap', taps: 2 }));
|
||||
mc.add(new Hammer.Tap());
|
||||
|
||||
mc.on("panstart panmove", onPan);
|
||||
mc.on("rotatestart rotatemove", onRotate);
|
||||
mc.on("pinchstart pinchmove", onPinch);
|
||||
mc.on("swipe", onSwipe);
|
||||
mc.on("tap", onTap);
|
||||
mc.on("doubletap", onDoubleTap);
|
||||
|
||||
mc.on("hammer.input", function(ev) {
|
||||
if(ev.isFinal) {
|
||||
resetElement();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function resetElement() {
|
||||
el.className = 'animate';
|
||||
transform = {
|
||||
translate: { x: START_X, y: START_Y },
|
||||
scale: 1,
|
||||
angle: 0,
|
||||
rx: 0,
|
||||
ry: 0,
|
||||
rz: 0
|
||||
};
|
||||
|
||||
requestElementUpdate();
|
||||
|
||||
if (log.textContent.length > 2000) {
|
||||
log.textContent = log.textContent.substring(0, 2000) + "...";
|
||||
}
|
||||
}
|
||||
|
||||
function updateElementTransform() {
|
||||
var value = [
|
||||
'translate3d(' + transform.translate.x + 'px, ' + transform.translate.y + 'px, 0)',
|
||||
'scale(' + transform.scale + ', ' + transform.scale + ')',
|
||||
'rotate3d('+ transform.rx +','+ transform.ry +','+ transform.rz +','+ transform.angle + 'deg)'
|
||||
];
|
||||
|
||||
value = value.join(" ");
|
||||
el.textContent = value;
|
||||
el.style.webkitTransform = value;
|
||||
el.style.mozTransform = value;
|
||||
el.style.transform = value;
|
||||
ticking = false;
|
||||
}
|
||||
|
||||
function requestElementUpdate() {
|
||||
if(!ticking) {
|
||||
reqAnimationFrame(updateElementTransform);
|
||||
ticking = true;
|
||||
}
|
||||
}
|
||||
|
||||
function logEvent(str) {
|
||||
//log.insertBefore(document.createTextNode(str +"\n"), log.firstChild);
|
||||
}
|
||||
|
||||
function onPan(ev) {
|
||||
el.className = '';
|
||||
transform.translate = {
|
||||
x: START_X + ev.deltaX,
|
||||
y: START_Y + ev.deltaY
|
||||
};
|
||||
|
||||
requestElementUpdate();
|
||||
logEvent(ev.type);
|
||||
}
|
||||
|
||||
var initScale = 1;
|
||||
function onPinch(ev) {
|
||||
if(ev.type == 'pinchstart') {
|
||||
initScale = transform.scale || 1;
|
||||
}
|
||||
|
||||
el.className = '';
|
||||
transform.scale = initScale * ev.scale;
|
||||
|
||||
requestElementUpdate();
|
||||
logEvent(ev.type);
|
||||
}
|
||||
|
||||
var initAngle = 0;
|
||||
function onRotate(ev) {
|
||||
if(ev.type == 'rotatestart') {
|
||||
initAngle = transform.angle || 0;
|
||||
}
|
||||
|
||||
el.className = '';
|
||||
transform.rz = 1;
|
||||
transform.angle = initAngle + ev.rotation;
|
||||
requestElementUpdate();
|
||||
logEvent(ev.type);
|
||||
}
|
||||
|
||||
function onSwipe(ev) {
|
||||
var angle = 50;
|
||||
transform.ry = (ev.direction & Hammer.DIRECTION_HORIZONTAL) ? 1 : 0;
|
||||
transform.rx = (ev.direction & Hammer.DIRECTION_VERTICAL) ? 1 : 0;
|
||||
transform.angle = (ev.direction & (Hammer.DIRECTION_RIGHT | Hammer.DIRECTION_UP)) ? angle : -angle;
|
||||
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(function () {
|
||||
resetElement();
|
||||
}, 300);
|
||||
requestElementUpdate();
|
||||
logEvent(ev.type);
|
||||
}
|
||||
|
||||
function onTap(ev) {
|
||||
transform.rx = 1;
|
||||
transform.angle = 25;
|
||||
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(function () {
|
||||
resetElement();
|
||||
}, 200);
|
||||
requestElementUpdate();
|
||||
logEvent(ev.type);
|
||||
}
|
||||
|
||||
function onDoubleTap(ev) {
|
||||
transform.rx = 1;
|
||||
transform.angle = 80;
|
||||
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(function () {
|
||||
resetElement();
|
||||
}, 500);
|
||||
requestElementUpdate();
|
||||
logEvent(ev.type);
|
||||
}
|
||||
|
||||
resetElement();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
5447
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/blanket.js
Normal file
5447
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/blanket.js
Normal file
File diff suppressed because one or more lines are too long
4
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/jquery.min.js
vendored
Normal file
4
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7157
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/lodash.compat.js
Normal file
7157
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/lodash.compat.js
Normal file
File diff suppressed because it is too large
Load Diff
237
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/qunit.css
Normal file
237
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/qunit.css
Normal file
@@ -0,0 +1,237 @@
|
||||
/*!
|
||||
* QUnit 1.14.0
|
||||
* http://qunitjs.com/
|
||||
*
|
||||
* Copyright 2013 jQuery Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Date: 2014-01-31T16:40Z
|
||||
*/
|
||||
|
||||
/** Font Family and Sizes */
|
||||
|
||||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
|
||||
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
|
||||
#qunit-tests { font-size: smaller; }
|
||||
|
||||
|
||||
/** Resets */
|
||||
|
||||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/** Header */
|
||||
|
||||
#qunit-header {
|
||||
padding: 0.5em 0 0.5em 1em;
|
||||
|
||||
color: #8699A4;
|
||||
background-color: #0D3349;
|
||||
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
font-weight: 400;
|
||||
|
||||
border-radius: 5px 5px 0 0;
|
||||
}
|
||||
|
||||
#qunit-header a {
|
||||
text-decoration: none;
|
||||
color: #C2CCD1;
|
||||
}
|
||||
|
||||
#qunit-header a:hover,
|
||||
#qunit-header a:focus {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar label {
|
||||
display: inline-block;
|
||||
padding: 0 0.5em 0 0.1em;
|
||||
}
|
||||
|
||||
#qunit-banner {
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar {
|
||||
padding: 0.5em 0 0.5em 2em;
|
||||
color: #5E740B;
|
||||
background-color: #EEE;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#qunit-userAgent {
|
||||
padding: 0.5em 0 0.5em 2.5em;
|
||||
background-color: #2B81AF;
|
||||
color: #FFF;
|
||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-container {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/** Tests: Pass/Fail */
|
||||
|
||||
#qunit-tests {
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests li {
|
||||
padding: 0.4em 0.5em 0.4em 2.5em;
|
||||
border-bottom: 1px solid #FFF;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#qunit-tests li strong {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#qunit-tests li a {
|
||||
padding: 0.5em;
|
||||
color: #C2CCD1;
|
||||
text-decoration: none;
|
||||
}
|
||||
#qunit-tests li a:hover,
|
||||
#qunit-tests li a:focus {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#qunit-tests li .runtime {
|
||||
float: right;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.qunit-assert-list {
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
background-color: #FFF;
|
||||
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.qunit-collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#qunit-tests table {
|
||||
border-collapse: collapse;
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
#qunit-tests th {
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
padding: 0 0.5em 0 0;
|
||||
}
|
||||
|
||||
#qunit-tests td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#qunit-tests pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#qunit-tests del {
|
||||
background-color: #E0F2BE;
|
||||
color: #374E0C;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-tests ins {
|
||||
background-color: #FFCACA;
|
||||
color: #500;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/*** Test Counts */
|
||||
|
||||
#qunit-tests b.counts { color: #000; }
|
||||
#qunit-tests b.passed { color: #5E740B; }
|
||||
#qunit-tests b.failed { color: #710909; }
|
||||
|
||||
#qunit-tests li li {
|
||||
padding: 5px;
|
||||
background-color: #FFF;
|
||||
border-bottom: none;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
/*** Passing Styles */
|
||||
|
||||
#qunit-tests li li.pass {
|
||||
color: #3C510C;
|
||||
background-color: #FFF;
|
||||
border-left: 10px solid #C6E746;
|
||||
}
|
||||
|
||||
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||
#qunit-tests .pass .test-name { color: #366097; }
|
||||
|
||||
#qunit-tests .pass .test-actual,
|
||||
#qunit-tests .pass .test-expected { color: #999; }
|
||||
|
||||
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||
|
||||
/*** Failing Styles */
|
||||
|
||||
#qunit-tests li li.fail {
|
||||
color: #710909;
|
||||
background-color: #FFF;
|
||||
border-left: 10px solid #EE5757;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#qunit-tests > li:last-child {
|
||||
border-radius: 0 0 5px 5px;
|
||||
}
|
||||
|
||||
#qunit-tests .fail { color: #000; background-color: #EE5757; }
|
||||
#qunit-tests .fail .test-name,
|
||||
#qunit-tests .fail .module-name { color: #000; }
|
||||
|
||||
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||
#qunit-tests .fail .test-expected { color: #008000; }
|
||||
|
||||
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||
|
||||
|
||||
/** Result */
|
||||
|
||||
#qunit-testresult {
|
||||
padding: 0.5em 0.5em 0.5em 2.5em;
|
||||
|
||||
color: #2B81AF;
|
||||
background-color: #D2E0E6;
|
||||
|
||||
border-bottom: 1px solid #FFF;
|
||||
}
|
||||
#qunit-testresult .module-name {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/** Fixture */
|
||||
|
||||
#qunit-fixture {
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
width: 1000px;
|
||||
height: 1000px;
|
||||
}
|
||||
2288
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/qunit.js
Normal file
2288
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/qunit.js
Normal file
File diff suppressed because it is too large
Load Diff
50
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/utils.js
Normal file
50
LittleShop/wwwroot/lib/hammerjs/tests/unit/assets/utils.js
Normal file
@@ -0,0 +1,50 @@
|
||||
var utils = {
|
||||
/**
|
||||
* trigger simple dom event
|
||||
* @param obj
|
||||
* @param name
|
||||
*/
|
||||
triggerDomEvent: function(obj, name) {
|
||||
var event = document.createEvent('Event');
|
||||
event.initEvent(name, true, true);
|
||||
obj.dispatchEvent(event);
|
||||
},
|
||||
|
||||
|
||||
createTouchEvent: function(name, x, y, identifier) {
|
||||
var event = document.createEvent('Event');
|
||||
event.initEvent('touch' + name, true, true);
|
||||
|
||||
event.touches = event.targetTouches = [{
|
||||
clientX: x,
|
||||
clientY: y,
|
||||
identifier: identifier || 0
|
||||
}];
|
||||
|
||||
//https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent.changedTouches
|
||||
event.changedTouches = [{
|
||||
clientX: x,
|
||||
clientY: y,
|
||||
identifier: identifier || 0
|
||||
}];
|
||||
|
||||
return event;
|
||||
},
|
||||
|
||||
dispatchTouchEvent: function(el, name, x, y, identifier) {
|
||||
var event = utils.createTouchEvent(name, x, y, identifier);
|
||||
el.dispatchEvent(event);
|
||||
},
|
||||
|
||||
createHitArea: function(parent) {
|
||||
if (parent == null) {
|
||||
parent = document.getElementById('qunit-fixture')
|
||||
}
|
||||
var hitArea = document.createElement('div');
|
||||
hitArea.style.background = '#eee';
|
||||
hitArea.style.height = '300px';
|
||||
|
||||
parent.appendChild(hitArea);
|
||||
return hitArea;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
var el,
|
||||
hammer;
|
||||
|
||||
module('Pan Gesture', {
|
||||
setup: function() {
|
||||
el = document.createElement('div');
|
||||
document.body.appendChild(el);
|
||||
|
||||
hammer = new Hammer(el, {recognizers: []});
|
||||
},
|
||||
teardown: function() {
|
||||
document.body.removeChild(el);
|
||||
hammer.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
test('`panstart` and `panmove` should be recognized', function() {
|
||||
expect(2);
|
||||
|
||||
var panMoveCount = 0;
|
||||
var pan = new Hammer.Pan({threshold: 1});
|
||||
|
||||
hammer.add(pan);
|
||||
hammer.on('panstart', function() {
|
||||
ok(true);
|
||||
});
|
||||
hammer.on('panmove', function() {
|
||||
panMoveCount++;
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'move', 70, 50);
|
||||
utils.dispatchTouchEvent(el, 'move', 90, 50);
|
||||
|
||||
equal(panMoveCount, 1);
|
||||
});
|
||||
|
||||
asyncTest('Pan event flow should be start -> left -> end', function() {
|
||||
expect(1);
|
||||
var pan = new Hammer.Pan({threshold: 1});
|
||||
hammer.add(pan);
|
||||
|
||||
var eventflow = "";
|
||||
var isCalledPanleft = false;
|
||||
hammer.on('panstart', function() {
|
||||
eventflow += "start";
|
||||
});
|
||||
hammer.on('panleft', function() {
|
||||
if(!isCalledPanleft){
|
||||
isCalledPanleft = true;
|
||||
eventflow += "left";
|
||||
}
|
||||
});
|
||||
hammer.on('panend', function() {
|
||||
eventflow += "end";
|
||||
isCalledPanleft = true;
|
||||
});
|
||||
|
||||
Simulator.gestures.pan(el, { deltaX: -100, deltaY: 0 }, function() {
|
||||
equal(eventflow,"startleftend");
|
||||
start();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
var el,
|
||||
hammer;
|
||||
|
||||
module('Pinch Gesture', {
|
||||
setup: function() {
|
||||
el = document.createElement('div');
|
||||
document.body.appendChild(el);
|
||||
|
||||
hammer = new Hammer(el, {recognizers: []});
|
||||
},
|
||||
teardown: function() {
|
||||
document.body.removeChild(el);
|
||||
hammer.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
asyncTest('Pinch event flow should be start -> in -> end', function() {
|
||||
expect(1);
|
||||
var pinch = new Hammer.Pinch({enable: true, threshold: .1});
|
||||
hammer.add(pinch);
|
||||
|
||||
var eventflow = "";
|
||||
var isFiredPinchin = false;
|
||||
hammer.on('pinchstart', function() {
|
||||
eventflow += "start";
|
||||
});
|
||||
hammer.on('pinchin', function() {
|
||||
if(!isFiredPinchin){
|
||||
isFiredPinchin = true;
|
||||
eventflow += "in";
|
||||
}
|
||||
});
|
||||
hammer.on('pinchend', function() {
|
||||
eventflow += "end";
|
||||
isFiredPinchin = false;
|
||||
});
|
||||
|
||||
Simulator.gestures.pinch(el, { duration: 500, scale: .5 }, function() {
|
||||
equal(eventflow,"startinend");
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
var el,
|
||||
hammer,
|
||||
swipeCount = 0;
|
||||
|
||||
module('Swipe Gesture', {
|
||||
setup: function() {
|
||||
el = utils.createHitArea();
|
||||
hammer = new Hammer(el, {recognizers: []});
|
||||
swipeCount = 0;
|
||||
},
|
||||
teardown: function() {
|
||||
hammer.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
test('swipe can be recognized', function() {
|
||||
expect(1);
|
||||
|
||||
var swipe = new Hammer.Swipe({threshold: 1});
|
||||
hammer.add(swipe);
|
||||
hammer.on('swipe', function() {
|
||||
ok(true);
|
||||
start();
|
||||
});
|
||||
|
||||
stop();
|
||||
|
||||
Simulator.gestures.swipe(el);
|
||||
});
|
||||
43
LittleShop/wwwroot/lib/hammerjs/tests/unit/index.html
Normal file
43
LittleShop/wwwroot/lib/hammerjs/tests/unit/index.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title>Tests</title>
|
||||
<link rel="stylesheet" href="assets/qunit.css">
|
||||
|
||||
<script src="assets/jquery.min.js"></script>
|
||||
<script src="assets/lodash.compat.js"></script>
|
||||
<script src="assets/qunit.js"></script>
|
||||
<!--[if !IE]> --><script src="assets/blanket.js"></script><!-- <![endif]-->
|
||||
<script src="assets/utils.js"></script>
|
||||
|
||||
<script src="../../node_modules/hammer-simulator/index.js"></script>
|
||||
<script>
|
||||
Simulator.setType('touch');
|
||||
Simulator.events.touch.fakeSupport();
|
||||
</script>
|
||||
|
||||
<script src="../build.js" data-cover></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
|
||||
<script src="test_utils.js"></script>
|
||||
<script src="test_enable.js"></script>
|
||||
<script src="test_hammer.js"></script>
|
||||
<script src="test_events.js"></script>
|
||||
<script src="test_nested_gesture_recognizers.js"></script>
|
||||
<script src="test_simultaneous_recognition.js"></script>
|
||||
<script src="test_propagation_bubble.js"></script>
|
||||
<script src="test_gestures.js"></script>
|
||||
<script src="test_multiple_taps.js"></script>
|
||||
<script src="test_require_failure.js"></script>
|
||||
|
||||
<script src="test_jquery_plugin.js"></script>
|
||||
<script src="gestures/test_pan.js"></script>
|
||||
<script src="gestures/test_pinch.js"></script>
|
||||
<script src="gestures/test_swipe.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
171
LittleShop/wwwroot/lib/hammerjs/tests/unit/test_enable.js
Normal file
171
LittleShop/wwwroot/lib/hammerjs/tests/unit/test_enable.js
Normal file
@@ -0,0 +1,171 @@
|
||||
var el,
|
||||
hammer,
|
||||
counter;
|
||||
|
||||
module('Test recognizer enable', {
|
||||
setup: function() {
|
||||
el = utils.createHitArea();
|
||||
hammer = new Hammer.Manager(el, {recognizers: []});
|
||||
counter = 0;
|
||||
},
|
||||
teardown: function() {
|
||||
hammer && hammer.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
test('should disable a recognizer through the `enable` constructor parameter', function() {
|
||||
expect(1);
|
||||
hammer.add(new Hammer.Tap({enable: false}));
|
||||
hammer.on('tap', function() {
|
||||
counter++;
|
||||
});
|
||||
|
||||
stop();
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
equal(counter, 0);
|
||||
}, 100);
|
||||
});
|
||||
|
||||
test('should disable recognizing when the manager is disabled.', function() {
|
||||
expect(1);
|
||||
hammer.set({ enable: false });
|
||||
hammer.add(new Hammer.Tap());
|
||||
hammer.on('tap', function() {
|
||||
counter++;
|
||||
});
|
||||
|
||||
stop();
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
equal(counter, 0);
|
||||
}, 100);
|
||||
});
|
||||
|
||||
test('should toggle a recognizer using the `set` call to the recognizer enable property', function() {
|
||||
expect(2);
|
||||
|
||||
hammer.add(new Hammer.Tap());
|
||||
hammer.on('tap', function() {
|
||||
counter++;
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
equal(counter, 1);
|
||||
|
||||
hammer.get('tap').set({ enable: false });
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
equal(counter, 1);
|
||||
});
|
||||
|
||||
test('should accept the `enable` constructor parameter as function', function() {
|
||||
expect(2);
|
||||
|
||||
var canRecognizeTap = false;
|
||||
|
||||
var tap = new Hammer.Tap({
|
||||
enable: function() {
|
||||
return canRecognizeTap;
|
||||
}
|
||||
});
|
||||
|
||||
hammer.add(tap);
|
||||
hammer.on('tap', function() {
|
||||
counter++;
|
||||
});
|
||||
|
||||
stop();
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
equal(counter, 0);
|
||||
|
||||
canRecognizeTap = true;
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
|
||||
equal(counter, 1);
|
||||
}, 100);
|
||||
});
|
||||
|
||||
test('should accept a function parameter with `set`', function() {
|
||||
expect(3);
|
||||
|
||||
hammer.add(new Hammer.Tap());
|
||||
hammer.on('tap', function() {
|
||||
counter++;
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
equal(counter, 1);
|
||||
|
||||
var canRecognizeTap = false;
|
||||
hammer.get('tap').set({ enable: function() {
|
||||
return canRecognizeTap;
|
||||
}});
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
equal(counter, 1);
|
||||
|
||||
canRecognizeTap = true;
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
equal(counter, 2);
|
||||
});
|
||||
|
||||
test('should pass the recognizer and optional the input parameter to the `enable` callback', function() {
|
||||
expect(2);
|
||||
|
||||
var tap;
|
||||
|
||||
// the enable function is called initially to setup the touch-action property
|
||||
// at that moment there isnt any input
|
||||
var canEnable = function(recognizer, input) {
|
||||
equal(recognizer, tap);
|
||||
return true;
|
||||
};
|
||||
tap = new Hammer.Tap({enable: canEnable});
|
||||
hammer.add(tap);
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
});
|
||||
|
||||
test('should toggle based on other object method', function() {
|
||||
expect(2);
|
||||
|
||||
var view = {
|
||||
state: 0,
|
||||
canRecognizeTap: function(recognizer, input) {
|
||||
return this.state !== 0;
|
||||
}
|
||||
};
|
||||
|
||||
hammer.add(new Hammer.Tap({enable: function(rec, input) { return view.canRecognizeTap(rec, input); } }));
|
||||
hammer.on('tap', function() {
|
||||
counter++;
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
equal(counter, 0);
|
||||
|
||||
view.state = 1;
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
equal(counter, 1);
|
||||
});
|
||||
61
LittleShop/wwwroot/lib/hammerjs/tests/unit/test_events.js
Normal file
61
LittleShop/wwwroot/lib/hammerjs/tests/unit/test_events.js
Normal file
@@ -0,0 +1,61 @@
|
||||
module('eventEmitter');
|
||||
|
||||
test('test the eventemitter', function() {
|
||||
expect(6);
|
||||
|
||||
var ee = new Hammer.Manager(utils.createHitArea());
|
||||
var inputData = {
|
||||
target: document.body,
|
||||
srcEvent: {
|
||||
preventDefault: function() {
|
||||
ok(true, 'preventDefault ref');
|
||||
},
|
||||
target: document.body
|
||||
}
|
||||
};
|
||||
|
||||
function event3Handler() {
|
||||
ok(true, 'emitted event3');
|
||||
}
|
||||
|
||||
ee.on('testEvent1', function() {
|
||||
ok(true, 'emitted event');
|
||||
});
|
||||
ee.on('testEvent2', function(ev) {
|
||||
ok(true, 'emitted event');
|
||||
ev.preventDefault();
|
||||
ok(ev.target === document.body, 'target is the body');
|
||||
});
|
||||
ee.on('testEvent3', event3Handler);
|
||||
|
||||
ee.emit('testEvent1', inputData);
|
||||
ee.emit('testEvent2', inputData);
|
||||
ee.emit('testEvent3', inputData);
|
||||
|
||||
// unbind testEvent2
|
||||
ee.off('testEvent2');
|
||||
ee.off('testEvent3', event3Handler);
|
||||
|
||||
ee.emit('testEvent1', inputData); // should trigger testEvent1 again
|
||||
ee.emit('testEvent2', inputData); // doenst trigger a thing
|
||||
ee.emit('testEvent3', inputData); // doenst trigger a thing
|
||||
|
||||
// destroy
|
||||
ee.destroy();
|
||||
|
||||
ee.emit('testEvent1', inputData); // doenst trigger a thing
|
||||
ee.emit('testEvent2', inputData); // doenst trigger a thing
|
||||
ee.emit('testEvent3', inputData); // doenst trigger a thing
|
||||
});
|
||||
|
||||
/*
|
||||
* Hammer.Manager.off method : exception handling
|
||||
*/
|
||||
test("When Hammer.Manager didn't attach an event, 'off' method is ignored", function() {
|
||||
var count = 0;
|
||||
hammer = new Hammer(el, { inputTarget: document.body });
|
||||
hammer.off("swipeleft", function(e) {
|
||||
count++;
|
||||
});
|
||||
ok(true, "nothing");
|
||||
});
|
||||
208
LittleShop/wwwroot/lib/hammerjs/tests/unit/test_gestures.js
Normal file
208
LittleShop/wwwroot/lib/hammerjs/tests/unit/test_gestures.js
Normal file
@@ -0,0 +1,208 @@
|
||||
// TODO: this tests fails because tapRecognizer changes
|
||||
// it could be that tapRecognizer setup its BEGAN state and
|
||||
// disable the other gesture recognition
|
||||
var el, hammer, events;
|
||||
var allGestureEvents = [
|
||||
'tap doubletap press',
|
||||
'pinch pinchin pinchout pinchstart pinchmove pinchend pinchcancel',
|
||||
'rotate rotatestart rotatemove rotateend rotatecancel',
|
||||
'pan panstart panmove panup pandown panleft panright panend pancancel',
|
||||
'swipe swipeleft swiperight swipeup swipedown'
|
||||
].join(' ');
|
||||
|
||||
module('Gesture recognition', {
|
||||
setup: function() {
|
||||
el = utils.createHitArea();
|
||||
hammer = new Hammer(el);
|
||||
hammer.get('pinch')
|
||||
.set({ // some threshold, since the simulator doesnt stays at scale:1 when rotating
|
||||
enable: true,
|
||||
threshold: .1
|
||||
});
|
||||
|
||||
hammer.get('rotate')
|
||||
.set({ enable: true });
|
||||
|
||||
hammer.on(allGestureEvents, function(ev) {
|
||||
events[ev.type] = true;
|
||||
});
|
||||
events = {};
|
||||
},
|
||||
teardown: function() {
|
||||
hammer && hammer.destroy();
|
||||
events = null;
|
||||
}
|
||||
});
|
||||
|
||||
asyncTest('recognize pan', function() {
|
||||
expect(1);
|
||||
|
||||
Simulator.gestures.pan(el, { duration: 500, deltaX: 100, deltaY: 0 }, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
pan: true,
|
||||
panstart: true,
|
||||
panmove: true,
|
||||
panright: true,
|
||||
panend: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('recognize press', function() {
|
||||
expect(1);
|
||||
|
||||
Simulator.gestures.press(el, null, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
press: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('recognize swipe', function() {
|
||||
expect(1);
|
||||
|
||||
Simulator.gestures.swipe(el, { duration: 300, deltaX: 400, deltaY: 0 }, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
pan: true,
|
||||
panstart: true,
|
||||
panmove: true,
|
||||
panright: true,
|
||||
panend: true,
|
||||
swipe: true,
|
||||
swiperight: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('recognize pinch', function() {
|
||||
expect(1);
|
||||
|
||||
Simulator.gestures.pinch(el, { duration: 500, scale: .5 }, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
pinch: true,
|
||||
pinchstart: true,
|
||||
pinchmove: true,
|
||||
pinchend: true,
|
||||
pinchin: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('recognize children multitouch pinch', function() {
|
||||
expect(1);
|
||||
|
||||
var el1 = utils.createHitArea(el),
|
||||
el2 = utils.createHitArea(el);
|
||||
|
||||
Simulator.gestures.pinch([el1, el2], { duration: 500, scale: .5 }, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
pinch: true,
|
||||
pinchstart: true,
|
||||
pinchmove: true,
|
||||
pinchend: true,
|
||||
pinchin: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('recognize parent-child multitouch pinch', function() {
|
||||
expect(1);
|
||||
|
||||
var el1 = utils.createHitArea(el);
|
||||
|
||||
Simulator.gestures.pinch([el, el1], { duration: 100, scale: .5 }, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
pinch: true,
|
||||
pinchstart: true,
|
||||
pinchmove: true,
|
||||
pinchend: true,
|
||||
pinchin: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('recognize rotate', function() {
|
||||
expect(1);
|
||||
|
||||
Simulator.gestures.rotate(el, { duration: 500, scale: 1 }, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
rotate: true,
|
||||
rotatestart: true,
|
||||
rotatemove: true,
|
||||
rotateend: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('recognize multitouch rotate', function() {
|
||||
expect(1);
|
||||
|
||||
var el1 = utils.createHitArea(el);
|
||||
|
||||
Simulator.gestures.rotate([el, el1], { duration: 500, scale: 1 }, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
rotate: true,
|
||||
rotatestart: true,
|
||||
rotatemove: true,
|
||||
rotateend: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('recognize rotate and pinch simultaneous', function() {
|
||||
expect(1);
|
||||
|
||||
Simulator.gestures.pinchRotate(el, { duration: 500, scale: 2 }, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
rotate: true,
|
||||
rotatestart: true,
|
||||
rotatemove: true,
|
||||
rotateend: true,
|
||||
pinch: true,
|
||||
pinchstart: true,
|
||||
pinchmove: true,
|
||||
pinchend: true,
|
||||
pinchout: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('don\'t recognize pan and swipe when moving down, when only horizontal is allowed', function() {
|
||||
expect(1);
|
||||
|
||||
Simulator.gestures.swipe(el, { duration: 250, deltaX: 0, deltaZ: 200 }, function() {
|
||||
start();
|
||||
deepEqual(events, { });
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('don\'t recognize press if duration is too short.', function() {
|
||||
expect(1);
|
||||
|
||||
Simulator.gestures.press(el, { duration: 240 });
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
deepEqual(events, { tap: true }, 'Tap gesture has been recognized.');
|
||||
}, 275);
|
||||
});
|
||||
|
||||
asyncTest('don\'t recognize tap if duration is too long.', function() {
|
||||
expect(1);
|
||||
|
||||
Simulator.gestures.tap(el, { duration: 255 });
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
deepEqual(events, { press: true }, 'Press gesture has been recognized.');
|
||||
}, 275);
|
||||
});
|
||||
187
LittleShop/wwwroot/lib/hammerjs/tests/unit/test_hammer.js
Normal file
187
LittleShop/wwwroot/lib/hammerjs/tests/unit/test_hammer.js
Normal file
@@ -0,0 +1,187 @@
|
||||
var el, el2,
|
||||
hammer, hammer2;
|
||||
|
||||
module('Tests', {
|
||||
setup: function() {
|
||||
el = utils.createHitArea();
|
||||
el2 = utils.createHitArea();
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
if (hammer) {
|
||||
hammer.destroy();
|
||||
hammer = null;
|
||||
}
|
||||
if (hammer2) {
|
||||
hammer2.destroy();
|
||||
hammer2 = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('hammer shortcut', function() {
|
||||
expect(2);
|
||||
|
||||
Hammer.defaults.touchAction = 'pan-y';
|
||||
hammer = Hammer(el);
|
||||
|
||||
ok(hammer instanceof Hammer.Manager, 'returns an instance of Manager');
|
||||
ok(hammer.touchAction.actions == Hammer.defaults.touchAction, 'set the default touchAction');
|
||||
});
|
||||
|
||||
test('hammer shortcut with options', function() {
|
||||
expect(2);
|
||||
|
||||
hammer = Hammer(el, {
|
||||
touchAction: 'none'
|
||||
});
|
||||
ok(hammer instanceof Hammer.Manager, 'returns an instance of Manager');
|
||||
ok(hammer.touchAction.actions == 'none', 'set the default touchAction');
|
||||
});
|
||||
|
||||
/* Creating a hammer instance does not work on the same way
|
||||
* when using Hammer or Hammer.Manager.
|
||||
*
|
||||
* This can confuse developers who read tests to use the library when doc is missing.
|
||||
*/
|
||||
test('Hammer and Hammer.Manager constructors work exactly on the same way.', function() {
|
||||
expect(2);
|
||||
|
||||
hammer = new Hammer(el, {});
|
||||
equal(Hammer.defaults.preset.length, hammer.recognizers.length);
|
||||
|
||||
hammer2 = new Hammer.Manager(el, {});
|
||||
equal(0, hammer2.recognizers.length);
|
||||
});
|
||||
|
||||
/* DOC to disable default recognizers should be added.
|
||||
*
|
||||
* - Hammer(el). IMO: Currently, well done.
|
||||
* - Hammer(el, {}) . IMO: should disable default recognizers
|
||||
* - Hammer(el, {recognizers: null}). IMO: now, it fails.
|
||||
* - Hammer(el, {recognizers: []}). It works, but it is likely not intuitive.
|
||||
*/
|
||||
test('A Hammer instance can be setup to not having default recognizers.', function() {
|
||||
expect(1);
|
||||
|
||||
hammer = new Hammer(el, { recognizers: false });
|
||||
equal(0, hammer.recognizers.length);
|
||||
});
|
||||
|
||||
/* The case was when I added a custom tap event which was added to the default
|
||||
* recognizers, and my custom tap gesture wasn't working (I do not know exactly the reason),
|
||||
* but removing the default recognizers solved the issue.
|
||||
*/
|
||||
test('Adding the same recognizer type should remove the old recognizer', function() {
|
||||
expect(4);
|
||||
|
||||
hammer = new Hammer(el);
|
||||
|
||||
ok(!!hammer.get('tap'));
|
||||
equal(7, hammer.recognizers.length);
|
||||
|
||||
var newTap = new Hammer.Tap({time: 1337});
|
||||
hammer.add(newTap);
|
||||
|
||||
equal(7, hammer.recognizers.length);
|
||||
equal(1337, hammer.get('tap').options.time);
|
||||
});
|
||||
|
||||
/*
|
||||
* Swipe gesture:
|
||||
* - in this tests, it does not update input.velocity ( always 0)
|
||||
* - does not fire swipeleft or swiperight events
|
||||
*/
|
||||
asyncTest('Swiping to the left should fire swipeleft event', function() {
|
||||
expect(2);
|
||||
|
||||
hammer = new Hammer(el, {recognizers: []});
|
||||
hammer.add(new Hammer.Swipe());
|
||||
hammer.on('swipe swipeleft', function() {
|
||||
ok(true);
|
||||
});
|
||||
|
||||
Simulator.gestures.swipe(el, {pos: [300, 300], deltaY: 0, deltaX: -200}, function() {
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* Input target change
|
||||
*/
|
||||
asyncTest('Should detect input while on other element', function() {
|
||||
expect(1);
|
||||
|
||||
hammer = new Hammer(el, { inputTarget: document.body });
|
||||
hammer.on('tap', function() {
|
||||
ok(true);
|
||||
});
|
||||
|
||||
Simulator.gestures.tap(document.body, null, function() {
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
/* Hammer.Manager constructor accepts a "recognizers" option in which each
|
||||
* element is an array representation of a Recognizer.
|
||||
*/
|
||||
test('Hammer.Manager accepts recognizers as arrays.', function() {
|
||||
expect(4);
|
||||
|
||||
hammer = new Hammer.Manager(el, {
|
||||
recognizers: [
|
||||
[Hammer.Swipe],
|
||||
[Hammer.Pinch],
|
||||
[Hammer.Rotate],
|
||||
[Hammer.Pan, { direction: Hammer.DIRECTION_UP }, ['swipe', 'pinch'], ['rotate']]
|
||||
]
|
||||
});
|
||||
equal(4, hammer.recognizers.length);
|
||||
|
||||
var recognizerActual = hammer.recognizers[3];
|
||||
equal(recognizerActual.options.direction, Hammer.DIRECTION_UP);
|
||||
equal(2, Object.keys(recognizerActual.simultaneous).length);
|
||||
equal(1, recognizerActual.requireFail.length);
|
||||
});
|
||||
|
||||
/*
|
||||
* Removing a recognizer which cannot be found would errantly remove the last recognizer in the
|
||||
* manager's list.
|
||||
*/
|
||||
test('Remove non-existent recognizer.', function() {
|
||||
expect(1);
|
||||
|
||||
hammer = new Hammer(el, {recognizers: []});
|
||||
hammer.add(new Hammer.Swipe());
|
||||
hammer.remove('tap');
|
||||
|
||||
equal(1, hammer.recognizers.length);
|
||||
});
|
||||
|
||||
test('check whether Hammer.defaults.cssProps is restored', function() {
|
||||
var beforeCssProps = {
|
||||
userSelect: 'text',
|
||||
touchSelect: 'grippers',
|
||||
touchCallout: 'default',
|
||||
contentZooming: 'chained',
|
||||
userDrag: 'element',
|
||||
tapHighlightColor: 'rgba(0, 1, 0, 0)'
|
||||
};
|
||||
var prop;
|
||||
Hammer.each(Hammer.defaults.cssProps, function(value, name) {
|
||||
prop = Hammer.prefixed(el.style, name);
|
||||
if (prop) {
|
||||
el.style[prop] = beforeCssProps[name];
|
||||
}
|
||||
});
|
||||
|
||||
hammer = Hammer(el);
|
||||
hammer.destroy();
|
||||
hammer = null;
|
||||
Hammer.each(Hammer.defaults.cssProps, function(value, name) {
|
||||
prop = Hammer.prefixed(el.style, name);
|
||||
if (prop) {
|
||||
equal(el.style[prop], beforeCssProps[name], "check if " + name + " is restored");
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,59 @@
|
||||
var el, hammer, events;
|
||||
|
||||
var jQueryPluginPath = '../../node_modules/jquery-hammerjs/jquery.hammer.js';
|
||||
|
||||
module('jQuery plugin', {
|
||||
setup: function() {
|
||||
el = utils.createHitArea();
|
||||
events = {};
|
||||
},
|
||||
teardown: function() {
|
||||
hammer && hammer.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
asyncTest('trigger pan with jQuery', function() {
|
||||
expect(2);
|
||||
|
||||
$.getScript(jQueryPluginPath, function() {
|
||||
jQuery(el).hammer();
|
||||
jQuery(el).bind('panstart pan panmove panright panend', function(ev) {
|
||||
if (ev.gesture) {
|
||||
events[ev.type] = true;
|
||||
}
|
||||
});
|
||||
|
||||
Simulator.gestures.pan(el, { deltaX: 50, deltaY: 0 }, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
pan: true,
|
||||
panstart: true,
|
||||
panmove: true,
|
||||
panright: true,
|
||||
panend: true
|
||||
});
|
||||
|
||||
ok(jQuery(el).data('hammer') instanceof Hammer.Manager, 'data attribute refers to the instance');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('trigger pan without jQuery should still work', function() {
|
||||
expect(1);
|
||||
|
||||
var hammer = Hammer(el);
|
||||
hammer.on('panstart pan panmove panright panend', function(ev) {
|
||||
events[ev.type] = true;
|
||||
});
|
||||
|
||||
Simulator.gestures.pan(el, { deltaX: 50, deltaY: 0 }, function() {
|
||||
start();
|
||||
deepEqual(events, {
|
||||
pan: true,
|
||||
panstart: true,
|
||||
panmove: true,
|
||||
panright: true,
|
||||
panend: true
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,90 @@
|
||||
var el, hammer;
|
||||
|
||||
var tripleTapCount = 0,
|
||||
doubleTapCount = 0,
|
||||
tapCount = 0;
|
||||
|
||||
module('Tap delay', {
|
||||
setup: function() {
|
||||
el = utils.createHitArea();
|
||||
hammer = new Hammer(el, {recognizers: []});
|
||||
|
||||
var tap = new Hammer.Tap();
|
||||
var doubleTap = new Hammer.Tap({event: 'doubleTap', taps: 2 });
|
||||
var tripleTap = new Hammer.Tap({event: 'tripleTap', taps: 3 });
|
||||
|
||||
hammer.add([tripleTap, doubleTap, tap]);
|
||||
|
||||
tripleTap.recognizeWith([doubleTap, tap]);
|
||||
doubleTap.recognizeWith(tap);
|
||||
|
||||
doubleTap.requireFailure(tripleTap);
|
||||
tap.requireFailure([tripleTap, doubleTap]);
|
||||
|
||||
tripleTapCount = 0;
|
||||
doubleTapCount = 0;
|
||||
tapCount = 0;
|
||||
|
||||
hammer.on('tap', function() {
|
||||
tapCount++;
|
||||
});
|
||||
hammer.on('doubleTap', function() {
|
||||
doubleTapCount++;
|
||||
});
|
||||
hammer.on('tripleTap', function() {
|
||||
tripleTapCount++;
|
||||
});
|
||||
},
|
||||
teardown: function() {
|
||||
hammer.destroy();
|
||||
}
|
||||
});
|
||||
asyncTest('When a tripleTap is fired, doubleTap and Tap should not be recognized', function() {
|
||||
expect(3);
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
equal(tripleTapCount, 1, 'one tripletap event');
|
||||
equal(doubleTapCount, 0, 'no doubletap event');
|
||||
equal(tapCount, 0, 'no singletap event');
|
||||
}, 350);
|
||||
});
|
||||
asyncTest('When a doubleTap is fired, tripleTap and Tap should not be recognized', function() {
|
||||
expect(3);
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
equal(tripleTapCount, 0);
|
||||
equal(doubleTapCount, 1);
|
||||
equal(tapCount, 0);
|
||||
}, 350);
|
||||
});
|
||||
|
||||
asyncTest('When a tap is fired, tripleTap and doubleTap should not be recognized', function() {
|
||||
expect(3);
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'end', 50, 50);
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
equal(tripleTapCount, 0);
|
||||
equal(doubleTapCount, 0);
|
||||
equal(tapCount, 1);
|
||||
}, 350);
|
||||
});
|
||||
@@ -0,0 +1,167 @@
|
||||
var parent,
|
||||
child,
|
||||
hammerChild,
|
||||
hammerParent;
|
||||
|
||||
module('Nested gesture recognizers (Tap Child + Pan Parent)', {
|
||||
setup: function() {
|
||||
parent = document.createElement('div');
|
||||
child = document.createElement('div');
|
||||
|
||||
document.getElementById('qunit-fixture').appendChild(parent);
|
||||
parent.appendChild(child);
|
||||
|
||||
hammerParent = new Hammer.Manager(parent, {
|
||||
touchAction: 'none'
|
||||
});
|
||||
hammerChild = new Hammer.Manager(child, {
|
||||
touchAction: 'none'
|
||||
});
|
||||
|
||||
hammerChild.add(new Hammer.Tap());
|
||||
hammerParent.add(new Hammer.Pan({threshold: 5, pointers: 1}));
|
||||
},
|
||||
teardown: function() {
|
||||
hammerChild.destroy();
|
||||
hammerParent.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
test('Tap on the child', function() {
|
||||
expect(1);
|
||||
|
||||
hammerChild.on('tap', function() {
|
||||
ok(true);
|
||||
});
|
||||
hammerParent.on('tap', function() {
|
||||
throw new Error('tap should not fire on parent');
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(child, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(child, 'end', 0, 10);
|
||||
});
|
||||
|
||||
test('Panning on the child should fire parent pan and should not fire child tap event', function() {
|
||||
expect(1);
|
||||
|
||||
hammerChild.on('tap', function() {
|
||||
throw new Error('tap should not fire on parent');
|
||||
});
|
||||
hammerParent.on('panend', function() {
|
||||
ok(true);
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(child, 'start', 10, 0);
|
||||
utils.dispatchTouchEvent(child, 'move', 20, 0);
|
||||
utils.dispatchTouchEvent(child, 'end', 30, 0);
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
// test (optional pointers validation)
|
||||
test('Panning with one finger down on child, other on parent', function () {
|
||||
expect(1);
|
||||
|
||||
var event,
|
||||
touches;
|
||||
|
||||
hammerParent.on('panend', function () {
|
||||
ok(true);
|
||||
});
|
||||
|
||||
// one finger one child
|
||||
utils.dispatchTouchEvent(child, 'start', 10, 0, 0);
|
||||
utils.dispatchTouchEvent(parent, 'start', 12, 0, 1);
|
||||
|
||||
touches = [
|
||||
{clientX: 20, clientY: 0, identifier: 0 },
|
||||
{clientX: 20, clientY: 0, identifier: 1 }
|
||||
];
|
||||
|
||||
event = document.createEvent('Event');
|
||||
event.initEvent('touchmove', true, true);
|
||||
event.touches = touches;
|
||||
event.changedTouches = touches;
|
||||
|
||||
parent.dispatchEvent(event);
|
||||
|
||||
touches = [
|
||||
{clientX: 30, clientY: 0, identifier: 0 },
|
||||
{clientX: 30, clientY: 0, identifier: 1 }
|
||||
];
|
||||
|
||||
event = document.createEvent('Event');
|
||||
event.initEvent('touchend', true, true);
|
||||
event.touches = touches;
|
||||
event.changedTouches = touches;
|
||||
|
||||
parent.dispatchEvent(event);
|
||||
});
|
||||
*/
|
||||
|
||||
var pressPeriod = 600;
|
||||
module('Nested gesture recognizers (Press Child + Pan Parent)', {
|
||||
setup: function() {
|
||||
parent = document.createElement('div');
|
||||
child = document.createElement('div');
|
||||
|
||||
document.getElementById('qunit-fixture').appendChild(parent);
|
||||
parent.appendChild(child);
|
||||
|
||||
hammerParent = new Hammer.Manager(parent, {
|
||||
touchAction: 'none'
|
||||
});
|
||||
hammerChild = new Hammer.Manager(child, {
|
||||
touchAction: 'none'
|
||||
});
|
||||
|
||||
hammerChild.add(new Hammer.Press({time: pressPeriod}));
|
||||
hammerParent.add(new Hammer.Pan({threshold: 5, pointers: 1}));
|
||||
},
|
||||
teardown: function() {
|
||||
hammerChild.destroy();
|
||||
hammerParent.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
test('Press on the child', function() {
|
||||
expect(1);
|
||||
|
||||
hammerChild.on('press', function() {
|
||||
ok(true);
|
||||
});
|
||||
hammerParent.on('press', function() {
|
||||
throw new Error('press should not fire on parent');
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(child, 'start', 0, 10);
|
||||
|
||||
stop();
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
}, pressPeriod);
|
||||
});
|
||||
|
||||
test('When Press is followed by Pan on the same element, both gestures are recognized', function() {
|
||||
expect(2);
|
||||
hammerChild.on('press', function() {
|
||||
ok(true);
|
||||
});
|
||||
hammerParent.on('panend', function() {
|
||||
ok(true);
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(child, 'start', 0, 10);
|
||||
stop();
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
|
||||
utils.dispatchTouchEvent(child, 'move', 10, 10);
|
||||
utils.dispatchTouchEvent(child, 'move', 20, 10);
|
||||
utils.dispatchTouchEvent(child, 'move', 30, 10);
|
||||
utils.dispatchTouchEvent(child, 'end', 30, 10);
|
||||
|
||||
}, pressPeriod);
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
var parent,
|
||||
child,
|
||||
hammerChild,
|
||||
hammerParent;
|
||||
|
||||
module('Propagation (Tap in Child and Parent)', {
|
||||
setup: function() {
|
||||
parent = document.createElement('div');
|
||||
child = document.createElement('div');
|
||||
|
||||
document.getElementById('qunit-fixture').appendChild(parent);
|
||||
parent.appendChild(child);
|
||||
|
||||
hammerParent = new Hammer.Manager(parent);
|
||||
hammerChild = new Hammer.Manager(child);
|
||||
|
||||
hammerChild.add(new Hammer.Tap());
|
||||
hammerParent.add(new Hammer.Tap());
|
||||
},
|
||||
teardown: function() {
|
||||
hammerChild.destroy();
|
||||
hammerParent.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
test('Tap on the child, fires also the tap event to the parent', function() {
|
||||
expect(2);
|
||||
|
||||
hammerChild.on('tap', function() {
|
||||
ok(true);
|
||||
});
|
||||
hammerParent.on('tap', function() {
|
||||
ok(true);
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(child, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(child, 'end', 0, 10);
|
||||
});
|
||||
|
||||
test('When tap on the child and the child stops the input event propagation, the tap event does not get fired in the parent', function() {
|
||||
expect(1);
|
||||
|
||||
hammerChild.on('tap', function() {
|
||||
ok(true);
|
||||
});
|
||||
hammerParent.on('tap', function() {
|
||||
throw new Error('parent tap gesture should not be recognized');
|
||||
});
|
||||
|
||||
child.addEventListener('touchend', function(ev) {
|
||||
ev.stopPropagation();
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(child, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(child, 'end', 0, 10);
|
||||
});
|
||||
@@ -0,0 +1,111 @@
|
||||
var el,
|
||||
hammer,
|
||||
pressPeriod = 200,
|
||||
pressThreshold = 20,
|
||||
pressCount = 0,
|
||||
panStartCount = 0,
|
||||
swipeCount = 0;
|
||||
|
||||
module('Require Failure ( Swipe & Press )', {
|
||||
setup: function() {
|
||||
el = utils.createHitArea();
|
||||
hammer = new Hammer(el, {recognizers: []});
|
||||
|
||||
var swipe = new Hammer.Swipe({threshold: 1});
|
||||
var press = new Hammer.Press({time: pressPeriod, threshold: pressThreshold});
|
||||
|
||||
hammer.add(swipe);
|
||||
hammer.add(press);
|
||||
|
||||
swipe.recognizeWith(press);
|
||||
press.requireFailure(swipe);
|
||||
|
||||
pressCount = 0;
|
||||
swipeCount = 0;
|
||||
hammer.on('press', function() {
|
||||
pressCount++;
|
||||
});
|
||||
hammer.on('swipe', function() {
|
||||
swipeCount++;
|
||||
});
|
||||
},
|
||||
teardown: function() {
|
||||
hammer.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
asyncTest('When swipe does not recognize the gesture, a press gesture can be fired', function() {
|
||||
expect(1);
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
equal(pressCount, 1);
|
||||
}, pressPeriod + 100);
|
||||
});
|
||||
|
||||
asyncTest('When swipe does recognize the gesture, a press gesture cannot be fired', function() {
|
||||
expect(2);
|
||||
|
||||
Simulator.gestures.swipe(el, null, function() {
|
||||
start();
|
||||
|
||||
ok(swipeCount > 0, 'swipe gesture should be recognizing');
|
||||
equal(pressCount, 0, 'press gesture should not be recognized because swipe gesture is recognizing');
|
||||
});
|
||||
});
|
||||
module('Require Failure ( Pan & Press )', {
|
||||
setup: function() {
|
||||
el = document.createElement('div');
|
||||
document.body.appendChild(el);
|
||||
|
||||
hammer = new Hammer(el, {recognizers: []});
|
||||
|
||||
var pan = new Hammer.Pan({threshold: 1});
|
||||
var press = new Hammer.Press({time: pressPeriod, threshold: pressThreshold});
|
||||
|
||||
hammer.add([pan, press]);
|
||||
|
||||
pan.recognizeWith(press);
|
||||
press.requireFailure(pan);
|
||||
|
||||
pressCount = 0;
|
||||
panStartCount = 0;
|
||||
hammer.on('press', function() {
|
||||
pressCount++;
|
||||
});
|
||||
hammer.on('panstart', function() {
|
||||
panStartCount++;
|
||||
});
|
||||
},
|
||||
teardown: function() {
|
||||
document.body.removeChild(el);
|
||||
hammer.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
asyncTest('When pan does not recognize the gesture, a press gesture can be fired', function() {
|
||||
expect(1);
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
equal(pressCount, 1);
|
||||
}, pressPeriod + 100);
|
||||
});
|
||||
|
||||
asyncTest('When pan recognizes the gesture, a press gesture cannot be fired', function() {
|
||||
expect(2);
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 50, 50);
|
||||
utils.dispatchTouchEvent(el, 'move', 50 + pressThreshold / 4, 50);
|
||||
|
||||
setTimeout(function() {
|
||||
start();
|
||||
|
||||
ok(panStartCount > 0, 'pan gesture should be recognizing');
|
||||
equal(pressCount, 0, 'press gesture should not be recognized because pan gesture is recognizing');
|
||||
}, pressPeriod + 100);
|
||||
});
|
||||
@@ -0,0 +1,234 @@
|
||||
var el,
|
||||
hammer;
|
||||
|
||||
module('Simultaenous recognition', {
|
||||
setup: function() {
|
||||
el = utils.createHitArea()
|
||||
},
|
||||
teardown: function() {
|
||||
hammer && hammer.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
asyncTest('should pinch and pan simultaneously be recognized when enabled', function() {
|
||||
expect(4);
|
||||
|
||||
var panCount = 0,
|
||||
pinchCount = 0;
|
||||
|
||||
hammer = new Hammer.Manager(el, {
|
||||
touchAction: 'none'
|
||||
});
|
||||
|
||||
hammer.add(new Hammer.Pan({threshold: 5, pointers: 2}));
|
||||
|
||||
var pinch = new Hammer.Pinch({ threshold: 0, pointers: 2});
|
||||
hammer.add(pinch);
|
||||
pinch.recognizeWith(hammer.get('pan'));
|
||||
|
||||
hammer.on('panend', function() {
|
||||
panCount++;
|
||||
});
|
||||
hammer.on('pinchend', function() {
|
||||
pinchCount++;
|
||||
});
|
||||
|
||||
var executeGesture = function(cb) {
|
||||
var event, touches;
|
||||
|
||||
touches = [
|
||||
{clientX: 0, clientY: 10, identifier: 0, target: el },
|
||||
{clientX: 10, clientY: 10, identifier: 1, target: el }
|
||||
];
|
||||
|
||||
event = document.createEvent('Event');
|
||||
event.initEvent('touchstart', true, true);
|
||||
event.touches = touches;
|
||||
event.targetTouches = touches;
|
||||
event.changedTouches = touches;
|
||||
el.dispatchEvent(event);
|
||||
|
||||
setTimeout(function() {
|
||||
touches = [
|
||||
{clientX: 10, clientY: 20, identifier: 0, target: el },
|
||||
{clientX: 20, clientY: 20, identifier: 1, target: el }
|
||||
];
|
||||
|
||||
event = document.createEvent('Event');
|
||||
event.initEvent('touchmove', true, true);
|
||||
event.touches = touches;
|
||||
event.targetTouches = touches;
|
||||
event.changedTouches = touches;
|
||||
|
||||
el.dispatchEvent(event);
|
||||
}, 100);
|
||||
|
||||
setTimeout(function() {
|
||||
touches = [
|
||||
{clientX: 20, clientY: 30, identifier: 0, target: el },
|
||||
{clientX: 40, clientY: 30, identifier: 1, target: el }
|
||||
];
|
||||
|
||||
event = document.createEvent('Event');
|
||||
event.initEvent('touchmove', true, true);
|
||||
event.touches = touches;
|
||||
event.targetTouches = touches;
|
||||
event.changedTouches = touches;
|
||||
el.dispatchEvent(event);
|
||||
|
||||
event = document.createEvent('Event');
|
||||
event.initEvent('touchend', true, true);
|
||||
event.touches = touches;
|
||||
event.targetTouches = touches;
|
||||
event.changedTouches = touches;
|
||||
el.dispatchEvent(event);
|
||||
|
||||
cb();
|
||||
}, 200);
|
||||
};
|
||||
|
||||
// 2 gesture will be recognized
|
||||
executeGesture(function() {
|
||||
equal(panCount, 1);
|
||||
equal(pinchCount, 1);
|
||||
|
||||
pinch.dropRecognizeWith(hammer.get('pan'));
|
||||
|
||||
// only the pan gesture will be recognized
|
||||
executeGesture(function() {
|
||||
equal(panCount, 2);
|
||||
equal(pinchCount, 1);
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('the first gesture should block the following gestures (Tap & DoubleTap)', function() {
|
||||
expect(4);
|
||||
|
||||
var tapCount = 0,
|
||||
doubleTapCount = 0;
|
||||
|
||||
hammer = new Hammer.Manager(el, {
|
||||
touchAction: 'none'
|
||||
});
|
||||
|
||||
var tap = new Hammer.Tap();
|
||||
var doubleTap = new Hammer.Tap({event: 'doubletap', taps: 2});
|
||||
|
||||
hammer.add(tap);
|
||||
hammer.add(doubleTap);
|
||||
|
||||
hammer.on('tap', function() {
|
||||
tapCount++;
|
||||
});
|
||||
hammer.on('doubletap', function() {
|
||||
doubleTapCount++;
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
|
||||
equal(tapCount, 2, 'on a double tap gesture, the tap gesture is recognized twice');
|
||||
equal(doubleTapCount, 0, 'double tap gesture is not recognized because the prior tap gesture does not recognize it simultaneously');
|
||||
|
||||
doubleTap.recognizeWith(hammer.get('tap'));
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
|
||||
equal(tapCount, 4);
|
||||
equal(doubleTapCount, 1, 'when the tap gesture is configured to work simultaneously, tap & doubleTap can be recognized simultaneously');
|
||||
});
|
||||
|
||||
test('when disabled, the first gesture should not block gestures (Tap & DoubleTap )', function() {
|
||||
expect(4);
|
||||
|
||||
var tapCount = 0,
|
||||
doubleTapCount = 0;
|
||||
|
||||
hammer = new Hammer.Manager(el, {
|
||||
touchAction: 'none'
|
||||
});
|
||||
|
||||
var tap = new Hammer.Tap();
|
||||
var doubleTap = new Hammer.Tap({event: 'doubletap', taps: 2});
|
||||
|
||||
hammer.add(tap);
|
||||
hammer.add(doubleTap);
|
||||
|
||||
hammer.on('tap', function() {
|
||||
tapCount++;
|
||||
});
|
||||
hammer.on('doubletap', function() {
|
||||
doubleTapCount++;
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
|
||||
equal(tapCount, 2, 'on a double tap gesture, the tap gesture is recognized twice');
|
||||
equal(doubleTapCount, 0, 'double tap gesture is not recognized because the prior tap gesture does not recognize it simultaneously');
|
||||
|
||||
hammer.get('tap').set({ enable: false });
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
|
||||
equal(tapCount, 2, 'tap gesture should not be recognized when the recognizer is disabled');
|
||||
equal(doubleTapCount, 1, 'when the tap gesture is disabled, doubleTap can be recognized');
|
||||
});
|
||||
|
||||
test('the first gesture should block the following gestures (DoubleTap & Tap)', function() {
|
||||
expect(4);
|
||||
|
||||
var tapCount = 0,
|
||||
doubleTapCount = 0;
|
||||
|
||||
hammer = new Hammer.Manager(el, {
|
||||
touchAction: 'none'
|
||||
});
|
||||
|
||||
var tap = new Hammer.Tap();
|
||||
var doubleTap = new Hammer.Tap({event: 'doubletap', taps: 2});
|
||||
|
||||
hammer.add(doubleTap);
|
||||
hammer.add(tap);
|
||||
|
||||
hammer.on('tap', function() {
|
||||
tapCount++;
|
||||
});
|
||||
hammer.on('doubletap', function() {
|
||||
doubleTapCount++;
|
||||
});
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
|
||||
equal(doubleTapCount, 1, 'double tap is recognized');
|
||||
equal(tapCount, 1, 'tap is detected, the doubletap is only catched by the doubletap recognizer');
|
||||
|
||||
// doubletap and tap together
|
||||
doubleTap.recognizeWith(hammer.get('tap'));
|
||||
doubleTapCount = 0;
|
||||
tapCount = 0;
|
||||
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'start', 0, 10);
|
||||
utils.dispatchTouchEvent(el, 'end', 0, 10);
|
||||
|
||||
equal(doubleTapCount, 1);
|
||||
equal(tapCount, 2, 'when the tap gesture is configured to work simultaneously, tap & doubleTap can be recognized simultaneously');
|
||||
});
|
||||
164
LittleShop/wwwroot/lib/hammerjs/tests/unit/test_utils.js
Normal file
164
LittleShop/wwwroot/lib/hammerjs/tests/unit/test_utils.js
Normal file
@@ -0,0 +1,164 @@
|
||||
module('utils');
|
||||
|
||||
// for the tests, all hammer properties and methods of Hammer are exposed to window.$H
|
||||
|
||||
test('get/set prefixed util', function() {
|
||||
ok(_.isUndefined($H.prefixed(window, 'FakeProperty')), 'non existent property returns undefined');
|
||||
|
||||
window.webkitFakeProperty = 1337;
|
||||
ok($H.prefixed(window, 'FakeProperty') == 'webkitFakeProperty', 'existent prefixed property returns the prefixed name');
|
||||
|
||||
delete window.webkitFakeProperty;
|
||||
});
|
||||
|
||||
test('fnBind', function() {
|
||||
var context = { a: true };
|
||||
|
||||
$H.bindFn(function(b) {
|
||||
ok(this.a === true, 'bindFn scope');
|
||||
ok(b === 123, 'bindFn argument');
|
||||
}, context)(123);
|
||||
});
|
||||
|
||||
test('Inherit objects', function() {
|
||||
function Base() {
|
||||
this.name = true;
|
||||
}
|
||||
|
||||
function Child() {
|
||||
Base.call(this);
|
||||
}
|
||||
|
||||
$H.inherit(Child, Base, {
|
||||
newMethod: function() {
|
||||
}
|
||||
});
|
||||
|
||||
var inst = new Child();
|
||||
|
||||
ok(inst.name == true, 'child has extended from base');
|
||||
ok(inst.newMethod, 'child has a new method');
|
||||
ok(Child.prototype.newMethod, 'child has a new prototype method');
|
||||
ok(inst instanceof Child, 'is instanceof Child');
|
||||
ok(inst instanceof Base, 'is instanceof Base');
|
||||
ok(inst._super === Base.prototype, '_super is ref to prototype of Base');
|
||||
});
|
||||
|
||||
test('toArray', function() {
|
||||
ok(_.isArray($H.toArray({ 0: true, 1: 'second', length: 2 })), 'converted an array-like object to an array');
|
||||
ok(_.isArray($H.toArray([true, true])), 'array stays an array');
|
||||
});
|
||||
|
||||
test('inArray', function() {
|
||||
ok($H.inArray([1, 2, 3, 4, 'hammer'], 'hammer') === 4, 'found item and returned the index');
|
||||
ok($H.inArray([1, 2, 3, 4, 'hammer'], 'notfound') === -1, 'not found an item and returned -1');
|
||||
ok($H.inArray([
|
||||
{id: 2},
|
||||
{id: 24}
|
||||
], '24', 'id') === 1, 'find by key and return the index');
|
||||
ok($H.inArray([
|
||||
{id: 2},
|
||||
{id: 24}
|
||||
], '22', 'id') === -1, 'not found by key and return -1');
|
||||
});
|
||||
|
||||
test('splitStr', function() {
|
||||
deepEqual($H.splitStr(' a b c d '), ['a', 'b', 'c', 'd'], 'str split valid');
|
||||
});
|
||||
|
||||
test('uniqueArray', function() {
|
||||
deepEqual($H.uniqueArray([
|
||||
{id: 1},
|
||||
{id: 2},
|
||||
{id: 2}
|
||||
], 'id'), [
|
||||
{id: 1},
|
||||
{id: 2}
|
||||
], 'remove duplicate ids')
|
||||
});
|
||||
|
||||
test('boolOrFn', function() {
|
||||
equal($H.boolOrFn(true), true, 'Passing an boolean');
|
||||
equal($H.boolOrFn(false), false, 'Passing an boolean');
|
||||
equal($H.boolOrFn(function() {
|
||||
return true;
|
||||
}), true, 'Passing an boolean');
|
||||
equal($H.boolOrFn(1), true, 'Passing an integer');
|
||||
});
|
||||
|
||||
test('hasParent', function() {
|
||||
var parent = document.createElement('div'),
|
||||
child = document.createElement('div');
|
||||
|
||||
document.body.appendChild(parent);
|
||||
parent.appendChild(child);
|
||||
|
||||
equal($H.hasParent(child, parent), true, 'Found parent');
|
||||
equal($H.hasParent(parent, child), false, 'Not in parent');
|
||||
|
||||
document.body.removeChild(parent);
|
||||
});
|
||||
|
||||
test('each', function() {
|
||||
var object = { hi: true };
|
||||
var array = ['a', 'b', 'c'];
|
||||
var loop;
|
||||
|
||||
loop = false;
|
||||
$H.each(object, function(value, key) {
|
||||
if (key == 'hi' && value === true) {
|
||||
loop = true;
|
||||
}
|
||||
});
|
||||
ok(loop, 'object loop');
|
||||
|
||||
loop = 0;
|
||||
$H.each(array, function(value, key) {
|
||||
if (value) {
|
||||
loop++;
|
||||
}
|
||||
});
|
||||
ok(loop == 3, 'array loop');
|
||||
|
||||
loop = 0;
|
||||
array.forEach = null;
|
||||
$H.each(array, function(value, key) {
|
||||
if (value) {
|
||||
loop++;
|
||||
}
|
||||
});
|
||||
ok(loop == 3, 'array loop without Array.forEach');
|
||||
});
|
||||
|
||||
test('assign', function() {
|
||||
expect(2);
|
||||
deepEqual(
|
||||
$H.assign(
|
||||
{a: 1, b: 3},
|
||||
{b: 2, c: 3}
|
||||
),
|
||||
{a: 1, b: 2, c: 3},
|
||||
'Simple extend'
|
||||
);
|
||||
|
||||
var src = { foo: true };
|
||||
var dest = $H.assign({}, src);
|
||||
src.foo = false;
|
||||
deepEqual(dest, {foo: true}, 'Clone reference');
|
||||
});
|
||||
|
||||
test('test add/removeEventListener', function() {
|
||||
function handleEvent() {
|
||||
ok(true, 'triggered event');
|
||||
}
|
||||
|
||||
expect(2);
|
||||
|
||||
$H.addEventListeners(window, 'testEvent1 testEvent2 ', handleEvent);
|
||||
utils.triggerDomEvent(window, 'testEvent1');
|
||||
utils.triggerDomEvent(window, 'testEvent2');
|
||||
|
||||
$H.removeEventListeners(window, ' testEvent1 testEvent2 ', handleEvent);
|
||||
utils.triggerDomEvent(window, 'testEvent1');
|
||||
utils.triggerDomEvent(window, 'testEvent2');
|
||||
});
|
||||
Reference in New Issue
Block a user