jQuery Tag Suggestion

If you’re familiar with del.icio.us you will be familiar with the tag suggesting as-you-type support.

The reason why, I believe, the tagging works so well within del.icio.us is that it helps you create a subset of tags that you commonly use for different types of links. This way, it makes it easier to find tagged content later on. i.e. conversely if it didn’t suggest links, it would be likely that you would have different variations or even spellings of the same tag on (what should be) grouped content.

So, in an effort to adopt this approach, I’ve created a jQuery plugin for tag suggestion.

Download jQuery tag suggestion

Download tag.js

The plugin has been tested with:

  • IE 7
  • Firefox 2
  • Safari 3
  • Opera 9

If anyone has any problems in any other browsers (or even these), I would appreciate the feedback.

Demonstration

View the tag suggestion demo

View the source for the demo

The demonstration shows off both the static based tags and the Ajax based tag suggestion. Although the tag sets are the same, be sure to open Firebug and check the Ajax hits in the second example.

Example code

Static example

Allows the input field to have their own set of tag suggestions.

$(function () {
  $('input.tagSuggest').tagSuggest({
    tags: ['javascript', 'js2', 'js', 'jquery', 'java']
  });
  $('#otherlanguages').tagSuggest({
    tags: ['applescript', 'php', 'perl', 'java']
  });
});

Static global example

setGlobalTags(['javascript', 'js2', 'js', 'jquery', 'java']);
$(function () {
  $('input.tagSuggest').tagSuggest();
});

Ajax example

$(function () {
  $('#tags').tagSuggest({
    url: '/tag-suggestion'
  });
});

Style

I would recommend the following styles for the suggested tags:

SPAN.tagMatches {
    margin-left: 10px;
}

SPAN.tagMatches SPAN {
    padding: 2px;
    margin-right: 4px;
    background-color: #0000AB;
    color: #fff;
    cursor: pointer;
}

Plugin parameters

All parameters are optional, so long as tags have been set via the setGlobalTags function.

  • delay – sets the delay between keyup and the request – can help throttle ajax requests, defaults to zero delay
  • matchClass – class applied to the suggestions, defaults to ‘tagMatches’
  • separator – optional tag separator string, defaults to ‘ ‘
  • sort – boolean to force the sorted order of suggestions, defaults to false
  • tagContainer – the type of element uses to contain the suggestions, defaults to ‘span’
  • tagWrap – the type of element the suggestions a wrapped in, defaults to ‘span’
  • tags – array of tags specific to this instance of element matches, defaults to global tags
  • url – url to get suggestions, overrides any specifically set tags. Must return array of suggested tags as JSON

75 Responses to “jQuery Tag Suggestion”

  1. As you can read on
    http://wiki.pylonshq.com/display/pylonsfaq/Warnings , the way you pass the tag-information might make CSRF or other malice easier.

    Thusly, it is recommended to pass the Information not in a JSONArray, but in a modified structure. E.g.: tags = {"result": [(tag.name) for tag in tag_q]} (in python)

    With this change, all you have to do is change line 112 of your script from
    matches = m;
    to
    matches = m.result;

  2. While using Firefox/3.0.10 on Mac OS X I sometimes get the following 2 errors when selecting/clicking one of several suggestions (I used jquery 1.3.2). Your demo here on-line displays the same errors when f.e. typing ‘ap’ and clicking one of the suggestions.

    Permission denied to get property XULElement.popupOpen
    http://remysharp.com/js/jquery.js
    Line 2039

    Permission denied to set property XULElement.selectedIndex
    http://remysharp.com/js/jquery.js
    Line 2039

    Were you aware of that? P.S. I made a usefull display-suggestions-in-element-with-this-id-not-right-next-to-input addition to your code which I will mail you later when our project is finished (and I finished the ‘replace with jQuery version’-part on line 256).

    —Cheers, André

  3. I would recommend disabling autocompletion in Firefox, f.e. by adding this line right after one of the above examples:

    $(‘#tagsuggest’).attr(‘autocomplete’, ‘off’);

  4. Great Tutorial,
    Question: Is it possible to define a target div where the tags appear? Right now the tags are shown at the right of the input field. How can I change this to specific div?
    Hopefully somebody can help me with this…

    Thx!

  5. Hi Remy. Thanks for this plugin – just what I was after. I’ve made a couple of small changes that I wanted to share

    Firstly, if the delimiter is not a space character, then it carries that when the spacebar is depressed, the list of tags is not reset. The change is as follows:


    case 32: {
    if(settings.separator === ' ') {
    setSelection();
    return true;
    }
    }

    Secondly, to reduce the number of AJAX requests. I’ve added an option for a minimum character length before a search is made – this wold likely be set to 2 or 3 chars. The key gain is not perfroming s search on the 1st character.


    if (currentTag.tag) {
    if(currentTag.tag.length < settings.minLength) {return};

    Thanks again

    Howie

  6. HI,
    The plugin tested with Chinese character wasn’t show anything,
    look forward fix it ,thx

  7. I’ve made some tweaks to my own copy of this code to a) retain and correct the case of tags (but still match case-insensitively) and also to allow use of the up/down arrow keys to select which tag gets inserted when tab or enter is pressed.

    If you want to incorporate these changes, let me know and I’ll mail them to you.

  8. Paul Stone: I would love to get those changes (about the keyboard navigation). Would you e-mail them? .. ola at raaw.se

  9. Great plugin, just implemented and works great for both username completion and tag completion.

  10. Is there any way to only have 5 tags per row

  11. Hi Remy thanks for creating this great plugin. I have used it in a ASP.NET MVC application I built. Where it returns the suggested tag list from an SQL database. I posted some learnings on my blog if anyone else is after the same kind of thing http://kmsystems.squarespace.com/journal/2009/8/26/jquery-tag-suggestion-in-aspnet-mvc.html

  12. Hi Remy, I have now added the source code and demo of a working ASP.NET MVC JQuery Tag Suggestion implementation, in case anyone would like to do something similar. The link is the same http://kmsystems.squarespace.com/journal/2009/8/26/jquery-tag-suggestion-in-aspnet-mvc.html

  13. The ajax request handling seems to by synchronous. As a consequence the input field is locked while the request is active. Especially if the backend is a bit slow or your user is a fast typer a few letters will get clipped.

    Setting the delay paramter reduces this effect a bit, but an asynchronous solution would solve that.

  14. I’m having trouble attaching the tagsuggest function to a dynamically id’d input. I am doing an ajax search that returns a bunch of id. then i create several input fields with those ids and i need each one to have the tagsuggest functionality.

    Any suggestions? Im sorry if this is a pretty dumb question. Any ideas?

  15. It definitely is locking up the text field while ajax does all the communicating. Remy, any chance you’ll be addressing this issue in a future release?

  16. I just plugged in a couple of changes (not really all that fancy, just really simple stuff) to make it asynchronous:

    1. Where the $.ajax call is, set “async” to true

    2. Copy everything inside the brackets containing the $.ajax but outside and after the if(settings.url) and the else statement. Copy that code and move it into the success function of the AJAX as well as after the “for” statement in the else statement (non-ajax).

  17. Is there anyway to simply check if a tag already exists, rather than find suggestions?

    This would be used when submitting the tags.

  18. It used to work now for some reason the error console says:

    Error: $(“#tags”).tagSuggest is not a function
    Source File: http://localhost/cmstut/submit_tutorial
    Line: 526

    I copy paste the javascript from the demo and I’m sure the link to the tag javascript file is set correctly

  19. I can confirm both Scott’s problem with firefox 3.5.5 (on OS X anyways) as well as his solution (thank you!). I was not having the problem in other browsers and I don’t think I used to have the problem in firefox. Not sure if it is new to firefox or perhaps new to a more recent jquery version since last testing (for me).

  20. Can we use your JQuery Tag Suggestion on commercial websites?

    I have a task management system (to be used internally in the company) that I am working on, and this would work well for the tagging system.

    Thanks,
    Chris

  21. I need a way to “post process” the tag selection. My application needs tags which contain special characters (e.g. space) to be quoted in the post submission. But if I quote these in the golbal tag list, the user must type the quote to get the match. Most would not even think of doing this. So I would like to post process the selection to check for these characters and add the containing quotes to what is inserted into the field.

  22. For those of you who want to use commas as the delimiter:

    Leave the default delimiter as a space. Then around line 168 of tag.js, change:

    if (index == workingTags.length - 1) tag = tag + settings.separator;

    with:

    if (index == workingTags.length - 1) tag = tag + "," + settings.separator;

    What that does is trigger the auto-suggest when the user puts in a space after the comma, and then when they select the word or hit enter, it puts the word plus the comma plus a space, and you’re ready to start typing again. Its the best solution I’ve found and is working great.

  23. I am trying to use Tag Suggestion with pre-defined dynamic tag suggestions. What I mean is instead of declaring static like this:

    
    $('#citTags').tagSuggest({
    
    tags: "agile","ajax","apache","api","apml","applescript","architecture","auth","autocomplete","beautify","bug"]
    
    });
    
    

    I want to populate the ‘tags:’ array with an array returned from another function, e.g.

    
    function myArrayFunc() {
    
        myArray = [];
        // load my data dyanmically and push into array myArray
    
        return myArray;
    }
    
    
    
    $('#citTags').tagSuggest({
    
    tags: myArrayFunc();
    });
    

    So, basically I want to some how load my suggestions from an array created elsewhere (which grabs data dynamically) and assign in to tags: so it works.

    How would i go about this? I have tried giving it an array and it didnt work

  24. Is there any way to only have 5 tags per row? The template loses its boundaries when finding a country match…assist me please. Thanks.

  25. This thing is awesome, thanks!

    My concern is placing the suggestions… Right now they just show up to the right of the text box and if there’s not room they spill over below the text box. Doesn’t give me any control and looks rather sloppy. Is there any way to target a div or a span like someone else suggested?

Leave a Reply
Not required

CODE: Please escape code and wrap in <pre><code>, doing so will automatically syntax highlight