A delicious javascript tagging input field

A brief review of existing components and the presentation of the powerful “jquery.tagInput”

Once again, working on one of our new secret products (which is called Licorize 🙂 ), I was in need to select a third party component for speeding up development:  this time, a tagging field.

… before continue reading do you like to go straight to live demo?

I realized in seconds that I already had in mind a delicious solution. Delicious (.com) and its wonderful tagging system its really nearly what I wanted, probably even a little more…

What I really love in this component as seen on Delicious is the smoothness of user interaction. Let me explain the concept: try to write a tag directly from the input field and the drop down will show your already used tags, in order of frequency. Amazing, mainly it saves me scrolling the list: most used on top, golden rule. This is not different from what usually the other components do, but in this case the string searched is a little bit “boldified”. This is stylish!

image

Another nice feature of delicious’s tagging field is the integration with “recommended” and “popular”: not only by clicking the tag it is inserted/removed like every nerd-programmer will be able to imagine, but even while you are typing in the input field, the suggested tag is magically highlighted – this is a masterpiece!

Of course the interface behavior is supported by meaningful contents: suggested tags are computed on the base of the analysis of the url contents and mainly, I suppose,  on other users tagging criteria; having million of users makes the term “statistic” meaningful.

(BTW you can access this data using the Delicious api)

The only things I would change in this jewel is the tag separator from [space] to [comma]; this will give you the capability to add multiple word tags, even if it may induce the user in using the tag field as a sort of notes one. So the separator “flavor” may open a Pandora’s box: if ever in my life I’ll write a tag component – which I’ll try to avoid as much as possible.

Apart from the separator, I needed exactly this component, but unluckily it is entangled in Delicious’ js library, so I decided to have a look at available jQuery based components.

As usual this list does not pretend to be complete as I’m focused on developing products, not on writing reviews, but someone else could find my hints useful (I have already wrote some reviews on charting and grid components).

The top ranked one  is jQuery tag suggestion by Remy Sharp.

image

This nice component is very easy to use and is based on an array of suggested tags that can be supplied via a js array or via Ajax.

A basic axample:

$('input.tagSuggest').tagSuggest({  tags: ['javascript', 'js2', 'js', 'jquery']});

An Ajax example

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

Layout is configurable via css, and some parameters will help you in fine tuning this component.

Even if this is a nice component it is quite far from Delicious one, at least because it does not implement multiple tag collection: mine, suggested, popular. Another little limitation is that the suggested tag list is static, even if called through Ajax.

Another cool component is Tagger by Chris Iufer.

image

Here the focus is on maintaining  a tag list, instead of filling a field.

Usage is really simple:

<input class=”tagger” type=”text” name=”tags[]” />

<script type=”text/javascript”>

$(document).ready(function(){

// add to tagger element by index

$(‘.tagger’).eq(0).addTag(‘photo, design, creative’);

// add to a specific tagger element by Id

$(‘#places’).addTag(‘mountain view’);

$(‘#places’).addTag(‘chico’);

});

</script>

But this is even farther from my goal…

Even Pines Tags by Hunter Perrin goes in the wrong direction, at least compared with Delicious. It is focused mainly on writing / removing tags (like the previous one):

image

The documentation is little bit weak but usage is still easy:

$(“#tags”).ptags();

In the same flow is JTAG by Benoît Vidis

image

cute, but not my prefered one.

Another component that cought my attention was MagicTags by Dave Geddes.

image

Nice graphics, but here the core seems the transitions effects, making the usage of this component at bit annoying.

Nice look, but similar behavior for  TestBoxList by Guillermo Rauch.

image

That’s all folks!  I didn’t find other components, maybe the “tag” search key induces too much noise in search engines, but differently from usual there aren’t dozens of components, the choice is limited.

So I reached this sad conclusion:

I MUST WRITE MY OWN COMPONENT!

At least now my requirements are clear:

  1. supporting already used tag list, eventually filled with an Ajax call
  2. filtering results using user inputs
  3. supporting suggested tags, with “smart” selection
  4. supporting multiple separators
  5. supporting frequency
  6. having a nice-ligth-stylish look
  7. be delicious!

After a couple of days of programming this is the result:

image

typing on the text field a drop down will show your used tags:

image

I’ve set up a live demo on BugVoice site (new secret product is offline for the moment).

The usage is quite easy at least in the minimal configuration:

<link rel=stylesheet href="jquery.tagInput.css" type="text/css">
<script type="text/javascript" src="jquery.tagInput.js"></script>

insert your input field:

tags: <input type="text" size="80" id="tag" >

then instantiate the component:

<script type="text/javascript">
var myTags=[
  {tag:"js",freq:30},{tag:"jquery",freq:25},
  {tag:"pojo",freq:10},{tag:"agile",freq:4},
  {tag:"blog",freq:3},{tag:"canvas",freq:8},
  {tag:"dialog",freq:3},{tag:"excel",freq:4} ]   $("#tag").tagInput({ tags:myTags})
</script>

This is just a static case example; in case you have thousands of tags, you should use something like a Json Ajax call.

There are some configuration parameters, this is the complete list:

  1. tags: is a Json array of objects with “tag” and “freq” properties; freq is not mandatory if you do not use it for sorting. It is not mandatory if jsonUrl is specified.
  2. jsonUrl: will receive the text of current tag typed in the “search” parameter.
  3. autoFilter:  true/false  default=true when active shows only matching tags, “false” should be used for server-side filtering
  4. autoStart: true/false default=false when active the dropdown will appear straight on entering the field, otherwise only while typing
  5. sortBy: “frequency”|”tag”|”none”  default=”tag”. When sorting by frequency is on, the filler should report the “freq” property for each tag
  6. tagSeparator: default=”,” any separator char as space, comma, semicolon
  7. boldify: true/false default true “boldify” the matching part of tag in the dropdown box
  8. suggestedTags: callback function to retrieve an object array like [“sugestedtag1″,”sugestedtag2″,”suggestedtag3”].If this parameter is not present tag suggestion functionality will be kept hidden.
  9. suggestedTagsPlaceHolder: jQuery proxy for suggested tag placeholder. If it is not supplied it is created below the input field. When placeholder is supplied (hence unique), tagField should be applied on a single input.Something like  $(“#myTagFiled”).tagField(…) will work fine: $(“:text”).tagField(…) probably not!

so a more complex example will look like:

<link rel=stylesheet href="jquery.tagInput.css" type="text/css">
<script type="text/javascript" src="jquery.tagInput.js"></script> 

tags: <input type="text" size="80" id="tag" >
suggested tags: <span id="suggested" class="tagInputSuggestedTagList"></span> 

<script type="text/javascript">
  $(function(){
    $("#tag").tagInput({
      jsonUrl:"tags.jsp",
      sortBy:"frequency",
      suggestedTags:  ["jquery","tagging","tag","component"],
      tagSeparator:" ",
      autoFilter:false,
      autoStart:false,
      boldify:true,
      suggestedTagsPlaceHolder:$("#suggested")
    })
})
</script>

in this case the jsonUrl “tags.jsp” is a silly JSP page that will return 4 tags starting with the text typed by the user. Here the sample code:

<%@ page import="net.sf.json.JSONArray, net.sf.json.JSONObject" %><%
  JSONArray jsa= new JSONArray();
  String search=request.getParameter("search")
  search=null?"":search;
  for (int i=1;i<5;i++){
    JSONObject o= new JSONObject();
    o.element("tag",search+i);
    o.element("freq",i);
    jsa.add(o);
  }
  out.print(jsa.toString());
%>

This component is released under MIT license. Enjoy it!

Any feedback will be really appreciated.

Tagged as:

37 thoughts on “A delicious javascript tagging input field”

  1. This is quite nice!

    A couple of tweaks would improve it I think.

    1) If you start typing a tag, and then you backspace to delete what you have typed, the drop-down should disappear when there is no text left. E.g. I start typing “a”, the word “agile” appears in the drop-down – but if I delete the “a”, the word “agile” still shows up.

    2) If I arrow-down to select a word in the drop-down and then hit tab, that should be my chosen tag. Instead it loses focus and moves on.

  2. That’s a pretty useful post, both for the implementation and the list of alternatives. I’d been looking for something similar a while back.

    I agree with Ade on the two additions. Being able to hit tab is second nature for me when using delicious, so I think it’d be a good addition.

    Good work!

  3. I’ve just updated and renamed the component to jquery.tagInput (tagBox was already taken).

    New version features:

    1) esc key close the dropdown
    2) clearing the tag will close the dropdown
    3) tab on dropdown will select the tag

    fixed a bug on safari, and a strange behavior pressing return

    Cheers

  4. It acts strange when you type the same word twice.

    Try the “hi jquery bye jquery test jquery” string. It correctly shows the JQuery tag present. So click it. It now removes one occurence, and (incorrectly) shows the jquery tag as gone… while in fact there are still 2 occurences

  5. Great plugin, thanks for making it available.

    I had problems with it using jquery 1.4.2 where after entering the first tag, it would remove the dropdown div from the DOM and then never add it back in till I clicked off the field and added it back in. Making this change so we only hide and don’t remove fixed that behavior for me in 1.4.2:

    diff --git a/jquery.tagInput.js b/jquery.tagInput.js
    --- a/jquery.tagInput.js
    +++ b/jquery.tagInput.js
    @@ -198,7 +198,7 @@
           var sep= lastComma<=0? (""):(options.tagSeparator+ (options.tagSeparator==" "?"":" "));
           var newVal = (theInput.val().substr(0, lastComma) + sep + theRow.find(".tagInputLineTag").text()).trim();
           theInput.val(newVal);
    -      theDiv.hide().remove();
    +      theDiv.hide();
           $().oneTime(200, function() {
             theInput.focus();
           });
    
  6. Hi,

    Nice work ! I tried the downloaded version, but it worked in Chrome and Foxpro. Not in IE8. The strange thing is that your demopage works in IE8 without a problem, but the downloaded version does not. I tried to modify some includes to other Javascript sources and it technically worked then, but the list with possible values appears on top of the input field. Can you refresh the download-file, so I can use the correct one?

    Thank you!
    regards!

  7. Hi Roberto,

    It technically works fine, no Javascript errors, but the list with possible values now appears on top of the input field where it should appear directly underneath it.

    Regards
    Jay

  8. Quick question – how do you make the suggested tags come from the server instead of a static array? Is there a way to provide a URL for suggested tags? Thanks for creating this plugin!

  9. No, by default suggested tags are “static”, but you can fill it using a $.getJSON to get an array.

    Remember that this component uses two list of tags. The suggested ones are intended to be filled from an heuristic once, and then the tag list that can be dynamically determined by the user input. For the latter list of tags you can use an url that will receive the “search” parameter in order to reduce the set of proposed tags.

    Hope this helps,

    Roberto

  10. Hello,
    Great plugin and a review of alternatives! Thank you!
    There some Opera (10.10 on OSX) issues in the plugin:
    1. Strange look of tagInputDiv in demo.html. Screenshot:
    http://img708.imageshack.us/img708/2941/baddiv.png

    However everything woks fine on http://bugsvoice.com/applications/bugsVoice/site/test/tagInputDemo.jsp. Screenshot:
    http://img52.imageshack.us/img52/8017/gooddiv.png

    Demo starts to work fine after removing float:right; from .tagInputLineFreq.

    2. When tag input text field is placed inside a form and I try to select a suggested tag in tagInputDiv using Enter key the form gets submitted.

    3. Tag icon in the left part of the tag input field is placed a little bit down. Screenshot:
    http://img208.imageshack.us/img208/8509/iconvc.png

    4. (Not Opera specific) When I initially fill tag input field with tags (using the value attribute when I generate the page on the server), none of the suggested tags get selected automatically. Screenshot:
    http://img682.imageshack.us/img682/4836/noselection.png

    Sergey

  11. Hi,

    it is really a nice work,

    but still not working with jquery 1.4.2 from ajax call.
    it does the ajax call, but nothing appears.

    however if I change jquery to 1.3.x , it works fine

    Regards>G

  12. Thank you very much for sharing this. I’ve been searching for hours for “input tag” and was only finding basic information about the standard HTML input field.

    You might also mention Google Web Toolskits SuggestBox, which is similar.

  13. Well done sir! I’ve found it to work in all browsers. This plug-in probably saved me several days worth of custom development and many more in testing.

    I intend on populating the count with another value but what could I do to extend it to show a 3rd value without breaking existing code. For example, let’s say I do a D&B look up on a company name, I would show the company name, taxid, and a tertiary element so let’s call it “company ID”.

    any suggestions?

  14. Hi,

    I use your component (thanks) with layout:

    [input type=text] [input type=button]

    On IE8 Compat mode (haven’t tried other IEs) the suggestion dropdown “__tagInputDiv” appears on top of the [input type=text], obscuring it.

    My solution was to explicitly set the vertical position (l.124):

    theDiv.css({
    left:theInput.position().left,
    top:theInput.position().top+theInput.outerHeight()+1
    });

    Positioning isn’t perfectly consistent across all browsers, though, but the “+1” seems the best compromise.

  15. This wasn’t working on jquery 1.6. Simple change on lines 324-25. There are 2 calls to $().stopTime and $().oneTime which need to be changed to $(document).stopTime and $(document).oneTime. It works for me, hopefully save somebody else some time.

      1. Hey Is it possible to use “name: property” instead of the default tag: property….

        I have a json which looks like this….
        {“name”:”Ipsum”,”frequency”:4}

        I am not able to get the autocomplete feature to work.

  16. Hey I got the above name property converted to tag property using to_json method.

    But now i am getting the following errors:

    I am Using Jquery 1.6.1

    Error: $().stopTime is not a function
    Source File: http://localhost:3000/javascripts/jquery.tagInput.js?1316199857
    Line: 324

    Error: $(document).stopTime is not a function
    Source File: http://localhost:3000/javascripts/jquery.tagInput.js?1316199857
    Line: 174

    Warning: The ‘charCode’ property of a keyup event should not be used. The value is meaningless.
    Source File: http://localhost:3000/posts/36/edit
    Line: 0

Leave a Reply

Your email address will not be published. Required fields are marked *