Question

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);
Was it helpful?

Solution

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().

OTHER TIPS

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));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top