2

I'm trying to create a generic "soft-search" menu dropdown for my bootstrap text-boxes, so that when a user types something on the keyboard, the app should dynamically lookup the back-end rest api through ajax and populate the results in a dynamically generated bootstrap menu just below it:

enter image description here

I use the jquery.bind to bind the keyup event of the input to read the input and dynamically create this dropdown. Now, the dropdown is generated fine, however, I want that when the user presses the "up/down" key, the focus should automatically shift to the dropdown menu, and then the user should select their choice using up/down keys again to select that particular option.

Now, the first part of this is achieved - the focus shifts to the first <li> element on the dropdown. However, the up/down keys aren't working on the dropdown. For example, in above case, when I click down key, the focus doesn't change, it stays stuck on the first item - "test--Foo Bar Limited". What can I do in order to make the dropdown "navigable" using the arrow keys once I shift focus to it? I've scavenged a lot of Internet, but unable to find the solution for this yet.

Below is my code for the keyup event where this dropdown is generated:

$("#searchbox").bind("keyup", function(e){
    console.log(e.type, e.which, e.keyCode);
    console.log('keycode:',e.key);
    var text = $(this).val(); //+(e.key=='Backspace' ? '': e.key);
    console.log('text:',text);
    if (e.key=='ArrowUp' || e.key=='ArrowDown') {
        //FOCUS ON THE DROPDOWN AND RETURN
        e.preventDefault();
        $('#thedrop li:first-child a').focus();
        // setTimeout(function() {
        // }, 700);
        return;
    }
    $("#spinner").addClass('glyphicon-refresh glyphicon-spin');
    //REST API CALL:
    $.get("/client/search/" + text, function(data){
        $("#spinner").removeClass('glyphicon-refresh glyphicon-spin');
        //CREATE THE DROPDOWN
        var darray = JSON.parse(data);
        var drop = '<ul tabindex="1" id="thedrop" class="dropdown-menu" role="menu" aria-expanded="true" >';
        for(var i=0;i<darray.length;i++){
            console.log(darray[i]['ein'],'::',darray[i]['company_name']);
            drop += '<li><a tabindex="-1" href="#">' + darray[i]['ein'] + '--' + darray[i]['company_name'] + '</a></li>';
        }
        drop += '</ul>';
        var top = $('#searchbox').offset().top;
        if (darray.length>0) {
            $('#thedrop').remove();
            $('body').append(drop);
            $('#thedrop').css({
                'top':top + $('#searchbox').outerHeight() ,
                'left':$('#searchbox').offset().left,
            });
            $('#thedrop').show();
        }
    });
});

edit

I've looked up this and this questions, but none of them helps me. They are both proposing that bootstrap already supports up/down keys as standard in a dropdown, then what am I doing wrong?

Community
  • 1
  • 1
Prahlad Yeri
  • 3,567
  • 4
  • 25
  • 55
  • 1
    i would suspect that because you are dynamically inserting the dropdown menu, you will need to fire `.dropdown()` on the newly created element after you append the new element to the body. This will be because bootstrap has already checked the DOM at page init, and isnt constantly listening for new items to be created – haxxxton Dec 01 '16 at 08:29
  • 1
    similarly, im not sure `e.key` is the best way to detect arrows, i would recommend `e.which` where `38` = up arrow and `40` = down arrow – haxxxton Dec 01 '16 at 08:32
  • @haxxxton Thanks a lot! Running `$('#thedrop').dropdown()` did the trick. Please write that down as an answer, so I can accept it. – Prahlad Yeri Dec 01 '16 at 08:51

1 Answers1

1

Bootstrap's JS checks for and generates its JS components on page init. As such, and new items added to the DOM after init will need to be manually instantiated.

To do this you will need to call $('#thedrop').dropdown() after appending it to the body, like so:

...
if (darray.length>0) {
    $('#thedrop').remove();
    $('body').append(drop);
    $('#thedrop').dropdown(); // <-- Inserted here
    $('#thedrop').css({
        'top':top + $('#searchbox').outerHeight() ,
        'left':$('#searchbox').offset().left,
    });
    $('#thedrop').show();
}
...
haxxxton
  • 6,422
  • 3
  • 27
  • 57