Implementing jquery UI autocomplete to show suggestions when you type "@"
Asked Answered
I

3

11

I'm using jquery UI AutoComplete to allow users to tag friends using @mentions. By default, the autocomplete suggestions appear when as soon you put focus on the textbox. How can you make the suggestions appear only when you type "@"? This is the code I have so far:

var availableTags = [
            "ActionScript",
            "AppleScript",
            "Asp",
            "BASIC",
            ];
$("#tags").autocomplete({
    source: availableTags,
    minLength: 0
});
Indevout answered 12/5, 2011 at 3:20 Comment(2)
A cheap and nasty: add "@" to each string?Breccia
I guess that would be last resort :-)Indevout
P
20

You can do this by providing a function to the source option of autocomplete:

var availableTags = [ /* Snip */];

function split(val) {
    return val.split(/@\s*/);
}

function extractLast(term) {
    return split(term).pop();
}

$("#tags")
// don't navigate away from the field on tab when selecting an item
.bind("keydown", function(event) {
    if (event.keyCode === $.ui.keyCode.TAB && $(this).data("autocomplete").menu.active) {
        event.preventDefault();
    }
}).autocomplete({
    minLength: 0,
    source: function(request, response) {
        var term = request.term,
            results = [];

        /* If the user typed an "@": */
        if (term.indexOf("@") >= 0) {
            term = extractLast(request.term);
            /* If they've typed anything after the "@": */
            if (term.length > 0) {
                results = $.ui.autocomplete.filter(
                availableTags, term);
            /* Otherwise, tell them to start typing! */
            } else {
                results = ['Start typing...'];
            }
        }
        /* Call the callback with the results: */
        response(results);
    },
    focus: function() {
        // prevent value inserted on focus
        return false;
    },
    select: function(event, ui) {
        var terms = split(this.value);
        // remove the current input
        terms.pop();
        // add the selected item
        terms.push(ui.item.value);
        // add placeholder to get the comma-and-space at the end
        terms.push("");
        this.value = terms.join("");
        return false;
    }
});

Here's a working example: http://jsfiddle.net/BfAtM/2/

Note that this is almost identical to this demo, except for the requirement for the user to type "@". That code is located inside the source option argument.

Hope that helps.

Pradeep answered 12/5, 2011 at 3:32 Comment(14)
Exactly what I need. But yes, I do need to be able to trigger the search multiple times...basically anytime you type @, the list should appear (preferably only the ones that haven't yet been added to the textbox).Indevout
@Prabhu: Do you need to type anything into the input and have the list only appear when @ is typed? For example "I like @JavaScript and @Html' would trigger the widget twice? or do you just need tagging ability?Pradeep
Also would you know how I could show a hint box that would appear below the text box every time you type @, something that would say "Start typing to receive suggestions..."Indevout
@Andrew That's awesome, thanks a lot! If I may ask two more questions...1) I'd like my tags to appear with the "@" in the textbox after selecting. I tried modifying the code, but it's keeping the @ only on the last tag. 2) Is there anyway that I can display an initial message saying "Start typing to receive suggestions.." after the @ is entered, and then when the next letter is entered, the suggestions are displayed? Thanks a lot once again!Indevout
@Andrew Perfect. You solved all my problems. Thanks for taking the time!Indevout
@Andrew--if I wanted to modify it slightly so my availableTags is a complex object with properties (Description, Icon, etc) instead of just strings, how could I modify it so that item.DisplayName is displayed on the dropdown list, but once selected, item.UserName is put into the textbox?Indevout
There is an example here: jqueryui.com/demos/autocomplete/#custom-data but I'm not very sure how to translate into the custom code that I have now. Trying out a few things though.Indevout
@Prabhu: In your object, as long as you have a value and label property, label will be used as the display value and value will be the value stored in the input. For example: [{ label: 'Andrew', value: 1234 }].Pradeep
@Andrew: You're awesome, didn't think it'd be that easy! Btw, I also see two other properties in the examples (desc and icon)...any idea what these are for?Indevout
@Prabhu: Those are just extra properties on the autocomplete source objects. You can specify whatever you want. In that demo, they are using them to display a description and show an icon (that is, there's nothing built in that uses those properties).Pradeep
Unfortunately I'm not able to run this code. I'm working on Ruby on Rails. I already have "keypress keydown input change" event on the element in js file. The ruby code can not be executed from there, So need to put in View file. I made changes as you mentioned but it did not work. :(Mordecai
If you're having trouble, I would recommend opening a new question.Pradeep
Hey your solution is awesome dude..+1 Can you help to pass json array from my database instead of fixed available tags???Yorker
@Andrew Whitaker Hi will you please help me to solve this #7886640 ?Yorker
M
4

As of the date of this note, I recommend the jquery.mentionsInput plugin. It supports @mention tagging just like on facebook, complete with avatars and either local or ajax data.

http://podio.github.com/jquery-mentions-input/

Maccabees answered 16/10, 2012 at 19:32 Comment(1)
Its 404 Now, do you have any suggestion around it.Crotchety
L
1

To expatiate Andrew Whittaker's answer a bit, the source option of jQuery UI Autocomplete is used to specify an array containing the items that are to be displayed in the drop-down list once the widget is triggered. It can be defined as such an array, a function that returns such an array, or a URL to a resource which produces such an array.

If the array which ultimately becomes the value of source is empty, the widget won't display a drop-down list. So, defining source as a function capable of returning a non-empty array only when @ is entered will make the widget behave as you desire.

The widget however, functions as just a part of a component of a tag (herein referred to as mention) management utility, which has 3 components:

  1. Autocomplete module: The component responsible for procuring and displaying the set of items that can be used to create a mention, given a string.

  2. Mention tracking module: The component responsible for keeping track of mention-associated data; at the bare minimum the location, as well as the superficial and substantive (if existent) values of each mention should be tracked throughout all modifications of the text of the input element to which the utility is affixed.

  3. Mention visual differentiation module: The component responsible for differentiating mention text from the rest of the text in the input element to which the utility is affixed

Delving further in to the implementation of the remaining 2 modules, in plain English, would be tedious; its much better to look at code! Fortunately, I've made a solution, Mentionator, that is robust (more so than all the other solutions suggested here), well-structured, easy to follow, and copiously commented. So its worth a look at whether you just want an out-of-the box solution, or reference material to create your own.

Larousse answered 3/7, 2016 at 11:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.