5
<title>fast-buttons.js - Ubuntu HTML5 API</title>
6
<link rel="stylesheet" href="http://yui.yahooapis.com/3.8.0pr2/build/cssgrids/cssgrids-min.css">
7
<link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
8
<link rel="stylesheet" href="../assets/css/main.css" id="site_styles">
9
<script src="http://yui.yahooapis.com/combo?3.8.0pr2/build/yui/yui-min.js"></script>
11
<body class="yui3-skin-sam">
14
<div id="hd" class="yui3-g header">
15
<div class="yui3-u-3-4">
16
<h1><a href="../index.html"><img src="../assets/css/logo.png">Ubuntu HTML5 API: fast-buttons.js</a></h1>
18
<div class="yui3-u-1-4 version">
19
<em>API Docs for: HTML-14.04-dev~bzr202</em>
24
<div id="sidebar" class="yui3-u">
25
<div id="modules" class="sidebox">
27
<h2 class="no-toc">Modules</h2>
31
<li><a href="../modules/UbuntuUI.html">UbuntuUI</a>
37
<div id="classes" class="sidebox">
39
<h2 class="no-toc">Classes</h2>
43
<li><a href="../classes/UbuntuUI.html">UbuntuUI</a></li>
44
<li><a href="../classes/UbuntuUI.Button.html">UbuntuUI.Button</a></li>
45
<li><a href="../classes/UbuntuUI.Dialog.html">UbuntuUI.Dialog</a></li>
46
<li><a href="../classes/UbuntuUI.Header.html">UbuntuUI.Header</a></li>
47
<li><a href="../classes/UbuntuUI.List.html">UbuntuUI.List</a></li>
48
<li><a href="../classes/UbuntuUI.OptionSelector.html">UbuntuUI.OptionSelector</a></li>
49
<li><a href="../classes/UbuntuUI.Page.html">UbuntuUI.Page</a></li>
50
<li><a href="../classes/UbuntuUI.Pagestack.html">UbuntuUI.Pagestack</a></li>
51
<li><a href="../classes/UbuntuUI.Popover.html">UbuntuUI.Popover</a></li>
52
<li><a href="../classes/UbuntuUI.Progress.html">UbuntuUI.Progress</a></li>
53
<li><a href="../classes/UbuntuUI.Shape.html">UbuntuUI.Shape</a></li>
54
<li><a href="../classes/UbuntuUI.Tab.html">UbuntuUI.Tab</a></li>
55
<li><a href="../classes/UbuntuUI.Tabs.html">UbuntuUI.Tabs</a></li>
56
<li><a href="../classes/UbuntuUI.Toolbar.html">UbuntuUI.Toolbar</a></li>
65
<div id="fileTree" class="sidebox">
67
<h2 class="no-toc">Files</h2>
70
<ul><li>buttons.js/<ul></ul></li><li>core.js/<ul></ul></li><li>dialogs.js/<ul></ul></li><li>fast-buttons.js/<ul></ul></li><li>header.js/<ul></ul></li><li>list.js/<ul></ul></li><li>option-selector.js/<ul></ul></li><li>page.js/<ul></ul></li><li>pagestacks.js/<ul></ul></li><li>popovers.js/<ul></ul></li><li>progress.js/<ul></ul></li><li>shape.js/<ul></ul></li><li>tab.js/<ul></ul></li><li>tabs.js/<ul></ul></li><li>toolbars.js/<ul></ul></li></ul>
76
<div id="main" class="yui3-u">
77
<div class="content"><h4>fast-buttons.js</h4>
79
<pre class="code prettyprint linenums">
81
* Copyright (C) 2013 Adnane Belmadiaf <daker@ubuntu.com>
82
* License granted by Canonical Limited
84
* This file is part of ubuntu-html5-ui-toolkit.
86
* This package is free software; you can redistribute it and/or modify
87
* it under the terms of the GNU Lesser General Public License as
88
* published by the Free Software Foundation; either version 3 of the
90
* (at your option) any later version.
92
* This package is distributed in the hope that it will be useful,
93
* but WITHOUT ANY WARRANTY; without even the implied warranty of
94
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
95
* GNU General Public License for more details.
97
* You should have received a copy of the GNU Lesser General Public
98
* License along with this program. If not, see
99
* <http://www.gnu.org/licenses/>.
104
* From: http://code.this.com/mobile/articles/fast_buttons.html
105
* Also see: http://stackoverflow.com/questions/6300136/trying-to-implement-googles-fast-button
108
/** For IE8 and earlier compatibility: https://developer.mozilla.org/en/DOM/element.addEventListener */
110
function addListener(el, type, listener, useCapture) {
111
if (el.addEventListener) {
112
el.addEventListener(type, listener, useCapture);
114
destroy: function () {
115
el.removeEventListener(type, listener, useCapture);
119
// see: http://stackoverflow.com/questions/5198845/javascript-this-losing-context-in-ie
120
var handler = function (e) {
121
listener.handleEvent(window.event, listener);
123
el.attachEvent('on' + type, handler);
126
destroy: function () {
127
el.detachEvent('on' + type, handler);
133
var isTouch = "ontouchstart" in window;
135
/* Construct the FastButton with a reference to the element and click handler. */
136
this.FastButton = function (element, handler, useCapture) {
137
// collect functions to call to cleanup events
139
this.touchEvents = [];
140
this.element = element;
141
this.handler = handler;
142
this.useCapture = useCapture;
144
this.events.push(addListener(element, 'touchstart', this, this.useCapture));
145
this.events.push(addListener(element, 'click', this, this.useCapture));
148
/* Remove event handling when no longer needed for this button */
149
this.FastButton.prototype.destroy = function () {
150
for (var i = this.events.length - 1; i >= 0; i -= 1)
151
this.events[i].destroy();
152
this.events = this.touchEvents = this.element = this.handler = this.fastButton = null;
155
/* acts as an event dispatcher */
156
this.FastButton.prototype.handleEvent = function (event) {
157
switch (event.type) {
158
case 'touchstart':
159
this.onTouchStart(event);
161
case 'touchmove':
162
this.onTouchMove(event);
164
case 'touchend':
167
case 'click':
173
/* Save a reference to the touchstart coordinate and start listening to touchmove and
174
touchend events. Calling stopPropagation guarantees that other behaviors don’t get a
175
chance to handle the same click event. This is executed at the beginning of touch. */
176
this.FastButton.prototype.onTouchStart = function (event) {
177
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
178
this.touchEvents.push(addListener(this.element, 'touchend', this, this.useCapture));
179
this.touchEvents.push(addListener(document.body, 'touchmove', this, this.useCapture));
180
this.startX = event.touches[0].clientX;
181
this.startY = event.touches[0].clientY;
184
/* When /if touchmove event is invoked, check if the user has dragged past the threshold of 10px. */
185
this.FastButton.prototype.onTouchMove = function (event) {
186
if (Math.abs(event.touches[0].clientX - this.startX) > 10 || Math.abs(event.touches[0].clientY - this.startY) > 10) {
187
this.reset(); //if he did, then cancel the touch event
191
/* Invoke the actual click handler and prevent ghost clicks if this was a touchend event. */
192
this.FastButton.prototype.onClick = function (event) {
193
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
195
// Use .call to call the method so that we have the correct "this": https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call
196
var result = this.handler.call(this.element, event);
197
if (event.type == 'touchend')
198
clickbuster.preventGhostClick(this.startX, this.startY);
202
this.FastButton.prototype.reset = function () {
203
for (var i = this.touchEvents.length - 1; i >= 0; i -= 1)
204
this.touchEvents[i].destroy();
205
this.touchEvents = [];
208
this.clickbuster = function () {};
210
/* Call preventGhostClick to bust all click events that happen within 25px of
211
the provided x, y coordinates in the next 2.5s. */
212
this.clickbuster.preventGhostClick = function (x, y) {
213
clickbuster.coordinates.push(x, y);
214
window.setTimeout(clickbuster.pop, 2500);
217
this.clickbuster.pop = function () {
218
clickbuster.coordinates.splice(0, 2);
221
/* If we catch a click event inside the given radius and time threshold then we call
222
stopPropagation and preventDefault. Calling preventDefault will stop links
223
from being activated. */
224
this.clickbuster.onClick = function (event) {
225
for (var i = 0; i < clickbuster.coordinates.length; i += 2) {
226
var x = clickbuster.coordinates[i];
227
var y = clickbuster.coordinates[i + 1];
228
if (Math.abs(event.clientX - x) < 25 && Math.abs(event.clientY - y) < 25) {
229
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
230
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
236
// Don't need to use our custom addListener function since we only bust clicks on touch devices
237
document.addEventListener('click', clickbuster.onClick, true);
238
clickbuster.coordinates = [];
248
<script src="../assets/vendor/prettify/prettify-min.js"></script>
249
<script>prettyPrint();</script>
250
<script src="../assets/js/yui-prettify.js"></script>
251
<script src="../assets/js/tabs.js"></script>