6

I'm displaying search results with a table. Each result has a button for user to click on to show the full detail of it. That's working well.

What I also want is to make it possible to navigat the search results by using keyboard's up and down arrow.

Now, user have to click on the Select button or tab to the button and press space bar.

I suppose I can trap the keyup and down event and then find the previous or next one I need to select and then set it, but it sounds like a lot of work. I wonder if there's a better way to do it?

javascript

var myModel = new function() {
    var self = this;

    self.selectedResult = ko.observable(new MyObj());
    self.searchResults = ko.observableArray();
    self.navUpDown = function (item, evt) {
        if (evt.keyCode == 38) { // up
            var id = item.ID();
            // find previous one and set selectedResult
        }

        if (evt.keyCode == 40) { // down
            var id = item.ID();
            // find next one and set selectedResult
        }
    };
};

html

<table class="table">
    <thead>
        <tr>
            <th>&nbsp;</th>
            <th>table header 1</th>
            <th>table header 2</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: searchResults">
        <tr data-bind="css: { 'btn-info': $parent.selectedResult() == $data }, event: { keyup: $parent.navUpDown } ">
            <td>
                <button class="btn btn-small" data-bind="click: $parent.selectResult">Select</button>
            </td>
            <td data-bind="text: data1"></td>
            <td data-bind="text: data2"></td>
        </tr>
    </tbody>
</table>
Ray Cheng
  • 12,230
  • 14
  • 74
  • 137
  • Finding the previous and next one shouldn't be hard at all. something like $(this).nextSibling() & $(this).prevSibling() should do what you need. – Johan Jun 06 '13 at 19:42

2 Answers2

3

I think this is what you are looking for.

var myModel = new function () {
        var self = this;
        self.selectResult = function (item) {
            self.selectedResult(item);
        };
        self.selectedResult = ko.observable();
        self.searchResults = ko.observableArray([{
            data1: "1",
            data2: "2"
        }, {
            data1: "2",
            data2: "2"
        }, {
            data1: "3",
            data2: "2"
        }]);


        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]);
        };


    };
ko.applyBindings(myModel);

$(window).keyup(function (evt) {
    if (evt.keyCode == 38) {
        myModel.selectPrevious();
    } else if (evt.keyCode == 40) {
        myModel.selectNext();
    }
});

See Fiddle

I hope it helps.

Damien
  • 8,889
  • 3
  • 32
  • 40
2

It's actually not that hard to find next and prev

For example

$(window).keyup(function (evt) {
    if (evt.keyCode == 38) { // up
       $('tbody tr:not(:first).selected').removeClass('selected').prev().addClass('selected')
    }
    if (evt.keyCode == 40) { // down
       $('tbody tr:not(:last).selected').removeClass('selected').next().addClass('selected')
    }
});

FIDDLE

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
Spokey
  • 10,974
  • 2
  • 28
  • 44