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!
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.
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.
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):
The documentation is little bit weak but usage is still easy:
$(“#tags”).ptags();
In the same flow is JTAG by Benoît Vidis
cute, but not my prefered one.
Another component that cought my attention was MagicTags by Dave Geddes.
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.
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:
- supporting already used tag list, eventually filled with an Ajax call
- filtering results using user inputs
- supporting suggested tags, with “smart” selection
- supporting multiple separators
- supporting frequency
- having a nice-ligth-stylish look
- be delicious!
After a couple of days of programming this is the result:
typing on the text field a drop down will show your used tags:
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:
- 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.
- jsonUrl: will receive the text of current tag typed in the “search” parameter.
- autoFilter: true/false default=true when active shows only matching tags, “false” should be used for server-side filtering
- autoStart: true/false default=false when active the dropdown will appear straight on entering the field, otherwise only while typing
- sortBy: “frequency”|”tag”|”none” default=”tag”. When sorting by frequency is on, the filler should report the “freq” property for each tag
- tagSeparator: default=”,” any separator char as space, comma, semicolon
- boldify: true/false default true “boldify” the matching part of tag in the dropdown box
- 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.
- 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.
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.
Thank Ade for your feedback.
I’ll release a new version soon. Stay tuned.
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!
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
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
Hi Kone,
Thank you for your feedback!
I’ve just fixed this issue, and released new files.
Try it now (refresh the browser!).
Cheers
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:
Thank you Ted,
I didn’t check this component with 1.4.x.
I’ll integrate your fix and will perform a complete testing with 1.4.x in the next week.
Cheers
Tested and fixed for jquery 1.4.2
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!
Hi,
yes there was a bug on ie.
Just fixed, thanks.
Let me know.
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
We will work on IE full compatibility on next weeks
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!
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
Finally I found this – THANK YOU.. I had been search and trying dozens of plugins, constantly being disappointed. thank you!
Is there a way to send additional data to the server along with the jsonUrl?
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
Hi!
Thanks for sharing this!
(no issues to report) 🙂
Davide 🙂
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
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.
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?
Hi Jose,
this component is strictly linked to a Date object. I think you can only get inspiration from layout, but I think will be very hard to reuse something.
Good luck!
Hi
Thanks a lot for sharing this information. Gave me a lot of ideas.
Unfortunately this one didn’t suit my needs. So I’m also working on a tagging field by my self.
You can check it out here. http://www.superbly.ch/?p=31
Keep the good work up.
cheers manu
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.
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.
Found another one, $(), at line 212.
Thanks for your fixes!
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.
Yes, but you have to change some lines of code. E.g. 235-239, 250 changing “.tag” to “.name”, but probably it’s easier to copy your array in a new one with “tag:”
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
there is a dependency to the jquery timers plugin (http://plugins.jquery.com/project/timers), you must include it.