How to modify jquery tag-it plugin: limit number of tags and only allow available tags
first add custom options (maxTags and onlyAvailableTags) to the plugin file like so...
options: {
itemName : 'item',
fieldName : 'tags',
availableTags : [],
tagSource : null,
removeConfirmation: false,
caseSensitive : true,
maxTags : 9999,//maximum tags allowed default almost unlimited
onlyAvailableTags : false,//boolean, allows tags that are in availableTags or not
allowSpaces: false,
animate: true,
singleField: false,
singleFieldDelimiter: ',',
singleFieldNode: null,
tabIndex: null,
onTagAdded : null,
onTagRemoved: null,
onTagClicked: null
}
next replace the _isNew function with this one...
_isNew: function(value) {
var that = this;
var isNew = true;
var count = 0;
this.tagList.children('.tagit-choice').each(function(i) {
count++;
if (that._formatStr(value) == that._formatStr(that.tagLabel(this))|| count >= that.options.maxTags) {
isNew = false;
return false;
}
if (that.options.onlyAvailableTags && $.inArray(that._formatStr(value),that.options.availableTags)==-1) {
isNew = false;
return false;
}
});
return isNew;
}
Now you can use the options when you initialize tagit. only the sampleTags are allowed with a maximum of 3 tags
$(function(){
var sampleTags = ['php', 'coldfusion', 'javascript', 'asp', 'ruby', 'python'];
//-------------------------------
// Tag events
//-------------------------------
var eventTags = $('#s_tags');
eventTags.tagit({
availableTags: sampleTags,
caseSensitive: false,
onlyAvailableTags: true,
maxTags:3,
})
});
You can just provide this parameter to .tagit:
beforeTagAdded: function(event, ui) {
if($.inArray(ui.tagLabel, availableTags)==-1) return false;
}
where availableTags is your autocomplete array.
Regarding @snuggles query below, I believe (my limited familiarity with the json protocols notwithstanding) you could probably do something like this:
//define autocomplete source
var returnedUsers, jsonUrl = "http://[your server]/user_lookup";
$.getJSON(jsonUrl,function(json){
returnedUsers = json; // or whatever handler you need to use
});
// instantiate tagit
$("#ccList").tagit({
availableTags: returnedUsers,
beforeTagAdded: function(event, ui) {
// only allow existing values
if($.inArray(ui.tagLabel, returnedUsers)==-1) return false;
// limit length
if ($(".tagit-choice").length >= 5) return false;
});
Update 2013-03-13:
First, re-reading the OP, I'm now not clear on if I'm really answering the question, as they specifically asked how to modify the tag-it plugin in order to accomplish the two tweaks. If the OP really wants to modify the plug-in, that's fine, but as I said before, it seems lame that you would have to--and you don't!
So here's how to accomplish both things without modifying the plugin :)
first, you do have to have some sort of global array to put stuff into, if there's a better way to do that, lmk, but otherwise:
var returnedUsers = [];
Then:
$("#ccList").tagit({
autocomplete: {
source: function( request, response ) {
$.ajax({
url: "http://[your server]/user_lookup",
dataType: "json",
data: {
term: request.term
},
success: function( data ) {
returnedUsers = data;
response( $.map( data, function( item ) {
return {
label: item,
value: item
}
}));
},
error: function(xhr, status, error) {
returnedUsers = [];
}
});
}
},
beforeTagAdded: function(event, ui) {
if ($.inArray(ui.tagLabel, returnedUsers)==-1)
return false;
if ($(".tagit-choice").length >= 5)
return false;
}
});
So basically you have to point the autocomplete.source at a function in which you handle all the ajax stuff and build your own list. Note that doing this allows you some flexbility in what you return from your cgi back end (ie, it doesn't have to be an array of strings, it could be an array of hashes which you parse and build into a custom list). Also note that this would not be needed if only I could find a way to access the list of returned values from the more basic autocomplete function in the 'beforeTagAdded' event--something Jack implied was possible but did not elaborate on.
Once you've build the array of things to display you return it using the response() function. At the same time now you have a copy of that list in 'returnedUsers', which you can use in the 'beforeTagAdded' function. Also, it's simple to limit the number of tags you allow in the box by just counting how many are already in there and returning false if it's >= to that number. Not sure if that's the best way to get the count, but it definitely works.
I know this is old, and I'm sure any expert would find a million ways to do it better than me, but I haven't found anyone that's laid out how to work around this issue better than what I've outlined without actually changing the plugin, which I do not prefer to do. HTH!