AngularJS: ngTouch 300ms Delay
Asked Answered
J

3

23

This Plunkr has 2 links. The one on the left side is using the ng-click directive with the on angular-touch module inserted. As said in the angular touch module description for ng-click, the ng-click link should not have a 300ms delay. But if you test it on mobile devices, this is still the case.

So is plunkr preventing the correct functionality because its executed in an iFrame or something like that or is it required to insert Fastclick.js into the project for the directive to work correctly ? I don't get it, please help.

Example: http://plnkr.co/NRRrmMFaIKg2zLu5C1Tg

edit: the example in the angularjs docs ist not working either. They didn't even inserted the angular-touch module.

Joannejoannes answered 21/12, 2013 at 10:32 Comment(3)
So apparently this ist still an issue since angular 1.2.0 which is not solved yet. Luckily you can just insert fastclick.js for the good and every ng-click will trigger fast then. You simply add the fastclick.js file to your project and insert their bootstrap code outside of any angular. FYI I've edited the plunkr from the example to test performance between some fastclick methods. It seems that the ng-click directive recognizes the least clicks, if clicked frequently test.Joannejoannes
Hey!.. did you find a solution to this problem?Krusche
@Krusche Because of the restrictions of ngTouch , which only removes 300ms delay on the ng-click directive, I'm using fastclick.js now. The problem I had is that I instantiated Fastclick before the its Library was loaded. Therefore it was not working. Wrapping it in angular.run() solved my problem, by instantiating fastlick when the DOM an Angular is ready.Joannejoannes
J
56

Because angulars ngTouch module is only removing the 300ms delay on ng-click directives, i'm using fastclick.js now which harmonates perfectly fine with angular.

At the beginning it did not work for me, because I attached the Fastclick library before its script was loaded, before the DOM was ready. I fixed this by wrapping the function in the run block of my angular app. This function executes code after the DOM is ready.

angular.module('myModule', []).
  run(function() {
    FastClick.attach(document.body);
  });

This way is suggested by the latest screencast on the angularjs youtube channel.

Joannejoannes answered 14/1, 2014 at 12:24 Comment(4)
What's the timestamp for when he mentions that? I tried fast forwarding through the videoJustinjustina
@Justinjustina youtu.be/xOAG7Ab_Oz0?t=20m48s just watch it for about 1 minute in and you'll see it ;)Joannejoannes
@Pascalius what do you mean with angular tooltip ? do you mean the tooltip directive from the angular-ui-bootstrap module ? or what do you mean ?Joannejoannes
Yes the angular-ui-bootstrap tooltip. It works, when tooltip-trigger="click" is addedFotinas
L
0

I've solved this by writing my own directive that listens for both touchstart and mousedown events (or touchend / mouseup, etc.). To de-dupe, I set a flag when a touch event happens, and if the flag is set I ignored all mouse events (since touch events happen before mouse events, not de-duping would result in double fires on mobile devices).

appControllers.controller('AppCtrl', ['$scope',
 function($scope) {
  $scope._usingTouch = false;
  /* app code */
}]).directive('lkClick', [function() {
  return function(scope, element, attr) {
    var fn = function() {
      scope.$apply(function() { 
          scope.$eval(attr.lkClick); 
        });
    }

    element.on('touchstart', function(event) {
        scope._usingTouch = true;
        lk();
    });

    element.on('mousedown', function(event) {
      if(!scope._usingTouch)
        lk();
    });
  };
}]);

Then you can add the lk-click="javascript()" directive in your app's html.

Using Fastclick is easier and quicker, but this is more customizable and doesn't require you to load Fastclick code.

Larynx answered 26/12, 2014 at 5:57 Comment(1)
It should work fine, but you have to unsubscribe from events on scope destroy, otherwise you will have the memory leaks in you app. Simply use element.off(<event>).Glossitis
V
0
   // Evita doble tap en dispositivos mobiles
    var TIME_BETWEEN_CLICK = 0;
    App.directive('ngSubmit', function () {
      return {
        restrict: 'A',
        replace: false,
        link: function (scope, el, attrs) {
          el.bind('submit', function (e) {
            if ((new Date().getTime() - TIME_BETWEEN_CLICK) > 300) {
              TIME_BETWEEN_CLICK = new Date().getTime();
            } else {
              e.stopImmediatePropagation();
            }
          });
        }
      };
    });

    App.directive('ngClick', function () {
      return {
        restrict: 'A',
        replace: false,
        link: function (scope, el) {
          el.bind('click', function (e) {
            if ((new Date().getTime() - TIME_BETWEEN_CLICK) > 300) {
              TIME_BETWEEN_CLICK = new Date().getTime();
            } else {
              e.stopImmediatePropagation();
            }
          });
        }
      };
    });
Valarievalda answered 18/5, 2018 at 22:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.