-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Bypass click/mouse handlers for any contenteditable elements #9491
Conversation
Fixes issues 9414 and 5937. I can't see any reason why ngMaterial would need to hijack clicks for elements that have contenteditable attribute set.
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed, please reply here (e.g.
|
1 similar comment
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed, please reply here (e.g.
|
I signed it! |
I signed it! |
CLAs look good, thanks! |
1 similar comment
CLAs look good, thanks! |
Pending/related to HammerJS efforts. |
@hanthomas - please add 1 or more unit tests. |
@ThomasBurleson - Unit tests have been added to gesture.spec.js. |
// Click tests should only be enabled when `$$hijackClicks == true` (for mobile) | ||
|
||
it('should not hijack click on contenteditable element', inject(function($document, $mdGesture) { | ||
if ( $mdGesture.$$hijackClicks ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does this property exist? Never saw this one in our gesture service.
Also the tests should enable hijacking by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... you're right. I used one of the existing tests as a template, but apparently that property no longer exists. I'll make the correction.
})); | ||
|
||
it('should not hijack mousedown/mouseup on contenteditable element', inject(function($document, $mdGesture) { | ||
if ( $mdGesture.$$hijackClicks ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See reply to previous comment
var spy2 = jasmine.createSpy('mouseup'); | ||
var el = angular.element('<div contenteditable>'); | ||
|
||
el.on('mousedown', spy1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where do you actually trigger the event? The tests seem to pass because you created that $$hijackClicks
check, which always doesn't pass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. So, once I take that condition out, it should pass if the mousedown and mouseup handlers are triggered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it gets more difficult for this tests.
You need the element you want to trigger the mouse event on to the document.body
to be able to test it with $mdGesture
.
Then you need to dispatch a fake mouse event and determine if the triggered event from the event handlers is the same as the fake mouse event.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right... plus, now the tests fail. So, it looks like I have some work to do on this. Thanks for the explanation.
@devversion - It took a few tries, but I think the unit tests are correct now. My basic approach was to make sure that ngMaterial allows the mouse events to be processed by the handler attached to the element instead of the click hijacker. |
var el; | ||
|
||
beforeEach(function() { | ||
inject(function($mdGesture) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can simplify this
beforeEach(inject(function($mdGesture) {
}));
}); | ||
|
||
it('should not hijack click on contenteditable element', inject(function($document, $mdGesture) { | ||
$document.triggerHandler('$$mdGestureReset'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this to the beforeEach
, since you are repeating it for each test
|
||
el.triggerHandler('click'); | ||
|
||
expect(spyClick).toHaveBeenCalled(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't those checks also check for the event to not being prevented.
// Something like this
var event = spyClick.calls.mostRecent().args[0];
bool = event.defaultPrevented
I will close that PR for now, because this is not a high priority on our queue right now, because it is planned to get rid of the Anyways, Thanks for the PR! |
This issue also affects regular elements when using angular-material for other elements on the same page. Using this code fixes it: function mouseInputHijacker(ev) { var isKeyClick = !ev.clientX && !ev.clientY; if (!isKeyClick && !ev.$material && !ev.isIonicTap && !isInputEventFromLabelClick(ev) && !ev.target.nodeName === 'SELECT') { ev.preventDefault(); ev.stopPropagation(); } } Would be good to have a directive to disable click hijacking on specific elements |
Fixes issues #9414 and #5937. I can't see any reason why ngMaterial would need to hijack clicks for elements that have contenteditable attribute set.