8

I have a stack of <DIV> siblings and I want to let the user use the up and down arrows to move up and down the list and "highlight" an item. Only one item should be highlighted at any given moment.

What's the easiest way to do this?

Hussein
  • 42,480
  • 25
  • 113
  • 143
dan
  • 43,914
  • 47
  • 153
  • 254
  • 3
    And what would your html look like? The View Source html, not a description of it. And what've you already tried, and what went wrong? – David Thomas Mar 14 '11 at 20:26
  • @david The question is very clear without the need to provide an html source. – Hussein Mar 14 '11 at 21:00
  • @Hussein: and the part about what has he already tried, and what went wrong..? His HTML is implied, it's not specified. And while the description is relatively clear, it's not exactly reproducible without some guesswork. – David Thomas Mar 14 '11 at 21:02

4 Answers4

12
$(document).keyup(function(e) {
    var $hlight = $('div.hlight'), $div = $('div');
    if (e.keyCode == 40) {
        $hlight.removeClass('hlight').next().addClass('hlight');
        if ($hlight.next().length == 0) {
            $div.eq(0).addClass('hlight')
        }
    } else if (e.keyCode === 38) {
        $hlight.removeClass('hlight').prev().addClass('hlight');
        if ($hlight.prev().length == 0) {
            $div.eq(-1).addClass('hlight')
        }
    }
})

Check working example at http://jsfiddle.net/wMdML/8/

Hussein
  • 42,480
  • 25
  • 113
  • 143
  • Wow, nicely done. I can't believe how long some of the answers are on here. – Pinkie Mar 14 '11 at 21:20
  • Can't get this work on Chrome actually. Also, what about traversing back to the first item after the last one? – pimvdb Mar 14 '11 at 21:21
  • Chrome doesn't look like it works well with keypress. Just change keypress to keyup. `$(document).keyup(function(e) { ` I updated the answer. – Hussein Mar 14 '11 at 21:36
  • Thanks, but still, after the last one is selected, moving down causes it to be unable to be selected back. – pimvdb Mar 14 '11 at 21:44
2

OK...

var highlight = function(upOrDown){
    var highlighted = $("#daddyDiv > div.higlighted");

    if(highlighted[0] == null){
        //If nothing is highlighted, highlight the first child
        $("#daddyDiv > div:first").addClass("highlighted");
    } else {
        //Highlight the next thing
        if(upOrDown == "down" && highlighted.index() != $("#daddyDiv > div").length()){
            $("#daddyDiv > div").eq(highlighted.index()+1).addClass("highlighted");
            $("#daddyDiv > div.higlighted").removeClass("highlighted");
        } else if(upOrDown == "up" && highlighted.index() != 1){
            $("#daddyDiv > div").eq(highlighted.index()-1).addClass("highlighted");
            $("#daddyDiv > div.higlighted").removeClass("highlighted");
        }
    }
};

//Assuming you are using up/down buttons...

$("#upButton").click(function(){ highlight("up"); });
$("#downButton").click(function(){ highlight("down"); });

//Using the arrow keys...

$("body").keyup(function(e){
    if(e.keyCode == "40"){
        //Down key
        highlight("down");
    } else if(e.keyCode == "38"){
        //Up key
        highlight("down");
    }
});
mattsven
  • 22,305
  • 11
  • 68
  • 104
  • 1
    If the OP is talking about using the arrow *keys* then they should bind to the keyUp event and check the event.which to find out which key was pressed. – Blair McMillan Mar 14 '11 at 20:47
1

I made this up: http://jsfiddle.net/JPy76/.

It basically removes a highlighted class when moving up/down and adds it to the next/previous. Some extra code is necessary for moving down after the last one / moving up after the first one.

$('body').keydown(function(e) {
    if(e.keyCode === 40) {
        if($('.highlighted').next().length) {
            $('.highlighted').removeClass('highlighted')
            .next().addClass('highlighted');
        }
        else {
            $('.highlighted').removeClass('highlighted');
            var d = $('div');
            d.length = 1;
            d.addClass('highlighted');
        }
    }
    if(e.keyCode === 38) {
        if($('.highlighted').prev().length) {
            $('.highlighted').removeClass('highlighted')
            .prev().addClass('highlighted');
        }
        else {
            $('.highlighted').removeClass('highlighted');
            var d = $('div');
            d = $(d[d.length - 1]);
            d.addClass('highlighted');
        }
    }
});
pimvdb
  • 151,816
  • 78
  • 307
  • 352
1

Here's one way to do it without using IDs or classes. A working jsfiddle example is available here (make sure to click on the Result pane first).

The javascript:

var $currentDiv = $("#myContainer").children().first();
$currentDiv.css("background", "red");

$("html").keyup( function(keyEvent) {
    if (keyEvent.keyCode == 40 ) {
        var $nextDiv;
        if ($currentDiv.next().size() == 0) {
            $nextDiv = $("#myContainer").children().first();
        }
        else {
            $nextDiv = $currentDiv.next();
        }
        $currentDiv.css("background", "");
        $nextDiv.css("background", "red");
        console.log($nextDiv);
        console.log($currentDiv);
        $currentDiv = $nextDiv;

    }
    else if (keyEvent.keyCode == 38) {
        var $previousDiv;
        if ($currentDiv.prev().size() == 0)
            $previousDiv = $("#myContainer").children().last();
        else {
            $previousDiv = $currentDiv.prev();
        }
        $currentDiv.css("background", "");
        $previousDiv.css("background", "red");
        $currentDiv = $previousDiv;
    }
});

The html:

<div id="myContainer">
    <div> Div 1 </div>
    <div> Div 2 </div>
    <div> Div 3 </div>
    <div> Div 4 </div>
</div>
Adam Prax
  • 6,413
  • 3
  • 30
  • 31