Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

ember-mobiletouch

runspired54MIT1.4.12

[DEPRECATED] Gesture support for Ember Apps

ember-addon

readme

!!!DEPRECATED!!!

This project has been deprecated in favor of Ember Gestures, which offers a better solution for fastclick via touch-action (and touch-action polyfill), much faster eventing, and a better ability to keep in step with both HammerJS (also maintained by this addon's author) and Ember.

A migration guide will be coming soon. Join #ember-mobile in the ember-community slack for answers to migration questions. Bugfix releases will continue here for the near future, but migration is encouraged.

Ember-mobiletouch

npm version Build Status Ember Observer Score

Ember addon for touch and gesture support in ember based mobile apps and websites.

Changelog

dependencies devDependency Status

Installation

npm install ember-mobiletouch

ember g ember-mobiletouch

(or, as of recent changes)

ember install:addon ember-mobiletouch

What's Included

This addon installs HammerJS 2.0.4 and wires it into your app as a global (Hammer).

It then sets up a single Hammer instance to manage gestures, and pushes the gestures received through Ember's eventing system. For a full feature list and configuration, continue reading.

Usage

Ember.View.extend({

  gestureAllow : [],

  gestureExclude : [],

  tap : function (e) {
    ;//do something!
  }

})

gestureAllow

Optionally specify jQuery selectors for children of the View that can trigger the defined gestures.

gestureExclude

Optionally specify child elements of the View which should never trigger the defined gestures.

gestureAllow and gestureExclude can be used in tandem and will never filter the View itself filters are not applied to non-gestures (e.g. events defined in defaultConfig.events)

Action helper

This triggers myAction on tap

<div {{action "myAction"}}></div>

This triggers myAction on press

<div {{action "myAction" on="press"}}></div>

Links trigger on tap.

{{#link-to 'dashboard'}}Dashboard{{/link-to}}

But this would trigger on press

{{#link-to 'dashboard' eventName="press"}}Dashboard{{/link-to}}

And this would trigger on swipeRight

{{#link-to 'dashboard' eventName="swipeRight"}}Dashboard{{/link-to}}

Mobile FastFocus

text/password and similar input types on Mobile and Cordova are focused on tap, press. Focus's dependency on click and the keyboard opening on mobile devices otherwise leads to the focus getting lost.

Mobile Keyboard based submit

On mobile / cordova, the iOS keyboard triggers a 'click' on a form's submit input/button. ember-mobiletouch captures this click, and triggers a submit event, allowing action handlers to work.

Custom Recognizers

You can define custom recognizers by adding them in app/recognizers.js. (See the example)[https://github.com/runspired/ember-mobiletouch/blob/master/app/recognizers.js].

For instance, to add a doubleTap gesture.

export default function () {

  //the DOM event will be all lowercase (doubletap)
  //the Ember event will be camelCase (doubleTap)
  //the key in this.Recognizers will be SnakeCase (DoubleTap)

  this.recognize({

    name : 'doubleTap', //always camelCase this

    gesture : 'tap', //the base Hammer recognizer to use

    tune : { //the settings to pass to the recognizer, event will be added automatically
      taps : 2
    },

    'with' : ['tap'], //an array of recognizers to recognize with.

    without : [] //an array of recognizers that must first fail
  });

}

Be forewarned, this example implementation will still also trigger two taps along with the doubleTap.

Vertical Swipe/Pan without breaking scroll

ember-mobileTouch now comes with two mixins you can use to add localized hammer instances when you need to add vertical swipe / pan functionality without breaking the ability to scroll on mobile devices.

import VerticalPanMixin from "ember-mobiletouch/mixins/vertical-pan"; import VerticalSwipeMixin from "ember-mobiletouch/mixins/vertical-swipe";

These mixins can be used together. The default recognizer configuration for both is

{
  direction : Hammer.DIRECTION_VERTICAL
}

You can adjust the recognizer configuration by setting the panConfiguration and swipeConfiguration properties respectively.

Configuration

The following settings can be configured in config/environment.js. They are shown below with their defaults. You can read more by reading the documentation comments in addon/default-config.js

The default configuration can be examined here: http://codepen.io/anon/pen/bNLJbN?editors=001

ENV.mobileTouch = {

    //which gesture families to allow, will create a recognizer for each
    //a minimum of tap must be present, turning off unused gestures can help performance
    use : ['tap', 'press', 'pan', 'swipe'],

    //whether to alias "press" to tap within Ember's eventing
    // very useful if you don't need to distinguish and don't want to lose
    // taps from people who tap longer
    alwaysTapOnPress : false,

    //whether links and actions should trigger tap behavior on press as well
    // if eventName or "on" has not been explicitly defined
    // currently does not work with actions
    defaultTapOnPress : true,

    //passed to new Hammer.Manager(element, options)
    options : {
       domEvents : true
    },

    //passed to the respective recognizer
    tune : {
      tap : { time : 250, threshold : 9 }, //Hammer default is 250 / 2
      press : { time : 251, threshold : 9 }, //Hammer default is 500 / 5
      swipe : { direction : 6, velocity : 0.3, threshold : 25 },
      pan : { direction : 6 },
      pinch : {},
      rotate : {}
    },

    //what default Ember events should be disabled
    events : [
      'touchstart',
      'touchmove',
      'touchend',
      'touchcancel',
      'mousedown',
      'mouseup',
      'click', //not removed, re-aliased to internalClick.  Use cautiously.
      'dblclick',
      'mousemove',
      'mouseenter',
      'mouseleave'
    ]

};

touchZone

Sometimes smaller buttons or critical buttons need a larger capture area than their visible area. You can increase the area that recognizes touch events for a specific button https://gist.github.com/runspired/506f39a4abb2be48d63f

Testing

When using ember-mobiletouch, actions etc. are no longer triggered by clicks, but by taps. This can break some of your apps existing tests.

In test-helper.js you will need to import the Ember.EventDispatcher changes.

import mobileTouchOverrides from 'yourapp/overrides/ember-mobiletouch';

In your tests on actions, you will need to use triggerEvent('#some-selector', 'tap') instead of click('#some-selector')

Important The jQuery events you need to trigger are the Hammer variant, meaning it is entirely lowercase swiperight, panup.

Click

==================================================

Q: Where did click go? Why not just alias tap/touchStart/touchEnd to click?

A: Aliasing other events to click has unintended results. You can't preventDefault() a tap the same way as a click, and a tap could have been triggered by many varying event conditions. Aliasing other events to click would force all of your click handlers to need to examine the event object to determine what type of event it originated as.

Removing click from eventing has it's own complications. It then becomes necessary to determine what click events to prevent default behavior on. Global handlers to catch clicks on links are error prone because event.target may be an element within the link and not the link itself, but adding a click handler to all views that need to prevent clicks would also introduce complications.

To provide a great gesture API while also addressing these challenges, Mobile Touch uses an cautious cancelling approach while still providing the ability to custom tailor the behavior where necessary.

As of 1.4.3, click is aliased to internalClick, and used to prevent default behavior on clicks on link-tos. Adding .allow-click or .needsclick to a view, link, or button that would otherwise cancel the click will allow the click to pass through. Synthetic clicks are also triggered on tap (not press), and used as a "fastclick" mechanism on links not within Ember's view ecosystem. "fastclick" clicks do not enter Ember's eventing as internalClicks but are instead filtered out when they reach the body.

The rules for whether mobile touch will prevent the default behavior of a click are as follows:

  • it does not have the .allow-click or .needsclick (added as a convenience for those coming from fastclick.js) class

AND

  • it was on or has bubbled to an Ember.linkView
  • (OR) it is button[type!="submit"] or input[type="button"]
  • (OR) it is input[type="submit"] or button[type="submit"] AND does not have the attribute data-ember-action

changelog

Changelog

1.4.1

  • [FIX] fixes the ability for swipe to be recognized along with pan (#8)

1.4.0

While loaded with some great new features, the main attraction is an internal refactor that improves testability and maintainability. This refactor produces one major change in config settings. A shim has been put into place to continue to support user's using the original way the config worked.

  • [FEAT] Fast focus on inputs on mobile web / Cordova apps.
  • [FEAT] Custom recognizers: Multi-Touch Gestures (e.g. 2/3/4 finger swipes) and doubleTap can be achieved via custom recognizers added in recognizers.js
  • [FIX] submit buttons on mobile keyboards will now work correctly.
  • [FIX] clicks are not busted on links with custom protocols (e.g. mailto: tel:)
  • [FEAT] adding the allow-click class to a link or button will prevent click busting.
  • [FEAT] mixins are now available for enabling vertical pan/swipe without breaking scrolling.
  • [FEAT] if you are using ENV.mobileTouch.events, this property is now an array of default ember events to disable.
  • [BREAKING] the default config for swipe and pan will now prevent vertical panning/swiping so as to not break scroll.

In order to make testing easier, we now reopen the EventManager instead of extending it. This means we subtract events from Ember's existing events instead of merely defining all our own. ENV.mobileTouch.events should now be an array containing only those events you wish to remove from Ember's defauly eventing. This has the added benefit of making configuration in this area easier.

In order to be backwards compatible, a shim has been included. When ENV.mobileTouch.events is defined as an object, the events in that object are diffed with Ember's default events and the difference is used to determine which default events are ignored.

1.3.2

  • [FIX] HTMLBars support

1.3.1

  • [FIX] brings in defaultTapOnPress (meant to be included in 1.3.0)

1.3.0

  • [FIX] Thanks to @huafu who identified and fixed an issue preventing action params from being sent with the action
  • [DOC] Better documentation of configuration (more coming)
  • [FEAT] alwaysTapOnPress is now fully implemented, when true press events are aliased to tap events
  • [FIX] defaultTapOnPress is now sent to linkView instead of alwaysTapOnPress
  • [BREAKING] pinch and rotate are no longer recognized by default.
  • [FEAT] ENV.mobileTouch.tune can now be used to add customized recognizer settings.
  • [BREAKING] As part of the new recognizer tune-ability, recognizer defaults have been changed (see below).

About Breaking Change 1: In the previously poorly documented configuration options, ENV.mobileTouch.use = ['tap', 'press'] should have stated tap and press as the only recognizers added by default. This is for performance reasons. Unfortunately, neither the docs nor the code actually implemented this intention properly, so until 2.0, the default recognizers will be ['tap', 'press', 'swipe', 'pan']. pinch and rotate have been removed as Hammer's implementation of them is very buggy. If your implementation was relying on pinch or rotate, you simply need to add the following to your config for mobileTouch. ENV.mobileTouch.use = ['tap', 'press', 'swipe', 'pan', 'pinch', 'rotate'];

About Breaking Change 2: Hammer's default settings for tap and press leave a gap in which a user can perform an action but no gesture will be recognized. Specifically, tap events time out at 250ms but press events don't begin until 500ms. While this gap is small, we noticed a high incidence of failed taps because of it. Press now triggers at 251ms, instead of 500ms.

Similarly, Hammer doesn't begin recognizing pan or swipe until 10px of movement have occurred (we adjusted swipe to 25px from the beginning). However, the default movement allowed for tap was 2px and for press 5px. This again left an error zone in which someone would trigger no behavior at all. We observed that clientele with less stable hands or whom tapped / pressed from the side of their finger would often record too much movement to trigger tap or press. For this reason, tap and press now allow up to 9px of movement by default

1.2.2

  • [FIX] fix issue from 1.2.1 which removed gestures from eventing

1.2.1 - BAD RELEASE, DO NOT USE THIS VERSION

  • [FIX] bubble events correctly, cancel events correctly, don't merge final events into the defaultConfig object

1.2.0

  • [FEAT] option "alwaysTapOnPress" causes linkView to trigger on tap (much more coming with this feature).
  • [DEPRECATE] hammerAllow and hammerExclude are now gestureAllow and gestureExclude, support for the other will be removed in 2.0.
  • [FIX] filters will no longer fail to review the view element itself if targeted.
  • [FIX] fixes bug where View.__useGesturesHash was always null
  • [FIX] __executeGestureWithFilters returns false after it runs a handler
  • [FIX] non gesture events are not sent through __filterTouchableElements

1.1.0

  • [Fix] Prevent Ghost Clicks
  • [Fix] Prevent HammerJS Tap firing twice
  • [FEATURE] Gesture's in action helper {{action 'myActionHandler' on='swipeLeft'}}
  • [FEATURE] Remove dependency on fastclick.js for a baked in implementation
  • [PERF] Utilize a single global Hammer instance
  • [PERF/FEATURE] Send gestures as Ember Events
  • [DEPRECATE] Convert handlers for "click" to tap with deprecation notice
  • Demo page (for testing)
  • EventManager support (add gestures to eventManager instead of directly to the view)
  • [FEATURE] hammerAllow and hammerExclude work on events defined directly on the view, in gestures, or in eventManager
  • [FEATURE] action handlers utilize tap by default
  • [PERF] The Gestures Mixin no longer sets up / tears down a Hammer instance
  • [BREAKING] hammerOptions on a View/Component has been replaced by global options set in ENV.mobileTouch.options

1.0.6

[BREAKING] setupGestures and teardownGestures are now private (begin with _) methods on the mixin.

1.0.5

[BREAKING] hammerFilter is now hammerAllow. This should always have been the case. Docs have read hammerAllow