2

Im using http://aehlke.github.io/tag-it/ for tagging but I am having a hard time adding a value when the autocomplete comes up and you hit enter or tab. If I use my mouse I can easily select a value like so:

enter image description here

And click on the value it correctly selects it:

enter image description here

However if I use the enter key it only adds the tag based on the text I've typed so far... For instance, assume I wanted to add "tryme" as a tag so I start typing try and I use my cursor on my keyboard and select the value I want and I hit the enter key I end up like so:

Before:

enter image description here

Then I press enter, I get "try" instead of "tryme":

enter image description here

Here is my code:

var entityId = '<%=(int)Module.Company%>'; //parameter for web service.
$("#MainContent_txtTags").tagit({
    singleField: true,
    singleFieldDelimiter: " ",
    autocomplete: ({
        delay: 0,
        minLength: 1,
        source: function(request, response) {
            $.ajax({
                type: "POST",
                contentType: "application/json; charset=utf-8",
                url: "/Code/WebServices/Tags.asmx/GetTags",
                dataType: "json",
                data: '{"entityId":"' + entityId + '","search":"' + request.term + '"}',
                success: function(data) {
                    response($.map(data.d, function(item) {
                        return {
                            label: item.TagName,
                            value: item.TagName
                        }
                    }));
                }
            });
        },
        open: function() {
            $(this).removeClass("ui-corner-all").addClass("ui-corner-top");
        },
        close: function() {
            $(this).removeClass("ui-corner-top").addClass("ui-corner-all");
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert(textStatus);
        },
        search: function(event, ui) {
            $(this).addClass('autocompleteloading');
            // custom minLength
            var term = extractLast(this.value);
            //alert(term);
            if (typeof(term) !== 'undefined') {
                if (term.length < 1) {
                    return false;
                }
            }
            return true;
        },
        select: function(event, ui) {
            alert("hi");
        },
        focus: function() {
            // prevent value inserted on focus
            return false;
        },
        response: function() {
            $(this).removeClass('autocompleteloading');
        }
    })
});

I tried playing with the select event but that only fires when I use the mouse. How can I handle the enter / tab key using this library?

Here's my edited code:

//tagging
//to clear
var entityId = '<%=(int)Module.Company%>'; //parameter for web service.
var availableTags = [];
$("#MainContent_txtTags").tagit({
    singleField: true,
    singleFieldDelimiter: " ",
    autocomplete: ({
        delay: 0,
        minLength: 1,
       // autoFocus: true,
        source: function(request, response) {
            $.ajax({
                type: "POST",
                contentType: "application/json; charset=utf-8",
                url: "/Code/WebServices/Tags.asmx/GetTags",
                dataType: "json",
                data: '{"entityId":"' + entityId + '","search":"' + request.term.toLowerCase() + '"}',
                success: function (data) {
                    availableTags = [];
                    response($.map(data.d, function (item) {
                        availableTags.push(item);
                        return {
                            label: item.TagName,
                            value: item.TagName
                        }
                    }));
                }
            });
        },
        open: function() {
            $(this).removeClass("ui-corner-all").addClass("ui-corner-top");
        },
        close: function() {
            $(this).removeClass("ui-corner-top").addClass("ui-corner-all");
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert(textStatus);
        },
        search: function(event, ui) {
            $(this).addClass('autocompleteloading');
            // custom minLength
            var term = extractLast(this.value);
            //alert(term);
            if (typeof(term) !== 'undefined') {
                if (term.length < 1) {
                    return false;
                }
            }
            return true;
        },
        select: function(event, ui) {

        },
        focus: function() {
            // prevent value inserted on focus
            return false;
        },

        response: function() {
            $(this).removeClass('autocompleteloading');
        }
    }),
    beforeTagAdded: function (evt, ui) {
        // If tag is incomplete..
        if ($.inArray(ui.tagLabel, availableTags) == -1) {
            var $tagdropdowns = $('body ul:last li a');
            // Add the selected tag (if there) from dropdown.
            var $activeTag = $tagdropdowns.filter(function () { return $(this).is(":hover") });
            if ($activeTag.length) {
                $(this).tagit("createTag", $activeTag.text());
                // Otherwise add the first tag from the dropdown.
            } else {
                $(this).tagit("createTag", $tagdropdowns.first().text());
            }
            // Stop adding incomplete tag.
            return false;
        }
    }
});

Ended up with this thank you Banana (the answerer from below):

//tagging
        //to clear
        var entityId = '<%=(int)Module.Company%>'; //parameter for web service.
        var callBeforeTagAdded = true;
        $("#MainContent_txtTags").tagit({
            singleField: true,
            singleFieldDelimiter: " ",
            autocomplete: ({
                delay: 0,
                minLength: 1,
                // autoFocus: true,
                source: function (request, response) {
                    $.ajax({
                        type: "POST",
                        contentType: "application/json; charset=utf-8",
                        url: "/Code/WebServices/Tags.asmx/GetTags",
                        dataType: "json",
                        data: '{"entityId":"' + entityId + '","search":"' + request.term.toLowerCase() + '"}',
                        success: function (data) {
                            response($.map(data.d, function (item) {
                                return {
                                    label: item.TagName,
                                    value: item.TagName
                                }
                            }));
                        }
                    });
                },
                open: function () {
                    $(this).removeClass("ui-corner-all").addClass("ui-corner-top");
                },
                close: function () {
                    $(this).removeClass("ui-corner-top").addClass("ui-corner-all");
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert(textStatus);
                },
                search: function (event, ui) {
                    $(this).addClass('autocompleteloading');
                    // custom minLength
                    var term = extractLast(this.value);
                    //alert(term);
                    if (typeof (term) !== 'undefined') {
                        if (term.length < 1) {
                            return false;
                        }
                    }
                    return true;
                },
                response: function () {
                    $(this).removeClass('autocompleteloading');
                }
            }),
            beforeTagAdded: function (evt, ui) {
                // If tag is incomplete.
                    var $tagdropdowns = $('body ul:last li a');

                    // Add the selected tag (if there) from dropdown.
                    var $activeTag = $tagdropdowns.filter(function () {
                        return $(this).hasClass("ui-state-focus");
                    });

                    $tagdropdowns.removeClass('ui-state-focus');
                    if ($activeTag.length && callBeforeTagAdded) {
                        $("#MainContent_txtTags").tagit("createTag", $activeTag.text());
                        callBeforeTagAdded = false;
                        return false;
                        // Otherwise add the first tag from the dropdown.
                    } else {
                        callBeforeTagAdded = true;
                    }
            }
        });
JonH
  • 32,732
  • 12
  • 87
  • 145
  • I'm looking at the demo for this library, which one of them are you using? – Mark Jul 11 '14 at 12:43
  • keydown http://api.jquery.com/keydown/ (and some others) -> look for event.which http://jsfiddle.net/lesson8/VLZGk/ and tab is the number 9 http://unixpapa.com/js/key.html – nicolallias Jul 11 '14 at 12:44
  • Not sure what you mean which one, its a single library but of course I am using a remote data source (see the webservice) to populate the values of the autocomplete. – JonH Jul 11 '14 at 12:44
  • @nicolallias - I already know the events, but how can I apply that to what I have...my textbox is "Tagged" like so: `$("#MainContent_txtTags").tagit({` as shown in the code above. – JonH Jul 11 '14 at 12:45
  • you may have a look to www.w3schools.com/jquery/event_stoppropagation.asp ... a more appropriate way would be to play with beforeTagAdded https://github.com/aehlke/tag-it/blob/master/README.markdown – nicolallias Jul 11 '14 at 12:52
  • I would listen to the `beforeTagAdded` event and check if the tag is member of the 'allowed tags array'. If you don't want to add the tag you have to return `false`. – GuyT Jul 15 '14 at 10:00
  • @GuyT - I'm not trying to check if a tag is allowed or not. That is not my question. I am asking about using enter / tag to select a tag. I don't care what is allowed or not allowed. – JonH Jul 15 '14 at 13:36
  • @JonH I get that. When I see your example a tag is added with whatever is typed into the texbox(after tab or enter). If you are able to catch the `beforeTagAdded` event you could add the 'autocomplete' tag by comparing it to the value you just typed in the textbox because it's called in both cases. – GuyT Jul 15 '14 at 14:21
  • Again that is not my question. I am asking how to get this library to respect the TAB or ENTER key so that I dont have to use a mouse. I've read this question over and over and it seems to make sense? – JonH Jul 16 '14 at 16:42
  • @JonH The `callBeforeTagAdded` flag should not be needed with your final code. – dwitvliet Jul 16 '14 at 19:45

2 Answers2

1

By default both tab and enter inserts the tag selected with the arrow keys. You have to remove the following code, as it overwrites the default focus and select options:

select: function(event, ui) {

},
focus: function() {
    // prevent value inserted on focus
    return false;
},

Furthermore, you can use the beforeTagAdded: to add tags that are in focus (because of a mouse hovering) when pressing enter or tab:

(...)
$("#MainContent_txtTags").tagit({
    (...)
    beforeTagAdded: function(evt, ui) {

        var $tagdropdowns = $('body ul:last li a');
        var $activeTag = $tagdropdowns.filter(function() { 
            return $(this).hasClass('ui-state-focus') 
        });
        $tagdropdowns.removeClass('ui-state-focus');

        if ($activeTag.length) {
            $(this).tagit("createTag", $activeTag.text());
            return false;
        }

    }
});
dwitvliet
  • 7,242
  • 7
  • 36
  • 62
  • What I am asking about is adding the tag via an enter key or tab key, this doesn't appear to be doing that? – JonH Jul 16 '14 at 16:43
  • The fiddle doesnt work, try typing the word test right after another tag. – JonH Jul 16 '14 at 16:44
  • @JonH It does indeed add the tag with both the enter and tab press. However, the tag has to be in the list of possible tags, otherwise it's not added, and therefore 'test' does not work. Try 'a' instead. – dwitvliet Jul 16 '14 at 16:47
  • Ahh I didn't realize you had that array of available tags, let me try again. – JonH Jul 16 '14 at 16:48
  • @JonH Doing ajax calls in jsfiddle is rather complicated, which is why I edited the example there. However, if you use the code I've written in my answer (not jsfiddle), it should work with your ajax call. – dwitvliet Jul 16 '14 at 16:59
  • I just tried, and I am close however, in the console I keep getting `Uncaught RangeError: Maximum call stack size exceeded`. Im no js expert but it started happening due to this: response($.map(data.d, function (item) { availableTags.push(item); return { label: item.TagName, value: item.TagName } })); – JonH Jul 16 '14 at 17:02
  • You're missing `availableTags = []` before `response($.map(data.d, function(item) {`. – dwitvliet Jul 16 '14 at 17:06
  • i placed that in there but still the same issue, can you look at my edit to the question? – JonH Jul 16 '14 at 17:19
  • Can you find out which line causes the error message? – dwitvliet Jul 16 '14 at 17:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57429/discussion-between-jonh-and-banana). – JonH Jul 16 '14 at 17:27
-1

Use value of key pressed

$('#inputbox').keypress(function(e) {
var code = e.keyCode || e.which;
});

following are desired values

tab => 9

enter => 13

According to it's docs

you can use Event

**beforeTagAdded (function, Callback)**

To check the value of input before adding it. Check if it is one of the values you require.If it is return true else false

Confused
  • 1,602
  • 15
  • 25
  • 1
    Please reread the question, I am not asking for keycodes, I can figure that out. What I am asking for is what event can I use within the autocomplete that will fire in the case of enter or tab. – JonH Jul 11 '14 at 13:13
  • This really doesn't help me. I need to capture enter on a selected item. Please use the code I posted from above and if you can modify that or give me an idea to use what I have. – JonH Jul 13 '14 at 21:17