Pregunta

I need to scroll on table rows using key up and key down . For that I need to capture key events on table div. If I replace 'keyup' with 'click' event, its working fine but same piece of code is not working for key up and key down. I am unable to figure out the issue.

$('#patientWL').on('keyup', '.bodyTable tbody tr', function(e) {
    if (e.keyCode == 38) {
        alert('key up');
    } else if (e.keyCode == 40) {
        alert('key down');
    }
});

Working fiddle of my problem can be seen here

¿Fue útil?

Solución

Please note that this is not a knockout specific problem. The problem is with the way elements handle keyup/down/press events.

A table (or tr, td) by default cannot be given focus. However, you can change that by adding a tabindex attribute:

<tr tabindex="0" id="example"></tr>

You can then give the tr focus, and also blur it with the hover event:

$("#example").hover(function() {
    this.focus();
}, function() {
    this.blur();
}).keydown(function(e) {
    alert(e.keyCode);
});

When the tr has focus, it will accept keyboard events. Look at a sample here.

Otros consejos

Although that's an old question, it's worth adding here a custom binding handler implementation (based on these posts: 1, 2):

ko.bindingHandlers.mapKeysToActions = {
    init: function (element, valueAccessor, allBindings, data) {
        var handler = function (data, event) {
            var keysAndActions = valueAccessor();
            if (Object.keys(keysAndActions).indexOf(event.keyCode.toString()) > -1) {
                keysAndActions[event.keyCode].call();
            };
        };
        var newValueAccessor = function () {
            return { keyup: handler };
        };
        ko.applyBindingAccessorsToNode(element, {
            event: newValueAccessor
        });
    }
};
var myModel = function () {
  var self = this;
  self.selectResult = function (item) {
    self.selectedResult(item);
  };
  self.setSelected = function ($data, $element) {
    var isSelected = self.selectedResult() == $data;
    if (isSelected) $($element).focus();
    return isSelected;
  };
  self.selectedResult = ko.observable();
  self.searchResults = ko.observableArray([
    { data1: "1", data2: "1" }, { data1: "2", data2: "2" }, { data1: "3", data2: "3" }
  ]);
  self.selectPrevious = function () {
    var index = self.searchResults().indexOf(self.selectedResult()) - 1;
    if (index < 0) index = 0;
    self.selectedResult(self.searchResults()[index]);
  };
  self.selectNext = function () {
    var index = self.searchResults().indexOf(self.selectedResult()) + 1;
    if (index >= self.searchResults().length) index = self.searchResults().length - 1;
    self.selectedResult(self.searchResults()[index]);
  };
  self.keysAndActions = {
    '38': self.selectPrevious,
    '40': self.selectNext
  };
};
ko.applyBindings(new myModel());
.btn-info {
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table>
  <thead>
    <tr>
	  <th>&nbsp;</th>
	  <th>table header 1</th>
	  <th>table header 2</th>
	</tr>
  </thead>
  <tbody data-bind="foreach: searchResults">
	<tr tabindex="0" 
        data-bind="click: $parent.selectResult, 
                   css: { 'btn-info': $parent.setSelected($data, $element) }, 
                   mapKeysToActions: $parent.keysAndActions">
	  <td data-bind="text: data1"></td>
	  <td data-bind="text: data2"></td>
	</tr>
  </tbody>
</table>

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top