Code Monkey home page Code Monkey logo

pointer.js's Introduction

Important note (August 7, 2013)

This project is deprecated.

For your future pointer event needs, please use this PointerEvents polyfill, part of the Polymer Project.

An early pointer events polyfill

For background and motivation, see this blog post: http://smus.com/mouse-touch-pointer/.

Implementation

This is a library that enables MSPointer*-style pointer events in all browsers.

Pointer events

The whole point of pointer.js is to use pointer* events instead of mouse* and touch*. You can do this by subscribing to these events in the same way as you would regular events:

var el = document.querySelector(mySelector);
el.addEventListener('pointerdown', function(e) {
  // ...
});

Approach: override addEventListener to intercept pointer* events. (Theoretical alternative: have an explicit el.emitPointers call.)

As soon as you start listening for pointer* events, both mouse and touch events are hijacked, and do not fire.

The event payload for a pointer event includes the following important features:

  • {String} pointerType - the kind of pointer it is (touch, mouse, pen)
  • {Object} originalEvent - the original event payload from the underlying event.
  • {Function} getPointerList() - gets the list of active pointers (ie mouse pressed, fingers on the screen).

The bottom line is that you code your input to a single spec: pointer events from pointer.js. The library abstracts all of the input differences for you under the consolidated model.

Pointer API

Events: pointerdown, pointermove, pointerup

Event payload class: originalEvent, pointerType, getPointerList()

Pointer class: clientX, clientY, screenX, screenY, pageX, pageY, tiltX, tiltY, pressure, hwTimestamp, pointerType, identifier

Gesture events

Now that we have a solid touch/mouse/stylus abstraction, we can build higher level gestures on top. Some interesting events to support are tap, double tap, longpress, swipe, pinch-zoom, and rotate.

Gesture API

Emit new gesture* events. For example, gesturedoubletap, gesturelongpress, gesturescale, etc. This is incompatible with Safari's gesturestart events, but in the future can also be consolidated under one umbrella.

This is done with the same addEventListener hack as is used for pointer events. Each of these gesture* events has a recognizer associated with it. If, for example, gesturescale is specified, the pointer-event-based recognizer gets pulled into the event loop.

Each gesture has a custom event associated with it. This function takes an HTMLElement as its only argument. The following gestures are supported:

gesture           gesture event
===================================
Double Tap        gesturedoubletap
Long Press        gesturelongpress
Scale             gesturescale

This is a nice place to contribute if you're so inclined. Gesture recognizers can easily be plugged into this architecture. They are completely standalone and can be registered easily. For an example, take a look at the doubletap handler.

The scale gesture implements a pinch-zoom and provides the scaling factor as part of the event payload through evt.scale.

Demos

Open questions

  • Will the way addEventListener is overridden cause problems in the future?

  • Is the overhead of firing a custom event vs. calling a function too high? See this test on jsperf.com

  • Does the gesture approach make sense on iOS, which provides built-in gesture support? How to consolidate?

pointer.js's People

Contributors

borismus avatar lhchavez avatar matthewrobertson avatar cwilso avatar snappedtogrid avatar

Stargazers

 avatar  avatar YC avatar  avatar  avatar Houfeng avatar Jamie Leviner avatar JULIAN avatar  avatar julabs avatar  avatar Alexandre Nicastro avatar  avatar My Kim Bui avatar  avatar changfuguo avatar Yige avatar mm-ikoma avatar Jase avatar  avatar harveyhaha avatar Tomáš Václavík avatar Neil Voss avatar Forrest avatar xiguaxigua avatar taotao avatar Jonas Frost avatar test avatar 吃鱼不吃胖 avatar  avatar Angus H. avatar  avatar  avatar Batuhan Göksu avatar Jesse avatar pandao avatar Brad Ward avatar Jerome Russ avatar  avatar fred avatar Shon Chan avatar  avatar  avatar yanjunqiang avatar McChen avatar Andy Pai avatar Babji Chetty avatar Anoop Gupta avatar Juan Carlos Alonso Holmstron avatar  avatar  avatar yyman001 avatar Minwe LUO avatar  avatar 墨神 avatar wc1217 avatar  avatar 忆年 avatar Rafael Bartalotti avatar Tom avatar Andrey Shipilov avatar lorezz avatar Stephen Parish avatar Aresy.z avatar  avatar johnny avatar gaogao avatar Benjamin James avatar Brandon Orther avatar Max Glenister avatar Ladislav Prskavec avatar chenxu zhao avatar Alaa Badran avatar  avatar William Dias avatar Blue Chen avatar Javier Sánchez - Marín avatar  avatar jeep avatar maxzhang avatar kenfrederick avatar M Haidar Hanif avatar Young for you avatar Nikos M. avatar Vilius Luneckas avatar LC avatar Junaid Mohammed avatar Christian Hochfilzer avatar David avatar Neo avatar Serf avatar Arnout Kazemier avatar  avatar Umur Kontacı avatar Peter avatar  avatar Julien avatar Daniel Weck avatar Charles Jacquin avatar  avatar

Watchers

arden avatar Abhishek Tiwari avatar Brad Jones avatar Razvan Caliman avatar Masaaki Kurihara avatar Adam Kempa avatar Roche julien avatar RJ avatar  avatar finscn avatar Christian Ferranti avatar Steve Bazyl avatar Christian Hochfilzer avatar Stevenson Gossage avatar Anthony Bowyer-Lowe avatar Nikki Koole avatar Tarmo Aidantausta avatar  avatar  avatar James Cloos avatar Krister Kari avatar debueb avatar Zhou Peng avatar  avatar Ruud Steltenpool avatar Florian Gutwald avatar ctam avatar  avatar Benjamin Kyd avatar

pointer.js's Issues

Duplicated handler invocation

If you attach pointer event handler to document.documentElement or document.body within another pointer handler, the original handler (within which you attach the document / body handler) is called twice).

Code:

var logContainer = document.querySelector('#log'),
    log = function (msg) {
      logContainer.innerHTML = logContainer.innerHTML + '\n' + msg;
    },

    pointerdownHandler,
    pointerupHandler,

    docElement = document.documentElement,
    el1 = document.querySelector('.el1');


pointerupHandler = function () {
  log('pointerup handler');
  docElement.removeEventListener('pointerup', pointerupHandler, false);
};

pointerdownHandler = function (e) {
  log('pointerdown handler');
  docElement.addEventListener('pointerup', pointerupHandler, false);

};

// why is pointerdownHandler invoked twice?
el1.addEventListener('pointerdown', pointerdownHandler, false);

Example: http://jsbin.com/iwuhar/1/edit
Example with comparison to mouse events: http://jsbin.com/iwuhar/4/edit

Support MSPointer* events

Currently on Win8, we fallback to mouse. This is no good. Pointer.js should just be rewriting MSPointer* events to pointer* events with small tweaks.

Scale or two finger-tilt?

Usual, we scale with two figera and touch the screen almost at same moment, but two finger-tilt is touch the screen one by one.

Shall we add a timer for scale to distinguish them?

Conflicting gestures

Was toying around with creating a rotate gesture event, which would be two fingers that rotate clockwise or counter clockwise from their reference points, respectively.

The problem I see is that this sort of gesture would easily also fire the scale gesture.

So, my question is, how can we provide a mechanism where conflicting gestures can co-exist?

One thought is that when you register a gesture that knows it conflicts with a previous one, that it can somehow disable or de-register the previously conflicting one, so you get a last-come-last-served sort of behavior. But this sort of thing is brittle and complex to manage.

Another is to perhaps have a way to consolidate an event into a combo event, where you say "both scale and rotate happened", and fire that combo event for BOTH handlers, respectively. That way inside the handlers the application developer can decide if they want to respond to only one, or the other, or in some cases, perhaps both simultaneously.

The mechanism could consolidate events that happen roughly simultaneously into this combo event, or even an event array, so a single handler can know all the eligible events that it participated in.

What do you think?


NOTE: similar frustrations have existed for years between click and double-click, so I'm seeking to find a way to have the event system be a little smarter, to prevent end-developers from having to manually handle those cases.

How is the user going to subscribe to events?

Have you thought much about how you want this all to work in terms of subscribing to events? One option is to do everything via jQuery so it might end up looking like this:

 $("#myDiv").bind("swipe:left", function() {...});

This is trivial to implement, but what about using it outside of jQuery? It would be nice to have our library work without it then just wrap it in a jQuery library for convenience. Hammer's solution for this is just to have the user create a Hammer in lui of subscribing. So it ends up being like this:

var hammer = new Hammer(document.getElementById("myDiv"));
hammer.onPinch(function() { "Do stuff" });

I don't know if I like this api style because I think you should still be able to subscribe to events in the normal way using addEventListener on the dom elements. I don't know if there is a proper way to do this but maybe we could opt for something like this:

var mydiv = document.getElementById("myDIv");
new SwipeEmitter(mydiv)
//later...
mydiv.addEventListener("swipe:left", function() {...})

Or we could hack into things a bit, get crazy and have something that looks like this:

document.getElementById("myDiv").emmitSwipeEvents();

But that might be taking things too far.

jquery bind pointerdown

I'm using jquery:

element.bind("pointerdown", function() {
alert("works");
});

on chrome it works fine, but not on the latest firefox... any ideas?

what if input mode changes after events are added?

If you only add a touchstart and later user starts using a mouse to interact things will break. (imagine an iPad with a mouse). More info about it here: http://webreflection.blogspot.com.br/2012/06/dealing-with-future-pointers.html

Feeling that the way would be to add listeners to all event types and normalize them internally (after you start a touch wait for touchend, if you start a mouse event wait for another mouse event..) I also feel the library shouldn't change the native addEventListener() because the dispatched event will differ from native events and names could clash (can lead to incompatibilities with other libs in the future).

Default touch functionality is broken on touch devices

Each touch event listener is forcing event.preventDefault(). This breaks the default functionality on touch devices, like page scrolling in Android for example.

I'd suggest removing those, if there is no specific reason to prevent the default actions.

preventDefault doesn't work when using event delegation

Here's an exmaple code that doesn't use any libs except for Modernizr and Pointer.js:
http://jsbin.com/uqudov/3

Here's an example of the code with jQuery:
http://jsbin.com/usuxif/3

For the sake of being short I'll only paste jQuery's example code:

// here the link is not followed and `#` doesn't appear in the address bar
$('.container-click').on('click', 'a', function (e) {
  e.preventDefault();
  console.log('link clicked');
});

// the links in this container are followed by browser
$('.container-pointer').on('pointerup', 'a', function (e) {
  e.preventDefault();
  console.log('link clicked');
});

Returning false doesn't work either (you can try to test it http://jsbin.com/uqudov/3/edit)

Firefox 13

The three examples don't work at all in Firefox 13 on Ubuntu 12.04.

No exceptions in console.

Pointer data does not bubble up the DOM tree

If for example in the pointer event logger you add an overlay above the div#test that spans 50% of the height (and it is a child of div#test) then you will see that when you click outside of div, everything works as expected, but when you click on the overlay you will always get pointer count = 0;

My guess is that the information does not bubble up on the DOM tree

Dual mode devices operate in single mode only

On devices that support both the touch events, and the mouse events (like say the chromebook pixel), pointer.js only responds to the touch events.

I might have an older version of the library, but I would expect any applicable input method to be allowed, and not restricted to a single input method...

[question] License

Hey,
just a simple question: I can't find any license, it would be nice to add an license.

Greetings

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.