Commit c2a3891c authored by nextime's avatar nextime

Readd hammer.js

parent d6121f4a
No related merge requests found
......@@ -2,13 +2,13 @@
<? if($GUIDEBUG) { ?>
<!-- JavaScript plugins (requires jQuery) -->
<script src="/resources/js/jquery-1.10.2.min.js"></script>
<script src="/resources/jquery-color/jquery.color.min.js"></script>
<script src="/resources/hammer.js/dist/hammer.min.js"></script>
<script src="/resources/jquery-color/jquery.color.js"></script>
<script src="/resources/hammer.js/hammer.min.js"></script>
<script src="/resources/hammer.js/plugins/hammer.fakemultitouch.js"></script>
<!--[if !IE]> -->
<script src="/resources/js/starthammer.js"></script>
<script src="<?=$BASEGUIPATH;?>/js/starthammer.js"></script>
<!-- <![endif]-->
<script src="/resources/hammer.js/dist/jquery.hammer.min.js"></script>
<script src="/resources/hammer.js/plugins/jquery.hammer.js/jquery.hammer.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/resources/bootstrap/js/bootstrap.min.js"></script>
<!-- Optionally enable responsive features in IE8 -->
......
{
"json": "bower.json"
}
\ No newline at end of file
# ide
.idea
.iml
# node
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
pids
logs
results
npm-debug.log
node_modules
\ No newline at end of file
[submodule "plugins/jquery.hammer.js"]
path = plugins/jquery.hammer.js
url = git://github.com/EightMedia/jquery.hammer.js.git
language: node_js
node_js:
- "0.10"
before_script:
- npm install -g grunt-cli
script:
- grunt test-travis
\ No newline at end of file
# Contributing to Hammer.js
Looking to contribute something to Hammer.js? **Here's how you can help.**
## Reporting issues
We only accept issues that are bug reports or feature requests. Bugs must be isolated and reproducible problems that can be fixed within the Hammer.js. Please read the following guidelines before opening any issue.
1. **Search for existing issues.** We get a lot of duplicate issues, and you'd help us out a lot by first checking if someone else has reported the same issue. Moreover, the issue may have already been resolved with a fix available. Also take a look if your problem is explained at the Wiki.
2. **Create an isolated and reproducible test case.** Be sure the problem exists in Hammer's code with a reduced test case that should be included in each bug report.
3. **Include a live example.** Make use of jsFiddle or jsBin to share your isolated test cases.
4. **Share as much information as possible.** Include operating system and version, browser and version, version of Hammer.js, customized or vanilla build, etc. where appropriate. Also include steps to reproduce the bug.
## Pull requests
- Changes must be done in `/src` files, never just the compiled files
- Try not to pollute your pull request with unintended changes--keep them simple and small
- Try to share which browsers your code has been tested in before submitting a pull request
- Try and write tests for your code, these can be found in `/tests`
\ No newline at end of file
module.exports = (grunt) ->
grunt.initConfig
pkg: grunt.file.readJSON 'package.json'
# meta options
meta:
banner: '
/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n
* <%= pkg.homepage %>\n
*\n
* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %> <<%= pkg.author.email %>>;\n
* Licensed under the <%= _.pluck(pkg.licenses, "type").join(", ") %> license */\n\n'
# concat src files
concat:
options:
separator: '\n\n'
dist:
options:
banner: '<%= meta.banner %>'
src: [
'src/intro.js'
'src/core.js'
'src/setup.js'
'src/utils.js'
'src/instance.js'
'src/event.js'
'src/pointerevent.js'
'src/detection.js'
'src/gestures/*.js'
'src/outro.js']
dest: 'hammer.js'
# minify the sourcecode
uglify:
options:
report: 'gzip'
sourceMap: 'hammer.min.map'
banner: '<%= meta.banner %>'
dist:
files:
'hammer.min.js': ['hammer.js']
# check for optimisations and errors
jshint:
options:
curly: true
expr: true
newcap: true
quotmark: 'single'
regexdash: true
trailing: true
undef: true
unused: true
maxerr: 100
eqnull: true
sub: false
browser: true
node: true
strict: true
laxcomma: true
globals:
define: false
dist:
src: ['hammer.js']
# watch for changes
watch:
scripts:
files: ['src/**/*.js']
tasks: ['concat']
options:
interrupt: true
# simple node server
connect:
server:
options:
directory: "."
hostname: "0.0.0.0"
# tests
qunit:
all: ['tests/**/*.html']
# saucelabs tests
'saucelabs-qunit':
all:
options:
username: 'hammerjs-ci'
key: '2ede6d02-65b3-4ba9-aec8-44a787af0c81'
build: process.env.TRAVIS_JOB_ID || 'dev'
concurrency: 3
urls: [
'http://0.0.0.0:8000/tests/utils.html',
'http://0.0.0.0:8000/tests/mouseevents.html',
'http://0.0.0.0:8000/tests/mousetouchevents.html',
'http://0.0.0.0:8000/tests/touchevents.html',
'http://0.0.0.0:8000/tests/pointerevents_mouse.html',
'http://0.0.0.0:8000/tests/pointerevents_touch.html'
]
browsers: [
{ browserName: 'chrome' }
{ browserName: 'firefox' }
{ browserName: 'internet explorer', platform: 'Windows 7', version: '9' }
{ browserName: 'internet explorer', platform: 'Windows 8', version: '10'}
]
# Load tasks
grunt.loadNpmTasks 'grunt-contrib-concat'
grunt.loadNpmTasks 'grunt-contrib-uglify'
grunt.loadNpmTasks 'grunt-contrib-watch'
grunt.loadNpmTasks 'grunt-contrib-jshint'
grunt.loadNpmTasks 'grunt-contrib-connect'
grunt.loadNpmTasks 'grunt-contrib-qunit'
grunt.loadNpmTasks 'grunt-saucelabs'
# Default task(s).
grunt.registerTask 'default', ['connect','watch']
grunt.registerTask 'build', ['concat','uglify','test']
grunt.registerTask 'test', ['jshint','qunit']
grunt.registerTask 'test-travis', ['build','jshint']
Copyright (C) 2013 by Jorik Tangelder (Eight Media)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
\ No newline at end of file
# Hammer.js
[![Build Status](https://travis-ci.org/EightMedia/hammer.js.png)](https://travis-ci.org/EightMedia/hammer.js/)
[![Selenium Test Status](https://saucelabs.com/buildstatus/hammerjs-ci)](https://saucelabs.com/u/hammerjs-ci)
### A javascript library for multi-touch gestures
> I told you, homeboy /
> You *CAN* touch this /
> Yeah, that's how we living and you know /
> You *CAN* touch this
[__Looking for the jQuery plugin? It has his own repository now.__](https://github.com/EightMedia/jquery.hammer.js)
## Features
- Detects Tap, DoubleTap, Swipe, Drag, Pinch, and Rotate gestures
- DOM Events
- Debug plugins
- Custom gestures
- Chainable instance methods
- AMD support (RequireJS)
- Unit tests
- Option to disable mouse support, so only for touch and pen input.
- Sourcemaps
- [jQuery plugin available here](https://github.com/EightMedia/jquery.hammer.js)
## Getting Started
See the [Wiki on GitHub](https://github.com/EightMedia/hammer.js/wiki) for documentation.
## Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style.
Add unit tests for any new or changed functionality. Lint and test your code using grunt.
Please don't commit the dist versions with your changes, only the changed source files.
## Further notes
Created by [Jorik Tangelder](http://twitter.com/jorikdelaporik) and developed at [Eight Media](http://www.eight.nl/) in Arnhem, the Netherlands.
It's recommend to listen to [this loop](http://soundcloud.com/eightmedia/hammerhammerhammer) while using hammer.js.
{
"name": "hammerjs",
"version": "1.0.6",
"main": ["hammer.js"],
"ignore": [
"tests",
"component.json",
"package.json",
"examples",
"src"
]
}
{
"name": "hammerjs",
"version": "1.0.6",
"main": "hammer.js",
"scripts": [
"hammer.js"
]
}
The demos are for illustration purposes only, and not production ready. Hammer.js is not a component library.
Web/resources/hammer.js/examples/assets/img/arrow.png

505 Bytes

This diff is collapsed.
Web/resources/hammer.js/examples/assets/img/spinner.png

795 Bytes

// google analytics
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-30289566-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
\ No newline at end of file
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<title>Hammer.js</title>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css" rel="stylesheet">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<style>
@keyframes highlight {
0%{ background: rgba(255, 240, 140, 1); }
100%{ background: rgba(255, 240, 140, 0); }
}
@-moz-keyframes highlight{
0%{ background: rgba(255, 240, 140, 1); }
100%{ background: rgba(255, 240, 140, 0); }
}
@-webkit-keyframes highlight{
0%{ background: rgba(255, 240, 140, 1); }
100%{ background: rgba(255, 240, 140, 0); }
}
body { padding: 0; }
#container {
padding: 20px;
}
.highlight {
background: #fff68d;
}
.hero-unit {
padding: 0;
}
#toucharea {
padding: 30px;
}
</style>
</head>
<body>
<div id="container">
<div class="hero-unit">
<div id="toucharea">
<h1>Touch me</h1>
<p>The tap event will be fired. Notice in the sourcecode that event delegation is also supported.<br>
In the console you can see the event data.</p>
<h4>List items with stopPropagation</h4>
<ul id="items">
<li>List item 1</li>
<li>List item 2</li>
<li>List item 3</li>
<li>List item 4</li>
<li>List item 5</li>
</ul>
<p>
<a href="#" id="add-list-item" class="btn btn-success">Add list item</a>
</p>
</div>
</div>
</div>
<script src="../hammer.js"></script>
<script>
function highlight(el) {
setTimeout(function() {
el.className = el.className.replace("highlight", "");
}, 100);
el.className = el.className + " highlight";
}
var hammertime = Hammer(document.getElementById("toucharea"));
console.log(hammertime);
// the whole area
hammertime.on("tap swipeleft drag", function(ev) {
if(window.console) { console.log(ev); }
highlight(this);
});
// on elements in the toucharea, with a stopPropagation
hammertime.on("tap swipe", function(ev) {
if(window.console) { console.log('nested', ev); }
highlight(this);
ev.stopPropagation();
});
</script>
<script src="assets/js/ga.js"></script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Hammer.js</title>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css" rel="stylesheet">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<style>
html, body, #carousel, #carousel ul, #carousel li {
min-height: 100%;
height: 100%;
padding: 0;
margin: 0;
position: relative;
}
#debug {
position: fixed;
background: #fff;
padding: 5px;
color: #000;
top: 0;
left: 0;
z-index: 1337;
}
#carousel {
background: silver;
overflow: hidden;
width:100%;
-webkit-backface-visibility: hidden;
-webkit-transform: translate3d(0,0,0) scale3d(1,1,1);
-webkit-transform-style: preserve-3d;
}
#carousel ul.animate {
-webkit-transition: all .3s;
-moz-transition: all .3s;
-o-transition: all .3s;
transition: all .3s;
}
#carousel ul {
transform: translate3d(0%,0,0) scale3d(1,1,1);
-o-transform: translate3d(0%,0,0) scale3d(1,1,1);
-ms-transform: translate3d(0%,0,0) scale3d(1,1,1);
-moz-transform: translate3d(0%,0,0) scale3d(1,1,1);
-webkit-transform: translate3d(0%,0,0) scale3d(1,1,1);
overflow: hidden;
-webkit-backface-visibility: hidden;
-webkit-transform-style: preserve-3d;
}
#carousel ul {
-webkit-box-shadow: 0 0 20px rgba(0,0,0,.2);
box-shadow: 0 0 20px rgba(0,0,0,.2);
position: relative;
}
#carousel li {
float: left;
overflow: hidden;
-webkit-transform-style: preserve-3d;
-webkit-transform: translate3d(0,0,0);
}
#carousel li h2 {
color: #fff;
font-size: 30px;
text-align: center;
position: absolute;
top: 40%;
left: 0;
width: 100%;
text-shadow: -1px -1px 0 rgba(0,0,0,.2);
}
#carousel li.pane1 { background: #42d692; }
#carousel li.pane2 { background: #4986e7; }
#carousel li.pane3 { background: #d06b64; }
#carousel li.pane4 { background: #cd74e6; }
#carousel li.pane5 { background: #9fe1e7; }
</style>
</head>
<body>
<!--<div id="debug">Log</div>-->
<div id="carousel">
<ul>
<li class="pane1"><h2>Swipe...</h2></li>
<li class="pane2"><h2>...or drag...</h2></li>
<li class="pane3"><h2>...or swipe...</h2></li>
<li class="pane4"><h2>..or drag...</h2></li>
<li class="pane5"><h2>Dit is het einde!</h2></li>
</ul>
</div>
<!-- jQuery is just for the demo! Hammer.js works without jQuery :-) -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="assets/js/modernizr.js"></script>
<script src="../hammer.js"></script>
<script>
var debug_el = $("#debug");
function debug(text) {
debug_el.text(text);
}
/**
* requestAnimationFrame and cancel polyfill
*/
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}());
/**
* super simple carousel
* animation between panes happens with css transitions
*/
function Carousel(element)
{
var self = this;
element = $(element);
var container = $(">ul", element);
var panes = $(">ul>li", element);
var pane_width = 0;
var pane_count = panes.length;
var current_pane = 0;
/**
* initial
*/
this.init = function() {
setPaneDimensions();
$(window).on("load resize orientationchange", function() {
setPaneDimensions();
//updateOffset();
})
};
/**
* set the pane dimensions and scale the container
*/
function setPaneDimensions() {
pane_width = element.width();
panes.each(function() {
$(this).width(pane_width);
});
container.width(pane_width*pane_count);
};
/**
* show pane by index
*/
this.showPane = function(index, animate) {
// between the bounds
index = Math.max(0, Math.min(index, pane_count-1));
current_pane = index;
var offset = -((100/pane_count)*current_pane);
setContainerOffset(offset, animate);
};
function setContainerOffset(percent, animate) {
container.removeClass("animate");
if(animate) {
container.addClass("animate");
}
if(Modernizr.csstransforms3d) {
container.css("transform", "translate3d("+ percent +"%,0,0) scale3d(1,1,1)");
}
else if(Modernizr.csstransforms) {
container.css("transform", "translate("+ percent +"%,0)");
}
else {
var px = ((pane_width*pane_count) / 100) * percent;
container.css("left", px+"px");
}
}
this.next = function() { return this.showPane(current_pane+1, true); };
this.prev = function() { return this.showPane(current_pane-1, true); };
function handleHammer(ev) {
console.log(ev);
// disable browser scrolling
ev.gesture.preventDefault();
switch(ev.type) {
case 'dragright':
case 'dragleft':
// stick to the finger
var pane_offset = -(100/pane_count)*current_pane;
var drag_offset = ((100/pane_width)*ev.gesture.deltaX) / pane_count;
// slow down at the first and last pane
if((current_pane == 0 && ev.gesture.direction == "right") ||
(current_pane == pane_count-1 && ev.gesture.direction == "left")) {
drag_offset *= .4;
}
setContainerOffset(drag_offset + pane_offset);
break;
case 'swipeleft':
self.next();
ev.gesture.stopDetect();
break;
case 'swiperight':
self.prev();
ev.gesture.stopDetect();
break;
case 'release':
// more then 50% moved, navigate
if(Math.abs(ev.gesture.deltaX) > pane_width/2) {
if(ev.gesture.direction == 'right') {
self.prev();
} else {
self.next();
}
}
else {
self.showPane(current_pane, true);
}
break;
}
}
var hammertime = new Hammer(element[0], { drag_lock_to_axis: true });
element.on("release dragleft dragright swipeleft swiperight", handleHammer);
}
var carousel = new Carousel("#carousel");
carousel.init();
</script>
<script src="assets/js/ga.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Hammer.js</title>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css" rel="stylesheet">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<style>
h1 {
margin: 30px;
text-align: center;
}
.drag {
position: absolute;
left: 100px;
top: 100px;
background: #9fe1e7;
border-radius: 50px;
width: 100px;
height: 100px;
}
.drag1 { background: #42d692; }
.drag2 { background: #4986e7; }
.drag3 { background: #d06b64; }
.drag4 { background: #cd74e6; }
.drag5 { background: #9fe1e7; }
</style>
</head>
<body>
<h1>Drag the balls!</h1>
<div class="drag drag1"></div>
<div class="drag drag2"></div>
<div class="drag drag3"></div>
<div class="drag drag4"></div>
<div class="drag drag5"></div>
<!-- jQuery is just for the demo! Hammer.js works without jQuery :-) -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="assets/js/modernizr.js"></script>
<script src="../hammer.js"></script>
<script>
var hammertime = new Hammer($(".drag")[0], { drag_max_touches:0});
$(".drag")
.on("touch drag", function(ev) {
var touches = ev.gesture.touches;
ev.gesture.preventDefault();
for(var t=0,len=touches.length; t<len; t++) {
var target = $(touches[t].target);
target.css({
zIndex: 1337,
left: touches[t].pageX-50,
top: touches[t].pageY-50
});
}
});
</script>
<script src="assets/js/ga.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Hammer.js</title>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css" rel="stylesheet">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<style>
body {
padding: 15px;
}
.container { position: relative; }
.hitarea {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,.05);
text-align: center;
border: dashed 3px red;
}
.log li {
display: inline-block;
width: 49%;
overflow: hidden;
}
@media screen and (min-width: 640px) {
.log li { width: 30%; }
}
.properties li { white-space: nowrap; }
.properties span { margin-left: 5px; }
.log li.active { background: lightgreen; }
.log li.property-gesture {
position: fixed;
right: 0;
top: 0;
background: lightgreen;
padding: 1px 4px;
width: auto;
}
</style>
</head>
<body>
<p class="alert"><strong>Press shift on your desktop for multitouch.</strong></p>
<p>
<label class="checkbox">
<input type="checkbox" checked id="prevent-default"> block browser behavior (preventDefault)
</label>
</p>
<div class="container">
<div class="log well well-small">
<h4>Events</h4>
<ul class="unstyled events" id="events-list">
<li>touch</li>
<li>release</li>
<li>hold</li>
<li>tap</li>
<li>doubletap</li>
<li>dragstart</li>
<li>drag</li>
<li>dragend</li>
<li>dragleft</li>
<li>dragright</li>
<li>dragup</li>
<li>dragdown</li>
<li>swipe</li>
<li>swipeleft</li>
<li>swiperight</li>
<li>swipeup</li>
<li>swipedown</li>
<li>transformstart</li>
<li>transform</li>
<li>transformend</li>
<li>rotate</li>
<li>rotateleft</li>
<li>rotateright</li>
<li>pinch</li>
<li>pinchin</li>
<li>pinchout</li>
</ul>
<h4>EventData</h4>
<ul class="unstyled properties">
<li class="property-gesture"><strong>gesture</strong> <span id="log-prop-gesture"></span></li>
<li><strong>touches</strong> <span id="log-prop-touches"></span></li>
<li><strong>pointerType</strong> <span id="log-prop-pointerType"></span></li>
<li><strong>center</strong> <span id="log-prop-center"></span></li>
<li><strong>angle</strong> <span id="log-prop-angle"></span>&deg;</li>
<li><strong>direction</strong> <span id="log-prop-direction"></span></li>
<li><strong>distance</strong> <span id="log-prop-distance"></span>px</li>
<li><strong>deltaTime</strong> <span id="log-prop-deltaTime"></span>ms</li>
<li><strong>deltaX</strong> <span id="log-prop-deltaX"></span>px</li>
<li><strong>deltaY</strong> <span id="log-prop-deltaY"></span>px</li>
<li><strong>velocityX</strong> <span id="log-prop-velocityX"></span></li>
<li><strong>velocityY</strong> <span id="log-prop-velocityY"></span></li>
<li><strong>scale</strong> <span id="log-prop-scale"></span></li>
<li><strong>rotation</strong> <span id="log-prop-rotation"></span>&deg;</li>
<li><strong>target</strong> <span id="log-prop-target"></span></li>
</ul>
</div>
<div id="hitarea" class="hitarea"></div>
</div>
<!-- jQuery is just for the demo! Hammer.js works without jQuery :-) -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="../hammer.js"></script>
<script src="../plugins/hammer.fakemultitouch.js"></script>
<script src="../plugins/hammer.showtouches.js"></script>
<!--[if !IE]> -->
<script>
Hammer.plugins.showTouches();
</script>
<!-- <![endif]-->
<script>
Hammer.plugins.fakeMultitouch();
function getEl(id) {
return document.getElementById(id);
}
var log_elements = {};
var prevent_scroll_drag = true;
$("#prevent-default").click(function() {
hammertime.options.prevent_default = this.checked;
});
function getLogElement(type, name) {
var el = log_elements[type + name];
if(!el) {
return log_elements[type + name] = getEl("log-"+ type +"-"+ name);
}
return el;
}
// log properties
var properties = ['gesture','center','deltaTime','angle','direction',
'distance','deltaX','deltaY','velocityX','velocityY', 'pointerType',
'scale','rotation','touches','target'];
function logEvent(ev) {
if(!ev.gesture) {
return;
}
// add to the large event log at the bottom of the page
var log = [this.id, ev.type];
//event_log.innerHTML = log.join(" - ") +"\n" + event_log.innerHTML;
// highlight gesture
var event_el = getLogElement('gesture', ev.type);
event_el.className = "active";
for(var i= 0,len=properties.length; i<len; i++) {
var prop = properties[i];
var value = ev.gesture[prop];
switch(prop) {
case 'center':
value = value.pageX +"x"+ value.pageY;
break;
case 'gesture':
value = ev.type;
break;
case 'target':
value = ev.gesture.target.tagName;
break;
case 'touches':
value = ev.gesture.touches.length;
break;
}
getLogElement('prop', prop).innerHTML = value;
}
}
// get all the events
var all_events = [];
$("#events-list li").each(function() {
var li = $(this);
var type = li.text();
li.attr("id", "log-gesture-"+type);
all_events.push(type);
});
// start!
var hammertime = Hammer(getEl('hitarea'), {
prevent_default: true,
no_mouseevents: true
})
.on(all_events.join(" "), logEvent);
</script>
<script src="assets/js/ga.js" async></script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Hammer.js</title>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css" rel="stylesheet">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<style>
body {
padding: 0;
overflow: hidden;
}
#pinchzoom {
-webkit-transform: translate3d(0,0,0);
overflow: hidden;
}
</style>
</head>
<body>
<div id="pinchzoom">
<div>
<img id="rect" src="assets/img/monalisa.jpg" width="2835" height="4289" ondragstart="return false" alt="" />
</div>
</div>
<!-- jQuery is just for the demo! Hammer.js works without jQuery :-) -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="../hammer.js"></script>
<script src="../plugins/hammer.fakemultitouch.js"></script>
<script src="../plugins/hammer.showtouches.js"></script>
<!--[if !IE]> -->
<script>
// show touches doesnt work well in older IE versions due lack of support of
// the pointer-event css property
if(!Hammer.HAS_TOUCHEVENTS && !Hammer.HAS_POINTEREVENTS) {
Hammer.plugins.showTouches();
}
</script>
<!-- <![endif]-->
<script>
if(!Hammer.HAS_TOUCHEVENTS && !Hammer.HAS_POINTEREVENTS) {
Hammer.plugins.fakeMultitouch();
}
var hammertime = Hammer(document.getElementById('pinchzoom'), {
transform_always_block: true,
transform_min_scale: 1,
drag_block_horizontal: true,
drag_block_vertical: true,
drag_min_distance: 0
});
var rect = document.getElementById('rect');
var posX=0, posY=0,
scale=1, last_scale,
rotation= 1, last_rotation;
hammertime.on('touch drag transform', function(ev) {
switch(ev.type) {
case 'touch':
last_scale = scale;
last_rotation = rotation;
break;
case 'drag':
posX = ev.gesture.deltaX;
posY = ev.gesture.deltaY;
break;
case 'transform':
rotation = last_rotation + ev.gesture.rotation;
scale = Math.max(1, Math.min(last_scale * ev.gesture.scale, 10));
break;
}
// transform!
var transform =
"translate3d("+posX+"px,"+posY+"px, 0) " +
"scale3d("+scale+","+scale+", 0) " +
"rotate("+rotation+"deg) ";
rect.style.transform = transform;
rect.style.oTransform = transform;
rect.style.msTransform = transform;
rect.style.mozTransform = transform;
rect.style.webkitTransform = transform;
});
</script>
<script src="assets/js/ga.js"></script>
</body>
</html>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{
"name": "hammerjs",
"title": "Hammer.JS",
"description": "A javascript library for multi-touch gestures",
"version": "1.0.6",
"homepage": "http://eightmedia.github.com/hammer.js",
"licenses": [
{
"type": "MIT",
"url": "https://github.com/eightmedia/hammer.js/blob/master/LICENSE"
}
],
"keywords": [
"touch",
"gestures",
"ender"
],
"author": {
"name": "Jorik Tangelder",
"email": "j.tangelder@gmail.com"
},
"repository": {
"type": "git",
"url": "git://github.com/eightmedia/hammer.js.git"
},
"bugs": {
"url": "https://github.com/eightmedia/hammer.js/issues"
},
"dependencies": {},
"devDependencies": {
"grunt": "0.4.x",
"grunt-contrib-connect": "0.5.x",
"grunt-contrib-concat": "0.3.x",
"grunt-contrib-uglify": "0.2.x",
"grunt-contrib-jshint": "0.7.x",
"grunt-contrib-watch": "0.5.x",
"faketouches": "git://github.com/jtangelder/faketouches.js.git",
"underscore": "1.5.x",
"grunt-saucelabs": "4.1.x",
"grunt-contrib-qunit": "~0.3.0"
},
"main": "hammer.js",
"engines": {
"node": ">=0.8.0"
},
"scripts": {
"test": "grunt test"
}
}
File added
(function(Hammer) {
/**
* enable multitouch on the desktop by pressing the shiftkey
* the other touch goes in the opposite direction so the center keeps at its place
* it's recommended to enable Hammer.debug.showTouches for this one
*/
Hammer.plugins.fakeMultitouch = function() {
// keeps the start position to keep it centered
var start_pos = false;
// test for msMaxTouchPoints to enable this for IE10 with only one pointer (a mouse in all/most cases)
Hammer.HAS_POINTEREVENTS = navigator.msPointerEnabled &&
navigator.msMaxTouchPoints && navigator.msMaxTouchPoints >= 1;
/**
* overwrites Hammer.event.getTouchList.
* @param {Event} ev
* @param TOUCHTYPE type
* @return {Array} Touches
*/
Hammer.event.getTouchList = function(ev, eventType) {
// get the fake pointerEvent touchlist
if(Hammer.HAS_POINTEREVENTS) {
return Hammer.PointerEvent.getTouchList();
}
// get the touchlist
else if(ev.touches) {
return ev.touches;
}
// reset on start of a new touch
if(eventType == Hammer.EVENT_START) {
start_pos = false;
}
// when the shift key is pressed, multitouch is possible on desktop
// why shift? because ctrl and alt are taken by osx and linux
if(ev.shiftKey) {
// on touchstart we store the position of the mouse for multitouch
if(!start_pos) {
start_pos = {
pageX: ev.pageX,
pageY: ev.pageY
};
}
var distance_x = start_pos.pageX - ev.pageX;
var distance_y = start_pos.pageY - ev.pageY;
// fake second touch in the opposite direction
return [
{
identifier: 1,
pageX : start_pos.pageX - distance_x - 50,
pageY : start_pos.pageY - distance_y - -50,
target : ev.target
},
{
identifier: 2,
pageX : start_pos.pageX + distance_x - -50,
pageY : start_pos.pageY + distance_y - 50,
target : ev.target
}
];
}
// normal single touch
else {
start_pos = false;
return [
{
identifier: 1,
pageX : ev.pageX,
pageY : ev.pageY,
target : ev.target
}
];
}
};
};
})(window.Hammer);
\ No newline at end of file
(function(Hammer) {
/**
* ShowTouches gesture
* show all touch on the screen by placing elements at there pageX and pageY
* @param {Boolean} [force]
*/
Hammer.plugins.showTouches = function(force) {
// the circles under your fingers
var template_style = 'position:absolute;z-index:9999;left:0;top:0;height:14px;width:14px;border:solid 2px #777;' +
'background:rgba(255,255,255,.7);border-radius:20px;pointer-events:none;' +
'margin-top:-9px;margin-left:-9px;';
// elements by identifier
var touch_elements = {};
var touches_index = {};
/**
* remove unused touch elements
*/
function removeUnusedElements() {
// remove unused touch elements
for(var key in touch_elements) {
if(touch_elements.hasOwnProperty(key) && !touches_index[key]) {
document.body.removeChild(touch_elements[key]);
delete touch_elements[key];
}
}
}
Hammer.detection.register({
name : 'show_touches',
priority: 0,
handler : function(ev, inst) {
touches_index = {};
// clear old elements when not using a mouse
if(ev.pointerType != Hammer.POINTER_MOUSE && !force) {
removeUnusedElements();
return;
}
// place touches by index
for(var t = 0, total_touches = ev.touches.length; t < total_touches; t++) {
var touch = ev.touches[t];
var id = touch.identifier;
touches_index[id] = touch;
// new touch element
if(!touch_elements[id]) {
// create new element and attach base styles
var template = document.createElement('div');
template.setAttribute('style', template_style);
// append element to body
document.body.appendChild(template);
touch_elements[id] = template;
}
// Paul Irish says that translate is faster then left/top
touch_elements[id].style.left = touch.pageX + 'px';
touch_elements[id].style.top = touch.pageY + 'px';
}
removeUnusedElements();
}
});
};
})(window.Hammer);
jquery.hammer.js @ 170f8a81
Subproject commit 170f8a818d02712568590f2004b72cefef1b434d
/**
* Hammer
* use this to create instances
* @param {HTMLElement} element
* @param {Object} options
* @returns {Hammer.Instance}
* @constructor
*/
var Hammer = function(element, options) {
return new Hammer.Instance(element, options || {});
};
// default settings
Hammer.defaults = {
// add styles and attributes to the element to prevent the browser from doing
// its native behavior. this doesnt prevent the scrolling, but cancels
// the contextmenu, tap highlighting etc
// set to false to disable this
stop_browser_behavior: {
// this also triggers onselectstart=false for IE
userSelect : 'none',
// this makes the element blocking in IE10 >, you could experiment with the value
// see for more options this issue; https://github.com/EightMedia/hammer.js/issues/241
touchAction : 'none',
touchCallout : 'none',
contentZooming : 'none',
userDrag : 'none',
tapHighlightColor: 'rgba(0,0,0,0)'
}
//
// more settings are defined per gesture at gestures.js
//
};
// detect touchevents
Hammer.HAS_POINTEREVENTS = window.navigator.pointerEnabled || window.navigator.msPointerEnabled;
Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window);
// dont use mouseevents on mobile devices
Hammer.MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android|silk/i;
Hammer.NO_MOUSEEVENTS = Hammer.HAS_TOUCHEVENTS && window.navigator.userAgent.match(Hammer.MOBILE_REGEX);
// eventtypes per touchevent (start, move, end)
// are filled by Hammer.event.determineEventTypes on setup
Hammer.EVENT_TYPES = {};
// direction defines
Hammer.DIRECTION_DOWN = 'down';
Hammer.DIRECTION_LEFT = 'left';
Hammer.DIRECTION_UP = 'up';
Hammer.DIRECTION_RIGHT = 'right';
// pointer type
Hammer.POINTER_MOUSE = 'mouse';
Hammer.POINTER_TOUCH = 'touch';
Hammer.POINTER_PEN = 'pen';
// touch event defines
Hammer.EVENT_START = 'start';
Hammer.EVENT_MOVE = 'move';
Hammer.EVENT_END = 'end';
// hammer document where the base events are added at
Hammer.DOCUMENT = window.document;
// plugins and gestures namespaces
Hammer.plugins = Hammer.plugins || {};
Hammer.gestures = Hammer.gestures || {};
\ No newline at end of file
Hammer.detection = {
// contains all registred Hammer.gestures in the correct order
gestures: [],
// data of the current Hammer.gesture detection session
current : null,
// the previous Hammer.gesture session data
// is a full clone of the previous gesture.current object
previous: null,
// when this becomes true, no gestures are fired
stopped : false,
/**
* start Hammer.gesture detection
* @param {Hammer.Instance} inst
* @param {Object} eventData
*/
startDetect: function startDetect(inst, eventData) {
// already busy with a Hammer.gesture detection on an element
if(this.current) {
return;
}
this.stopped = false;
this.current = {
inst : inst, // reference to HammerInstance we're working for
startEvent: Hammer.utils.extend({}, eventData), // start eventData for distances, timing etc
lastEvent : false, // last eventData
name : '' // current gesture we're in/detected, can be 'tap', 'hold' etc
};
this.detect(eventData);
},
/**
* Hammer.gesture detection
* @param {Object} eventData
*/
detect: function detect(eventData) {
if(!this.current || this.stopped) {
return;
}
// extend event data with calculations about scale, distance etc
eventData = this.extendEventData(eventData);
// instance options
var inst_options = this.current.inst.options;
// call Hammer.gesture handlers
Hammer.utils.each(this.gestures, function(gesture) {
// only when the instance options have enabled this gesture
if(!this.stopped && inst_options[gesture.name] !== false) {
// if a handler returns false, we stop with the detection
if(gesture.handler.call(gesture, eventData, this.current.inst) === false) {
this.stopDetect();
return false;
}
}
}, this);
// store as previous event event
if(this.current) {
this.current.lastEvent = eventData;
}
// endevent, but not the last touch, so dont stop
if(eventData.eventType == Hammer.EVENT_END && !eventData.touches.length - 1) {
this.stopDetect();
}
return eventData;
},
/**
* clear the Hammer.gesture vars
* this is called on endDetect, but can also be used when a final Hammer.gesture has been detected
* to stop other Hammer.gestures from being fired
*/
stopDetect: function stopDetect() {
// clone current data to the store as the previous gesture
// used for the double tap gesture, since this is an other gesture detect session
this.previous = Hammer.utils.extend({}, this.current);
// reset the current
this.current = null;
// stopped!
this.stopped = true;
},
/**
* extend eventData for Hammer.gestures
* @param {Object} ev
* @returns {Object} ev
*/
extendEventData: function extendEventData(ev) {
var startEv = this.current.startEvent;
// if the touches change, set the new touches over the startEvent touches
// this because touchevents don't have all the touches on touchstart, or the
// user must place his fingers at the EXACT same time on the screen, which is not realistic
// but, sometimes it happens that both fingers are touching at the EXACT same time
if(startEv && (ev.touches.length != startEv.touches.length || ev.touches === startEv.touches)) {
// extend 1 level deep to get the touchlist with the touch objects
startEv.touches = [];
Hammer.utils.each(ev.touches, function(touch) {
startEv.touches.push(Hammer.utils.extend({}, touch));
});
}
var delta_time = ev.timeStamp - startEv.timeStamp
, delta_x = ev.center.pageX - startEv.center.pageX
, delta_y = ev.center.pageY - startEv.center.pageY
, velocity = Hammer.utils.getVelocity(delta_time, delta_x, delta_y)
, interimAngle
, interimDirection;
// end events (e.g. dragend) don't have useful values for interimDirection & interimAngle
// because the previous event has exactly the same coordinates
// so for end events, take the previous values of interimDirection & interimAngle
// instead of recalculating them and getting a spurious '0'
if(ev.eventType === 'end') {
interimAngle = this.current.lastEvent && this.current.lastEvent.interimAngle;
interimDirection = this.current.lastEvent && this.current.lastEvent.interimDirection;
}
else {
interimAngle = this.current.lastEvent && Hammer.utils.getAngle(this.current.lastEvent.center, ev.center);
interimDirection = this.current.lastEvent && Hammer.utils.getDirection(this.current.lastEvent.center, ev.center);
}
Hammer.utils.extend(ev, {
deltaTime: delta_time,
deltaX: delta_x,
deltaY: delta_y,
velocityX: velocity.x,
velocityY: velocity.y,
distance: Hammer.utils.getDistance(startEv.center, ev.center),
angle: Hammer.utils.getAngle(startEv.center, ev.center),
interimAngle: interimAngle,
direction: Hammer.utils.getDirection(startEv.center, ev.center),
interimDirection: interimDirection,
scale: Hammer.utils.getScale(startEv.touches, ev.touches),
rotation: Hammer.utils.getRotation(startEv.touches, ev.touches),
startEvent: startEv
});
return ev;
},
/**
* register new gesture
* @param {Object} gesture object, see gestures.js for documentation
* @returns {Array} gestures
*/
register: function register(gesture) {
// add an enable gesture options if there is no given
var options = gesture.defaults || {};
if(options[gesture.name] === undefined) {
options[gesture.name] = true;
}
// extend Hammer default options with the Hammer.gesture options
Hammer.utils.extend(Hammer.defaults, options, true);
// set its index
gesture.index = gesture.index || 1000;
// add Hammer.gesture to the list
this.gestures.push(gesture);
// sort the list by index
this.gestures.sort(function(a, b) {
if(a.index < b.index) { return -1; }
if(a.index > b.index) { return 1; }
return 0;
});
return this.gestures;
}
};
/**
* this holds the last move event,
* used to fix empty touchend issue
* see the onTouch event for an explanation
* @type {Object}
*/
var last_move_event = null;
/**
* when the mouse is hold down, this is true
* @type {Boolean}
*/
var enable_detect = false;
/**
* when touch events have been fired, this is true
* @type {Boolean}
*/
var touch_triggered = false;
Hammer.event = {
/**
* simple addEventListener
* @param {HTMLElement} element
* @param {String} type
* @param {Function} handler
*/
bindDom: function(element, type, handler) {
var types = type.split(' ');
Hammer.utils.each(types, function(type){
element.addEventListener(type, handler, false);
});
},
/**
* touch events with mouse fallback
* @param {HTMLElement} element
* @param {String} eventType like Hammer.EVENT_MOVE
* @param {Function} handler
*/
onTouch: function onTouch(element, eventType, handler) {
var self = this;
this.bindDom(element, Hammer.EVENT_TYPES[eventType], function bindDomOnTouch(ev) {
var sourceEventType = ev.type.toLowerCase();
// onmouseup, but when touchend has been fired we do nothing.
// this is for touchdevices which also fire a mouseup on touchend
if(sourceEventType.match(/mouse/) && touch_triggered) {
return;
}
// mousebutton must be down or a touch event
else if(sourceEventType.match(/touch/) || // touch events are always on screen
sourceEventType.match(/pointerdown/) || // pointerevents touch
(sourceEventType.match(/mouse/) && ev.which === 1) // mouse is pressed
) {
enable_detect = true;
}
// mouse isn't pressed
else if(sourceEventType.match(/mouse/) && !ev.which) {
enable_detect = false;
}
// we are in a touch event, set the touch triggered bool to true,
// this for the conflicts that may occur on ios and android
if(sourceEventType.match(/touch|pointer/)) {
touch_triggered = true;
}
// count the total touches on the screen
var count_touches = 0;
// when touch has been triggered in this detection session
// and we are now handling a mouse event, we stop that to prevent conflicts
if(enable_detect) {
// update pointerevent
if(Hammer.HAS_POINTEREVENTS && eventType != Hammer.EVENT_END) {
count_touches = Hammer.PointerEvent.updatePointer(eventType, ev);
}
// touch
else if(sourceEventType.match(/touch/)) {
count_touches = ev.touches.length;
}
// mouse
else if(!touch_triggered) {
count_touches = sourceEventType.match(/up/) ? 0 : 1;
}
// if we are in a end event, but when we remove one touch and
// we still have enough, set eventType to move
if(count_touches > 0 && eventType == Hammer.EVENT_END) {
eventType = Hammer.EVENT_MOVE;
}
// no touches, force the end event
else if(!count_touches) {
eventType = Hammer.EVENT_END;
}
// store the last move event
if(count_touches || last_move_event === null) {
last_move_event = ev;
}
// trigger the handler
handler.call(Hammer.detection, self.collectEventData(element, eventType, self.getTouchList(last_move_event, eventType), ev));
// remove pointerevent from list
if(Hammer.HAS_POINTEREVENTS && eventType == Hammer.EVENT_END) {
count_touches = Hammer.PointerEvent.updatePointer(eventType, ev);
}
}
// on the end we reset everything
if(!count_touches) {
last_move_event = null;
enable_detect = false;
touch_triggered = false;
Hammer.PointerEvent.reset();
}
});
},
/**
* we have different events for each device/browser
* determine what we need and set them in the Hammer.EVENT_TYPES constant
*/
determineEventTypes: function determineEventTypes() {
// determine the eventtype we want to set
var types;
// pointerEvents magic
if(Hammer.HAS_POINTEREVENTS) {
types = Hammer.PointerEvent.getEvents();
}
// on Android, iOS, blackberry, windows mobile we dont want any mouseevents
else if(Hammer.NO_MOUSEEVENTS) {
types = [
'touchstart',
'touchmove',
'touchend touchcancel'];
}
// for non pointer events browsers and mixed browsers,
// like chrome on windows8 touch laptop
else {
types = [
'touchstart mousedown',
'touchmove mousemove',
'touchend touchcancel mouseup'];
}
Hammer.EVENT_TYPES[Hammer.EVENT_START] = types[0];
Hammer.EVENT_TYPES[Hammer.EVENT_MOVE] = types[1];
Hammer.EVENT_TYPES[Hammer.EVENT_END] = types[2];
},
/**
* create touchlist depending on the event
* @param {Object} ev
* @param {String} eventType used by the fakemultitouch plugin
*/
getTouchList: function getTouchList(ev/*, eventType*/) {
// get the fake pointerEvent touchlist
if(Hammer.HAS_POINTEREVENTS) {
return Hammer.PointerEvent.getTouchList();
}
// get the touchlist
else if(ev.touches) {
return ev.touches;
}
// make fake touchlist from mouse position
else {
ev.identifier = 1;
return [ev];
}
},
/**
* collect event data for Hammer js
* @param {HTMLElement} element
* @param {String} eventType like Hammer.EVENT_MOVE
* @param {Object} eventData
*/
collectEventData: function collectEventData(element, eventType, touches, ev) {
// find out pointerType
var pointerType = Hammer.POINTER_TOUCH;
if(ev.type.match(/mouse/) || Hammer.PointerEvent.matchType(Hammer.POINTER_MOUSE, ev)) {
pointerType = Hammer.POINTER_MOUSE;
}
return {
center : Hammer.utils.getCenter(touches),
timeStamp : new Date().getTime(),
target : ev.target,
touches : touches,
eventType : eventType,
pointerType: pointerType,
srcEvent : ev,
/**
* prevent the browser default actions
* mostly used to disable scrolling of the browser
*/
preventDefault: function() {
if(this.srcEvent.preventManipulation) {
this.srcEvent.preventManipulation();
}
if(this.srcEvent.preventDefault) {
this.srcEvent.preventDefault();
}
},
/**
* stop bubbling the event up to its parents
*/
stopPropagation: function() {
this.srcEvent.stopPropagation();
},
/**
* immediately stop gesture detection
* might be useful after a swipe was detected
* @return {*}
*/
stopDetect: function() {
return Hammer.detection.stopDetect();
}
};
}
};
\ No newline at end of file
# Custom gestures
With Hammer.js it is easy to add your own gestures, just take a look at the gesture files.
When an gesture is added to the Hammer.gestures object, it is auto registered
at the setup of the first Hammer instance. You can also call Hammer.detection.register
manually and pass your gesture object as a param
## Gesture object
The object structure of a gesture:
````js
{ name: 'mygesture',
index: 1337,
defaults: {
mygesture_option: true
}
handler: function(type, ev, inst) {
// trigger gesture event
inst.trigger(this.name, ev);
}
}
````
`@param {String} name`
this should be the name of the gesture, lowercase
it is also being used to disable/enable the gesture per instance config.
`@param {Number} [index=1000]`
the index of the gesture, where it is going to be in the stack of gestures detection
like when you build an gesture that depends on the drag gesture, it is a good
idea to place it after the index of the drag gesture.
`@param {Object} [defaults={}]`
the default settings of the gesture. these are added to the instance settings,
and can be overruled per instance. you can also add the name of the gesture,
but this is also added by default (and set to true).
### Gesture handler
`@param {Function} handler`
this handles the gesture detection of your custom gesture and receives the
following arguments:
`@param {Object} eventData`
event data containing the following properties:
````js
timeStamp {Number} time the event occurred
target {HTMLElement} target element
touches {Array} touches (fingers, pointers, mouse) on the screen
pointerType {String} kind of pointer that was used. matches Hammer.POINTER_MOUSE|TOUCH
center {Object} center position of the touches. contains pageX and pageY
deltaTime {Number} the total time of the touches in the screen
deltaX {Number} the delta on x axis we haved moved
deltaY {Number} the delta on y axis we haved moved
velocityX {Number} the velocity on the x
velocityY {Number} the velocity on y
angle {Number} the angle we are moving
direction {String} the direction we are moving. matches Hammer.DIRECTION_UP|DOWN|LEFT|RIGHT
distance {Number} the distance we haved moved
scale {Number} scaling of the touches, needs 2 touches
rotation {Number} rotation of the touches, needs 2 touches *
eventType {String} matches Hammer.EVENT_START|MOVE|END
srcEvent {Object} the source event, like TouchStart or MouseDown *
startEvent {Object} contains the same properties as above,
but from the first touch. this is used to calculate
distances, deltaTime, scaling etc
````
`@param {Hammer.Instance} inst`
the instance we are doing the detection for. you can get the options from
the inst.options object and trigger the gesture event by calling inst.trigger
## Handle gestures
inside the handler you can get/set Hammer.detection.current. This is the current
detection session. It has the following properties
`@param {String} name`
contains the name of the gesture we have detected. it has not a real function,
only to check in other gestures if something is detected.
like in the drag gesture we set it to 'drag' and in the swipe gesture we can
check if the current gesture is 'drag' by accessing Hammer.detection.current.name
`@readonly
@param {Hammer.Instance} inst`
the instance we do the detection for
`@readonly
@param {Object} startEvent`
contains the properties of the first gesture detection in this session.
Used for calculations about timing, distance, etc.
`@readonly
@param {Object} lastEvent`
contains all the properties of the last gesture detect in this session.
after the gesture detection session has been completed (user has released the screen)
the Hammer.detection.current object is copied into Hammer.detection.previous,
this is usefull for gestures like doubletap, where you need to know if the
previous gesture was a tap
options that have been set by the instance can be received by calling inst.options
You can trigger a gesture event by calling inst.trigger("mygesture", event).
The first param is the name of your gesture, the second the event argument
/**
* Drag
* Move with x fingers (default 1) around on the page. Blocking the scrolling when
* moving left and right is a good practice. When all the drag events are blocking
* you disable scrolling on that area.
* @events drag, drapleft, dragright, dragup, dragdown
*/
Hammer.gestures.Drag = {
name : 'drag',
index : 50,
defaults : {
drag_min_distance : 10,
// Set correct_for_drag_min_distance to true to make the starting point of the drag
// be calculated from where the drag was triggered, not from where the touch started.
// Useful to avoid a jerk-starting drag, which can make fine-adjustments
// through dragging difficult, and be visually unappealing.
correct_for_drag_min_distance: true,
// set 0 for unlimited, but this can conflict with transform
drag_max_touches : 1,
// prevent default browser behavior when dragging occurs
// be careful with it, it makes the element a blocking element
// when you are using the drag gesture, it is a good practice to set this true
drag_block_horizontal : false,
drag_block_vertical : false,
// drag_lock_to_axis keeps the drag gesture on the axis that it started on,
// It disallows vertical directions if the initial direction was horizontal, and vice versa.
drag_lock_to_axis : false,
// drag lock only kicks in when distance > drag_lock_min_distance
// This way, locking occurs only when the distance has become large enough to reliably determine the direction
drag_lock_min_distance : 25
},
triggered: false,
handler : function dragGesture(ev, inst) {
// current gesture isnt drag, but dragged is true
// this means an other gesture is busy. now call dragend
if(Hammer.detection.current.name != this.name && this.triggered) {
inst.trigger(this.name + 'end', ev);
this.triggered = false;
return;
}
// max touches
if(inst.options.drag_max_touches > 0 &&
ev.touches.length > inst.options.drag_max_touches) {
return;
}
switch(ev.eventType) {
case Hammer.EVENT_START:
this.triggered = false;
break;
case Hammer.EVENT_MOVE:
// when the distance we moved is too small we skip this gesture
// or we can be already in dragging
if(ev.distance < inst.options.drag_min_distance &&
Hammer.detection.current.name != this.name) {
return;
}
// we are dragging!
if(Hammer.detection.current.name != this.name) {
Hammer.detection.current.name = this.name;
if(inst.options.correct_for_drag_min_distance && ev.distance > 0) {
// When a drag is triggered, set the event center to drag_min_distance pixels from the original event center.
// Without this correction, the dragged distance would jumpstart at drag_min_distance pixels instead of at 0.
// It might be useful to save the original start point somewhere
var factor = Math.abs(inst.options.drag_min_distance / ev.distance);
Hammer.detection.current.startEvent.center.pageX += ev.deltaX * factor;
Hammer.detection.current.startEvent.center.pageY += ev.deltaY * factor;
// recalculate event data using new start point
ev = Hammer.detection.extendEventData(ev);
}
}
// lock drag to axis?
if(Hammer.detection.current.lastEvent.drag_locked_to_axis || (inst.options.drag_lock_to_axis && inst.options.drag_lock_min_distance <= ev.distance)) {
ev.drag_locked_to_axis = true;
}
var last_direction = Hammer.detection.current.lastEvent.direction;
if(ev.drag_locked_to_axis && last_direction !== ev.direction) {
// keep direction on the axis that the drag gesture started on
if(Hammer.utils.isVertical(last_direction)) {
ev.direction = (ev.deltaY < 0) ? Hammer.DIRECTION_UP : Hammer.DIRECTION_DOWN;
}
else {
ev.direction = (ev.deltaX < 0) ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT;
}
}
// first time, trigger dragstart event
if(!this.triggered) {
inst.trigger(this.name + 'start', ev);
this.triggered = true;
}
// trigger normal event
inst.trigger(this.name, ev);
// direction event, like dragdown
inst.trigger(this.name + ev.direction, ev);
// block the browser events
if((inst.options.drag_block_vertical && Hammer.utils.isVertical(ev.direction)) ||
(inst.options.drag_block_horizontal && !Hammer.utils.isVertical(ev.direction))) {
ev.preventDefault();
}
break;
case Hammer.EVENT_END:
// trigger dragend
if(this.triggered) {
inst.trigger(this.name + 'end', ev);
}
this.triggered = false;
break;
}
}
};
\ No newline at end of file
/**
* Hold
* Touch stays at the same place for x time
* @events hold
*/
Hammer.gestures.Hold = {
name : 'hold',
index : 10,
defaults: {
hold_timeout : 500,
hold_threshold: 1
},
timer : null,
handler : function holdGesture(ev, inst) {
switch(ev.eventType) {
case Hammer.EVENT_START:
// clear any running timers
clearTimeout(this.timer);
// set the gesture so we can check in the timeout if it still is
Hammer.detection.current.name = this.name;
// set timer and if after the timeout it still is hold,
// we trigger the hold event
this.timer = setTimeout(function() {
if(Hammer.detection.current.name == 'hold') {
inst.trigger('hold', ev);
}
}, inst.options.hold_timeout);
break;
// when you move or end we clear the timer
case Hammer.EVENT_MOVE:
if(ev.distance > inst.options.hold_threshold) {
clearTimeout(this.timer);
}
break;
case Hammer.EVENT_END:
clearTimeout(this.timer);
break;
}
}
};
\ No newline at end of file
/**
* Release
* Called as last, tells the user has released the screen
* @events release
*/
Hammer.gestures.Release = {
name : 'release',
index : Infinity,
handler: function releaseGesture(ev, inst) {
if(ev.eventType == Hammer.EVENT_END) {
inst.trigger(this.name, ev);
}
}
};
\ No newline at end of file
/**
* Swipe
* triggers swipe events when the end velocity is above the threshold
* @events swipe, swipeleft, swiperight, swipeup, swipedown
*/
Hammer.gestures.Swipe = {
name : 'swipe',
index : 40,
defaults: {
// set 0 for unlimited, but this can conflict with transform
swipe_min_touches: 1,
swipe_max_touches: 1,
swipe_velocity : 0.7
},
handler : function swipeGesture(ev, inst) {
if(ev.eventType == Hammer.EVENT_END) {
// max touches
if(inst.options.swipe_max_touches > 0 &&
ev.touches.length < inst.options.swipe_min_touches &&
ev.touches.length > inst.options.swipe_max_touches) {
return;
}
// when the distance we moved is too small we skip this gesture
// or we can be already in dragging
if(ev.velocityX > inst.options.swipe_velocity ||
ev.velocityY > inst.options.swipe_velocity) {
// trigger swipe events
inst.trigger(this.name, ev);
inst.trigger(this.name + ev.direction, ev);
}
}
}
};
\ No newline at end of file
/**
* Tap/DoubleTap
* Quick touch at a place or double at the same place
* @events tap, doubletap
*/
Hammer.gestures.Tap = {
name : 'tap',
index : 100,
defaults: {
tap_max_touchtime : 250,
tap_max_distance : 10,
tap_always : true,
doubletap_distance: 20,
doubletap_interval: 300
},
handler : function tapGesture(ev, inst) {
if(ev.eventType == Hammer.EVENT_END && ev.srcEvent.type != 'touchcancel') {
// previous gesture, for the double tap since these are two different gesture detections
var prev = Hammer.detection.previous,
did_doubletap = false;
// when the touchtime is higher then the max touch time
// or when the moving distance is too much
if(ev.deltaTime > inst.options.tap_max_touchtime ||
ev.distance > inst.options.tap_max_distance) {
return;
}
// check if double tap
if(prev && prev.name == 'tap' &&
(ev.timeStamp - prev.lastEvent.timeStamp) < inst.options.doubletap_interval &&
ev.distance < inst.options.doubletap_distance) {
inst.trigger('doubletap', ev);
did_doubletap = true;
}
// do a single tap
if(!did_doubletap || inst.options.tap_always) {
Hammer.detection.current.name = 'tap';
inst.trigger(Hammer.detection.current.name, ev);
}
}
}
};
\ No newline at end of file
/**
* Touch
* Called as first, tells the user has touched the screen
* @events touch
*/
Hammer.gestures.Touch = {
name : 'touch',
index : -Infinity,
defaults: {
// call preventDefault at touchstart, and makes the element blocking by
// disabling the scrolling of the page, but it improves gestures like
// transforming and dragging.
// be careful with using this, it can be very annoying for users to be stuck
// on the page
prevent_default : false,
// disable mouse events, so only touch (or pen!) input triggers events
prevent_mouseevents: false
},
handler : function touchGesture(ev, inst) {
if(inst.options.prevent_mouseevents && ev.pointerType == Hammer.POINTER_MOUSE) {
ev.stopDetect();
return;
}
if(inst.options.prevent_default) {
ev.preventDefault();
}
if(ev.eventType == Hammer.EVENT_START) {
inst.trigger(this.name, ev);
}
}
};
\ No newline at end of file
/**
* Transform
* User want to scale or rotate with 2 fingers
* @events transform, pinch, pinchin, pinchout, rotate
*/
Hammer.gestures.Transform = {
name : 'transform',
index : 45,
defaults : {
// factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1
transform_min_scale : 0.01,
// rotation in degrees
transform_min_rotation: 1,
// prevent default browser behavior when two touches are on the screen
// but it makes the element a blocking element
// when you are using the transform gesture, it is a good practice to set this true
transform_always_block: false
},
triggered: false,
handler : function transformGesture(ev, inst) {
// current gesture isnt drag, but dragged is true
// this means an other gesture is busy. now call dragend
if(Hammer.detection.current.name != this.name && this.triggered) {
inst.trigger(this.name + 'end', ev);
this.triggered = false;
return;
}
// atleast multitouch
if(ev.touches.length < 2) {
return;
}
// prevent default when two fingers are on the screen
if(inst.options.transform_always_block) {
ev.preventDefault();
}
switch(ev.eventType) {
case Hammer.EVENT_START:
this.triggered = false;
break;
case Hammer.EVENT_MOVE:
var scale_threshold = Math.abs(1 - ev.scale);
var rotation_threshold = Math.abs(ev.rotation);
// when the distance we moved is too small we skip this gesture
// or we can be already in dragging
if(scale_threshold < inst.options.transform_min_scale &&
rotation_threshold < inst.options.transform_min_rotation) {
return;
}
// we are transforming!
Hammer.detection.current.name = this.name;
// first time, trigger dragstart event
if(!this.triggered) {
inst.trigger(this.name + 'start', ev);
this.triggered = true;
}
inst.trigger(this.name, ev); // basic transform event
// trigger rotate event
if(rotation_threshold > inst.options.transform_min_rotation) {
inst.trigger('rotate', ev);
}
// trigger pinch event
if(scale_threshold > inst.options.transform_min_scale) {
inst.trigger('pinch', ev);
inst.trigger('pinch' + ((ev.scale < 1) ? 'in' : 'out'), ev);
}
break;
case Hammer.EVENT_END:
// trigger dragend
if(this.triggered) {
inst.trigger(this.name + 'end', ev);
}
this.triggered = false;
break;
}
}
};
\ No newline at end of file
This diff is collapsed.
(function(window, undefined) {
'use strict';
\ No newline at end of file
// Based off Lo-Dash's excellent UMD wrapper (slightly modified) - https://github.com/bestiejs/lodash/blob/master/lodash.js#L5515-L5543
// some AMD build optimizers, like r.js, check for specific condition patterns like the following:
if(typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// define as an anonymous module
define(function() {
return Hammer;
});
// check for `exports` after `define` in case a build optimizer adds an `exports` object
}
else if(typeof module === 'object' && typeof module.exports === 'object') {
module.exports = Hammer;
}
else {
window.Hammer = Hammer;
}
})(this);
\ No newline at end of file
This diff is collapsed.
// if the window events are set...
Hammer.READY = false;
/**
* setup events to detect gestures on the document
*/
function setup() {
if(Hammer.READY) {
return;
}
// find what eventtypes we add listeners to
Hammer.event.determineEventTypes();
// Register all gestures inside Hammer.gestures
Hammer.utils.each(Hammer.gestures, function(gesture){
Hammer.detection.register(gesture);
});
// Add touch events on the document
Hammer.event.onTouch(Hammer.DOCUMENT, Hammer.EVENT_MOVE, Hammer.detection.detect);
Hammer.event.onTouch(Hammer.DOCUMENT, Hammer.EVENT_END, Hammer.detection.detect);
// Hammer is ready...!
Hammer.READY = true;
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Basic Test Suite</title>
<!-- Load local QUnit. -->
<link rel="stylesheet" href="libs/qunit.css" media="screen">
<script src="libs/jquery.js"></script>
<script src="libs/qunit.js"></script>
<script src="libs/underscore.js"></script>
<script src="../node_modules/faketouches/faketouches.js"></script>
<script src="../hammer.js"></script>
<script src="../plugins/hammer.showtouches.js"></script>
</head>
<body>
<script>
Hammer.HAS_POINTEREVENTS = false;
Hammer.HAS_TOUCHEVENTS = false;
var set_faketouches_type = FakeTouches.MOUSE_EVENTS;
</script>
<div id="toucharea" style="width:500px;height:500px;"></div>
<div id="qunit"></div>
<script src="gestures.js"></script>
</body>
</html>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment