admin管理员组文章数量:1420668
I have an angular.js webapp which use shortcuts. When I press any key, I get N keydown events, then N keyup events, where N is between 2 and 5, while I expect it to fire only once. Here is the code that I use to catch keyboard events:
// Controller.js
var allowed = true;
$document.bind('keyup', function (event) {
console.log('keyup');
allowed = true;
});
$document.bind('keydown', function (event) {
if (allowed) {
allowed = false;
var key = event.which || event.keyCode || event.charCode;
console.log('key down: ' + key);
if (key === 32) { // Space bar
$scope.showAll();
event.stopPropagation();
}
else if ($scope.visible.answerButtons === true) {
if (key === 37) { // Left arrow, wrong answer
$scope.session.addAnswer(false);
event.stopPropagation();
}
else if (key === 39) { // Right arrow, right answer
$scope.session.addAnswer(true);
event.stopPropagation();
}
}
if (!$scope.$$phase) { $scope.$apply(); }
}
});
The use of the allow variable does not work here since all keydown events are fired before keyup. The result when I press any key is:
"key down: 32"
"keyup"
"key down: 39" // I'm pressing the right arrow only once, and release it immediately
"key down: 39" // but it fires 3 times
"key down: 39"
"keyup"
"keyup"
"keyup"
Note that everything works fine the first time I display the page. The problem occurs when I display it again (reload the template and the controller, not refreshing the entire app using F5).
Any idea about why I get all these events after the first display ?
EDIT:
Okay, I got it, the reason why it fires multiple events after the first display is simply because angular does not remove event listeners on scope destruction. Therefore, old listeners are kept, so when I reload the page, I get several handlers for the same event, which do the same thing. So when I display the page N times, there is N handlers for keydown event.
The solution is to remove manually the handlers on $destroy event (keyboardManager can be found at the link Dave gave in his answer, you can use $document.unbind as well):
keyboardManager.bind('space', function () {
console.log('press space');
});
keyboardManager.bind('right', function () {
console.log('press right');;
});
keyboardManager.bind('left', function () {
console.log('press left');
});
$scope.$on('$destroy', function () {
keyboardManager.unbind('space');
keyboardManager.unbind('right');
keyboardManager.unbind('left');
});
I have an angular.js webapp which use shortcuts. When I press any key, I get N keydown events, then N keyup events, where N is between 2 and 5, while I expect it to fire only once. Here is the code that I use to catch keyboard events:
// Controller.js
var allowed = true;
$document.bind('keyup', function (event) {
console.log('keyup');
allowed = true;
});
$document.bind('keydown', function (event) {
if (allowed) {
allowed = false;
var key = event.which || event.keyCode || event.charCode;
console.log('key down: ' + key);
if (key === 32) { // Space bar
$scope.showAll();
event.stopPropagation();
}
else if ($scope.visible.answerButtons === true) {
if (key === 37) { // Left arrow, wrong answer
$scope.session.addAnswer(false);
event.stopPropagation();
}
else if (key === 39) { // Right arrow, right answer
$scope.session.addAnswer(true);
event.stopPropagation();
}
}
if (!$scope.$$phase) { $scope.$apply(); }
}
});
The use of the allow variable does not work here since all keydown events are fired before keyup. The result when I press any key is:
"key down: 32"
"keyup"
"key down: 39" // I'm pressing the right arrow only once, and release it immediately
"key down: 39" // but it fires 3 times
"key down: 39"
"keyup"
"keyup"
"keyup"
Note that everything works fine the first time I display the page. The problem occurs when I display it again (reload the template and the controller, not refreshing the entire app using F5).
Any idea about why I get all these events after the first display ?
EDIT:
Okay, I got it, the reason why it fires multiple events after the first display is simply because angular does not remove event listeners on scope destruction. Therefore, old listeners are kept, so when I reload the page, I get several handlers for the same event, which do the same thing. So when I display the page N times, there is N handlers for keydown event.
The solution is to remove manually the handlers on $destroy event (keyboardManager can be found at the link Dave gave in his answer, you can use $document.unbind as well):
keyboardManager.bind('space', function () {
console.log('press space');
});
keyboardManager.bind('right', function () {
console.log('press right');;
});
keyboardManager.bind('left', function () {
console.log('press left');
});
$scope.$on('$destroy', function () {
keyboardManager.unbind('space');
keyboardManager.unbind('right');
keyboardManager.unbind('left');
});
Share
Improve this question
edited Apr 30, 2014 at 12:35
Carl Levasseur
asked Apr 30, 2014 at 10:50
Carl LevasseurCarl Levasseur
4,7115 gold badges20 silver badges19 bronze badges
2
- did u tried event.preventDefault(); inside keydown event. – Dave Commented Apr 30, 2014 at 10:53
- I just tried it, but it doesn't solve the problem – Carl Levasseur Commented Apr 30, 2014 at 11:04
1 Answer
Reset to default 5Did you try event.stopImmediatePropagation() ? It solves this I think.
本文标签: javascriptkeydown fires multiple times before keyupStack Overflow
版权声明:本文标题:javascript - keydown fires multiple times before keyup - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745334701a2653984.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论