Proper way to pass on “this” to custom Tap event callback

I picked up a some code for a JavaScript tap event for touch devices here : GitHub page. Credit to Jørn Kinderås for this code.

My problem is that if I do something like this : $('.support input').tap(function () { $(this).click(); });

It doesn't work because this is referring to DOMWindow (as I can see by doing a console.log(this).

The workaround I have found for now is to change a couple lines in the tap event code. I changed the following :

elem.on('touchend', _bind(function (e) {
    endTime = new Date().getTime();
    if (!didMove && ((endTime - startTime) < tapCancelTime)) {
        callback(e);
    }
}, this));

To this:

elem.on('touchend', _bind(function (e) {
    endTime = new Date().getTime();
    if (!didMove && ((endTime - startTime) < tapCancelTime)) {
        elem.onTap = callback;
        elem.onTap(e);
    }
}, this));

I feel there is probably a better way to do this the the whole elem.onTap = callback; feels dirty.

Here is the source code from GitHub :

(function ($) {
    "use strict"
    $.fn.tap = function (callback) {
        var version, didMove, tapCancelTime, startTime, endTime, _bind;
        version = "1.0.1";
        tapCancelTime = 2 * 1000;
        _bind = function (fn, me) { return function () { return fn.apply(me, arguments); }; };

        return this.each(
            function (index, element) {
                var elem = $(element);

                elem.on('click', function (e) {
                    e.preventDefault();
                });

                elem.on('touchstart', _bind(function (e) {
                    didMove = false;
                    startTime = new Date().getTime();
                }, this));
                elem.on('touchmove', _bind(function (e) {
                    didMove = true;
                }, this));
                elem.on('touchend', _bind(function (e) {
                    endTime = new Date().getTime();
                    if (!didMove && ((endTime - startTime) < tapCancelTime)) {
            callback(e);
                    }
                }, this));
                elem.on('touchcancel', _bind(function (e) {
                    callback(e);
                }, this));
            }
        );
    };
})(jQuery);

Answers


Use .apply() or .call() to pass on a desired value of this to any function.

In your case, you can change this:

callback(e);

to this:

callback.call(this, e);

or this (either will probably work in your case):

callback.call(elem, e);

and then the callback function will have the value of this from your event handler instead of window. FYI, you use .call() when you know all the arguments you want to pass to your method/function. You use .apply() when you have an array-like data structure of arguments and you want to pass all the arguments in the array.

For reference, see MDN for more info on .call() and .apply().


You have a couple of options:

var $this = this;
$('.support input').tap(function () { $this.click(); });

or

$('.support input').tap(function(o){return function () { o.click(); };}(this));

Need Your Help

jquery rebinding event

jquery bind dynamic-rebinding

I am trying to rebind the keydown event on focusout. Not really sure how what to pass to the keydown when rebinding. I tried passing this, but had no luck.

Listbox (JList) Won't update dynamically from custom ListModel

swing clojure jlist seesaw

I'm working on a GUI app in Clojure using Seesaw and am having trouble getting a listbox (JList in Java) to update when my custom ListModel gets updated.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.