Search code examples
jqueryjquery-uiautocompletejquery-autocompleteslickgrid

Autocomplete Combobox Up and Down Key don't work in SlickGrid


I created a custom SlickGrid editor called AutoCompleteEditor to hook related fields which are required to be a Autocomplete combobox. It works fine so far except trying to scroll up and down the items by pressing Up and Down Keys on keyboard. I believe the problem is since this Autocomplete combobox is embedded in SlickGrid, when you key Down, it navigates to the cell right below of the activeCell in the grid.

So my question is how am I supposed to scroll up/down the items in suggestions with UP/DOWN key presses in autocomplete combobox embedded in SlickGrid?

Note: I know how to disable left and right keys to function but up/down keys function different than left/right key presses.

This is the source code of the custom editor:

function AutoCompleteEditor(args) {
     var $input;
     var defaultValue;
     var scope = this;
     var calendarOpen = false;


     this.init = function () {

       $input = $("<INPUT id='tags' class='editor-text' />");
       $input.width($(args.container).innerWidth() - 28);
       $input.appendTo(args.container);

        $input.bind("keydown.nav", function (e) {
        if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
          e.stopImmediatePropagation();
        }
        else if (e.keyCode === $.ui.keyCode.UP || e.keyCode === $.ui.keyCode.DOWN) {
         // e.stopImmediatePropagation();

         e.stopImmediatePropagation();
        }
       });


       $( "<a>" )
            .attr( "tabIndex", -1 )
            .attr( "title", "Show All Items" )
            .appendTo( args.container )
            .button({
                icons: {
                    primary: "ui-icon-triangle-1-s"
                },
                text: false
            })
            .removeClass( "ui-corner-all" )
            .addClass( "ui-corner-right ui-combobox-toggle" )

            .click(function() {

                // close if already visible
                if ( $input.autocomplete( "widget" ).is( ":visible" ) ) {
                    $input.autocomplete( "close" );
                    return;
                }

                // work around a bug (likely same cause as #5265)
                $( this ).blur();

                // pass empty string as value to search for, displaying all results

                $input.autocomplete( "search", "" );

                //achieve the positioning in case of scrolling 
                $(".ui-autocomplete").position({
                    my: "left top",
                    at: "left bottom",
                    of: $("#tags"),
                    collision: "flip flip"
                 });

                $input.focus().select();
            });

       $input.focus().select();

       $input.autocomplete({
            delay: 0,
            minLength: 0,
            source: args.column.options
        });

     };


     this.destroy = function () {
       $input.autocomplete("destroy");
     };

     this.focus = function () {
       $input.focus();
     };

     this.position = function (position) {

     $(".ui-autocomplete").position({
        my: "left top",
        at: "left bottom",
        of: $("#tags"),
        collision: "flip flip"
     });

    };

     this.loadValue = function (item) {
       defaultValue = item[args.column.field];
       $input.val(defaultValue);
       $input[0].defaultValue = defaultValue;
       $input.select();
     };

     this.serializeValue = function () {
       return $input.val();
     };

     this.applyValue = function (item, state) {

        var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( state ) + "$", "i" ),
            valid = false;

        jQuery.each(args.column.options , function(index, value){

            if ( value.match( matcher ) ) {
                valid = true;
                item[args.column.field] = state;
                return false;
            }       
        });

        if ( !valid ) {
        // remove invalid value, as it didn't match anything
            $( this ).val( "" );
            $input.data( "autocomplete" ).term = "";
            item[args.column.field]="";
            return false;
        }

          // item[args.column.field] = matcher;
     };


     this.isValueChanged = function () {
       return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
     };


     this.validate = function () {
       return {
         valid: true,
         msg: null
       };
     };

     this.init();
   }

Solution

  • Call e.stopPropagation() in your keydown handlers.