0

I am developing a autoComplete plugin in jquery. The the result is populated in a div as a unordered list based on the input in the input field. The ajax call is made on keyUp event. Everything is working fine. Now I have to add navigation to the list populated. I am doing this on keyDown event and the navigation works, but after keyDown, the keyUp event is generated and once again ajax call is made.

Is there a way to add navigation so that on arrow key down the ajax call is not made.

Below is my Code.

HTML Code

<!doctype html>
<html>
<head>
<script type="text/javascript" src="@{'/public/javascripts/jquery-1.9.1.js'}"></script>
<script type="text/javascript" src="@{'/public/javascripts/jquery-ui.js'}"></script>
<script type="text/javascript" src="@{'/public/javascripts/comboBox.js'}"></script>
</head>
<body>
 <label class="formlabel">Vessel</label>
                <div id="vesselDropDown"></div>

</body>
<script>
$(document).ready(function(){
    $("#vesselDropDown").hermesComboBox({
        width:130,
        height:25,
        role:"vessel",
        URL:"application/vessel"
    });
});
</script>
</html>

Plugin Code

(function ( $ ) {
        $.fn.hermesComboBox = function( options ){

        var settings = $.extend({
            width:150,
            height:25,
            role:"none",
            minLength:3,
            URL:"none"
        },options);

        var elementId=settings.role; // inputField ID

        // positioning input field
        var inputWidth=settings.width;
        var inputHeight=settings.height-5;

        $(this).append('<input type="text" id="'+elementId+'"/>');
        $("#"+elementId).css({ width:inputWidth,height:inputHeight});
        $(this).append('<div id="resultContainer'+elementId+'"><ul></ul></div>');
        $("#resultContainer"+elementId).css({position:'absolute',left:-300,top:-300,background:'#eeeeee'});
        $("#resultContainer"+elementId).hide();

        $("#"+elementId).keyup(function(e){
            var inputValue=$(this).val(); 
            if(inputValue.length>=settings.minLength){

                $.post(settings.URL,{vesselCode:inputValue},function(data){
                    var dataSize=data.length;   
                    $("#resultContainer"+elementId).html("").append("<ul></ul>");
                    for(var i=0;i<dataSize;i++){
                        $("#resultContainer"+elementId+" ul").append('<li rel="'+data[i].vesselCode+'">'+data[i].vesselCode+','+data[i].vesselName+'</li>');
                    }

                });
                var position=$(this).position();
                var resultContainerleftPosition=position.left;
                var resultContainertopPosition=position.top+settings.height+5;

                $("#resultContainer"+elementId).fadeIn().css({ width:inputWidth,left:resultContainerleftPosition,top:resultContainertopPosition});

            }
        });

        $("#"+elementId).blur(function(){
            $("#resultContainer"+elementId).fadeOut()
        });

        var start = -1;
        $(document).on('keydown',"#"+elementId,function(e){

            if(e.keyCode == 38){
                if (start == -1){
                    start = ($("#resultContainer"+elementId+" ul li").size() - 1);  
                    }
                    else
                    {
                        start--;
                        if (start < 0){
                        start = ($("#resultContainer"+elementId+" ul li").size() - 1);  
                    }
                }
                $("#resultContainer"+elementId+" ul li").removeClass('active').focus();
                $("#resultContainer"+elementId+" ul li").eq(start).addClass('active').focus();
                e.preventDefault();
            }

            if(e.keyCode == 40){
                if (start == -1){
                    start = 0;  
                    }
                    else
                    {
                        start++;
                        if (start > ($("#resultContainer"+elementId+" ul li").size() - 1)){
                        start = 0;  
                    }
                }
                $("#resultContainer"+elementId+" ul li").removeClass('active').focus();
                $("#resultContainer"+elementId+" ul li").eq(start).addClass('active').focus();
                e.preventDefault();
            }

        });
    };
}(jQuery));

Please help or suggest me a way to achieve this. Thanks in advance

Vivek
  • 49
  • 1
  • 10
  • Set a variable, or check the DOM, to see that the autocomplete list is showing. Then, don't execute the AJAX. – crush Jan 08 '14 at 22:36
  • Have you tried checking which key was pressed, and doing nothing if it's an arrow? – Jasper Jan 08 '14 at 22:36
  • This is really similar to this question: http://stackoverflow.com/questions/1402698/binding-arrow-keys-in-js-jquery Just adapt it to your situation. In the keyup event trap for the arrow key codes and ignore the ajax call if it's an arrow key. Look at the second answer though, the first (and unfortunately accepted answer) is not cross browser compatible. – akousmata Jan 08 '14 at 22:37

1 Answers1

0

That is simple, just disable autocomplete on arrow keys.

...
if(!(e.which>=37 && e.which<=40)){
    // execute xhr and stuff..
}
...

NOTICE

There are also other keys you should disable - ctrl, shift, caps-lock, scroll-lock, F1, F2, infact there are so many keys you should disable that it would be easier if you just allowed keys you want, since they will most probably go in a sequence in numbers ( ascii or whatever )

php_nub_qq
  • 15,199
  • 21
  • 74
  • 144