7

First of, I'd like to use only native JavaScript to complete this task.

Let's say I am to make a custom dropdown, and the HTML code looks kind of like this.

<div class="dropdown">
  <span class="dropdown-label" style="display:block">Select a thing</span>
  <ul class="dropdownItemContainer">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
    <li>Item 6</li>
  </ul>
</div>

In the CSS file I have something close to this:

ul.dropdownItemContainer li:hover {
  background-color: #FF0000;
}

Yeah, there's really no dropdownish behavior, but it's not the point of discussion actually. The problem is that I couldn't think of a decent way to enable keyboard control for this dropdown. The desired outcome is the following: I press the down key, and the first option is highlighted; I press it again, and the second option is highlighted and so on.

The only option that I see at this point (just started studying JS) is to fetch all of the ul's children, stick'em into an array and assign the tags a background color through JS methods in a proper way whenever the down key is pressed.

On the other hand, I still have the :hover behavior described in the CSS for mouse countrol. Is there a smart way of simulating hovers?

David
  • 8,340
  • 7
  • 49
  • 71
Anton Matyulkov
  • 722
  • 1
  • 7
  • 15

4 Answers4

8

I would go with a simple assignment of a class on your li-elements and steer it with a keydown handler. The following code is not meant to be complete but give you something you can work with.

var active = document.querySelector(".hover") || document.querySelector(".dropdownItemContainer li");

document.addEventListener("keydown",handler);
document.addEventListener("mouseover",handler);

function handler(e){
    console.log(e.which);
        active.classList.remove("hover");
    if (e.which == 40){
        active = active.nextElementSibling || active;
    }else if (e.which == 38){      
        active = active.previousElementSibling || active;
    }else{
        active = e.target;
    }
        active.classList.add("hover");
}

You can see a working example here

Christoph
  • 50,121
  • 21
  • 99
  • 128
1

You may want to use a library instead of coding this from scratch.

http://vebersol.net/demos/jquery-custom-forms/

http://www.dreamcss.com/2009/05/15-jquery-plugins-to-enhance-your-html.html

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
  • Thank you for your answer, but, as I've mentioned, I'm trying to study native JS, so I actually want to code this whole thing from scratch. I know that JQuery provides a lot of possibilities and customization options, and I admit they're cool and useful, but I'll get to it eventually :) – Anton Matyulkov Feb 07 '13 at 09:26
  • http://jsfiddle.net/Hd7X9/ - here you go. I've written you on facebook, guess I'll need to give you some more background. – Anton Matyulkov Feb 07 '13 at 09:55
0

Reality you didn't need any js for dropdown but You can use JavaScript Event for simulating it. You can use event like hover, focus, onclick

In JS You Can use This For Set Event

  document.getElementById('id').addEventListener('focus',function(e){
    //place code that want ran at event happened
  }  

In JQuery you can use bind, click ,...

  $('#id')bind('focus',function(e){
    //place code that want ran at event happened
  }

List of Event

http://www.quirksmode.org/dom/events/index.html

slava
  • 1,901
  • 6
  • 28
  • 32
mohammad mohsenipur
  • 3,218
  • 2
  • 17
  • 22
  • @Christoph Yes we can use focus event http://www.quirksmode.org/dom/events/index.html – mohammad mohsenipur Feb 07 '13 at 09:40
  • 1
    well, the fact that the focus element is supported does not change the fact that only `window`, links and formfields can be focussed by default. You need to declare `tabindex` on an element otherwise, and even then, focus is inconsistently supported. – Christoph Feb 07 '13 at 10:15
0

I would suggest removing the hover attribute from css. And add only a hovered class which is applied on keypresses and on mouseover

This could look like this in Code

var dropDown = document.getElementsByClassName("dropdownItemContainer")[0]

document.addEventListener("keydown",function (e) {
    if(e.keyCode == 38 || e.keyCode == 40 ) {
        var key = e.keyCode
        var hovered = dropDown.getElementsByClassName("hovered")
        if(hovered.length != 0 ) {
            cur = hovered[0]
            cur.className = ""
            cur = cur[(key==38?"previous":"next")+"ElementSibling"] || dropDown.children[key==38?dropDown.children.length-1:0] 
        } else {
            cur = dropDown.children[key==38?dropDown.children.length-1:0]
        }
        cur.className="hovered"
    }
});


dropDown.addEventListener("mouseover",function (e) {
    for( var i = 0,j; j = dropDown.getElementsByClassName("hovered")[i];i++)
        j.className = "";
    e.srcElement.className = "hovered";
});

Heres an example on JSFiddle

Moritz Roessler
  • 8,542
  • 26
  • 51