I have implemented some extra functionality for the tag-it JavaScript plugin, where I need an option where availableTag
s are displayed in one box, and the user can click these options to add them to the actual tag input (selection box is on the right, real input on the left):
The user can then click on the selected tags to move them back to the selection box and remove them from the input.
My implementation works fine, but I am pretty sure it can be greatly improved, perhaps by integrating it with a fork of the plugin (I am unsure of how to do this).
HTML
First function adds the selected tag to the input and styles it
<script type="text/javascript">
function addSelectedColourToInput(colour) {
// add tag to input
$('#colourTagInput').tagit('createTag', colour);
// get the newly created tag
var colourTagLi = $('#colourTagInput').find('.tagit-label:contains("' + colour + '")').parent();
processNewColourTag(colourTagLi, colour);
}
function processNewColourTag(tagLi, colour) {
// remove from selection box
$('#colourTagSelection').find('.tagit-label:contains("' + colour + '")').parent().remove();
// style
tagLi.css({ 'background': colour }).addClass('colour-tag');
// click to remove
tagLi.click(function () { $('#colourTagInput').tagit('removeTagByLabel', colour); });
}
document.ready retrieves the available tags from a c#
List (using Razor)
$(document).ready(function () {
// Set available colour tags
var availableColourTags = [];
@{
foreach (var colourTag in MasterTags.Where(t => t.Type == "Colour"))
{
@:availableColourTags.push("@colourTag.Name");
}
}
Initialise tagit with my custom clickSelector
option
// after remove colour tag event
var removeColour = function (colour) {
$('#colourTagSelection')
.append('<li onclick="addSelectedColourToInput(\''+colour+'\')" class="tagit-choice ui-widget-content ui-state-default ui-corner-all tagit-choice-read-only selector-tag colour-tag" style="background:' + colour + ';"><span class="tagit-label">' + colour + '</span></li>');
};
// tag-it init
var colourTags = $('#colourTagInput');
colourTags.tagit({
availableTags: availableColourTags,
singleField: true,
singleFieldNode: $('#colourTagField'),
clickSelector: $('#colourTagSelection'),
afterTagRemoved: function (evt, ui) {
removeColour(colourTags.tagit('tagLabel', ui.tag));
}
});
Prevents selected items resetting on refresh (this only seems to work in FireFox)
// keep existing items on page refresh (only seems to work in Firefox)
$('#colourTagInput li').each(function () {
var colour = $(this).find('.tagit-label').text();
if (colour == '') { return true; }
processNewColourTag($(this), colour);
});
Without this, the tag input value is not passed to the controller
// Allow validation on hidden fields!
$.validator.setDefaults({
ignore: [],
});
});
</script>
The form input area:
<div class="form-group">
@Html.LabelFor(model => model.ColourTags, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-5">
@Html.HiddenFor(model => model.ColourTags, new { @class = "form-control", @name = "tags", @id = "colourTagField" } )
<ul id="colourTagInput" class="form-control"></ul>
@Html.ValidationMessageFor(model => model.ColourTags, "", new { @class = "text-danger" })
</div>
<div class="col-md-5">
<ul id="colourTagSelection" class="form-control tagit ui-widget ui-widget-content ui-corner-all"></ul>
</div>
</div>
tag-it.js
added option:
clickSelector : null
in _create
// Add options to selection box
if (this.options.clickSelector != null) {
var selectionBox = this.options.clickSelector;
var availableTags = this.options.availableTags;
for (i = 0; i < availableTags.length; i++) {
selectionBox.append('<li onclick="addSelectedColourToInput(\'' + availableTags[i] +'\')" class="tagit-choice ui-widget-content ui-state-default ui-corner-all tagit-choice-read-only selector-tag colour-tag" style="background:' + availableTags[i] + ';"><span class="tagit-label">' + availableTags[i] + '</span></li>');
}
}
I would really appreciate any tips or guidance, and let me know if I can add anything to the question!