| Current Path : /home/emeraadmin/www/4d695/ |
| Current File : /home/emeraadmin/www/4d695/bootstrap-tagsinput.tar |
karma.conf.js 0000644 00000000746 15167672471 0007150 0 ustar 00 module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
files: [
'lib/jquery/jquery.js',
'lib/angular/angular.js',
'dist/bootstrap-tagsinput.min.js',
'dist/bootstrap-tagsinput-angular.min.js',
'test/helpers.js',
{ pattern: 'test/bootstrap-tagsinput/*.tests.js' }
],
reporters: ['progress'],
port: 9876,
logLevel: config.LOG_DEBUG,
captureTimeout: 60000
});
};
src/bootstrap-tagsinput.js 0000644 00000053635 15167672471 0011756 0 ustar 00 (function ($) {
"use strict";
var defaultOptions = {
tagClass: function(item) {
return 'label label-info';
},
itemValue: function(item) {
return item ? item.toString() : item;
},
itemText: function(item) {
return this.itemValue(item);
},
itemTitle: function(item) {
return null;
},
freeInput: true,
addOnBlur: true,
maxTags: undefined,
maxChars: undefined,
confirmKeys: [13, 44],
delimiter: ',',
delimiterRegex: null,
cancelConfirmKeysOnEmpty: false,
onTagExists: function(item, $tag) {
$tag.hide().fadeIn();
},
trimValue: false,
allowDuplicates: false
};
/**
* Constructor function
*/
function TagsInput(element, options) {
this.isInit = true;
this.itemsArray = [];
this.$element = $(element);
this.$element.hide();
this.isSelect = (element.tagName === 'SELECT');
this.multiple = (this.isSelect && element.hasAttribute('multiple'));
this.objectItems = options && options.itemValue;
this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : '';
this.inputSize = Math.max(1, this.placeholderText.length);
this.$container = $('<div class="bootstrap-tagsinput"></div>');
this.$input = $('<input type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
this.$element.before(this.$container);
this.build(options);
this.isInit = false;
}
TagsInput.prototype = {
constructor: TagsInput,
/**
* Adds the given item as a new tag. Pass true to dontPushVal to prevent
* updating the elements val()
*/
add: function(item, dontPushVal, options) {
var self = this;
if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags)
return;
// Ignore falsey values, except false
if (item !== false && !item)
return;
// Trim value
if (typeof item === "string" && self.options.trimValue) {
item = $.trim(item);
}
// Throw an error when trying to add an object while the itemValue option was not set
if (typeof item === "object" && !self.objectItems)
throw("Can't add objects when itemValue option is not set");
// Ignore strings only containg whitespace
if (item.toString().match(/^\s*$/))
return;
// If SELECT but not multiple, remove current tag
if (self.isSelect && !self.multiple && self.itemsArray.length > 0)
self.remove(self.itemsArray[0]);
if (typeof item === "string" && this.$element[0].tagName === 'INPUT') {
var delimiter = (self.options.delimiterRegex) ? self.options.delimiterRegex : self.options.delimiter;
var items = item.split(delimiter);
if (items.length > 1) {
for (var i = 0; i < items.length; i++) {
this.add(items[i], true);
}
if (!dontPushVal)
self.pushVal();
return;
}
}
var itemValue = self.options.itemValue(item),
itemText = self.options.itemText(item),
tagClass = self.options.tagClass(item),
itemTitle = self.options.itemTitle(item);
// Ignore items allready added
var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0];
if (existing && !self.options.allowDuplicates) {
// Invoke onTagExists
if (self.options.onTagExists) {
var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; });
self.options.onTagExists(item, $existingTag);
}
return;
}
// if length greater than limit
if (self.items().toString().length + item.length + 1 > self.options.maxInputLength)
return;
// raise beforeItemAdd arg
var beforeItemAddEvent = $.Event('beforeItemAdd', { item: item, cancel: false, options: options});
self.$element.trigger(beforeItemAddEvent);
if (beforeItemAddEvent.cancel)
return;
// register item in internal array and map
self.itemsArray.push(item);
// add a tag element
var $tag = $('<span class="tag ' + htmlEncode(tagClass) + (itemTitle !== null ? ('" title="' + itemTitle) : '') + '">' + htmlEncode(itemText) + '<span data-role="remove"></span></span>');
$tag.data('item', item);
self.findInputWrapper().before($tag);
$tag.after(' ');
// Check to see if the tag exists in its raw or uri-encoded form
var optionExists = (
$('option[value="' + encodeURIComponent(itemValue) + '"]', self.$element).length ||
$('option[value="' + htmlEncode(itemValue) + '"]', self.$element).length
);
// add <option /> if item represents a value not present in one of the <select />'s options
if (self.isSelect && !optionExists) {
var $option = $('<option selected>' + htmlEncode(itemText) + '</option>');
$option.data('item', item);
$option.attr('value', itemValue);
self.$element.append($option);
}
if (!dontPushVal)
self.pushVal();
// Add class when reached maxTags
if (self.options.maxTags === self.itemsArray.length || self.items().toString().length === self.options.maxInputLength)
self.$container.addClass('bootstrap-tagsinput-max');
// If using typeahead, once the tag has been added, clear the typeahead value so it does not stick around in the input.
if ($('.typeahead, .twitter-typeahead', self.$container).length) {
self.$input.typeahead('val', '');
}
if (this.isInit) {
self.$element.trigger($.Event('itemAddedOnInit', { item: item, options: options }));
} else {
self.$element.trigger($.Event('itemAdded', { item: item, options: options }));
}
},
/**
* Removes the given item. Pass true to dontPushVal to prevent updating the
* elements val()
*/
remove: function(item, dontPushVal, options) {
var self = this;
if (self.objectItems) {
if (typeof item === "object")
item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == self.options.itemValue(item); } );
else
item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == item; } );
item = item[item.length-1];
}
if (item) {
var beforeItemRemoveEvent = $.Event('beforeItemRemove', { item: item, cancel: false, options: options });
self.$element.trigger(beforeItemRemoveEvent);
if (beforeItemRemoveEvent.cancel)
return;
$('.tag', self.$container).filter(function() { return $(this).data('item') === item; }).remove();
$('option', self.$element).filter(function() { return $(this).data('item') === item; }).remove();
if($.inArray(item, self.itemsArray) !== -1)
self.itemsArray.splice($.inArray(item, self.itemsArray), 1);
}
if (!dontPushVal)
self.pushVal();
// Remove class when reached maxTags
if (self.options.maxTags > self.itemsArray.length)
self.$container.removeClass('bootstrap-tagsinput-max');
self.$element.trigger($.Event('itemRemoved', { item: item, options: options }));
},
/**
* Removes all items
*/
removeAll: function() {
var self = this;
$('.tag', self.$container).remove();
$('option', self.$element).remove();
while(self.itemsArray.length > 0)
self.itemsArray.pop();
self.pushVal();
},
/**
* Refreshes the tags so they match the text/value of their corresponding
* item.
*/
refresh: function() {
var self = this;
$('.tag', self.$container).each(function() {
var $tag = $(this),
item = $tag.data('item'),
itemValue = self.options.itemValue(item),
itemText = self.options.itemText(item),
tagClass = self.options.tagClass(item);
// Update tag's class and inner text
$tag.attr('class', null);
$tag.addClass('tag ' + htmlEncode(tagClass));
$tag.contents().filter(function() {
return this.nodeType == 3;
})[0].nodeValue = htmlEncode(itemText);
if (self.isSelect) {
var option = $('option', self.$element).filter(function() { return $(this).data('item') === item; });
option.attr('value', itemValue);
}
});
},
/**
* Returns the items added as tags
*/
items: function() {
return this.itemsArray;
},
/**
* Assembly value by retrieving the value of each item, and set it on the
* element.
*/
pushVal: function() {
var self = this,
val = $.map(self.items(), function(item) {
return self.options.itemValue(item).toString();
});
self.$element.val(val, true).trigger('change');
},
/**
* Initializes the tags input behaviour on the element
*/
build: function(options) {
var self = this;
self.options = $.extend({}, defaultOptions, options);
// When itemValue is set, freeInput should always be false
if (self.objectItems)
self.options.freeInput = false;
makeOptionItemFunction(self.options, 'itemValue');
makeOptionItemFunction(self.options, 'itemText');
makeOptionFunction(self.options, 'tagClass');
// Typeahead Bootstrap version 2.3.2
if (self.options.typeahead) {
var typeahead = self.options.typeahead || {};
makeOptionFunction(typeahead, 'source');
self.$input.typeahead($.extend({}, typeahead, {
source: function (query, process) {
function processItems(items) {
var texts = [];
for (var i = 0; i < items.length; i++) {
var text = self.options.itemText(items[i]);
map[text] = items[i];
texts.push(text);
}
process(texts);
}
this.map = {};
var map = this.map,
data = typeahead.source(query);
if ($.isFunction(data.success)) {
// support for Angular callbacks
data.success(processItems);
} else if ($.isFunction(data.then)) {
// support for Angular promises
data.then(processItems);
} else {
// support for functions and jquery promises
$.when(data)
.then(processItems);
}
},
updater: function (text) {
self.add(this.map[text]);
return this.map[text];
},
matcher: function (text) {
return (text.toLowerCase().indexOf(this.query.trim().toLowerCase()) !== -1);
},
sorter: function (texts) {
return texts.sort();
},
highlighter: function (text) {
var regex = new RegExp( '(' + this.query + ')', 'gi' );
return text.replace( regex, "<strong>$1</strong>" );
}
}));
}
// typeahead.js
if (self.options.typeaheadjs) {
var typeaheadConfig = null;
var typeaheadDatasets = {};
// Determine if main configurations were passed or simply a dataset
var typeaheadjs = self.options.typeaheadjs;
if ($.isArray(typeaheadjs)) {
typeaheadConfig = typeaheadjs[0];
typeaheadDatasets = typeaheadjs[1];
} else {
typeaheadDatasets = typeaheadjs;
}
self.$input.typeahead(typeaheadConfig, typeaheadDatasets).on('typeahead:selected', $.proxy(function (obj, datum) {
if (typeaheadDatasets.valueKey)
self.add(datum[typeaheadDatasets.valueKey]);
else
self.add(datum);
self.$input.typeahead('val', '');
}, self));
}
self.$container.on('click', $.proxy(function(event) {
if (! self.$element.attr('disabled')) {
self.$input.removeAttr('disabled');
}
self.$input.focus();
}, self));
if (self.options.addOnBlur && self.options.freeInput) {
self.$input.on('focusout', $.proxy(function(event) {
// HACK: only process on focusout when no typeahead opened, to
// avoid adding the typeahead text as tag
if ($('.typeahead, .twitter-typeahead', self.$container).length === 0) {
self.add(self.$input.val());
self.$input.val('');
}
}, self));
}
self.$container.on('keydown', 'input', $.proxy(function(event) {
var $input = $(event.target),
$inputWrapper = self.findInputWrapper();
if (self.$element.attr('disabled')) {
self.$input.attr('disabled', 'disabled');
return;
}
switch (event.which) {
// BACKSPACE
case 8:
if (doGetCaretPosition($input[0]) === 0) {
var prev = $inputWrapper.prev();
if (prev.length) {
self.remove(prev.data('item'));
}
}
break;
// DELETE
case 46:
if (doGetCaretPosition($input[0]) === 0) {
var next = $inputWrapper.next();
if (next.length) {
self.remove(next.data('item'));
}
}
break;
// LEFT ARROW
case 37:
// Try to move the input before the previous tag
var $prevTag = $inputWrapper.prev();
if ($input.val().length === 0 && $prevTag[0]) {
$prevTag.before($inputWrapper);
$input.focus();
}
break;
// RIGHT ARROW
case 39:
// Try to move the input after the next tag
var $nextTag = $inputWrapper.next();
if ($input.val().length === 0 && $nextTag[0]) {
$nextTag.after($inputWrapper);
$input.focus();
}
break;
default:
// ignore
}
// Reset internal input's size
var textLength = $input.val().length,
wordSpace = Math.ceil(textLength / 5),
size = textLength + wordSpace + 1;
$input.attr('size', Math.max(this.inputSize, $input.val().length));
}, self));
self.$container.on('keypress', 'input', $.proxy(function(event) {
var $input = $(event.target);
if (self.$element.attr('disabled')) {
self.$input.attr('disabled', 'disabled');
return;
}
var text = $input.val(),
maxLengthReached = self.options.maxChars && text.length >= self.options.maxChars;
if (self.options.freeInput && (keyCombinationInList(event, self.options.confirmKeys) || maxLengthReached)) {
// Only attempt to add a tag if there is data in the field
if (text.length !== 0) {
self.add(maxLengthReached ? text.substr(0, self.options.maxChars) : text);
$input.val('');
}
// If the field is empty, let the event triggered fire as usual
if (self.options.cancelConfirmKeysOnEmpty === false) {
event.preventDefault();
}
}
// Reset internal input's size
var textLength = $input.val().length,
wordSpace = Math.ceil(textLength / 5),
size = textLength + wordSpace + 1;
$input.attr('size', Math.max(this.inputSize, $input.val().length));
}, self));
// Remove icon clicked
self.$container.on('click', '[data-role=remove]', $.proxy(function(event) {
if (self.$element.attr('disabled')) {
return;
}
self.remove($(event.target).closest('.tag').data('item'));
}, self));
// Only add existing value as tags when using strings as tags
if (self.options.itemValue === defaultOptions.itemValue) {
if (self.$element[0].tagName === 'INPUT') {
self.add(self.$element.val());
} else {
$('option', self.$element).each(function() {
self.add($(this).attr('value'), true);
});
}
}
},
/**
* Removes all tagsinput behaviour and unregsiter all event handlers
*/
destroy: function() {
var self = this;
// Unbind events
self.$container.off('keypress', 'input');
self.$container.off('click', '[role=remove]');
self.$container.remove();
self.$element.removeData('tagsinput');
self.$element.show();
},
/**
* Sets focus on the tagsinput
*/
focus: function() {
this.$input.focus();
},
/**
* Returns the internal input element
*/
input: function() {
return this.$input;
},
/**
* Returns the element which is wrapped around the internal input. This
* is normally the $container, but typeahead.js moves the $input element.
*/
findInputWrapper: function() {
var elt = this.$input[0],
container = this.$container[0];
while(elt && elt.parentNode !== container)
elt = elt.parentNode;
return $(elt);
}
};
/**
* Register JQuery plugin
*/
$.fn.tagsinput = function(arg1, arg2, arg3) {
var results = [];
this.each(function() {
var tagsinput = $(this).data('tagsinput');
// Initialize a new tags input
if (!tagsinput) {
tagsinput = new TagsInput(this, arg1);
$(this).data('tagsinput', tagsinput);
results.push(tagsinput);
if (this.tagName === 'SELECT') {
$('option', $(this)).attr('selected', 'selected');
}
// Init tags from $(this).val()
$(this).val($(this).val());
} else if (!arg1 && !arg2) {
// tagsinput already exists
// no function, trying to init
results.push(tagsinput);
} else if(tagsinput[arg1] !== undefined) {
// Invoke function on existing tags input
if(tagsinput[arg1].length === 3 && arg3 !== undefined){
var retVal = tagsinput[arg1](arg2, null, arg3);
}else{
var retVal = tagsinput[arg1](arg2);
}
if (retVal !== undefined)
results.push(retVal);
}
});
if ( typeof arg1 == 'string') {
// Return the results from the invoked function calls
return results.length > 1 ? results : results[0];
} else {
return results;
}
};
$.fn.tagsinput.Constructor = TagsInput;
/**
* Most options support both a string or number as well as a function as
* option value. This function makes sure that the option with the given
* key in the given options is wrapped in a function
*/
function makeOptionItemFunction(options, key) {
if (typeof options[key] !== 'function') {
var propertyName = options[key];
options[key] = function(item) { return item[propertyName]; };
}
}
function makeOptionFunction(options, key) {
if (typeof options[key] !== 'function') {
var value = options[key];
options[key] = function() { return value; };
}
}
/**
* HtmlEncodes the given value
*/
var htmlEncodeContainer = $('<div />');
function htmlEncode(value) {
if (value) {
return htmlEncodeContainer.text(value).html();
} else {
return '';
}
}
/**
* Returns the position of the caret in the given input field
* http://flightschool.acylt.com/devnotes/caret-position-woes/
*/
function doGetCaretPosition(oField) {
var iCaretPos = 0;
if (document.selection) {
oField.focus ();
var oSel = document.selection.createRange();
oSel.moveStart ('character', -oField.value.length);
iCaretPos = oSel.text.length;
} else if (oField.selectionStart || oField.selectionStart == '0') {
iCaretPos = oField.selectionStart;
}
return (iCaretPos);
}
/**
* Returns boolean indicates whether user has pressed an expected key combination.
* @param object keyPressEvent: JavaScript event object, refer
* http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
* @param object lookupList: expected key combinations, as in:
* [13, {which: 188, shiftKey: true}]
*/
function keyCombinationInList(keyPressEvent, lookupList) {
var found = false;
$.each(lookupList, function (index, keyCombination) {
if (typeof (keyCombination) === 'number' && keyPressEvent.which === keyCombination) {
found = true;
return false;
}
if (keyPressEvent.which === keyCombination.which) {
var alt = !keyCombination.hasOwnProperty('altKey') || keyPressEvent.altKey === keyCombination.altKey,
shift = !keyCombination.hasOwnProperty('shiftKey') || keyPressEvent.shiftKey === keyCombination.shiftKey,
ctrl = !keyCombination.hasOwnProperty('ctrlKey') || keyPressEvent.ctrlKey === keyCombination.ctrlKey;
if (alt && shift && ctrl) {
found = true;
return false;
}
}
});
return found;
}
/**
* Initialize tagsinput behaviour on inputs and selects which have
* data-role=tagsinput
*/
$(function() {
$("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput();
});
})(window.jQuery);
src/bootstrap-tagsinput-angular.js 0000644 00000005676 15167672471 0013407 0 ustar 00 angular.module('bootstrap-tagsinput', [])
.directive('bootstrapTagsinput', [function() {
function getItemProperty(scope, property) {
if (!property)
return undefined;
if (angular.isFunction(scope.$parent[property]))
return scope.$parent[property];
return function(item) {
return item[property];
};
}
return {
restrict: 'EA',
scope: {
model: '=ngModel'
},
template: '<select multiple></select>',
replace: false,
link: function(scope, element, attrs) {
$(function() {
if (!angular.isArray(scope.model))
scope.model = [];
var select = $('select', element);
var typeaheadSourceArray = attrs.typeaheadSource ? attrs.typeaheadSource.split('.') : null;
var typeaheadSource = typeaheadSourceArray ?
(typeaheadSourceArray.length > 1 ?
scope.$parent[typeaheadSourceArray[0]][typeaheadSourceArray[1]]
: scope.$parent[typeaheadSourceArray[0]])
: null;
select.tagsinput(scope.$parent[attrs.options || ''] || {
typeahead : {
source : angular.isFunction(typeaheadSource) ? typeaheadSource : null
},
itemValue: getItemProperty(scope, attrs.itemvalue),
itemText : getItemProperty(scope, attrs.itemtext),
confirmKeys : getItemProperty(scope, attrs.confirmkeys) ? JSON.parse(attrs.confirmkeys) : [13],
tagClass : angular.isFunction(scope.$parent[attrs.tagclass]) ? scope.$parent[attrs.tagclass] : function(item) { return attrs.tagclass; }
});
for (var i = 0; i < scope.model.length; i++) {
select.tagsinput('add', scope.model[i]);
}
select.on('itemAdded', function(event) {
if (scope.model.indexOf(event.item) === -1)
scope.model.push(event.item);
});
select.on('itemRemoved', function(event) {
var idx = scope.model.indexOf(event.item);
if (idx !== -1)
scope.model.splice(idx, 1);
});
// create a shallow copy of model's current state, needed to determine
// diff when model changes
var prev = scope.model.slice();
scope.$watch("model", function() {
var added = scope.model.filter(function(i) {return prev.indexOf(i) === -1;}),
removed = prev.filter(function(i) {return scope.model.indexOf(i) === -1;}),
i;
prev = scope.model.slice();
// Remove tags no longer in binded model
for (i = 0; i < removed.length; i++) {
select.tagsinput('remove', removed[i]);
}
// Refresh remaining tags
select.tagsinput('refresh');
// Add new items in model as tags
for (i = 0; i < added.length; i++) {
select.tagsinput('add', added[i]);
}
}, true);
});
}
};
}]);
src/bootstrap-tagsinput-typeahead.css 0000644 00000002000 15167672471 0014050 0 ustar 00 .twitter-typeahead .tt-query,
.twitter-typeahead .tt-hint {
margin-bottom: 0;
}
.twitter-typeahead .tt-hint
{
display: none;
}
.tt-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
list-style: none;
font-size: 14px;
background-color: #ffffff;
border: 1px solid #cccccc;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
background-clip: padding-box;
cursor: pointer;
}
.tt-suggestion {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: 1.428571429;
color: #333333;
white-space: nowrap;
}
.tt-suggestion:hover,
.tt-suggestion:focus {
color: #ffffff;
text-decoration: none;
outline: 0;
background-color: #428bca;
}
src/bootstrap-tagsinput.css 0000644 00000002534 15167672471 0012122 0 ustar 00 .bootstrap-tagsinput {
background-color: #fff;
border: 1px solid #ccc;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
display: inline-block;
padding: 4px 6px;
color: #555;
vertical-align: middle;
border-radius: 4px;
max-width: 100%;
line-height: 22px;
cursor: text;
}
.bootstrap-tagsinput input {
border: none;
box-shadow: none;
outline: none;
background-color: transparent;
padding: 0 6px;
margin: 0;
width: auto;
max-width: inherit;
}
.bootstrap-tagsinput.form-control input::-moz-placeholder {
color: #777;
opacity: 1;
}
.bootstrap-tagsinput.form-control input:-ms-input-placeholder {
color: #777;
}
.bootstrap-tagsinput.form-control input::-webkit-input-placeholder {
color: #777;
}
.bootstrap-tagsinput input:focus {
border: none;
box-shadow: none;
}
.bootstrap-tagsinput .tag {
margin-right: 2px;
color: white;
}
.bootstrap-tagsinput .tag [data-role="remove"] {
margin-left: 8px;
cursor: pointer;
}
.bootstrap-tagsinput .tag [data-role="remove"]:after {
content: "x";
padding: 0px 2px;
}
.bootstrap-tagsinput .tag [data-role="remove"]:hover {
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.bootstrap-tagsinput .tag [data-role="remove"]:hover:active {
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
package.json 0000644 00000004474 15167672471 0007063 0 ustar 00 {
"_args": [
[
"bootstrap-tagsinput@0.7.1",
"C:\\Users\\Ovi-PC\\Downloads\\themekit-master\\themekit"
]
],
"_from": "bootstrap-tagsinput@0.7.1",
"_id": "bootstrap-tagsinput@0.7.1",
"_inBundle": false,
"_integrity": "sha1-/+Owa74qEGlF7ygUVoAFqU8hGTc=",
"_location": "/bootstrap-tagsinput",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "bootstrap-tagsinput@0.7.1",
"name": "bootstrap-tagsinput",
"escapedName": "bootstrap-tagsinput",
"rawSpec": "0.7.1",
"saveSpec": null,
"fetchSpec": "0.7.1"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/bootstrap-tagsinput/-/bootstrap-tagsinput-0.7.1.tgz",
"_spec": "0.7.1",
"_where": "C:\\Users\\Ovi-PC\\Downloads\\themekit-master\\themekit",
"author": {
"name": "Tim Schlechter"
},
"banner": "/*\n * <%= pkg.name %> v<%= pkg.version %> by <%= pkg.author %>\n * <%= pkg.license.url %>\n */\n",
"bugs": {
"url": "https://github.com/timschlechter/bootstrap-tagsinput/issues"
},
"contributors": [
{
"name": "Luckner Jr Jean-Baptiste"
}
],
"description": "jQuery plugin providing a Twitter Bootstrap user interface for managing tags.",
"devDependencies": {
"bower": "~1.3.8",
"grunt": "~0.4.1",
"grunt-bower-task": "~0.4.0",
"grunt-cli": "~0.1.13",
"grunt-contrib-copy": "~0.5.0",
"grunt-contrib-uglify": "^0.9.1",
"grunt-jquerymanifest": "~0.1.4",
"grunt-karma": "~0.8.3",
"grunt-zip": "~0.15.0",
"karma": "~0.12.19",
"karma-jasmine": "~0.1.5",
"karma-phantomjs-launcher": "~0.1.3",
"phantomjs": "~1.9.7-15"
},
"download": "http://timschlechter.github.io/bootstrap-tagsinput/build/bootstrap-tagsinput.zip",
"homepage": "http://timschlechter.github.io/bootstrap-tagsinput/examples/",
"keywords": [
"tags",
"bootstrap",
"input",
"select",
"form"
],
"license": "MIT",
"main": "dist/bootstrap-tagsinput.js",
"name": "bootstrap-tagsinput",
"repository": {
"type": "git",
"url": "git://github.com/timschlechter/bootstrap-tagsinput.git"
},
"scripts": {
"test": "karma start --single-run --no-auto-watch"
},
"title": "Bootstrap Tags Input",
"version": "0.7.1"
}
.travis.yml 0000644 00000000334 15167672471 0006675 0 ustar 00 language: node_js
node_js:
- 0.10
before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm install
- ./node_modules/.bin/grunt install
script:
- ./node_modules/.bin/grunt test
test/bootstrap-tagsinput-angular.tests.js 0000644 00000005063 15167672471 0014726 0 ustar 00 describe('bootstrap-tagsinput', function() {
// Load the myApp module, which contains the directive
beforeEach(module('bootstrap-tagsinput'));
describe("with strings as items" , function() {
describe("compile with 2 tags in model" , function() {
var $scope,
$element;
beforeEach(inject(function($compile, $rootScope){
$scope = $rootScope;
$scope.tags = ['Amsterdam', 'New York'];
$element = $compile(angular.element('<bootstrap-tagsinput ng-model="tags" />'))($scope);
$scope.$digest();
}));
it('should hide the element', function() {
expect($element.is(":visible")).toBe(false);
});
it('should have 2 tags', function() {
expect($('.tag', $element).length).toBe(2);
});
});
});
describe("with objects as items" , function() {
describe("compile with 2 tags in model" , function() {
var $scope,
$element;
beforeEach(inject(function($compile, $rootScope){
$scope = $rootScope;
$scope.tags = [{ value: 1, text: 'Amsterdam'}, { value: 2, text: 'New York'} ];
$element = $compile(angular.element('<bootstrap-tagsinput ng-model="tags" itemvalue="value" itemtext="text"/>'))($scope);
$scope.$digest();
}));
it('should hide the element', function() {
expect($element.is(":visible")).toBe(false);
});
it('should have 2 tags', function() {
expect($('.tag', $element).length).toBe(2);
});
describe("changing a tag's text" , function() {
beforeEach(function() {
$scope.tags[0].text = 'Paris';
$scope.$digest();
});
it("should update tag's text", function() {
expect($('.tag', $element).first().text()).toBe('Paris');
});
});
describe("adding an item to the model" , function() {
beforeEach(function() {
$scope.tags.push({ value: 3, text: 'Beijing'});
$scope.$digest();
});
it("should add a tag", function() {
expect($('.tag', $element).length).toBe(3);
});
});
describe("BACKSPACE", function() {
beforeEach(function() {
$element.tagsinput('focus');
});
it('after last tag, should remove item from model', function() {
$('input', $element).trigger($.Event('keydown', { which: 8 }));
$scope.$digest();
expect($scope.tags.length).toBe(1);
});
});
});
});
}); test/bootstrap-tagsinput/input_with_object_items.tests.js 0000644 00000010560 15167672471 0020216 0 ustar 00 describe("bootstrap-tagsinput", function() {
describe("with objects as items", function() {
testTagsInput('<input type="text" />', function() {
it("adding a item should throw an exception", function() {
var element = this.$element;
expect(function() { element.tagsinput('add', {}); }).toThrow("Can't add objects when itemValue option is not set");
});
});
testTagsInput('<input type="text" />', { itemValue: function(item) { return item.value; } }, function() {
describe("adding an item", function() {
var item;
beforeEach(function() {
item = { value: 1 };
this.$element.tagsinput('add', item);
});
it("'items' should return the item", function() {
expect(this.$element.tagsinput('items')[0]).toBe(item);
});
it("val() should return the item's value", function() {
expect(this.$element.val()).toBe("1");
});
it("tag's text should be the item's value", function() {
expect($('.tag', this.$sandbox).text()).toBe("1");
});
});
});
testTagsInput('<input type="text" />', { itemValue: 'value' }, function() {
describe("adding an item", function() {
var item;
beforeEach(function() {
item = { value: 1 };
this.$element.tagsinput('add', item);
});
it("'items' should return the item", function() {
expect(this.$element.tagsinput('items')[0]).toBe(item);
});
it("'items' should returns exactly 1 item", function() {
expect(this.$element.tagsinput('items').length).toBe(1);
});
it("val() should return the item's value", function() {
expect(this.$element.val()).toBe("1");
});
it("tag's text should be the item's value", function() {
expect($('.tag', this.$sandbox).text()).toBe("1");
});
});
});
testTagsInput('<input type="text" />', { itemValue: function(item) { return item.value; }, itemText: function(item) { return item.text; } }, function() {
describe("adding an item", function() {
var item = { value: 1, text: 'some' };
beforeEach(function() {
this.$element.tagsinput('add', item);
});
it("'items' should return the item", function() {
expect(this.$element.tagsinput('items')[0]).toBe(item);
});
it("val() should return the item's value", function() {
expect(this.$element.val()).toBe("1");
});
it("tag's text should be the item's text", function() {
expect($('.tag', this.$sandbox).text()).toBe("some");
});
describe("change item and invoke 'refesh'", function() {
beforeEach(function() {
item.text = 'changed';
this.$element.tagsinput('refresh');
});
it("should update tags's text", function() {
expect($('.tag', this.$sandbox).text()).toBe('changed');
});
it("tag should still have remove button", function() {
expect($('[data-role=remove]', this.$sandbox)[0]).not.toBeUndefined();
});
});
});
});
testTagsInput('<input type="text" />', { itemValue: function(item) { return item.value; }, itemText: function(item) { return item.text; }, itemTitle: function(item) { return item.title; } }, function() {
describe("adding an item with a title", function() {
var item;
beforeEach(function() {
item = { value: 1, text: 'one', title: 'number one' };
this.$element.tagsinput('add', item);
});
it("'items' should return the item", function() {
expect(this.$element.tagsinput('items')[0]).toBe(item);
});
it("'items' should returns exactly 1 item", function() {
expect(this.$element.tagsinput('items').length).toBe(1);
});
it("val() should return the item's value", function() {
expect(this.$element.val()).toBe("1");
});
it("tag's text should be the item's value", function() {
expect($('.tag', this.$sandbox).text()).toBe("one");
});
it("tag's title should be the item's title", function() {
expect($('.tag', this.$sandbox).attr('title')).toBe("number one");
});
});
});
});
}); test/bootstrap-tagsinput/reproduced_bugs.tests.js 0000644 00000014511 15167672471 0016451 0 ustar 00 describe("bootstrap-tagsinput", function() {
describe("Reproduced bugs", function() {
describe("#1: Demo error", function() {
testTagsInput('<input type="text" value="some_tag" />', function() {
it("clicking remove button should remove item", function() {
$('[data-role=remove]', this.$sandbox).trigger('click');
expect(this.$element.tagsinput('items').length).toBe(0);
});
it("clicking remove button should remove tag element", function() {
$('[data-role=remove]', this.$sandbox).trigger('click');
expect($('.tag', this.$sandbox).length).toBe(0);
});
});
});
describe("#11: Cannot remove an item by programming", function() {
testTagsInput('<input type="text" />', { itemValue: function(item) { return item.value; } }, function() {
describe("add two different objects with same value", function() {
var item1 = { value: 1 },
item2 = { value: 1 };
beforeEach(function() {
this.$element.tagsinput('add', item1);
this.$element.tagsinput('add', item2);
});
it("'items' should return the first added item", function() {
expect(this.$element.tagsinput('items')[0]).toBe(item1);
});
it("'items' should return exactly 1 item", function() {
expect(this.$element.tagsinput('items').length).toBe(1);
});
it("should have exactly 1 tag", function() {
expect($('.tag', this.$sandbox).length).toBe(1);
});
});
describe("remove item", function() {
beforeEach(function() {
this.$element.tagsinput('add', { value: 1 });
});
it("by value, should remove then item", function() {
this.$element.tagsinput('remove', 1);
expect(this.$element.tagsinput('items').length).toBe(0);
});
it("by value, should remove then tag", function() {
this.$element.tagsinput('remove', 1);
expect($('.tag', this.$sandbox).length).toBe(0);
});
it("by different instance, should remove then tag", function() {
this.$element.tagsinput('remove', { value: 1 });
expect($('.tag', this.$sandbox).length).toBe(0);
});
it("should remove items when none of the items have a matching value", function() {
this.$element.tagsinput('add', { value: 1 });
this.$element.tagsinput('remove', 2);
expect(this.$element.tagsinput('items').length).toBe(1);
});
});
});
testTagsInput('<select />', { itemValue: function(item) { return item.value; } }, function() {
describe("add two objects", function() {
var item1 = { value: 1 },
item2 = { value: 2 };
beforeEach(function() {
this.$element.tagsinput('add', item1);
this.$element.tagsinput('add', item2);
});
it("'items' should return the last added item", function() {
expect(this.$element.tagsinput('items')[0]).toBe(item2);
});
it("'items' should return exactly 1 item", function() {
expect(this.$element.tagsinput('items').length).toBe(1);
});
it("should have exactly 1 tag", function() {
expect($('.tag', this.$sandbox).length).toBe(1);
});
it("val() should return first item's value", function() {
expect(this.$element.val()).toBe("2");
});
});
});
});
describe("#34: Error in ReloadPage", function() {
describe("init tagsinput with objects as items, but with value set on element", function() {
testTagsInput('<input type="text" value="1" />', { itemValue: function(item) { return item.value; } }, function() {
it("should have no tags", function() {
expect(this.$element.tagsinput('items').length).toBe(0);
});
});
testTagsInput('<select><option value="1" /></select>', { itemValue: function(item) { return item.value; } }, function() {
it("should have no tags", function() {
expect(this.$element.tagsinput('items').length).toBe(0);
});
});
});
});
describe("#90: Error in reinitialization (arg1 and arg2 are undefined)", function() {
describe("init tagsinput twice", function() {
testTagsInput('<input type="text" value="1" />', { itemValue: function(item) { return item.value; } }, function() {
it("should not fail if an element is reinitialized", function () {
this.$element.tagsinput();
});
it("should return the original instance if already initialized", function () {
return this.$element.tagsinput() === this;
});
});
});
});
describe("#142: Initialization of Null Values for Multi Select field", function() {
testTagsInput('<select multiple data-role="tagsinput"></select>', function() {
it("Initializing an empty select shouldn't throw an error.", function() {
$("select[multiple][data-role=tagsinput]").tagsinput();
});
});
});
describe("#128: Custom classes for tags don't work if entered as strings", function() {
testTagsInput('<input type="text" value="1" />', { tagClass: 'big' }, function() {
it("should have a tag with class 'big' when using tagClass option as string", function() {
expect($(".big", this.$tagsinput).length).toBe(1);
});
});
testTagsInput('<input type="text" value="1" />', { tagClass: function() { return 'big'; } }, function() {
it("should have a tag with class 'big' when using tagClass option as function", function() {
expect($(".big", this.$tagsinput).length).toBe(1);
});
});
});
describe("#107: Fixed bug when removing items", function() {
testTagsInput('<input type="text" value="yes,no" />', function() {
it("should not remove items when remove a non-existing item", function() {
this.$element.tagsinput('remove', 'maybe');
expect(this.$element.tagsinput('items').length).toBe(2);
});
});
});
});
}); test/bootstrap-tagsinput/input_with_string_items.tests.js 0000644 00000017114 15167672471 0020260 0 ustar 00 describe("bootstrap-tagsinput", function() {
describe("with strings as items", function() {
testTagsInput('<input type="text" />', { trimValue: true }, function(){
it("trim item values", function() {
this.$element.tagsinput('add', ' some_tag ');
this.$element.tagsinput('add', 'some_tag ');
expect(this.$element.val()).toBe('some_tag');
});
});
testTagsInput('<input type="text" />', function() {
it("should hide input", function() {
expect(this.$element.css('display')).toBe('none');
});
it("should add tag on when pressing ENTER", function() {
this.$tagsinput_input.val('some_tag');
this.$tagsinput_input.trigger($.Event('keypress', { which: 13 }));
expect(this.$element.tagsinput('items').length).toBe(1);
});
it("should add tag on when pressing COMMA ,", function() {
this.$tagsinput_input.val('some_tag');
this.$tagsinput_input.trigger($.Event('keypress', { which: 44 }));
expect(this.$element.tagsinput('items').length).toBe(1);
});
describe("should not add tag", function() {
it("when adding same item twice", function() {
this.$element.tagsinput('add', 'some_tag');
this.$element.tagsinput('add', 'some_tag');
expect(this.$element.val()).toBe('some_tag');
});
it("when adding empty string", function() {
this.$element.tagsinput('add', '');
expect(this.$element.tagsinput('items').length).toBe(0);
});
it("when adding whitespace string", function() {
this.$element.tagsinput('add', ' ');
expect(this.$element.tagsinput('items').length).toBe(0);
});
it("when adding undefined", function() {
this.$element.tagsinput('add', undefined);
expect(this.$element.tagsinput('items').length).toBe(0);
});
it("when adding null", function() {
this.$element.tagsinput('add', null);
expect(this.$element.tagsinput('items').length).toBe(0);
});
});
describe("should add tag", function() {
it("when adding boolean false", function() {
this.$element.tagsinput('add', false);
expect(this.$element.tagsinput('items').length).toBe(1);
});
it("when adding boolean true", function() {
this.$element.tagsinput('add', false);
expect(this.$element.tagsinput('items').length).toBe(1);
});
});
describe("invoke 'add' with a string", function() {
beforeEach(function() {
this.$element.tagsinput('add', 'some_tag');
});
it("val() should return 'some_tag'", function() {
expect(this.$element.val()).toBe('some_tag');
});
it("'items' should return 1 item", function() {
expect(this.$element.tagsinput('items').length).toBe(1);
});
describe("invoking 'remove'", function() {
beforeEach(function() {
this.$element.tagsinput('remove', 'some_tag');
});
it("val() should should return null", function() {
expect(this.$element.val()).toBe('');
});
});
});
describe("invoke 'add' with a string containing a comma", function() {
beforeEach(function() {
this.$element.tagsinput('add', 'before,after');
});
it("val() should return 'before,after'", function() {
expect(this.$element.val()).toBe('before,after');
});
it("'items' should return 2 items", function() {
expect(this.$element.tagsinput('items').length).toBe(2);
});
});
it("'focus' should place focus in input", function() {
this.$element.tagsinput('focus');
expect(hasFocus(this.$tagsinput_input)).toBe(true);
});
});
testTagsInput('<input type="text" value="some,tags" />', function() {
it('should have 2 tags', function() {
expect(this.$element.tagsinput('items').length).toBe(2);
});
describe("invoke 'removeAll'", function() {
beforeEach(function() {
this.$element.tagsinput('removeAll');
});
it("should remove both tags", function() {
expect(this.$element.tagsinput('items').length).toBe(0);
});
it("val() should return ''", function() {
expect(this.$element.val()).toBe('');
});
});
describe("BACKSPACE", function() {
beforeEach(function() {
this.$element.tagsinput('focus');
});
it('after last tag, should remove the last tag', function() {
this.$tagsinput_input.trigger($.Event('keydown', { which: 8 }));
expect(this.$element.tagsinput('items')[0]).toBe('some');
});
it('after last tag, should remove the last tag', function() {
this.$tagsinput_input.trigger($.Event('keydown', { which: 8 }));
expect(this.$element.tagsinput('items').length).toBe(1);
});
it('after first tag, should remove the first tag', function() {
this.$tagsinput_input.trigger($.Event('keydown', { which: 37 }));
this.$tagsinput_input.trigger($.Event('keydown', { which: 8 }));
expect(this.$element.tagsinput('items')[0]).toBe('tags');
});
});
describe("DELETE", function() {
beforeEach(function() {
this.$element.tagsinput('focus');
// move cursor before last tag
this.$tagsinput_input.trigger($.Event('keydown', { which: 37 }));
});
it('before last tag, should remove the last tag', function() {
this.$tagsinput_input.trigger($.Event('keydown', { which: 46 }));
expect(this.$element.tagsinput('items')[0]).toBe('some');
});
it('before last tag, should remove the last tag', function() {
this.$tagsinput_input.trigger($.Event('keydown', { which: 46 }));
expect(this.$element.tagsinput('items').length).toBe(1);
});
it('before first tag, should remove the first tag', function() {
this.$tagsinput_input.trigger($.Event('keydown', { which: 37 }));
this.$tagsinput_input.trigger($.Event('keydown', { which: 46 }));
expect(this.$element.tagsinput('items')[0]).toBe('tags');
});
});
});
testTagsInput('<input type="text" value="some,tag"/>', { maxTags: 2 }, function() {
it("should have class 'bootstrap-tagsinput-max'", function() {
expect(this.$tagsinput.hasClass('bootstrap-tagsinput-max')).toBe(true);
});
describe("adding another tag", function() {
it("should not add the tag", function() {
this.$element.tagsinput('add', 'another');
expect(this.$element.tagsinput('items').length).toBe(2);
});
});
describe("removing a tags", function() {
it("should not have class 'bootstrap-tagsinput-max'", function() {
this.$element.tagsinput('remove', 'some');
expect(this.$tagsinput.hasClass('bootstrap-tagsinput-max')).toBe(false);
});
})
});
testTagsInput('<input type="text" />', { confirmKeys: [9] }, function() {
it("should add tag on when pressing TAB", function() {
this.$tagsinput_input.val('some_tag');
this.$tagsinput_input.trigger($.Event('keypress', { which: 9 }));
expect(this.$element.tagsinput('items').length).toBe(1);
});
});
});
});
test/bootstrap-tagsinput/select_with_string_items.tests.js 0000644 00000002747 15167672471 0020406 0 ustar 00 describe("bootstrap-tagsinput", function() {
describe("with strings as items", function() {
testTagsInput("<select multiple />", function() {
describe("when added 1 item", function() {
beforeEach(function() {
this.$element.tagsinput('add', 'some_tag');
});
it("val() should return array containing 1 item", function() {
expect(this.$element.val()[0]).toBe('some_tag');
});
describe("invoking 'remove'", function() {
beforeEach(function() {
this.$element.tagsinput('remove', 'some_tag');
});
it("val() should should return null", function() {
expect(this.$element.val()).toBeNull();
});
it("there should be no <option /> elements", function() {
expect($("option", this.$sandbox).length).toBe(0);
});
});
});
describe("when added item containing a comma", function() {
beforeEach(function() {
this.$element.tagsinput('add', 'before,after');
});
it("val() should return array containing 1 item", function() {
expect(this.$element.val()[0]).toBe('before,after');
});
});
});
testTagsInput('<select multiple><option value="some">some</option></select>', function() {
it('should have one tag', function() {
expect(this.$element.tagsinput('items')[0]).toBe('some');
});
});
});
}); test/bootstrap-tagsinput/select_with_object_items.tests.js 0000644 00000002655 15167672471 0020344 0 ustar 00 describe("bootstrap-tagsinput", function() {
describe("with objects as items", function() {
testTagsInput('<select multiple />', { itemValue: function(item) { return item.value; }, itemText: function(item) { return item.text; } }, function() {
describe("adding an item", function() {
var item;
beforeEach(function() {
item = { value: 1, text: 'some' };
this.$element.tagsinput('add', item);
});
it("'items' should return the item", function() {
expect(this.$element.tagsinput('items')[0]).toBe(item);
});
it("val() should return the item's value", function() {
expect(this.$element.val()[0]).toBe("1");
});
it("tag's text should be the item's text", function() {
expect($('.tag', this.$sandbox).text()).toBe("some");
});
describe("change item's value and text and invoke 'refesh'", function() {
beforeEach(function() {
item.value = 2;
item.text = 'changed';
this.$element.tagsinput('refresh');
});
it("should update tags's text", function() {
expect($('.tag', this.$sandbox).text()).toBe('changed');
});
it("val() should return item's new value", function() {
expect(this.$element.val()[0]).toBe("2");
});
});
});
});
});
}); test/bootstrap-tagsinput/events.tests.js 0000644 00000001447 15167672471 0014605 0 ustar 00 describe("bootstrap-tagsinput", function() {
describe("events", function() {
testTagsInput('<input type="text" />', function() {
it("beforeItemAdd canceled", function() {
this.$element.on('beforeItemAdd', function(event) {
event.cancel = true;
});
this.$element.tagsinput('add', 'some');
expect(this.$element.tagsinput('items').length).toBe(0);
});
});
testTagsInput('<input type="text" value="1" />', function() {
it("beforeItemRemove canceled", function() {
this.$element.on('beforeItemRemove', function(event) {
event.cancel = true;
});
this.$element.tagsinput('remove', '1');
expect(this.$element.tagsinput('items').length).toBe(1);
});
});
});
});
test/index.html 0000644 00000003416 15167672471 0007544 0 ustar 00 <!DOCTYPE html>
<html>
<head>
<title>Jasmine Test Runner</title>
<meta name="robots" content="noindex, nofollow" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="lib/jasmine/lib/jasmine-core/jasmine.css"/>
<script type="text/javascript" src="lib/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="lib/angular/angular.min.js"></script>
<script type="text/javascript" src="lib/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="lib/jasmine/lib/jasmine-core/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine/lib/jasmine-core/jasmine-html.js"></script>
<script type="text/javascript" src="lib/jasmine/lib/jasmine-core/boot.js"></script>
<script type="text/javascript" src="../src/bootstrap-tagsinput.js"></script>
<script type="text/javascript" src="../src/bootstrap-tagsinput-angular.js"></script>
<script type="text/javascript" src="helpers.js"></script>
<script type="text/javascript" src="bootstrap-tagsinput/input_with_string_items.tests.js"></script>
<script type="text/javascript" src="bootstrap-tagsinput/input_with_object_items.tests.js"></script>
<script type="text/javascript" src="bootstrap-tagsinput/select_with_string_items.tests.js"></script>
<script type="text/javascript" src="bootstrap-tagsinput/select_with_object_items.tests.js"></script>
<script type="text/javascript" src="bootstrap-tagsinput/reproduced_bugs.tests.js"></script>
<script type="text/javascript" src="bootstrap-tagsinput/events.tests.js"></script>
<script type="text/javascript" src="bootstrap-tagsinput-angular.tests.js"></script>
</head>
<body>
</body>
</html>
test/helpers.js 0000644 00000002237 15167672471 0007547 0 ustar 00 // Creates a new element from the given elementHtml in a sandbox before each
// tests defined in the tests function. It initializes it as a tags input with
// the given options.
function testTagsInput(elementHtml, options, tests) {
if (typeof options === 'function') {
tests = options;
options = undefined;
}
describe(elementHtml + ' (options: ' + JSON.stringify(options, function(name, value) { return (typeof value === "function") ? value.toString() : value; }) + ')', function() {
beforeEach(function() {
this.$sandbox = $('<div />').appendTo($('body'));
this.$element = $(elementHtml).appendTo(this.$sandbox);
this.$element.tagsinput(options);
this.$tagsinput = $('.bootstrap-tagsinput', this.$sandbox);
this.$tagsinput_input = $('input', this.$tagsinput);
});
afterEach(function() {
this.$element.tagsinput('destroy');
this.$sandbox.remove();
delete this.$tagsinput_input;
delete this.$tagsinput;
delete this.$sandbox;
delete this.$element;
});
tests();
});
}
function hasFocus($elt) {
return $elt.get(0) === document.activeElement;
} bootstrap-tagsinput.jquery.json 0000644 00000001243 15167672471 0013026 0 ustar 00 {
"name": "bootstrap-tagsinput",
"version": "0.7.1",
"title": "Bootstrap Tags Input",
"author": {
"name": "Tim Schlechter"
},
"licenses": [
{
"type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}
],
"dependencies": {
"jquery": "*"
},
"description": "jQuery plugin providing a Twitter Bootstrap user interface for managing tags.",
"keywords": [
"tags",
"bootstrap",
"input",
"select",
"form"
],
"download": "http://timschlechter.github.io/bootstrap-tagsinput/build/bootstrap-tagsinput.zip",
"homepage": "http://timschlechter.github.io/bootstrap-tagsinput/examples/"
} LICENSE 0000644 00000002115 15167672471 0005570 0 ustar 00 The MIT License (MIT)
Copyright (c) 2013 Tim Schlechter
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Gruntfile.js 0000644 00000004236 15167672471 0007066 0 ustar 00 module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-zip');
grunt.loadNpmTasks('grunt-jquerymanifest');
grunt.loadNpmTasks('grunt-bower-task');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
bower: {
install: {
options: {
targetDir: './lib',
layout: 'byType',
install: true,
verbose: true,
cleanTargetDir: false,
cleanBowerDir: true,
bowerOptions: {
forceLatest: true
}
}
}
},
copy: {
build: {
files: [
{ expand: true, flatten: true, src: ['src/*.*'], dest: 'dist/', filter: 'isFile' }
]
}
},
uglify: {
options: {
banner: '<%= pkg.banner %>',
sourceMap: 'dist/<%= pkg.name %>.min.js.map',
sourceMappingURL: '<%= pkg.name %>.min.js.map'
},
build: {
files: {
'dist/<%= pkg.name %>.min.js': 'src/<%= pkg.name %>.js',
'dist/<%= pkg.name %>-angular.min.js': 'src/<%= pkg.name %>-angular.js'
}
}
},
karma: {
unit: {
configFile: 'karma.conf.js',
runnerPort: 9999,
singleRun: true,
autoWatch: false,
browsers: ['PhantomJS']
}
},
zip: {
delpoy: {
// cwd: 'dist/',
src: [
'dist/bootstrap-tagsinput*.js',
'dist/bootstrap-tagsinput*.css',
'dist/bootstrap-tagsinput*.less',
'dist/bootstrap-tagsinput*.map'
],
dest: 'dist/<%= pkg.name %>.zip'
}
},
jquerymanifest: {
options: {
source: grunt.file.readJSON('package.json'),
overrides: {
title: '<%= pkg.title %>'
}
}
}
});
grunt.registerTask('install', ['bower']);
grunt.registerTask('compile', ['uglify', 'copy']);
grunt.registerTask('test', ['compile', 'karma']);
grunt.registerTask('build', ['test', 'jquerymanifest', 'zip']);
};
dist/bootstrap-tagsinput.js 0000644 00000053635 15167672471 0012132 0 ustar 00 (function ($) {
"use strict";
var defaultOptions = {
tagClass: function(item) {
return 'label label-info';
},
itemValue: function(item) {
return item ? item.toString() : item;
},
itemText: function(item) {
return this.itemValue(item);
},
itemTitle: function(item) {
return null;
},
freeInput: true,
addOnBlur: true,
maxTags: undefined,
maxChars: undefined,
confirmKeys: [13, 44],
delimiter: ',',
delimiterRegex: null,
cancelConfirmKeysOnEmpty: false,
onTagExists: function(item, $tag) {
$tag.hide().fadeIn();
},
trimValue: false,
allowDuplicates: false
};
/**
* Constructor function
*/
function TagsInput(element, options) {
this.isInit = true;
this.itemsArray = [];
this.$element = $(element);
this.$element.hide();
this.isSelect = (element.tagName === 'SELECT');
this.multiple = (this.isSelect && element.hasAttribute('multiple'));
this.objectItems = options && options.itemValue;
this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : '';
this.inputSize = Math.max(1, this.placeholderText.length);
this.$container = $('<div class="bootstrap-tagsinput"></div>');
this.$input = $('<input type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
this.$element.before(this.$container);
this.build(options);
this.isInit = false;
}
TagsInput.prototype = {
constructor: TagsInput,
/**
* Adds the given item as a new tag. Pass true to dontPushVal to prevent
* updating the elements val()
*/
add: function(item, dontPushVal, options) {
var self = this;
if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags)
return;
// Ignore falsey values, except false
if (item !== false && !item)
return;
// Trim value
if (typeof item === "string" && self.options.trimValue) {
item = $.trim(item);
}
// Throw an error when trying to add an object while the itemValue option was not set
if (typeof item === "object" && !self.objectItems)
throw("Can't add objects when itemValue option is not set");
// Ignore strings only containg whitespace
if (item.toString().match(/^\s*$/))
return;
// If SELECT but not multiple, remove current tag
if (self.isSelect && !self.multiple && self.itemsArray.length > 0)
self.remove(self.itemsArray[0]);
if (typeof item === "string" && this.$element[0].tagName === 'INPUT') {
var delimiter = (self.options.delimiterRegex) ? self.options.delimiterRegex : self.options.delimiter;
var items = item.split(delimiter);
if (items.length > 1) {
for (var i = 0; i < items.length; i++) {
this.add(items[i], true);
}
if (!dontPushVal)
self.pushVal();
return;
}
}
var itemValue = self.options.itemValue(item),
itemText = self.options.itemText(item),
tagClass = self.options.tagClass(item),
itemTitle = self.options.itemTitle(item);
// Ignore items allready added
var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0];
if (existing && !self.options.allowDuplicates) {
// Invoke onTagExists
if (self.options.onTagExists) {
var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; });
self.options.onTagExists(item, $existingTag);
}
return;
}
// if length greater than limit
if (self.items().toString().length + item.length + 1 > self.options.maxInputLength)
return;
// raise beforeItemAdd arg
var beforeItemAddEvent = $.Event('beforeItemAdd', { item: item, cancel: false, options: options});
self.$element.trigger(beforeItemAddEvent);
if (beforeItemAddEvent.cancel)
return;
// register item in internal array and map
self.itemsArray.push(item);
// add a tag element
var $tag = $('<span class="tag ' + htmlEncode(tagClass) + (itemTitle !== null ? ('" title="' + itemTitle) : '') + '">' + htmlEncode(itemText) + '<span data-role="remove"></span></span>');
$tag.data('item', item);
self.findInputWrapper().before($tag);
$tag.after(' ');
// Check to see if the tag exists in its raw or uri-encoded form
var optionExists = (
$('option[value="' + encodeURIComponent(itemValue) + '"]', self.$element).length ||
$('option[value="' + htmlEncode(itemValue) + '"]', self.$element).length
);
// add <option /> if item represents a value not present in one of the <select />'s options
if (self.isSelect && !optionExists) {
var $option = $('<option selected>' + htmlEncode(itemText) + '</option>');
$option.data('item', item);
$option.attr('value', itemValue);
self.$element.append($option);
}
if (!dontPushVal)
self.pushVal();
// Add class when reached maxTags
if (self.options.maxTags === self.itemsArray.length || self.items().toString().length === self.options.maxInputLength)
self.$container.addClass('bootstrap-tagsinput-max');
// If using typeahead, once the tag has been added, clear the typeahead value so it does not stick around in the input.
if ($('.typeahead, .twitter-typeahead', self.$container).length) {
self.$input.typeahead('val', '');
}
if (this.isInit) {
self.$element.trigger($.Event('itemAddedOnInit', { item: item, options: options }));
} else {
self.$element.trigger($.Event('itemAdded', { item: item, options: options }));
}
},
/**
* Removes the given item. Pass true to dontPushVal to prevent updating the
* elements val()
*/
remove: function(item, dontPushVal, options) {
var self = this;
if (self.objectItems) {
if (typeof item === "object")
item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == self.options.itemValue(item); } );
else
item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == item; } );
item = item[item.length-1];
}
if (item) {
var beforeItemRemoveEvent = $.Event('beforeItemRemove', { item: item, cancel: false, options: options });
self.$element.trigger(beforeItemRemoveEvent);
if (beforeItemRemoveEvent.cancel)
return;
$('.tag', self.$container).filter(function() { return $(this).data('item') === item; }).remove();
$('option', self.$element).filter(function() { return $(this).data('item') === item; }).remove();
if($.inArray(item, self.itemsArray) !== -1)
self.itemsArray.splice($.inArray(item, self.itemsArray), 1);
}
if (!dontPushVal)
self.pushVal();
// Remove class when reached maxTags
if (self.options.maxTags > self.itemsArray.length)
self.$container.removeClass('bootstrap-tagsinput-max');
self.$element.trigger($.Event('itemRemoved', { item: item, options: options }));
},
/**
* Removes all items
*/
removeAll: function() {
var self = this;
$('.tag', self.$container).remove();
$('option', self.$element).remove();
while(self.itemsArray.length > 0)
self.itemsArray.pop();
self.pushVal();
},
/**
* Refreshes the tags so they match the text/value of their corresponding
* item.
*/
refresh: function() {
var self = this;
$('.tag', self.$container).each(function() {
var $tag = $(this),
item = $tag.data('item'),
itemValue = self.options.itemValue(item),
itemText = self.options.itemText(item),
tagClass = self.options.tagClass(item);
// Update tag's class and inner text
$tag.attr('class', null);
$tag.addClass('tag ' + htmlEncode(tagClass));
$tag.contents().filter(function() {
return this.nodeType == 3;
})[0].nodeValue = htmlEncode(itemText);
if (self.isSelect) {
var option = $('option', self.$element).filter(function() { return $(this).data('item') === item; });
option.attr('value', itemValue);
}
});
},
/**
* Returns the items added as tags
*/
items: function() {
return this.itemsArray;
},
/**
* Assembly value by retrieving the value of each item, and set it on the
* element.
*/
pushVal: function() {
var self = this,
val = $.map(self.items(), function(item) {
return self.options.itemValue(item).toString();
});
self.$element.val(val, true).trigger('change');
},
/**
* Initializes the tags input behaviour on the element
*/
build: function(options) {
var self = this;
self.options = $.extend({}, defaultOptions, options);
// When itemValue is set, freeInput should always be false
if (self.objectItems)
self.options.freeInput = false;
makeOptionItemFunction(self.options, 'itemValue');
makeOptionItemFunction(self.options, 'itemText');
makeOptionFunction(self.options, 'tagClass');
// Typeahead Bootstrap version 2.3.2
if (self.options.typeahead) {
var typeahead = self.options.typeahead || {};
makeOptionFunction(typeahead, 'source');
self.$input.typeahead($.extend({}, typeahead, {
source: function (query, process) {
function processItems(items) {
var texts = [];
for (var i = 0; i < items.length; i++) {
var text = self.options.itemText(items[i]);
map[text] = items[i];
texts.push(text);
}
process(texts);
}
this.map = {};
var map = this.map,
data = typeahead.source(query);
if ($.isFunction(data.success)) {
// support for Angular callbacks
data.success(processItems);
} else if ($.isFunction(data.then)) {
// support for Angular promises
data.then(processItems);
} else {
// support for functions and jquery promises
$.when(data)
.then(processItems);
}
},
updater: function (text) {
self.add(this.map[text]);
return this.map[text];
},
matcher: function (text) {
return (text.toLowerCase().indexOf(this.query.trim().toLowerCase()) !== -1);
},
sorter: function (texts) {
return texts.sort();
},
highlighter: function (text) {
var regex = new RegExp( '(' + this.query + ')', 'gi' );
return text.replace( regex, "<strong>$1</strong>" );
}
}));
}
// typeahead.js
if (self.options.typeaheadjs) {
var typeaheadConfig = null;
var typeaheadDatasets = {};
// Determine if main configurations were passed or simply a dataset
var typeaheadjs = self.options.typeaheadjs;
if ($.isArray(typeaheadjs)) {
typeaheadConfig = typeaheadjs[0];
typeaheadDatasets = typeaheadjs[1];
} else {
typeaheadDatasets = typeaheadjs;
}
self.$input.typeahead(typeaheadConfig, typeaheadDatasets).on('typeahead:selected', $.proxy(function (obj, datum) {
if (typeaheadDatasets.valueKey)
self.add(datum[typeaheadDatasets.valueKey]);
else
self.add(datum);
self.$input.typeahead('val', '');
}, self));
}
self.$container.on('click', $.proxy(function(event) {
if (! self.$element.attr('disabled')) {
self.$input.removeAttr('disabled');
}
self.$input.focus();
}, self));
if (self.options.addOnBlur && self.options.freeInput) {
self.$input.on('focusout', $.proxy(function(event) {
// HACK: only process on focusout when no typeahead opened, to
// avoid adding the typeahead text as tag
if ($('.typeahead, .twitter-typeahead', self.$container).length === 0) {
self.add(self.$input.val());
self.$input.val('');
}
}, self));
}
self.$container.on('keydown', 'input', $.proxy(function(event) {
var $input = $(event.target),
$inputWrapper = self.findInputWrapper();
if (self.$element.attr('disabled')) {
self.$input.attr('disabled', 'disabled');
return;
}
switch (event.which) {
// BACKSPACE
case 8:
if (doGetCaretPosition($input[0]) === 0) {
var prev = $inputWrapper.prev();
if (prev.length) {
self.remove(prev.data('item'));
}
}
break;
// DELETE
case 46:
if (doGetCaretPosition($input[0]) === 0) {
var next = $inputWrapper.next();
if (next.length) {
self.remove(next.data('item'));
}
}
break;
// LEFT ARROW
case 37:
// Try to move the input before the previous tag
var $prevTag = $inputWrapper.prev();
if ($input.val().length === 0 && $prevTag[0]) {
$prevTag.before($inputWrapper);
$input.focus();
}
break;
// RIGHT ARROW
case 39:
// Try to move the input after the next tag
var $nextTag = $inputWrapper.next();
if ($input.val().length === 0 && $nextTag[0]) {
$nextTag.after($inputWrapper);
$input.focus();
}
break;
default:
// ignore
}
// Reset internal input's size
var textLength = $input.val().length,
wordSpace = Math.ceil(textLength / 5),
size = textLength + wordSpace + 1;
$input.attr('size', Math.max(this.inputSize, $input.val().length));
}, self));
self.$container.on('keypress', 'input', $.proxy(function(event) {
var $input = $(event.target);
if (self.$element.attr('disabled')) {
self.$input.attr('disabled', 'disabled');
return;
}
var text = $input.val(),
maxLengthReached = self.options.maxChars && text.length >= self.options.maxChars;
if (self.options.freeInput && (keyCombinationInList(event, self.options.confirmKeys) || maxLengthReached)) {
// Only attempt to add a tag if there is data in the field
if (text.length !== 0) {
self.add(maxLengthReached ? text.substr(0, self.options.maxChars) : text);
$input.val('');
}
// If the field is empty, let the event triggered fire as usual
if (self.options.cancelConfirmKeysOnEmpty === false) {
event.preventDefault();
}
}
// Reset internal input's size
var textLength = $input.val().length,
wordSpace = Math.ceil(textLength / 5),
size = textLength + wordSpace + 1;
$input.attr('size', Math.max(this.inputSize, $input.val().length));
}, self));
// Remove icon clicked
self.$container.on('click', '[data-role=remove]', $.proxy(function(event) {
if (self.$element.attr('disabled')) {
return;
}
self.remove($(event.target).closest('.tag').data('item'));
}, self));
// Only add existing value as tags when using strings as tags
if (self.options.itemValue === defaultOptions.itemValue) {
if (self.$element[0].tagName === 'INPUT') {
self.add(self.$element.val());
} else {
$('option', self.$element).each(function() {
self.add($(this).attr('value'), true);
});
}
}
},
/**
* Removes all tagsinput behaviour and unregsiter all event handlers
*/
destroy: function() {
var self = this;
// Unbind events
self.$container.off('keypress', 'input');
self.$container.off('click', '[role=remove]');
self.$container.remove();
self.$element.removeData('tagsinput');
self.$element.show();
},
/**
* Sets focus on the tagsinput
*/
focus: function() {
this.$input.focus();
},
/**
* Returns the internal input element
*/
input: function() {
return this.$input;
},
/**
* Returns the element which is wrapped around the internal input. This
* is normally the $container, but typeahead.js moves the $input element.
*/
findInputWrapper: function() {
var elt = this.$input[0],
container = this.$container[0];
while(elt && elt.parentNode !== container)
elt = elt.parentNode;
return $(elt);
}
};
/**
* Register JQuery plugin
*/
$.fn.tagsinput = function(arg1, arg2, arg3) {
var results = [];
this.each(function() {
var tagsinput = $(this).data('tagsinput');
// Initialize a new tags input
if (!tagsinput) {
tagsinput = new TagsInput(this, arg1);
$(this).data('tagsinput', tagsinput);
results.push(tagsinput);
if (this.tagName === 'SELECT') {
$('option', $(this)).attr('selected', 'selected');
}
// Init tags from $(this).val()
$(this).val($(this).val());
} else if (!arg1 && !arg2) {
// tagsinput already exists
// no function, trying to init
results.push(tagsinput);
} else if(tagsinput[arg1] !== undefined) {
// Invoke function on existing tags input
if(tagsinput[arg1].length === 3 && arg3 !== undefined){
var retVal = tagsinput[arg1](arg2, null, arg3);
}else{
var retVal = tagsinput[arg1](arg2);
}
if (retVal !== undefined)
results.push(retVal);
}
});
if ( typeof arg1 == 'string') {
// Return the results from the invoked function calls
return results.length > 1 ? results : results[0];
} else {
return results;
}
};
$.fn.tagsinput.Constructor = TagsInput;
/**
* Most options support both a string or number as well as a function as
* option value. This function makes sure that the option with the given
* key in the given options is wrapped in a function
*/
function makeOptionItemFunction(options, key) {
if (typeof options[key] !== 'function') {
var propertyName = options[key];
options[key] = function(item) { return item[propertyName]; };
}
}
function makeOptionFunction(options, key) {
if (typeof options[key] !== 'function') {
var value = options[key];
options[key] = function() { return value; };
}
}
/**
* HtmlEncodes the given value
*/
var htmlEncodeContainer = $('<div />');
function htmlEncode(value) {
if (value) {
return htmlEncodeContainer.text(value).html();
} else {
return '';
}
}
/**
* Returns the position of the caret in the given input field
* http://flightschool.acylt.com/devnotes/caret-position-woes/
*/
function doGetCaretPosition(oField) {
var iCaretPos = 0;
if (document.selection) {
oField.focus ();
var oSel = document.selection.createRange();
oSel.moveStart ('character', -oField.value.length);
iCaretPos = oSel.text.length;
} else if (oField.selectionStart || oField.selectionStart == '0') {
iCaretPos = oField.selectionStart;
}
return (iCaretPos);
}
/**
* Returns boolean indicates whether user has pressed an expected key combination.
* @param object keyPressEvent: JavaScript event object, refer
* http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
* @param object lookupList: expected key combinations, as in:
* [13, {which: 188, shiftKey: true}]
*/
function keyCombinationInList(keyPressEvent, lookupList) {
var found = false;
$.each(lookupList, function (index, keyCombination) {
if (typeof (keyCombination) === 'number' && keyPressEvent.which === keyCombination) {
found = true;
return false;
}
if (keyPressEvent.which === keyCombination.which) {
var alt = !keyCombination.hasOwnProperty('altKey') || keyPressEvent.altKey === keyCombination.altKey,
shift = !keyCombination.hasOwnProperty('shiftKey') || keyPressEvent.shiftKey === keyCombination.shiftKey,
ctrl = !keyCombination.hasOwnProperty('ctrlKey') || keyPressEvent.ctrlKey === keyCombination.ctrlKey;
if (alt && shift && ctrl) {
found = true;
return false;
}
}
});
return found;
}
/**
* Initialize tagsinput behaviour on inputs and selects which have
* data-role=tagsinput
*/
$(function() {
$("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput();
});
})(window.jQuery);
dist/bootstrap-tagsinput.min.js 0000644 00000021725 15167672471 0012707 0 ustar 00 /*
* bootstrap-tagsinput v0.7.1 by Tim Schlechter
*
*/
!function(a){"use strict";function b(b,c){this.isInit=!0,this.itemsArray=[],this.$element=a(b),this.$element.hide(),this.isSelect="SELECT"===b.tagName,this.multiple=this.isSelect&&b.hasAttribute("multiple"),this.objectItems=c&&c.itemValue,this.placeholderText=b.hasAttribute("placeholder")?this.$element.attr("placeholder"):"",this.inputSize=Math.max(1,this.placeholderText.length),this.$container=a('<div class="bootstrap-tagsinput"></div>'),this.$input=a('<input type="text" placeholder="'+this.placeholderText+'"/>').appendTo(this.$container),this.$element.before(this.$container),this.build(c),this.isInit=!1}function c(a,b){if("function"!=typeof a[b]){var c=a[b];a[b]=function(a){return a[c]}}}function d(a,b){if("function"!=typeof a[b]){var c=a[b];a[b]=function(){return c}}}function e(a){return a?i.text(a).html():""}function f(a){var b=0;if(document.selection){a.focus();var c=document.selection.createRange();c.moveStart("character",-a.value.length),b=c.text.length}else(a.selectionStart||"0"==a.selectionStart)&&(b=a.selectionStart);return b}function g(b,c){var d=!1;return a.each(c,function(a,c){if("number"==typeof c&&b.which===c)return d=!0,!1;if(b.which===c.which){var e=!c.hasOwnProperty("altKey")||b.altKey===c.altKey,f=!c.hasOwnProperty("shiftKey")||b.shiftKey===c.shiftKey,g=!c.hasOwnProperty("ctrlKey")||b.ctrlKey===c.ctrlKey;if(e&&f&&g)return d=!0,!1}}),d}var h={tagClass:function(a){return"label label-info"},itemValue:function(a){return a?a.toString():a},itemText:function(a){return this.itemValue(a)},itemTitle:function(a){return null},freeInput:!0,addOnBlur:!0,maxTags:void 0,maxChars:void 0,confirmKeys:[13,44],delimiter:",",delimiterRegex:null,cancelConfirmKeysOnEmpty:!1,onTagExists:function(a,b){b.hide().fadeIn()},trimValue:!1,allowDuplicates:!1};b.prototype={constructor:b,add:function(b,c,d){var f=this;if(!(f.options.maxTags&&f.itemsArray.length>=f.options.maxTags)&&(b===!1||b)){if("string"==typeof b&&f.options.trimValue&&(b=a.trim(b)),"object"==typeof b&&!f.objectItems)throw"Can't add objects when itemValue option is not set";if(!b.toString().match(/^\s*$/)){if(f.isSelect&&!f.multiple&&f.itemsArray.length>0&&f.remove(f.itemsArray[0]),"string"==typeof b&&"INPUT"===this.$element[0].tagName){var g=f.options.delimiterRegex?f.options.delimiterRegex:f.options.delimiter,h=b.split(g);if(h.length>1){for(var i=0;i<h.length;i++)this.add(h[i],!0);return void(c||f.pushVal())}}var j=f.options.itemValue(b),k=f.options.itemText(b),l=f.options.tagClass(b),m=f.options.itemTitle(b),n=a.grep(f.itemsArray,function(a){return f.options.itemValue(a)===j})[0];if(!n||f.options.allowDuplicates){if(!(f.items().toString().length+b.length+1>f.options.maxInputLength)){var o=a.Event("beforeItemAdd",{item:b,cancel:!1,options:d});if(f.$element.trigger(o),!o.cancel){f.itemsArray.push(b);var p=a('<span class="tag '+e(l)+(null!==m?'" title="'+m:"")+'">'+e(k)+'<span data-role="remove"></span></span>');p.data("item",b),f.findInputWrapper().before(p),p.after(" ");var q=a('option[value="'+encodeURIComponent(j)+'"]',f.$element).length||a('option[value="'+e(j)+'"]',f.$element).length;if(f.isSelect&&!q){var r=a("<option selected>"+e(k)+"</option>");r.data("item",b),r.attr("value",j),f.$element.append(r)}c||f.pushVal(),(f.options.maxTags===f.itemsArray.length||f.items().toString().length===f.options.maxInputLength)&&f.$container.addClass("bootstrap-tagsinput-max"),a(".typeahead, .twitter-typeahead",f.$container).length&&f.$input.typeahead("val",""),this.isInit?f.$element.trigger(a.Event("itemAddedOnInit",{item:b,options:d})):f.$element.trigger(a.Event("itemAdded",{item:b,options:d}))}}}else if(f.options.onTagExists){var s=a(".tag",f.$container).filter(function(){return a(this).data("item")===n});f.options.onTagExists(b,s)}}}},remove:function(b,c,d){var e=this;if(e.objectItems&&(b="object"==typeof b?a.grep(e.itemsArray,function(a){return e.options.itemValue(a)==e.options.itemValue(b)}):a.grep(e.itemsArray,function(a){return e.options.itemValue(a)==b}),b=b[b.length-1]),b){var f=a.Event("beforeItemRemove",{item:b,cancel:!1,options:d});if(e.$element.trigger(f),f.cancel)return;a(".tag",e.$container).filter(function(){return a(this).data("item")===b}).remove(),a("option",e.$element).filter(function(){return a(this).data("item")===b}).remove(),-1!==a.inArray(b,e.itemsArray)&&e.itemsArray.splice(a.inArray(b,e.itemsArray),1)}c||e.pushVal(),e.options.maxTags>e.itemsArray.length&&e.$container.removeClass("bootstrap-tagsinput-max"),e.$element.trigger(a.Event("itemRemoved",{item:b,options:d}))},removeAll:function(){var b=this;for(a(".tag",b.$container).remove(),a("option",b.$element).remove();b.itemsArray.length>0;)b.itemsArray.pop();b.pushVal()},refresh:function(){var b=this;a(".tag",b.$container).each(function(){var c=a(this),d=c.data("item"),f=b.options.itemValue(d),g=b.options.itemText(d),h=b.options.tagClass(d);if(c.attr("class",null),c.addClass("tag "+e(h)),c.contents().filter(function(){return 3==this.nodeType})[0].nodeValue=e(g),b.isSelect){var i=a("option",b.$element).filter(function(){return a(this).data("item")===d});i.attr("value",f)}})},items:function(){return this.itemsArray},pushVal:function(){var b=this,c=a.map(b.items(),function(a){return b.options.itemValue(a).toString()});b.$element.val(c,!0).trigger("change")},build:function(b){var e=this;if(e.options=a.extend({},h,b),e.objectItems&&(e.options.freeInput=!1),c(e.options,"itemValue"),c(e.options,"itemText"),d(e.options,"tagClass"),e.options.typeahead){var i=e.options.typeahead||{};d(i,"source"),e.$input.typeahead(a.extend({},i,{source:function(b,c){function d(a){for(var b=[],d=0;d<a.length;d++){var g=e.options.itemText(a[d]);f[g]=a[d],b.push(g)}c(b)}this.map={};var f=this.map,g=i.source(b);a.isFunction(g.success)?g.success(d):a.isFunction(g.then)?g.then(d):a.when(g).then(d)},updater:function(a){return e.add(this.map[a]),this.map[a]},matcher:function(a){return-1!==a.toLowerCase().indexOf(this.query.trim().toLowerCase())},sorter:function(a){return a.sort()},highlighter:function(a){var b=new RegExp("("+this.query+")","gi");return a.replace(b,"<strong>$1</strong>")}}))}if(e.options.typeaheadjs){var j=null,k={},l=e.options.typeaheadjs;a.isArray(l)?(j=l[0],k=l[1]):k=l,e.$input.typeahead(j,k).on("typeahead:selected",a.proxy(function(a,b){k.valueKey?e.add(b[k.valueKey]):e.add(b),e.$input.typeahead("val","")},e))}e.$container.on("click",a.proxy(function(a){e.$element.attr("disabled")||e.$input.removeAttr("disabled"),e.$input.focus()},e)),e.options.addOnBlur&&e.options.freeInput&&e.$input.on("focusout",a.proxy(function(b){0===a(".typeahead, .twitter-typeahead",e.$container).length&&(e.add(e.$input.val()),e.$input.val(""))},e)),e.$container.on("keydown","input",a.proxy(function(b){var c=a(b.target),d=e.findInputWrapper();if(e.$element.attr("disabled"))return void e.$input.attr("disabled","disabled");switch(b.which){case 8:if(0===f(c[0])){var g=d.prev();g.length&&e.remove(g.data("item"))}break;case 46:if(0===f(c[0])){var h=d.next();h.length&&e.remove(h.data("item"))}break;case 37:var i=d.prev();0===c.val().length&&i[0]&&(i.before(d),c.focus());break;case 39:var j=d.next();0===c.val().length&&j[0]&&(j.after(d),c.focus())}var k=c.val().length;Math.ceil(k/5);c.attr("size",Math.max(this.inputSize,c.val().length))},e)),e.$container.on("keypress","input",a.proxy(function(b){var c=a(b.target);if(e.$element.attr("disabled"))return void e.$input.attr("disabled","disabled");var d=c.val(),f=e.options.maxChars&&d.length>=e.options.maxChars;e.options.freeInput&&(g(b,e.options.confirmKeys)||f)&&(0!==d.length&&(e.add(f?d.substr(0,e.options.maxChars):d),c.val("")),e.options.cancelConfirmKeysOnEmpty===!1&&b.preventDefault());var h=c.val().length;Math.ceil(h/5);c.attr("size",Math.max(this.inputSize,c.val().length))},e)),e.$container.on("click","[data-role=remove]",a.proxy(function(b){e.$element.attr("disabled")||e.remove(a(b.target).closest(".tag").data("item"))},e)),e.options.itemValue===h.itemValue&&("INPUT"===e.$element[0].tagName?e.add(e.$element.val()):a("option",e.$element).each(function(){e.add(a(this).attr("value"),!0)}))},destroy:function(){var a=this;a.$container.off("keypress","input"),a.$container.off("click","[role=remove]"),a.$container.remove(),a.$element.removeData("tagsinput"),a.$element.show()},focus:function(){this.$input.focus()},input:function(){return this.$input},findInputWrapper:function(){for(var b=this.$input[0],c=this.$container[0];b&&b.parentNode!==c;)b=b.parentNode;return a(b)}},a.fn.tagsinput=function(c,d,e){var f=[];return this.each(function(){var g=a(this).data("tagsinput");if(g)if(c||d){if(void 0!==g[c]){if(3===g[c].length&&void 0!==e)var h=g[c](d,null,e);else var h=g[c](d);void 0!==h&&f.push(h)}}else f.push(g);else g=new b(this,c),a(this).data("tagsinput",g),f.push(g),"SELECT"===this.tagName&&a("option",a(this)).attr("selected","selected"),a(this).val(a(this).val())}),"string"==typeof c?f.length>1?f:f[0]:f},a.fn.tagsinput.Constructor=b;var i=a("<div />");a(function(){a("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput()})}(window.jQuery);
//# sourceMappingURL=bootstrap-tagsinput.min.js.map dist/bootstrap-tagsinput.min.js.map 0000644 00000030003 15167672471 0013450 0 ustar 00 {"version":3,"sources":["../src/bootstrap-tagsinput.js"],"names":["$","TagsInput","element","options","this","isInit","itemsArray","$element","hide","isSelect","tagName","multiple","hasAttribute","objectItems","itemValue","placeholderText","attr","inputSize","Math","max","length","$container","$input","appendTo","before","build","makeOptionItemFunction","key","propertyName","item","makeOptionFunction","value","htmlEncode","htmlEncodeContainer","text","html","doGetCaretPosition","oField","iCaretPos","document","selection","focus","oSel","createRange","moveStart","selectionStart","keyCombinationInList","keyPressEvent","lookupList","found","each","index","keyCombination","which","alt","hasOwnProperty","altKey","shift","shiftKey","ctrl","ctrlKey","defaultOptions","tagClass","toString","itemText","itemTitle","freeInput","addOnBlur","maxTags","undefined","maxChars","confirmKeys","delimiter","delimiterRegex","cancelConfirmKeysOnEmpty","onTagExists","$tag","fadeIn","trimValue","allowDuplicates","prototype","constructor","add","dontPushVal","self","trim","match","remove","items","split","i","pushVal","existing","grep","maxInputLength","beforeItemAddEvent","Event","cancel","trigger","push","data","findInputWrapper","after","optionExists","encodeURIComponent","$option","append","addClass","typeahead","$existingTag","filter","other","beforeItemRemoveEvent","inArray","splice","removeClass","removeAll","pop","refresh","contents","nodeType","nodeValue","option","val","map","extend","source","query","process","processItems","texts","isFunction","success","then","when","updater","matcher","toLowerCase","indexOf","sorter","sort","highlighter","regex","RegExp","replace","typeaheadjs","typeaheadConfig","typeaheadDatasets","isArray","on","proxy","obj","datum","valueKey","event","removeAttr","target","$inputWrapper","prev","next","$prevTag","$nextTag","textLength","ceil","maxLengthReached","substr","preventDefault","closest","destroy","off","removeData","show","input","elt","container","parentNode","fn","tagsinput","arg1","arg2","arg3","results","retVal","Constructor","window","jQuery"],"mappings":"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","file":"bootstrap-tagsinput.min.js"} dist/bootstrap-tagsinput.less 0000644 00000002004 15167672471 0012444 0 ustar 00 .bootstrap-tagsinput {
background-color: #fff;
border: 1px solid #ccc;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
display: inline-block;
padding: 4px 6px;
margin-bottom: 10px;
color: #555;
vertical-align: middle;
border-radius: 4px;
max-width: 100%;
line-height: 22px;
cursor: text;
input {
border: none;
box-shadow: none;
outline: none;
background-color: transparent;
padding: 0;
margin: 0;
width: auto !important;
max-width: inherit;
&:focus {
border: none;
box-shadow: none;
}
}
.tag {
margin-right: 2px;
color: white;
[data-role="remove"] {
margin-left:8px;
cursor:pointer;
&:after{
content: "x";
padding:0px 2px;
}
&:hover {
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
&:active {
box-shadow: inset 0 3px 5px rgba(0,0,0,0.125);
}
}
}
}
}
dist/bootstrap-tagsinput.zip 0000644 00000152250 15167672471 0012311 0 ustar 00 PK
�jG dist/PK
�jGv��g g # dist/bootstrap-tagsinput-angular.jsangular.module('bootstrap-tagsinput', [])
.directive('bootstrapTagsinput', [function() {
function getItemProperty(scope, property) {
if (!property)
return undefined;
if (angular.isFunction(scope.$parent[property]))
return scope.$parent[property];
return function(item) {
return item[property];
};
}
return {
restrict: 'EA',
scope: {
model: '=ngModel'
},
template: '<select multiple></select>',
replace: false,
link: function(scope, element, attrs) {
$(function() {
if (!angular.isArray(scope.model))
scope.model = [];
var select = $('select', element);
var typeaheadSourceArray = attrs.typeaheadSource ? attrs.typeaheadSource.split('.') : null;
var typeaheadSource = typeaheadSourceArray ?
(typeaheadSourceArray.length > 1 ?
scope.$parent[typeaheadSourceArray[0]][typeaheadSourceArray[1]]
: scope.$parent[typeaheadSourceArray[0]])
: null;
select.tagsinput(scope.$parent[attrs.options || ''] || {
typeahead : {
source : angular.isFunction(typeaheadSource) ? typeaheadSource : null
},
itemValue: getItemProperty(scope, attrs.itemvalue),
itemText : getItemProperty(scope, attrs.itemtext),
confirmKeys : getItemProperty(scope, attrs.confirmkeys) ? JSON.parse(attrs.confirmkeys) : [13],
tagClass : angular.isFunction(scope.$parent[attrs.tagclass]) ? scope.$parent[attrs.tagclass] : function(item) { return attrs.tagclass; }
});
for (var i = 0; i < scope.model.length; i++) {
select.tagsinput('add', scope.model[i]);
}
select.on('itemAdded', function(event) {
if (scope.model.indexOf(event.item) === -1)
scope.model.push(event.item);
});
select.on('itemRemoved', function(event) {
var idx = scope.model.indexOf(event.item);
if (idx !== -1)
scope.model.splice(idx, 1);
});
// create a shallow copy of model's current state, needed to determine
// diff when model changes
var prev = scope.model.slice();
scope.$watch("model", function() {
var added = scope.model.filter(function(i) {return prev.indexOf(i) === -1;}),
removed = prev.filter(function(i) {return scope.model.indexOf(i) === -1;}),
i;
prev = scope.model.slice();
// Remove tags no longer in binded model
for (i = 0; i < removed.length; i++) {
select.tagsinput('remove', removed[i]);
}
// Refresh remaining tags
select.tagsinput('refresh');
// Add new items in model as tags
for (i = 0; i < added.length; i++) {
select.tagsinput('add', added[i]);
}
}, true);
});
}
};
}]);
PK
�jG�T+� � '