Completely solve tap (TAP) Boost Mobile click Response speed

Source: Internet
Author: User

Using Fastclick

Nima use is too simple, a straight sentence:

Fastclick.attach (document.body);

So all the click response speed directly increased, just! What input gets the focus of the problem also solved!!! If you really can, the original change page colleague Will chew me

Step by step, we follow in, the entrance is the Attach method:

Fastclick.attach = function (layer) {    ' use strict ';    return new Fastclick (layer);};

This brother just instantiated the code, so we're going to look at our constructors:

function Fastclick (layer) {' Use strict '; var oldonclick, self = this; This.trackingclick = false; This.trackingclickstart = 0; This.targetelement = null; This.touchstartx = 0; This.touchstarty = 0; This.lasttouchidentifier = 0; This.touchboundary = 10; This.layer = layer; if (!layer | |!layer.nodetype) {throw new TypeError (' layer must be a document node '); This.onclick = function () {Retu RN FastClick.prototype.onClick.apply (self, arguments); }; This.onmouse = function () {return FastClick.prototype.onMouse.apply (self, arguments);}; This.ontouchstart = function () {return FastClick.prototype.onTouchStart.apply (self, arguments);}; This.ontouchmove = function () {return FastClick.prototype.onTouchMove.apply (self, arguments);}; This.ontouchend = function () {return FastClick.prototype.onTouchEnd.apply (self, arguments);}; This.ontouchcancel = function () {return FastClick.prototype.onTouchCancel.apply (self, arguments);}; if (fastclick.notneeded (layer)) {return;} if (This.deviceisandroid) {layer.addeventlistener (' mouseover ', this.onmouse, true);  Layer.addeventlistener (' MouseDown ', this.onmouse, true); Layer.addeventlistener (' MouseUp ', this.onmouse, true); } layer.addeventlistener (' Click ', This.onclick, true); Layer.addeventlistener (' Touchstart ', This.ontouchstart, false); Layer.addeventlistener (' Touchmove ', This.ontouchmove, false); Layer.addeventlistener (' Touchend ', this.ontouchend, false); Layer.addeventlistener (' Touchcancel ', This.ontouchcancel, false); if (! Event.prototype.stopImmediatePropagation) {Layer.removeeventlistener = function (type, callback, capture) {var RMV = N   Ode.prototype.removeEventListener;   if (type = = = ' click ') { (layer, type, callback.hijacked | | callback, capture);   } else { (layer, type, callback, capture);  }  };   Layer.addeventlistener = function (type, callback, capture) {var adv = Node.prototype.addEventListener; if (type = = = ' click ') { (layer, type, callback.hijacked | | (callback.hijacked = function (event) {if (!event.propagationstopped) {callback (event);   }), capture);   } else { (layer, type, callback, capture); }  };  } if (typeof Layer.onclick = = = ' function ') {Oldonclick = Layer.onclick;  Layer.addeventlistener (' click ', Function (event) {Oldonclick (event);  }, False); Layer.onclick = null; }}

Look at this code, many of the above attributes do what I do not know ... So I ignored the

if (!layer | |!layer.nodetype) {    throw new TypeError (' layer must be a document node ');

Here to note that we have to pass a node to the constructor, otherwise it will be a problem, and then this guy will have some basic mouse events registered in their own property method, specifically the dry god horse behind us, and in the back point there is a notneeded method:

fastclick.notneeded = function (layer) {' Use strict '; var metaviewport; if (typeof Window.ontouchstart = = = ' undefined ') { C1/>return true; } if ((/chrome\/[0-9]+/). Test (Navigator.useragent)) {  if (FastClick.prototype.deviceIsAndroid) {   Metaviewport = Document.queryselector (' meta[name=viewport] ');   if (Metaviewport && metaViewport.content.indexOf (' User-scalable=no ')!==-1) {    return true;   }  } else {   return true;}  if ( = = = ' None ') {  return true;} return false;};

This method is used to determine if you need to use the Fastclick, the meaning of the note is not quite clear, let's look at the code, the first sentence:

if (typeof Window.ontouchstart = = = ' undefined ') {    return true;}

Returns true if the Touchstart event is not supported.

PS: Now just feel is fastclick should also be a touch event simulation, but it does not point through the problem, the back also judged some of the problems of Android, I do not pay attention here, meaning should be supported by touch to support it, so back to the skeleton code, skeleton code, We see that if the browser does not support touch events or other problems just jump out, and then there is a deviceisandroid attribute, we go to see (actually do not see and know whether it is the Android device)

FastClick.prototype.deviceIsAndroid = navigator.userAgent.indexOf (' Android ') > 0;
Binding events

Okay, this guy's starting to bind the registration event, so far.

if (this.deviceisandroid) {    layer.addeventlistener (' mouseover ', this.onmouse, true);    Layer.addeventlistener (' MouseDown ', this.onmouse, true);    Layer.addeventlistener (' MouseUp ', this.onmouse, true);} Layer.addeventlistener (' Click ', This.onclick, True); Layer.addeventlistener (' Touchstart ', This.ontouchstart, False) ; Layer.addeventlistener (' Touchmove ', This.ontouchmove, false); Layer.addeventlistener (' Touchend ', This.ontouchend, FALSE); Layer.addeventlistener (' Touchcancel ', This.ontouchcancel, false);

The specific event function is rewritten in the front, and we don't care about him for the time being, just keep looking back (say, this guy has a lot of events to bind to)


It's over. One property:

Blocks the bubbling behavior of the current event and prevents the continuation of event handlers for all the same type events on the element that is currently on the event.

If an element has more than one event listener function of the same type of event, multiple event listener functions are executed sequentially when the event of that type is triggered. If a listener function executes the event.stopimmediatepropagation () method, In addition to the event's bubbling behavior being blocked (the role of the Event.stoppropagation method), the execution of the listener function for the remaining same type of event that the element binds is also blocked.

if (! Event.prototype.stopImmediatePropagation) {Layer.removeeventlistener = function (type, callback, capture) {  var RMV = Node.prototype.removeEventListener;  if (type = = = ' click ') { (layer, type, callback.hijacked | | callback, capture);  } else { (Laye R, type, callback, capture);  } }; Layer.addeventlistener = function (type, callback, capture) {  var adv = Node.prototype.addEventListener;  if (type = = = ' click ') { (layer, type, callback.hijacked | | (callback.hijacked = function (event) {    if (!event.propagationstopped) {     callback (event);    }   }), capture);  } else { (layer, type, callback, capture);}}  ;}

And then this guy redefined the method of registering and Unregistering events, and we first look at the registration event, which uses node's AddEventListener, what is this node? From this point of view, node is a system attribute that represents our node bar, so here we rewrite the logout event here, we found that in fact he only had a special deal on the click (layer, type, callback.hijacked | | (callback.hijacked = function (event) {    if (!event.propagationstopped) {        callback (event);    }}), capture);

One of the hijacked hijacking is a dry God horse is not known for a while, it is estimated that in the middle whether to rewrite the meaning of it, and then rewrite it here, hijacked estimate is a method, is to prevent the registration of multiple events on a DOM multiple executions of the situation exists.

Logout and registration almost we do not care, to this we actually rewrite our incoming DOM registration logoff event, as if it is very powerful appearance, meaning after this DOM call Click event with our, of course, this is only my temporary judgment, specifically to read down, and I think the current judgment is not reliable, So let's go ahead.

We can use AddEventListener or dom.onclick=function () {} When we unregister the event, so here's the following code:

if (typeof Layer.onclick = = = ' function ') {Oldonclick = Layer.onclick; Layer.addeventlistener (' Click ', Function (event) { C3/>oldonclick (event); }, False); Layer.onclick = null;}

Here, his main process is actually finished, meaning that all his logic is here, regardless of the entrance or exit should be the event registration, so we write a code to see.

Test Portal
<input type= "button" id= "Addevent" value= "addevent" ><input type= "button" id= "AddEvent1" value= "Addevent1" >$ (' #addEvent '). Click (function () {    var dom = $ (' #addEvent1 ') [0]    dom.addeventlistener (' click ', Function () {        alert (')        var s = ';})    });

Let's take a look at this breakpoint and see what we have done after clicking, we now click Button 1 to register the event for Button 2:

But unfortunately, we can not test on the computer, so increase the difficulty we read the code, after testing on the phone, found that the button 2 response quickly, but there is a bit of a look at the problem, the last alert one! Event.prototype.stopImmediatePropagation found that both the phone and the computer were false, so the things we did on top of it were temporarily useless.

FastClick.prototype.onClick = function (event) {    ' use strict ';    var permitted;    Alert (' finally coming in ');    if (This.trackingclick) {        this.targetelement = null;        This.trackingclick = false;        return true;    }    if ( = = = ' Submit ' && event.detail = = = 0) {        return true;    }    permitted = This.onmouse (event);    if (!permitted) {        this.targetelement = null;    }    return permitted;};

And then we finally came in, and now we need to know what a trackingclick is.

This.trackingclick = false;

We initially this property is false, but here is set to True, the direct exit, indicating that the binding event terminates, forget this we do not care, we do something else,
Because, I think the focus should be on the touch event.

PS: Here we find that this library should not only speed up the click, but all of the responses are accelerated

I am in the various Events section log out of things, found that there is a click of the place are only executed Touchstart and touchend, so far, I think my point of view is set up
He uses the touch event analog Click, so we'll just follow up on this one:

FastClick.prototype.onTouchStart = function (event) {' Use strict ';    var targetelement, touch, selection;    Log (' Touchstart ');    if (Event.targetTouches.length > 1) {return true;    } targetelement = This.gettargetelementfromeventtarget (;    touch = event.targettouches[0];        if (This.deviceisios) {selection = Window.getselection ();        if (Selection.rangecount &&!selection.iscollapsed) {return true; } if (!this.deviceisios4) {if (Touch.identifier = = = This.lasttouchidentifier) {EVENT.PR                Eventdefault ();            return false;            } this.lasttouchidentifier = Touch.identifier;        This.updatescrollparent (targetelement);    }} This.trackingclick = true;    This.trackingclickstart = Event.timestamp;    This.targetelement = targetelement;    This.touchstartx = Touch.pagex;    This.touchstarty = Touch.pagey; if ((EVENT.TIMESTAMP-THIS.LASTCLIcktime) < () {event.preventdefault (); } return true;};

One method is used:

FastClick.prototype.getTargetElementFromEventTarget = function (eventtarget) {    ' use strict ';    if (Eventtarget.nodetype = = = Node.text_node) {        return eventtarget.parentnode;    }    return eventtarget;};

He's the element that gets our current touchstart.

Then the mouse information recorded down, he recorded the mouse information is mainly in the back of the touchend time according to X, Y to determine whether the click, is the iOS case also engaged in some things, I jumped here, and then here to record some things on the jump out, no special things, Now we are entering our export touchend.

FastClick.prototype.onTouchEnd = function (event) {' Use strict ';    var forelement, Trackingclickstart, Targettagname, Scrollparent, touch, targetelement = this.targetelement;    Log (' Touchend ');    if (!this.trackingclick) {return true;        } if ((Event.timestamp-this.lastclicktime) < $) {This.cancelnextclick = true;    return true;    } this.lastclicktime = Event.timestamp;    Trackingclickstart = This.trackingclickstart;    This.trackingclick = false;    This.trackingclickstart = 0;        if (this.deviceisioswithbadtarget) {touch = event.changedtouches[0]; Targetelement = Document.elementfrompoint (Touch.pagex-window.pagexoffset, touch.pagey-window.pageyoffset) | |        Targetelement;    Targetelement.fastclickscrollparent = this.targetElement.fastClickScrollParent;    } targettagname = TargetElement.tagName.toLowerCase ();        if (targettagname = = = ' label ') {forelement = This.findcontrol (targetelement); if (forelement) {This.focus (targetelement);            if (this.deviceisandroid) {return false;        } targetelement = Forelement; }} else if (This.needsfocus (targetelement)) {if ((event.timestamp-trackingclickstart) > 100 | | (This.deviceisios &&!== window && targettagname = = = ' input '))            {this.targetelement = null;        return false;        } this.focus (Targetelement);            if (!this.deviceisios4 | | targettagname!== ' SELECT ') {this.targetelement = null;        Event.preventdefault ();    } return false;        } if (This.deviceisios &&!this.deviceisios4) {scrollparent = targetelement.fastclickscrollparent;        if (scrollparent && scrollparent.fastclicklastscrolltop!== scrollparent.scrolltop) {return true;        }} if (!this.needsclick (targetelement)) {Event.preventdefault (); This.sendclick (Targetelement, event); } return false;};

This guy voluminous done a lot of things, here to correct a mistake, he onclick those things are now also carried out ... It may be that my screen has changed (sliding) caused.

if ((Event.timestamp-this.lastclicktime) <) {    This.cancelnextclick = true;    return true;}

This code is very important, we first click will execute the following logic, if the continuous click on the straight end, the following logic ya do not execute, this does not execute, then this unwinnable and do what things? In fact, there is no logic, meaning if you do click too fast, two clicks will only be executed once, this threshold is 200ms, this temporarily seems to be no problem

Well, we went on, so I realized that there was another key point, because we didn't use the tap event to get the focus, but Fastclick got the focus, and here's a key, so let's look at a couple of functions related to getting focus.

FastClick.prototype.focus = function (targetelement) {    ' use strict ';    var length;    if (This.deviceisios && targetelement.setselectionrange) {        length = targetElement.value.length;        Targetelement.setselectionrange (length, length);    } else {        targetelement.focus ();    }};

Setselectionrange is the key to us, maybe he gets the focus ... I also want to come down to test, leave the next deal, and then if the time interval is too long, the code does not think that the operation is the same DOM structure, and finally ushered in the key: Sendclick, whether it is touchend or onmouse will converge here.

FastClick.prototype.sendClick = function (Targetelement, event) {    ' use strict ';    var clickevent, touch;    On some Android devices activeelement needs to be blurred otherwise the synthetic click would have no effect (#24)    I F (document.activeelement && document.activeelement!== targetelement) {        document.activeElement.blur ();    }    touch = event.changedtouches[0];    Synthesise A click event, with the extra attribute so it can be tracked    clickevent = document.createevent (' Mouseeven TS ');    Clickevent.initmouseevent (' Click ', True, true, window, 1, Touch.screenx, Touch.screeny, Touch.clientx, Touch.clienty, False, False, False, FALSE, 0, null);    Clickevent.forwardedtouchevent = true;    Targetelement.dispatchevent (clickevent);};

He creates a mouse event and then dispatchevent the event (this is similar to fireevent)

The document is bound to a custom event Ondataavailabledocument.addeventlistener (' ondataavailable ', function (event) {alert ( Event.eventtype), var obj = document.getElementById ("obj"),//obj element bind click event Obj.addeventlistener (' click ', function (event) {alert (event.eventtype);}, false);//Call the CreateEvent method of the Document object to get an object instance of the event. var event = document.createevent (' htmlevents ');//Initevent accepts 3 parameters://Event type, whether bubbling, whether to block the default behavior of the browser event.initevent (" OnDataAvailable ", True, true); event.eventtype = ' message ';// Trigger the custom event ondataavailabledocument.dispatchevent that the document is bound to (event); var event1 = document.createevent (' htmlevents '); Event1.initevent ("Click", True, true); event1.eventtype = ' message ';//trigger obj element bind Click event document.getElementById (" Test "). onclick = function () {obj.dispatchevent (event1);};

At this point, we know that we have first bound the mouse event for the DOM, and then touchend the time to trigger, and as to why itself registered click does not trigger to go back to the above code to solve the "dot" (results) with this idea, let's try our abstract code:

<! DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 transitional//en" "Http:// "> 

Then the Fastclick processing comparison is basically consistent with the zepto, but different

    1. Fastclick is to bind an event to the element you pass (typically Document.body)

② The Click event of the DOM element is manually triggered after the Touchstart and Touchend (will manually get the current click el) If the class click event

So the Click event is triggered at Touchend and the entire response speed is up, triggering the actual zepto tap.

Well, why is it that the same code is zepto and Fastclick not?

The reason is that there is a settimeout in Zepto code, and even E.preventdefault () is not useful in this code.

This is the fundamental difference, because settimeout will have a lower priority

With a timer, when the code executes to settimeout, it puts the code on the last side of the JS engine.

And our code will immediately detect the E.preventdefault, once joined Settimeout,e.preventdefault will not take effect, this is the root cause of Zepto point penetration.


Completely solve tap (TAP) Boost Mobile click Response speed

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.