From 411f289e3d99e4e41f631f368f18c57b00b5d89e Mon Sep 17 00:00:00 2001 From: Max Favilli Date: Thu, 22 Aug 2013 12:43:13 +0200 Subject: [PATCH] added tagmanager v3.0.0 tagmanager is a jQuery plugin (working nicely with Bootstrap) to manage tags input from users --- ajax/libs/tagmanager/3.0.0/tagmanager.css | 102 +++++ ajax/libs/tagmanager/3.0.0/tagmanager.js | 501 +++++++++++++++++++++ ajax/libs/tagmanager/3.0.0/tagmanager.less | 178 ++++++++ ajax/libs/tagmanager/package.json | 41 ++ 4 files changed, 822 insertions(+) create mode 100644 ajax/libs/tagmanager/3.0.0/tagmanager.css create mode 100644 ajax/libs/tagmanager/3.0.0/tagmanager.js create mode 100644 ajax/libs/tagmanager/3.0.0/tagmanager.less create mode 100644 ajax/libs/tagmanager/package.json diff --git a/ajax/libs/tagmanager/3.0.0/tagmanager.css b/ajax/libs/tagmanager/3.0.0/tagmanager.css new file mode 100644 index 000000000..837df6268 --- /dev/null +++ b/ajax/libs/tagmanager/3.0.0/tagmanager.css @@ -0,0 +1,102 @@ +/* + * DO NOT EDIT THIS FILE DIRECTLY + * Compiled from bootstrap-tagmanager.less based on Bootstrap 2.3.1 variables + * https://github.com/twitter/bootstrap/blob/master/less/variables.less + */ +.tm-tag { + color: #555555; + background-color: #f5f5f5; + border: #bbbbbb 1px solid; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset; + display: inline-block; + border-radius: 3px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + margin: 0 5px 5px 0; + padding: 4px; + text-decoration: none; + transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s; + -moz-transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s; + -webkit-transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s; + vertical-align: middle; +} +.tm-tag .tm-tag-remove { + color: #000000; + font-weight: bold; + margin-left: 4px; + opacity: 0.2; +} +.tm-tag .tm-tag-remove:hover { + color: #000000; + text-decoration: none; + opacity: 0.4; +} +.tm-tag.tm-tag-warning { + color: #945203; + background-color: #f2c889; + border-color: #f0a12f; +} +.tm-tag.tm-tag-error { + color: #84212e; + background-color: #e69ca6; + border-color: #d24a5d; +} +.tm-tag.tm-tag-success { + color: #638421; + background-color: #cde69c; + border-color: #a5d24a; +} +.tm-tag.tm-tag-info { + color: #4594b5; + background-color: #c5eefa; + border-color: #5dc8f7; +} +.tm-tag.tm-tag-inverse { + color: #cccccc; + background-color: #555555; + border-color: #333333; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2) inset; +} +.tm-tag.tm-tag-inverse .tm-tag-remove { + color: #ffffff; +} +.tm-tag.tm-tag-large { + font-size: 16.25px; + border-radius: 4px; + padding: 11px 7px; +} +.tm-tag.tm-tag-small { + font-size: 11.049999999999999px; + border-radius: 3px; + padding: 2px 4px; +} +.tm-tag.tm-tag-mini { + font-size: 9.75px; + border-radius: 2px; + padding: 0px 2px; +} +.tm-tag.tm-tag-plain { + color: #333333; + box-shadow: none; + background: none; + border: none; +} +.tm-tag.tm-tag-disabled { + color: #aaaaaa; + background-color: #e6e6e6; + border-color: #cccccc; + box-shadow: none; +} +.tm-tag.tm-tag-disabled .tm-tag-remove { + display: none; +} +input[type="text"].tm-input { + margin-bottom: 5px; + vertical-align: middle !important; +} +.control-group.tm-group { + margin-bottom: 5px; +} +.form-horizontal .control-group.tm-group { + margin-bottom: 15px; +} diff --git a/ajax/libs/tagmanager/3.0.0/tagmanager.js b/ajax/libs/tagmanager/3.0.0/tagmanager.js new file mode 100644 index 000000000..a0d14c0ae --- /dev/null +++ b/ajax/libs/tagmanager/3.0.0/tagmanager.js @@ -0,0 +1,501 @@ +/* =================================================== + * tagmanager.js v3.0.0 + * http://welldonethings.com/tags/manager + * =================================================== + * Copyright 2012 Max Favilli + * + * Licensed under the Mozilla Public License, Version 2.0 You may not use this work except in compliance with the License. + * + * http://www.mozilla.org/MPL/2.0/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + +(function ($) { + + "use strict"; + + if (typeof console === "undefined" || typeof console.log === "undefined") { + console = {}; + console.log = function () { }; + } + + $.fn.tagsManager = function (options, tagToManipulate) { + var obj = this; + var rndid = ""; + + var tagManagerOptions = { + prefilled: null, + CapitalizeFirstLetter: false, + preventSubmitOnEnter: true, // deprecated + isClearInputOnEsc: true, // deprecated + AjaxPush: null, + AjaxPushAllTags: null, + AjaxPushParameters: null, + delimiters: [9, 13, 44], // tab, enter, comma + backspace: [8], + maxTags: 0, + hiddenTagListName: null, // deprecated + hiddenTagListId: null, // deprecated + replace: true, + output: null, + deleteTagsOnBackspace: true, // deprecated + tagsContainer: null, + tagCloseIcon: 'x', + tagClass: '', + validator: null, + onlyTagList: false + }; + + // exit when no matched elements + if (!(0 in this)) { + return this; + } + + if (typeof options == 'string') { + tagManagerOptions = obj.data("tm_options"); + } else { + $.extend(tagManagerOptions, options); + obj.data("tm_options", tagManagerOptions); + } + + if (typeof options == 'string') { + rndid = obj.data("tm_rndid"); + } else { + var albet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + for (var i = 0; i < 5; i++) + rndid += albet.charAt(Math.floor(Math.random() * albet.length)); + obj.data("tm_rndid", rndid); + } + + if (tagManagerOptions.replace === true && tagManagerOptions.hiddenTagListName === null) { + var original_name = obj.attr('name'); + tagManagerOptions.hiddenTagListName = original_name; + obj.attr('name', "display-" + rndid); + } + if (tagManagerOptions.hiddenTagListName === null) { + tagManagerOptions.hiddenTagListName = "hidden-" + rndid; + } + + var delimiters = tagManagerOptions.delimeters || tagManagerOptions.delimiters; // 'delimeter' is deprecated + // delimiter values to be handled as key codes + var keyNums = [9, 13, 17, 18, 19, 37, 38, 39, 40]; + var delimiterChars = [], delimiterKeys = []; + $.each(delimiters, function (i, v) { + if ($.inArray(v, keyNums) != -1) { + delimiterKeys.push(v); + } else { + delimiterChars.push(v); + } + }); + var baseDelimiter = String.fromCharCode(delimiterChars[0] || 44); + var backspace = tagManagerOptions.backspace; + var tagBaseClass = 'tm-tag'; + var inputBaseClass = 'tm-input'; + + if ($.isFunction(tagManagerOptions.validator)) obj.data('validator', tagManagerOptions.validator); + + + //var ajaxPolling = function (query, process) { + // if (typeof (tagManagerOptions.typeaheadAjaxSource) == "string") { + // $.ajax({ + // cache: false, + // type: "POST", + // contentType: "application/json", + // dataType: "json", + // url: tagManagerOptions.typeaheadAjaxSource, + // data: JSON.stringify({ typeahead: query }), + // success: function (data) { onTypeaheadAjaxSuccess(data, false, process); } + // }); + // } + //}; + + + var tagClasses = function () { + // 1) default class (tm-tag) + var cl = tagBaseClass; + // 2) interpolate from input class: tm-input-xxx --> tm-tag-xxx + if (obj.attr('class')) { + $.each(obj.attr('class').split(' '), function (index, value) { + if (value.indexOf(inputBaseClass + '-') != -1) { + cl += ' ' + tagBaseClass + value.substring(inputBaseClass.length); + } + }); + } + // 3) tags from tagClass option + cl += (tagManagerOptions.tagClass ? ' ' + tagManagerOptions.tagClass : ''); + return cl; + }; + + var trimTag = function (tag) { + tag = $.trim(tag); + // truncate at the first delimiter char + var i = 0; + for (i; i < tag.length; i++) { + if ($.inArray(tag.charCodeAt(i), delimiterChars) != -1) break; + } + return tag.substring(0, i); + }; + + var showOrHide = function () { + var tlis = obj.data("tlis"); + if (tagManagerOptions.maxTags > 0 && tlis.length < tagManagerOptions.maxTags) { + obj.show(); + obj.trigger('tm:show'); + } + if (tagManagerOptions.maxTags > 0 && tlis.length >= tagManagerOptions.maxTags) { + obj.hide(); + obj.trigger('tm:hide'); + } + }; + + var popTag = function () { + var tlis = obj.data("tlis"); + var tlid = obj.data("tlid"); + + if (tlid.length > 0) { + var tagId = tlid.pop(); + + var tagBeingRemoved = tlis[tlis.length - 1]; + obj.trigger('tm:beforePop', tagBeingRemoved); + tlis.pop(); + + // console.log("TagIdToRemove: " + tagId); + $("#" + rndid + "_" + tagId).remove(); + refreshHiddenTagList(); + obj.trigger('tm:afterPop', tagBeingRemoved); + // console.log(tlis); + } + + showOrHide(); + //if (tagManagerOptions.maxTags > 0 && tlis.length < tagManagerOptions.maxTags) { + // obj.show(); + //} + }; + + var empty = function () { + var tlis = obj.data("tlis"); + var tlid = obj.data("tlid"); + + while (tlid.length > 0) { + var tagId = tlid.pop(); + tlis.pop(); + // console.log("TagIdToRemove: " + tagId); + $("#" + rndid + "_" + tagId).remove(); + refreshHiddenTagList(); + // console.log(tlis); + } + obj.trigger('tm:emptied', null); + + showOrHide(); + //if (tagManagerOptions.maxTags > 0 && tlis.length < tagManagerOptions.maxTags) { + // obj.show(); + //} + }; + + var refreshHiddenTagList = function () { + var tlis = obj.data("tlis"); + var lhiddenTagList = obj.data("lhiddenTagList"); + + if (lhiddenTagList) { + $(lhiddenTagList).val(tlis.join(baseDelimiter)).change(); + } + + obj.trigger('tm:refresh', tlis.join(baseDelimiter)); + }; + + var spliceTag = function (tagId) { + var tlis = obj.data("tlis"); + var tlid = obj.data("tlid"); + + var p = $.inArray(tagId, tlid); + + // console.log("TagIdToRemove: " + tagId); + // console.log("position: " + p); + + if (-1 != p) { + var tagBeingRemoved = tlis[p]; + + obj.trigger('tm:beforeSplice', tagBeingRemoved); + + $("#" + rndid + "_" + tagId).remove(); + tlis.splice(p, 1); + tlid.splice(p, 1); + refreshHiddenTagList(); + + obj.trigger('tm:afterSplice', tagBeingRemoved); + + // console.log(tlis); + } + + + showOrHide(); + //if (tagManagerOptions.maxTags > 0 && tlis.length < tagManagerOptions.maxTags) { + // obj.show(); + //} + }; + + var pushAllTags = function (e, tag) { + if (tagManagerOptions.AjaxPushAllTags) { + if (e.type != 'tm:afterPush' || $.inArray(tag, tagManagerOptions.prefilled) == -1) { + var tlis = obj.data("tlis"); + $.post(tagManagerOptions.AjaxPush, { tags: tlis.join(baseDelimiter) }); + } + } + }; + + var pushTag = function (tag, ignore_events) { + tag = trimTag(tag); + + if (!tag || tag.length <= 0) return; + + if (tagManagerOptions.CapitalizeFirstLetter && tag.length > 1) { + tag = tag.charAt(0).toUpperCase() + tag.slice(1).toLowerCase(); + } + + // call the validator (if any) and do not let the tag pass if invalid + if (obj.data('validator') && !obj.data('validator')(tag)) return; + + var tlis = obj.data("tlis"); + var tlid = obj.data("tlid"); + + // dont accept new tags beyond the defined maximum + if (tagManagerOptions.maxTags > 0 && tlis.length >= tagManagerOptions.maxTags) return; + + var alreadyInList = false; + var tlisLowerCase = tlis.map(function (elem) { return elem.toLowerCase(); }); + var p = $.inArray(tag.toLowerCase(), tlisLowerCase); + if (-1 != p) { + // console.log("tag:" + tag + " !!already in list!!"); + alreadyInList = true; + } + + if (alreadyInList) { + var pTagId = tlid[p]; + $("#" + rndid + "_" + pTagId).stop() + .animate({ backgroundColor: tagManagerOptions.blinkBGColor_1 }, 100) + .animate({ backgroundColor: tagManagerOptions.blinkBGColor_2 }, 100) + .animate({ backgroundColor: tagManagerOptions.blinkBGColor_1 }, 100) + .animate({ backgroundColor: tagManagerOptions.blinkBGColor_2 }, 100) + .animate({ backgroundColor: tagManagerOptions.blinkBGColor_1 }, 100) + .animate({ backgroundColor: tagManagerOptions.blinkBGColor_2 }, 100); + } else { + if(!ignore_events) + obj.trigger('tm:beforePush', tag); + + var max = Math.max.apply(null, tlid); + max = max == -Infinity ? 0 : max; + + var tagId = ++max; + tlis.push(tag); + tlid.push(tagId); + + if (!ignore_events) + if (tagManagerOptions.AjaxPush != null) { + if ($.inArray(tag, tagManagerOptions.prefilled) == -1) { + $.post(tagManagerOptions.AjaxPush, $.extend({ tag: tag }, tagManagerOptions.AjaxPushParameters)); + } + } + + // console.log("tagList: " + tlis); + + var newTagId = rndid + '_' + tagId; + var newTagRemoveId = rndid + '_Remover_' + tagId; + var escaped = $("").text(tag).html(); + + var html = ''; + html += '' + escaped + ''; + html += ''; + html += tagManagerOptions.tagCloseIcon + ' '; + var $el = $(html); + + if (tagManagerOptions.tagsContainer != null) { + $(tagManagerOptions.tagsContainer).append($el); + } else { + if (tagId > 1) { + var lastTagId = tagId - 1; + var lastTagObj = $("#" + rndid + "_" + lastTagId); + lastTagObj.after($el); + } else { + obj.before($el); + } + } + + $el.find("#" + newTagRemoveId).on("click", obj, function (e) { + e.preventDefault(); + var TagIdToRemove = parseInt($(this).attr("TagIdToRemove")); + spliceTag(TagIdToRemove, e.data); + }); + + refreshHiddenTagList(); + + if (!ignore_events) + obj.trigger('tm:afterPush', tag); + + showOrHide(); + //if (tagManagerOptions.maxTags > 0 && tlis.length >= tagManagerOptions.maxTags) { + // obj.hide(); + //} + } + obj.val(""); + }; + + var prefill = function (pta) { + $.each(pta, function (key, val) { + pushTag(val,true); + }); + }; + + var killEvent = function (e) { + e.cancelBubble = true; + e.returnValue = false; + e.stopPropagation(); + e.preventDefault(); + }; + + var keyInArray = function (e, ary) { + return $.inArray(e.which, ary) != -1 + }; + + var applyDelimiter = function (e) { + pushTag(obj.val()); + e.preventDefault(); + }; + + var returnValue = null; + this.each(function () { + + if (typeof options == 'string') { + switch (options) { + case "empty": + empty(); + break; + case "popTag": + popTag(); + break; + case "pushTag": + pushTag(tagToManipulate); + break; + case "tags": + returnValue = { tags: obj.data("tlis") }; + break; + } + return; + } + + // prevent double-initialization of TagManager + if ($(this).data('tagManager')) { return false; } + $(this).data('tagManager', true); + + // store instance-specific data in the DOM object + var tlis = new Array(); + var tlid = new Array(); + obj.data("tlis", tlis); //list of string tags + obj.data("tlid", tlid); //list of ID of the string tags + + if (tagManagerOptions.output == null) { + var hiddenObj = jQuery('', { + type: 'hidden', + name: tagManagerOptions.hiddenTagListName + }); + obj.after(hiddenObj); + obj.data("lhiddenTagList", hiddenObj); + } else { + obj.data("lhiddenTagList", jQuery(tagManagerOptions.output)) + } + + if (tagManagerOptions.AjaxPushAllTags) { + obj.on('tm:afterSplice', pushAllTags); + obj.on('tm:afterPop', pushAllTags); + obj.on('tm:afterPush', pushAllTags); + } + + // hide popovers on focus and keypress events + obj.on('focus keypress', function (e) { + if ($(this).popover) { + $(this).popover('hide'); + } + }); + + // handle ESC (keyup used for browser compatibility) + if (tagManagerOptions.isClearInputOnEsc) { + obj.on('keyup', function (e) { + if (e.which == 27) { + // console.log('esc detected'); + $(this).val(''); + killEvent(e); + } + }); + } + + obj.on('keypress', function (e) { + // push ASCII-based delimiters + if (keyInArray(e, delimiterChars)) { + applyDelimiter(e); + } + }); + + obj.on('keydown', function (e) { + // disable ENTER + if (e.which == 13) { + if (tagManagerOptions.preventSubmitOnEnter) { + killEvent(e); + } + } + + // push key-based delimiters (includes by default) + if (keyInArray(e, delimiterKeys)) { + applyDelimiter(e); + } + }); + + // BACKSPACE (keydown used for browser compatibility) + if (tagManagerOptions.deleteTagsOnBackspace) { + obj.on('keydown', function (e) { + if (keyInArray(e, backspace)) { + // console.log("backspace detected"); + if ($(this).val().length <= 0) { + popTag(); + killEvent(e); + } + } + }); + } + + obj.change(function (e) { + + if (!/webkit/.test(navigator.userAgent.toLowerCase())) { $(this).focus(); } // why? + + /* unimplemented mode to push tag on blur + else if (tagManagerOptions.pushTagOnBlur) { + console.log('change: pushTagOnBlur ' + tag); + pushTag($(this).val()); + } */ + killEvent(e); + }); + + if (tagManagerOptions.prefilled != null) { + if (typeof (tagManagerOptions.prefilled) == "object") { + prefill(tagManagerOptions.prefilled); + } else if (typeof (tagManagerOptions.prefilled) == "string") { + prefill(tagManagerOptions.prefilled.split(baseDelimiter)); + } else if (typeof (tagManagerOptions.prefilled) == "function") { + prefill(tagManagerOptions.prefilled()); + } + } else if (tagManagerOptions.output != null) { + if (jQuery(tagManagerOptions.output) && jQuery(tagManagerOptions.output).val()) + var existing_tags = jQuery(tagManagerOptions.output) + prefill(jQuery(tagManagerOptions.output).val().split(baseDelimiter)); + } + }); + + if (!returnValue) + returnValue = this; + + return returnValue; + } +})(jQuery); \ No newline at end of file diff --git a/ajax/libs/tagmanager/3.0.0/tagmanager.less b/ajax/libs/tagmanager/3.0.0/tagmanager.less new file mode 100644 index 000000000..aea0bdc99 --- /dev/null +++ b/ajax/libs/tagmanager/3.0.0/tagmanager.less @@ -0,0 +1,178 @@ +// +// Bootstrap TagManager +// -------------------------------------------------- + +// Tag Variables +// -------------------------------------------------- + +// Colors +// ------------------------- + +@tagText: @gray; +@tagBackground: #f5f5f5; +@tagBorder: #bbb; + +@tagWarningText: #945203; +@tagWarningBackground: #f2c889; +@tagWarningBorder: #f0a12f; + +@tagErrorText: #84212e; +@tagErrorBackground: #e69ca6; +@tagErrorBorder: #d24a5d; + +@tagSuccessText: #638421; +@tagSuccessBackground: #cde69c; +@tagSuccessBorder: #a5d24a; + +@tagInfoText: #4594b5; +@tagInfoBackground: #c5eefa; +@tagInfoBorder: #5dc8f7; + +@tagInverseText: #ccc; +@tagInverseBackground: @gray; +@tagInverseBorder: @grayDark; + +@tagDisabledText: #aaa; +@tagDisabledBackground: #e6e6e6; +@tagDisabledBorder: #ccc; + +// Sizing +// ------------------------- + +@tagFontSize: 13px; +@tagFontSizeLarge: @tagFontSize * 1.25; // ~16px +@tagFontSizeSmall: @tagFontSize * 0.85; // ~11px +@tagFontSizeMini: @tagFontSize * 0.75; // ~10px + +@tagPadding: 4px; +@tagMargin: 5px; + +// Tag Classes +// -------------------------------------------------- + +// Base tag class +// ------------------------- + +.tm-tag { + color: @tagText; + background-color: @tagBackground; + border: @tagBorder 1px solid; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset; + display: inline-block; + border-radius: @borderRadiusSmall; + font-family: @sansFontFamily; + font-size: @tagFontSize; + margin: 0 @tagMargin @tagMargin 0; + padding: @tagPadding; + text-decoration: none; + transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s; + -moz-transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s; + -webkit-transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s; + vertical-align: middle; + + // Remove button + // ------------------------- + + .tm-tag-remove { + color: @black; + font-weight: bold; + margin-left: @tagPadding; + opacity: 0.2; + &:hover { + color: @black; + text-decoration: none; + opacity: 0.4; + } + } + + // Semantic Colors + // ------------------------- + + &.tm-tag-warning { + color: @tagWarningText; + background-color: @tagWarningBackground; + border-color: @tagWarningBorder; + } + &.tm-tag-error { + color: @tagErrorText; + background-color: @tagErrorBackground; + border-color: @tagErrorBorder; + } + &.tm-tag-success { + color: @tagSuccessText; + background-color: @tagSuccessBackground; + border-color: @tagSuccessBorder; + } + &.tm-tag-info { + color: @tagInfoText; + background-color: @tagInfoBackground; + border-color: @tagInfoBorder; + } + &.tm-tag-inverse { + color: @tagInverseText; + background-color: @tagInverseBackground; + border-color: @tagInverseBorder; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2) inset; + .tm-tag-remove { + color: @white; + } + } + + // Sizes + // ------------------------- + + &.tm-tag-large { + font-size: @tagFontSizeLarge; + border-radius: @baseBorderRadius; + padding: 11px 7px; + } + &.tm-tag-small { + font-size: @tagFontSizeSmall; + border-radius: @borderRadiusSmall; + padding: 2px 4px; + } + &.tm-tag-mini { + font-size: @tagFontSizeMini; + border-radius: 2px; + padding: 0px 2px; + } + + // Miscellaneous Styles + // ------------------------- + + &.tm-tag-plain { + color: @textColor; + box-shadow: none; + background: none; + border: none; + } + &.tm-tag-disabled { + color: @tagDisabledText; + background-color: @tagDisabledBackground; + border-color: @tagDisabledBorder; + box-shadow: none; + .tm-tag-remove { + display: none; + } + } +} + +// Forms +// -------------------------------------------------- + +// Input style (Recommended) +// ------------------------- + +input[type="text"].tm-input { + margin-bottom: @tagMargin; +} + +// Form wrappers (Optional) +// ------------------------- + +.control-group.tm-group { + margin-bottom: (@baseLineHeight / 2) - @tagMargin; +} +.form-horizontal .control-group.tm-group { + margin-bottom: @baseLineHeight - @tagMargin; +} diff --git a/ajax/libs/tagmanager/package.json b/ajax/libs/tagmanager/package.json new file mode 100644 index 000000000..a1657dda1 --- /dev/null +++ b/ajax/libs/tagmanager/package.json @@ -0,0 +1,41 @@ +{ + "name": "TagManager", + "version": "3.0.0", + "title": "Tag Manager", + "author": { + "name": "Max Favilli", + "url": "http://maxfavilli.com" + }, + "licenses": [ + { + "type": "MPL", + "url": "http://www.mozilla.org/MPL/2.0/index.txt" + } + ], + "dependencies": { + "jquery": "1" + }, + "description": "A tags manager, with this plugin a input field is used to collect tags and rendered as tags.", + "keywords": [ + "tags", + "manager", + "input", + "form" + ], + "homepage": "https://github.com/max-favilli/tagmanager", + "maintainers": [ + { + "name": "Max Favilli", + "url": "https://github.com/max-favilli" + },{ + "name": "Johnny Shields", + "url": "https://github.com/johnnyshields" + } + ], + "files": [ + "README.md", + "tagmanager.css", + "tagmanager.js", + "license.txt" + ] +}