Leave alone freeze events used for target descendants

I have a (home) table with multiple physical rows that has a lot of logical rows that I want to scroll (also) using the keyboard. In case of concentration of the descendant who understands the key, I want the event to be processed by the descendant and ignored by my table.

Perhaps the code makes it clear:

scroll.keydown = function(e) { if (e.shiftKey | e.controlKey | e.altKey) return; var isText = e.target.type === "text"; var K = $.ui.keyCode; switch (e.keyCode) { case K.HOME: if (isText) return; scroll.move(-1000000); break; case K.END: if (isText) return; scroll.move(+1000000); break; case K.PAGE_UP: scroll.move(-10); break; case K.PAGE_DOWN: scroll.move(+10); break; case K.UP: scroll.move(-1); break; case K.DOWN: scroll.move(+1); break; default: return; } e.preventDefault(); }; <table tabindex="0" ng-keydown="scroll.keydown($event)" ...> ... <input ...> 

This works fine, but it is very stupid: the table knows that it contains input elements, and knows that such an element can use, for example, the HOME key, so it does a test to leave it alone.

This is very wrong. Now I have added select , which will require a similar test in the case of DOWN for it to work.

Funny, there is another ng-keydown component inside my table that handles events in a very similar way, but no problem:

  • When I press DOWN while my internal component is focused, it hits the event first, and everything is fine.
  • When I press DOWN and select focuses, my table first receives the event and scrolls. Instead, I want the choice to be open, as usual.

Tested in chrome version 60.0.3112.113 using angle symbols v1.5.0 and 1.12.1.

Plunkr

http://plnkr.co/edit/nr2JVJU1U16465F1WKkC?p=preview

Explanation

  • Any event that is meaningless for the current focused child must be handled by the table.
  • For example, PAGE_UP means nothing for input , so you need to scroll through the table even if the focused child handles some other events, for example, HOME .
  • This is why I added if (isText) return; in HOME and END only those that are useful in input , and not for other keys that are not.
+5
source share
1 answer

I took the code of your plunkr and made a very small change to help you get what you wanted.

At the very top of your $ scope.keydown function, I added a condition that checks if the target is input or selected, and then ignores scrolling.

This works with the nodeName property, like this (check the function $ scope.keydown ):

 var app = angular.module('plunker', []); app.controller('MainCtrl', function($scope) { $scope.name = 'World'; var data = []; for (var i = 0; i < 10000; ++i) data.push({ id: i, value: i * i }); var scroll = $scope.scroll = { start: 0, limit: 10, move: function(delta) { var start = scroll.start + delta; start = Math.max(start, 0); start = Math.min(start, data.length - scroll.limit); scroll.start = start; }, keydown: function(e) { // With the e.target.nodeName you can // can check if the keydown is being // triggered from the input or the select // and then avoid the table scroll if(e.target.nodeName === 'INPUT' || e.target.nodeName === 'SELECT') { return false; } if (e.shiftKey | e.controlKey | e.altKey) return; var isText = e.target.type === "text"; var K = $.ui.keyCode; switch (e.keyCode) { case K.HOME: if (isText) return; scroll.move(-1000000); break; case K.END: if (isText) return; scroll.move(+1000000); break; case K.PAGE_UP: scroll.move(-10); break; case K.PAGE_DOWN: scroll.move(+10); break; case K.UP: scroll.move(-1); break; case K.DOWN: scroll.move(+1); break; default: return; } e.preventDefault(); }, }; $scope.visibleData = []; $scope.$watchCollection("scroll", function() { for (var i = 0; i < scroll.limit; ++i) { $scope.visibleData[i] = data[i + scroll.start]; } }); }); 
 table:focus { border: 1px solid red; } table { border: 1px dotted blue; } 
 <!DOCTYPE html> <html ng-app="plunker"> <head> <meta charset="utf-8" /> <title>AngularJS Plunker</title> <script> document.write('<base href="' + document.location + '" />'); </script> <link rel="stylesheet" href="style.css" /> <script data-require=" angular.js@1.5.x " src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script> <script data-require=" jquery@3.0.0 " data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script> <script data-require=" jquery-ui@1.10.4 " data-semver="1.10.4" src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script> <script src="app.js"></script> </head> <body ng-controller="MainCtrl"> <ul> <li>Click in the input</li> <li>Press Shift-Tab</li> <li>Observe thar arrow-up and down control the outer select.</li> <li>Pres Tabl twice</li> <li>Observe that the the arrows scroll the table instead!</li> </ul> <select name="outer"> <option>first</option> <option>second</option> </select> <table tabindex="1" ng-keydown="scroll.keydown($event)"> <tr> <td> <input name="unused"> </td> <td> <select name="select"> <option>first</option> <option>second</option> </select> </td> </tr> <tr> <th>row</th> <th>value</th> </tr> <tr ng-repeat="x in visibleData"> <td>{{x.id}}</td> <td>{{x.value}}</td> </tr> </table> </body> </html> 
0
source

Source: https://habr.com/ru/post/1271462/


All Articles