diff options
| -rw-r--r-- | src/ngTouch/directive/ngClick.js | 16 | ||||
| -rw-r--r-- | test/ngTouch/directive/ngClickSpec.js | 106 | 
2 files changed, 98 insertions, 24 deletions
| diff --git a/src/ngTouch/directive/ngClick.js b/src/ngTouch/directive/ngClick.js index 6cd0ff76..7e558def 100644 --- a/src/ngTouch/directive/ngClick.js +++ b/src/ngTouch/directive/ngClick.js @@ -53,6 +53,7 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',    var ACTIVE_CLASS_NAME = 'ng-click-active';    var lastPreventedTime;    var touchCoordinates; +  var lastLabelClickCoordinates;    // TAP EVENTS AND GHOST CLICKS @@ -124,10 +125,23 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',      var y = touches[0].clientY;      // Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label      // and on the input element). Depending on the exact browser, this second click we don't want -    // to bust has either (0,0) or negative coordinates. +    // to bust has either (0,0), negative coordinates, or coordinates equal to triggering label +    // click event      if (x < 1 && y < 1) {        return; // offscreen      } +    if (lastLabelClickCoordinates && +        lastLabelClickCoordinates[0] === x && lastLabelClickCoordinates[1] === y) { +      return; // input click triggered by label click +    } +    // reset label click coordinates on first subsequent click +    if (lastLabelClickCoordinates) { +      lastLabelClickCoordinates = null; +    } +    // remember label click coordinates to prevent click busting of trigger click event on input +    if (event.target.tagName.toLowerCase() === 'label') { +      lastLabelClickCoordinates = [x, y]; +    }      // Look for an allowable region containing this click.      // If we find one, that means it was created by touchstart and not removed by diff --git a/test/ngTouch/directive/ngClickSpec.js b/test/ngTouch/directive/ngClickSpec.js index 43735709..921c6457 100644 --- a/test/ngTouch/directive/ngClickSpec.js +++ b/test/ngTouch/directive/ngClickSpec.js @@ -370,40 +370,100 @@ describe('ngClick (touch)', function() {      })); -    it('should not cancel clicks that come long after', inject(function($rootScope, $compile) { -      element1 = $compile('<div ng-click="count = count + 1"></div>')($rootScope); +    describe('when clicking on a label immediately following a touch event', function() { +      var touch = function(element, x, y) { +        time = 10; +        browserTrigger(element, 'touchstart',{ +          keys: [], +          x: x, +          y: y +        }); -      $rootScope.count = 0; +        time = 50; +        browserTrigger(element, 'touchend',{ +          keys: [], +          x: x, +          y: y +        }); +      }; -      $rootScope.$digest(); +      var click = function(element, x, y) { +        browserTrigger(element, 'click',{ +          keys: [], +          x: x, +          y: y +        }); +      }; -      expect($rootScope.count).toBe(0); +      var $rootScope; +      var container, otherElement, input, label; +      beforeEach(inject(function(_$rootScope_, $compile, $rootElement) { +        $rootScope = _$rootScope_; +        var container = $compile('<div><div ng-click="count = count + 1"></div>' + +          '<input id="input1" type="radio" ng-model="selection" value="radio1">' + +          '<label for="input1">Input1</label></div>')($rootScope); +        $rootElement.append(container); +        otherElement = container.children()[0]; +        input = container.children()[1]; +        label = container.children()[2]; -      time = 10; -      browserTrigger(element1, 'touchstart',{ -        keys: [], -        x: 10, -        y: 10 +        $rootScope.selection = 'initial'; + +        $rootScope.$digest(); +      })); + + +      afterEach(function() { +        dealoc(label); +        dealoc(input); +        dealoc(otherElement); +        dealoc(container);        }); -      time = 50; -      browserTrigger(element1, 'touchend',{ -        keys: [], -        x: 10, -        y: 10 + +      it('should not cancel input clicks with (0,0) coordinates', function() { +        touch(otherElement, 100, 100); + +        time = 500; +        click(label, 10, 10); +        click(input, 0, 0); + +        expect($rootScope.selection).toBe('radio1');        }); -      expect($rootScope.count).toBe(1); -      time = 2700; -      browserTrigger(element1, 'click',{ -        keys: [], -        x: 10, -        y: 10 +      it('should not cancel input clicks with negative coordinates', function() { +        touch(otherElement, 100, 100); + +        time = 500; +        click(label, 10, 10); +        click(input, -1, -1); + +        expect($rootScope.selection).toBe('radio1');        }); -      expect($rootScope.count).toBe(2); -    })); + +      it('should not cancel input clicks with positive coordinates identical to label click', function() { +        touch(otherElement, 100, 100); + +        time = 500; +        click(label, 10, 10); +        click(input, 10, 10); + +        expect($rootScope.selection).toBe('radio1'); +      }); + + +      it('should cancel input clicks with positive coordinates different than label click', function() { +        touch(otherElement, 100, 100); + +        time = 500; +        click(label, 10, 10); +        click(input, 11, 11); + +        expect($rootScope.selection).toBe('initial'); +      }); +    });    }); | 
