From 7e46857b7d6b6f2241f837a6c9db774e5f2ee98a Mon Sep 17 00:00:00 2001 From: Elad Bezalel Date: Wed, 7 Oct 2015 18:43:37 +0300 Subject: [PATCH] fix(mdDialog): Switched the click action to mouse down/up Changed the click event to mousedown and mouseup so we can save the origin element on mouse down and close on mouseup if the origin and the target is the backdrop fixes #3873 --- src/components/dialog/dialog.js | 26 ++++++-- src/components/dialog/dialog.spec.js | 96 ++++++++++++++++++++++++++-- 2 files changed, 111 insertions(+), 11 deletions(-) diff --git a/src/components/dialog/dialog.js b/src/components/dialog/dialog.js index 5c131ee53d5..22fbf5d5da1 100644 --- a/src/components/dialog/dialog.js +++ b/src/components/dialog/dialog.js @@ -648,9 +648,21 @@ function MdDialogProvider($$interimElementProvider) { } if (options.clickOutsideToClose) { var target = element; - var clickHandler = function(ev) { - // Only close if we click the flex container outside on the backdrop - if (ev.target === target[0]) { + var sourceElem; + + // Keep track of the element on which the mouse originally went down + // so that we can only close the backdrop when the 'click' started on it. + // A simple 'click' handler does not work, + // it sets the target object as the element the mouse went down on. + var mousedownHandler = function(ev) { + sourceElem = ev.target; + }; + + // We check if our original element and the target is the backdrop + // because if the original was the backdrop and the target was inside the dialog + // we don't want to dialog to close. + var mouseupHandler = function(ev) { + if (sourceElem === target[0] && ev.target === target[0]) { ev.stopPropagation(); ev.preventDefault(); @@ -658,12 +670,14 @@ function MdDialogProvider($$interimElementProvider) { } }; - // Add click listeners - target.on('click', clickHandler); + // Add listeners + target.on('mousedown', mousedownHandler); + target.on('mouseup', mouseupHandler); // Queue remove listeners function removeListeners.push(function() { - target.off('click', clickHandler); + target.off('mousedown', mousedownHandler); + target.off('mouseup', mouseupHandler); }); } diff --git a/src/components/dialog/dialog.spec.js b/src/components/dialog/dialog.spec.js index 2d434315e09..0bef54418cd 100644 --- a/src/components/dialog/dialog.spec.js +++ b/src/components/dialog/dialog.spec.js @@ -132,7 +132,7 @@ describe('$mdDialog', function() { expect($document.activeElement).toBe(parent[0].querySelector('md-dialog-content')); })); - it('should remove `md-dialog-container` on click and remove', inject(function($mdDialog, $rootScope, $timeout) { + it('should remove `md-dialog-container` on mousedown mouseup and remove', inject(function($mdDialog, $rootScope, $timeout) { jasmine.mockElementFocus(this); var container, parent = angular.element('
'); @@ -152,7 +152,11 @@ describe('$mdDialog', function() { container = angular.element(parent[0].querySelector('.md-dialog-container')); container.triggerHandler({ - type: 'click', + type: 'mousedown', + target: container[0] + }); + container.triggerHandler({ + type: 'mouseup', target: container[0] }); @@ -290,7 +294,7 @@ describe('$mdDialog', function() { expect($document.activeElement).toBe(parent[0].querySelector('.dialog-close')); })); - it('should remove `md-dialog-container` after click outside', inject(function($mdDialog, $rootScope, $timeout, $animate) { + it('should remove `md-dialog-container` after mousedown mouseup outside', inject(function($mdDialog, $rootScope, $timeout, $animate) { jasmine.mockElementFocus(this); var container, parent = angular.element('
'); @@ -311,7 +315,11 @@ describe('$mdDialog', function() { container = angular.element(parent[0].querySelector('.md-dialog-container')); container.triggerHandler({ - type: 'click', + type: 'mousedown', + target: container[0] + }); + container.triggerHandler({ + type: 'mouseup', target: container[0] }); @@ -322,6 +330,80 @@ describe('$mdDialog', function() { expect(container.length).toBe(0); })); + it('should not remove `md-dialog-container` after mousedown outside mouseup inside', inject(function($mdDialog, $rootScope, $timeout, $animate) { + jasmine.mockElementFocus(this); + var container, parent = angular.element('
'); + + $mdDialog.show( + $mdDialog.confirm({ + template: '' + + '' + + '

Muppets are the best

' + + '
' + + '
', + parent: parent, + clickOutsideToClose: true, + ok: 'OK', + cancel: 'CANCEL' + }) + ); + runAnimation(); + + container = angular.element(parent[0].querySelector('.md-dialog-container')); + var content = angular.element(parent[0].querySelector('md-dialog-content')); + container.triggerHandler({ + type: 'mousedown', + target: container[0] + }); + content.triggerHandler({ + type: 'mouseup', + target: content[0] + }); + + runAnimation(); + runAnimation(); + + container = angular.element(parent[0].querySelector('.md-dialog-container')); + expect(container.length).toBe(1); + })); + + it('should not remove `md-dialog-container` after mousedown inside mouseup outside', inject(function($mdDialog, $rootScope, $timeout, $animate) { + jasmine.mockElementFocus(this); + var container, parent = angular.element('
'); + + $mdDialog.show( + $mdDialog.confirm({ + template: '' + + '' + + '

Muppets are the best

' + + '
' + + '
', + parent: parent, + clickOutsideToClose: true, + ok: 'OK', + cancel: 'CANCEL' + }) + ); + runAnimation(); + + container = angular.element(parent[0].querySelector('.md-dialog-container')); + var content = angular.element(parent[0].querySelector('md-dialog-content')); + content.triggerHandler({ + type: 'mousedown', + target: content[0] + }); + container.triggerHandler({ + type: 'mouseup', + target: container[0] + }); + + runAnimation(); + runAnimation(); + + container = angular.element(parent[0].querySelector('.md-dialog-container')); + expect(container.length).toBe(1); + })); + it('should remove `md-dialog-container` after ESCAPE key', inject(function($mdDialog, $rootScope, $timeout, $mdConstant) { jasmine.mockElementFocus(this); var container, parent = angular.element('
'); @@ -569,7 +651,11 @@ describe('$mdDialog', function() { expect(parent.find('md-dialog').length).toBe(1); container.triggerHandler({ - type: 'click', + type: 'mousedown', + target: container[0] + }); + container.triggerHandler({ + type: 'mouseup', target: container[0] }); runAnimation();