Tags! tagtacular.js

About Tagtacular

Tagtacular is an open source jQuery plugin by Eric Burns for managing tags. It is released under the MIT License, the same license jQuery and jQueryUI use.

The goals of this project are that a tags management jQuery plugin should:

Tagtacular on GitHub
Download Tagtacular 1.1.0
Complete Documentation

Examples and Demo

Example 1: Textlike

This is styled very simply. Enter or comma after typing a tag name adds it. Backspace deletes the last tag. Always in edit mode.

	var tags1 = $('#tagtacular_1').tagtacular({
		entityId: 101,
		entityTags: ['Boston', 'Chicago', 'New York City', 'Atlanta'],
		systemTags: ['Austin', 'Dallas', 'Raleigh', 'Richmond', 'Augusta', 'Portland', 'Durham', 'Memphis', 'Nashville', 'Seattle', 'Toronto'],
		configTagSeparator: ', ',
		configShowAddButton: false,
		configShowSwitchButton: false,
		configDeleteLastOnEmptyKeys: [8],
		configSortTags: false
	})	

Example 2: Keep it Simple

Using the tagtacular_basic style and the default configuration. Edit and view modes, starting in edit, with Add and Switch Mode buttons. Enter or comma add a new tag, as does the Add button.

	var tags2 = $('#tagtacular_2').tagtacular({
		entityId: 102,
		entityTags: ['Boston', 'Chicago', 'New York City', 'Atlanta'],
		systemTags: ['Austin', 'Dallas', 'Raleigh', 'Richmond', 'Augusta', 'Portland', 'Durham', 'Memphis', 'Nashville', 'Seattle', 'Toronto']
	})

Example 3: Limit to Existing Tags

Similar to the last example, but always in edit mode (no mode switch button). No add button or add delimiters, so we restrict the user to adding from a predefined list of tags.

	var tags3 = $('#tagtacular_3').tagtacular({
		entityId: 103,
		entityTags: ['Alpha', 'Beta', 'Epsilon'],
		systemTags: ['Alpha', 'Beta', 'Gamma', 'Delta', 'Epsilon', 'Zeta', 'Eta', 'Theta', 'Iota', 'Kappa', 
		             'Lambda', 'Mu', 'Nu', 'Xi', 'Omicron', 'Pi', 'Rho', 'Sigma', 'Tau', 'Upsilon', 'Phi',
		             'Chi', 'Psi', 'Omega'],
		configShowAddButton: false,
		configDelimiters: []
	})

Example 4: Custom Validator and Commit Functions

Using the tagtacular_basic.blue style. Here we change validation behavior and run code to commit changes to the backend (simulated by sending a success message two seconds later). This instance is also configured to start in view mode. This is also a good example of how you can call any callback defined in your settings object from any other callback that gets a settings object.

	var tags4 = $('#tagtacular_4').tagtacular({
		entityId: 104,
		entityTags: ['Boston', 'Chicago', 'New York City', 'Atlanta'],
		systemTags: ['Austin', 'Dallas', 'Raleigh', 'Richmond', 'Augusta', 'Portland', 'Durham', 'Memphis', 'Nashville', 'Seattle', 'Toronto'],
		configMinimumTagLength: 2,
		configMaximumTagLength: 24,
		validationPattern: /^[0-9A-Za-z\.]+$/,
		messageTagNameInvalid: 'illegal characters: tag names can only include letters, numbers, and periods',
		commitAddTag: function(tag, entityId, settings) {
			setTimeout(function() {
				settings.flashSuccess('saved add of ' + tag + ' to entity #' + entityId);
			}, 2000);
		},
		commitRemoveTag: function(tag, entityId, settings) {
			setTimeout(function() {
				settings.flashSuccess('saved remove of ' + tag + ' from entity #' + entityId);
			}, 2000);
		},
		mode: 'view'
	})

Example 5: Custom Tags

Using getTagHtml setting to define custom tag html. Here we make each tag a link to a Wikipedia search. You could apply this general method to make each tag link to a search that returned all entities with that tag in your web app. We're also applying a filter on the tag names themselves using formatTagName and configFormatTagNamesOnInit. The first letter of each word is capitalized and the rest is converted to lower case.

	var tags5 = $('#tagtacular_5').tagtacular({
		entityId: 105,
		entityTags: ['boston', 'chicago', 'new york city', 'atlanta'],
		systemTags: ['austin', 'dallas', 'raleigh', 'richmond', 'augusta', 'portland', 'durham', 'memphis', 'nashville', 'seattle', 'toronto'],
		getTagHtml: function(tag, mode, settings) {
			var encodedTag = tag.replace(' ', '+');
			encodedTag = encodedTag.replace('-', '+');
			encodedTag = encodedTag.replace('_', '+');

			var url = 'http://en.wikipedia.org/wiki/Special:Search?search=' + encodedTag + '&go=Go';

			if (mode=='edit') {
				return '<span class="tagtacular_tag"><a href="'+url+'" target="_blank" ><span class="tagtacular_value">'+tag+
				'</span></a>&nbsp;<a class="tagtacular_delete" href="#">'+settings.configDeleteSymbol+
				'</a><span class="tagtacular_delim">'+settings.configTagSeparator+'</span></span>';
			} else if (mode=='view') {
				return '<span class="tagtacular_tag"><a href="'+url+'" target="_blank" ><span class="tagtacular_value">'+tag+
				'</span></a><span class="tagtacular_delim">'+settings.configTagSeparator+'</span></span>';
			}
		},
		formatTagName: function(tag) {
			// capitalize first letter of each word and make the rest lower case
			tag = tag.toLowerCase();
			return tag.replace(/(^([a-zA-Z\p{M}]))|([ -_][a-zA-Z\p{M}])/g,
				function($1){
					return $1.toUpperCase();
				});
		},
		configFormatTagNamesOnInit: true		
	});

Example 6: Edit Bar On Top

Moving the edit tray to before the tag tray with the configEditTrayFirst setting. More layout customization would have been possible with the getLayoutHtml callback setting. Also, we're giving the buttons some custom text. We're also disabling add tag on switch mode and setting some placeholder text.

	var tags6 = $('#tagtacular_6').tagtacular({
		entityId: 106,
		entityTags: ['Boston', 'Chicago', 'New York City', 'Atlanta'],
		systemTags: ['Austin', 'Dallas', 'Raleigh', 'Richmond', 'Augusta', 'Portland', 'Durham', 'Memphis', 'Nashville', 'Seattle', 'Toronto'],
		configEditTrayFirst: true,
		configAddButtonText: 'Boom! Add it.',
		configSwitchButtonTextInEdit: 'No more change!',
		configSwitchButtonTextInView: 'It\'s time for a change!',
		configPlaceholderText: 'Wanna add a tag?',
		configAddOnSwitch: false
	});

Example 7: Limit to Existing Tags, Use a Select Box

Let's use a select box! Also, disable edit/view mode switching by setting configShowSwitchButton to false.

	var tags7 = $('#tagtacular_7').tagtacular({
		entityId: 107,
		entityTags: ['Alpha', 'Beta', 'Epsilon'],
		systemTags: ['Alpha', 'Beta', 'Gamma', 'Delta', 'Epsilon', 'Zeta', 'Eta', 'Theta', 'Iota', 'Kappa', 
		             'Lambda', 'Mu', 'Nu', 'Xi', 'Omicron', 'Pi', 'Rho', 'Sigma', 'Tau', 'Upsilon', 'Phi',
		             'Chi', 'Psi', 'Omega'],
		configEditTrayFirst: true,
		configSelectBox: true,
		configShowSwitchButton: false
	});

Example 8: Limit to Existing Tags, but still use an autocomplete

An autocomplete that limits you to existing tags.

	var tags8 = $('#tagtacular_8').tagtacular({
		entityId: 108,
		entityTags: ['Alpha', 'Beta', 'Epsilon'],
		systemTags: ['Alpha', 'Beta', 'Gamma', 'Delta', 'Epsilon', 'Zeta', 'Eta', 'Theta', 'Iota', 'Kappa', 
		             'Lambda', 'Mu', 'Nu', 'Xi', 'Omicron', 'Pi', 'Rho', 'Sigma', 'Tau', 'Upsilon', 'Phi',
		             'Chi', 'Psi', 'Omega'],
		configEditTrayFirst: true,
		configLimitToExisting: true
	});

Example 9: Use an API as the data source

An autocomplete that limits you to existing tags. remoteDataSource is a callback compatible with jQueryUI Autocompleter's source callbacks.

	var tags9 = $('#tagtacular_9').tagtacular({
		entityId: 109,
		entityTags: ['Canada', 'France', 'Japan'],
		remoteDataSource: function(request, response) {
			var url = 'https://restcountries.eu/rest/v1/name/' + encodeURIComponent(request.term);

			$.get(url, function(data){
				processed = $(data).map(function() { return this.name; });

				// restcountries.eu matches alternate spellings by default (which are alternate names in some cases). 
				// We're throwing out those matches in order to not confuse the user.
				processed = processed.filter(function(i, value) {
					return value.toLowerCase().indexOf(request.term.toLowerCase()) >= 0;
				});
				response(processed);
			});
		},
		configEditTrayFirst: true,
		configLimitToExisting: true,
		configShowAddButton: false,
		configShowSwitchButton: false
	});
tagtacular.js: tags should be easy.