In Android Browser link does not always execute onClick causing focus instead

后端 未结 5 2212
梦如初夏
梦如初夏 2021-02-09 07:51

I am trying to program a very standard JS behavior for a link using an HREF onClick handler, and I am facing a strange problem caused by what I believe to be focus/touch mode be

5条回答
  •  醉梦人生
    2021-02-09 08:30

    Try inserting this "driver" into your page code, and let us know if it works . . . It seems to be working on my site which had the same problem:

    //Mouse & Touch -> Consistent Click / Mouse Commands -> Useful driver
    (function() {
      var isTouch = false;
      var simulated_flag = 'handler_simulated';
      var touch_click_array = {};
      const clickMoveThreshold = 20; //Pixels
    
      function mouseHandler(event) {
        if (isTouch) {
          if (!event.hasOwnProperty(simulated_flag)) {
            //Unreliable mouse commands - In my opinion
            var fixed = new jQuery.Event(event);
            fixed.preventDefault();
            fixed.stopPropagation();
          }
        }
        else {
          //Mouse commands are consistent
          //TODO: generate corresponding touches
        }
      }
    
      function mouseFromTouch(type, touch) {
        var event = document.createEvent("MouseEvent");
        event.initMouseEvent(type, true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY
          , false, false, false, false, 0, null);
        event[simulated_flag] = true;
    
        touch.target.dispatchEvent(event);
      };
    
      function touchHandler(event) {
        var touches = event.changedTouches
          ,first = touches[0]
          ,type = ""
          ;
    
        if (!event.hasOwnProperty(simulated_flag)) {
          isTouch = true;
    
          //Simulate mouse commands
          switch (event.type) {
            case "touchstart":
              for (var i = 0; i < touches.length; i++) {
                var touch = touches[i];
                touch_click_array[touch.identifier] = { x: touch.screenX, y: touch.screenY };
              }
              mouseFromTouch("mousedown", first);
              break;
    
            case "touchmove":
              for (var i = 0; i < touches.length; i++) {
                var touch = touches[i];
                var id = touch.identifier;
                var data = touch_click_array[id];
                if (data !== undefined) {
                  if (Math.abs(data.x - touch.screenX) + Math.abs(data.y - touch.screenY) > clickMoveThreshold) {
                    delete touch_click_array[id];
                  }
                }
              }
              mouseFromTouch("mousemove", first);
              break;
    
            case "touchcancel":
              //Not sure what should happen here . . .
              break;
    
            case "touchend":
              mouseFromTouch("mouseup", first);
              for (var i = 0; i < touches.length; i++) {
                var touch = touches[i];
                if (touch_click_array.hasOwnProperty(touch.identifier)) {
                  mouseFromTouch("click", touch);
                  delete touch_click_array[touch.identifier];
                }
              }
              break;
          }
        }
      }
    
      document.addEventListener("mousedown", mouseHandler, true);
      document.addEventListener("mousemove", mouseHandler, true);
      document.addEventListener("mouseup", mouseHandler, true);
      document.addEventListener("click", mouseHandler, true);
    
      document.addEventListener("touchstart", touchHandler, true);
      document.addEventListener("touchmove", touchHandler, true);
      document.addEventListener("touchcancel", touchHandler, true);
      document.addEventListener("touchend", touchHandler, true);
    
    })();
    

    Now it isn't a 100% complete script - multi-touch would probably be a little wonky, and if you built an interface depending on touch commands, it doesn't generate those in this version. But, it fixed my link-clicking problem.

    Erm - ps - it's using jQuery. If you need a non-jQuery version, you can probably just remove the new jQuery.Event from the mouseHandler() function (in other words, use the original event: var fixed = event;), and I believe most browsers would be ok. I am not exactly a js compatibility expert though.

    PPS - Tested with Android 1.6

    PPPS - Had to modify script to allow a threshold - actual devices were having some problems with a move event being fired during the press. Probably not ideal; if anyone wants to chime in on a better way for doing that, I'd be interested in hearing...

提交回复
热议问题