views:

1102

answers:

5

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 behavior on Android.

Sometimes when I click on the link, instead of executing the action, it simply becomes selected/focused, with either just a focus rectangle or even also with a filled focus rectangle (selected as opposed to just focused?).

The pseudo-code right now is

<a href="#" onClick="toggleDivBelowToShowHide(); return false;">go</a>

I have tried doing something like:

<a href="#" onTouchStart="toggleDivBelowToShowHide(); return false;">go</a>

But I still get the same pesky problem some of the time.

A: 

Try getting rid of the href attribute and see if that helps. For example, this works when viewed with the WebView component:

<p><a onClick="whereami()">Update Location</a></p>
CommonsWare
I am sorry, that does not work for me -- it's still possible to "select" the link. I've also tried DIVs -- those are selectable too as long as they have an onClick attribute on them.
Artem
A: 

I wonder if it's related to the onclick -- am I correct to assume that every now and then clicking any link does not follow it? To me, this seems related to the way you touch the screen (or how this is interpreted), like maybe by clicking next to the link and dragging a bit, rather than clicking on the link?

(If my assumption is correct, then this might be faulty hardware: maybe you can try on another device? Or maybe it only happens on a particular side of the link if the screen is not aligned well, and then there might be some software offset one can change?)

Arjan
Sorry, we have many phones here -- it's not a hardware issue. It's somehow by the fact that you can select elements.
Artem
@Artem, but this never occurs for normal links? (Links without any `onclick`?)
Arjan
It is a lot harder to tell with normal links, because normal links usually leave the page, whereas this behavior requires clicking on it several times to get it to be selected. I will keep testing this.
Artem
A: 

Try enabling Javascript on the webview.

In the activity that holds the webview, try this...

WebView wv = (WebView) findViewById(R.id.webview);
wv.getSettings().setJavaScriptEnabled(true);

I was having he same problem, but figured out it was because I did not enabled Javascript.

Pulkit Sethi
A: 

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

Walt W
Very interesting solution... We had a bit more luck with all of this clicking by simply making a larger colored rectangle around the text... I would love to try your solution though when we get back to this.
Artem
Yeah, it works pretty well - I had to write the touch -> mouse events anyway in my app to get real-time information on dragging operations; I *should* have started with a mouse -> touch driver, and just written my app using the touch code, and will probably go that direction, but unfortunately I myself do not actually own a smartphone, so I started with mouse code.
Walt W
A: 

Ugh, I'm facing the same issue. Sometimes our onClick handlers are not being fired. When this happens, the orange "focus" border is stuck there or under the <canvas> image. If you unfocus by clicking on the surrounding page then scroll a bit and try to click the image again it almost always starts working...until it breaks again.

This is craziness, have people had luck with Walt W's driver script below? Any updates anyone can give me?

Rob Barreca