123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- /*
- jQuery Tags Input Plugin 1.3.3 (with minor modifications for CardDavMATE)
-
- Copyright (c) 2011 XOXCO, Inc
-
- Documentation for this plugin lives here:
- http://xoxco.com/clickable/jquery-tags-input
-
- Licensed under the MIT license:
- http://www.opensource.org/licenses/mit-license.php
- ben@xoxco.com
- */
- (function($){
- var tags_settings=new Array();
- var tags_callbacks=new Array();
- String.prototype.escapeCustom=function(inputDelimiter)
- {
- var value=(this==undefined ? '' : this),
- output='';
- for(var i=0; i<value.length; i++)
- {
- if(value[i]==inputDelimiter || value[i]=='\\')
- output+='\\';
- output+=value[i];
- }
- return output;
- }
- // split and unescape values
- String.prototype.splitCustom=function(inputDelimiter)
- {
- var outputArray=new Array(),
- value=this,
- j=0;
- for(var i=0; i<value.length; i++)
- {
- if(value[i]==inputDelimiter)
- {
- if(outputArray[j]==undefined)
- outputArray[j]='';
- ++j;
- continue;
- }
- else if(value[i]=='\\')
- ++i;
- outputArray[j]=(outputArray[j]==undefined ? '' : outputArray[j])+value[i];
- }
- return outputArray;
- }
- $.fn.doAutosize=function(o)
- {
- var minWidth=$(this).data('minwidth'),
- maxWidth=$(this).data('maxwidth'),
- val='',
- input=$(this),
- testSubject=$('#'+$(this).data('tester_id'));
- if(val===(val=input.val()))
- return;
- // Enter new content into testSubject
- var escaped=val.replace(/\s/g,' '); // get proper width for values with leading spaces (or only spaces)
- testSubject.html(escaped);
- // Calculate new width + whether to change
- var testerWidth=testSubject.width(),
- newWidth=(testerWidth+o.comfortZone)>=minWidth ? testerWidth+o.comfortZone : minWidth,
- currentWidth=input.width(),
- isValidWidthChange=(newWidth<currentWidth && newWidth>=minWidth) || (newWidth>minWidth && newWidth<maxWidth);
- // Animate width
- if(isValidWidthChange)
- input.width(newWidth);
- };
- $.fn.resetAutosize=function(options)
- {
- // alert(JSON.stringify(options));
- var minWidth=$(this).data('minwidth') || options.minInputWidth || $(this).width(),
- maxWidth=$(this).data('maxwidth') || options.maxInputWidth || ($(this).closest('.tagsinput').width()-options.inputPadding),
- val='',
- input=$(this),
- testSubject=$('<tester/>').css({
- position: 'absolute',
- top: -9999,
- left: -9999,
- width: 'auto',
- fontSize: input.css('fontSize'),
- fontFamily: input.css('fontFamily'),
- fontWeight: input.css('fontWeight'),
- letterSpacing: input.css('letterSpacing'),
- whiteSpace: 'nowrap'
- }),
- testerId=$(this).attr('id')+'_autosize_tester';
- if(!$('#'+testerId).length>0)
- {
- testSubject.attr('id', testerId);
- testSubject.appendTo('body');
- }
- input.data('minwidth', minWidth);
- input.data('maxwidth', maxWidth);
- input.data('tester_id', testerId);
- input.css('width', minWidth);
- };
- $.fn.addTag=function(value, options)
- {
- options=jQuery.extend({focus: false, callback: true, imported: false}, options);
- this.each(function()
- {
- var id=$(this).attr('id');
- if(tags_settings[id].allowDelimiterInValue==true)
- var tagslist=$(this).val().splitCustom(tags_settings[id].delimiter);
- else
- var tagslist=$(this).val().split(delimiter[id]);
- if(tagslist[0]=='')
- tagslist=new Array();
- if(options.trimInput==true)
- value=jQuery.trim(value);
- var skipTag=false;
- var duplicate=$(tagslist).tagExist(value);
- if(tags_callbacks[id] && tags_callbacks[id]['validateTag'])
- skipTag=!tags_callbacks[id]['validateTag'].call(this, value, options.imported, duplicate);
- if(!skipTag && options.unique)
- skipTag=duplicate;
- if(skipTag)
- $(this).parent().find('#'+id+'_tag').addClass('not_valid'); //Marks fake input as not_valid to let styling it
- if(value!='' && skipTag!=true)
- {
- $('<span>').addClass('tag').append(
- $('<span>').text(value),
- $('<a>', {
- href: '#',
- title: 'Removing tag',
- text: 'x'
- }).click(function(){return $('#'+id).removeTag(value)})
- ).insertBefore($(this).parent().find('#'+id+'_addTag'));
- tagslist.push(value);
- var tmpRef=$(this).parent().find('#'+id+'_tag');
- tmpRef.val('');
- if(options.focus)
- tmpRef.focus();
- else
- tmpRef.blur();
- $.fn.tagsInput.updateTagsField(this, tagslist);
- if(options.callback && tags_callbacks[id] && tags_callbacks[id]['onAddTag'])
- {
- var f=tags_callbacks[id]['onAddTag'];
- f.call(this, value);
- }
- if(tags_callbacks[id] && tags_callbacks[id]['onChange'])
- {
- var i=tagslist.length;
- var f=tags_callbacks[id]['onChange'];
- f.call(this, tagslist[i-1], options.imported);
- }
- }
- });
- return false;
- };
- $.fn.removeTag = function(value)
- {
- this.each(function()
- {
- var id=$(this).attr('id');
- if(tags_settings[id].allowDelimiterInValue==true)
- var old=$(this).val().splitCustom(tags_settings[id].delimiter);
- else
- var old=$(this).val().split(delimiter[id]);
- $(this).parent().find('#'+id+'_tagsinput .tag').remove();
- var str='';
- for(i=0; i<old.length; i++)
- if(old[i]!=value)
- str=(str=='' ? '' : str+tags_settings[id].delimiter)+(tags_settings[id].allowDelimiterInValue==true ? old[i].escapeCustom(tags_settings[id].delimiter) : old[i]);
- $.fn.tagsInput.importTags(this, str);
- if(tags_callbacks[id] && tags_callbacks[id]['onRemoveTag'])
- {
- var f=tags_callbacks[id]['onRemoveTag'];
- f.call(this, value);
- }
- });
- return false;
- };
- $.fn.tagExist=function(val)
- {
- return (jQuery.inArray(val, $(this))>=0); //true when tag exists, false when not
- };
- // clear all existing tags and import new ones from a string
- $.fn.importTags=function(str)
- {
- $(this).parent().find('#'+$(this).attr('id')+'_tagsinput .tag').remove();
- $.fn.tagsInput.importTags(this, str);
- }
- $.fn.tagsInput=function(options)
- {
- var settings=jQuery.extend({
- interactive: true,
- defaultText: 'add a tag',
- useNativePlaceholder:false,
- minChars: 0,
- width: '300px',
- height: '100px',
- autocomplete: {selectFirst: false},
- hide: true,
- delimiter: ',',
- allowDelimiterInValue: false,
- trimInput: true,
- unique: true,
- removeWithBackspace: true,
- color: '#000000',
- placeholderColor: '#666666',
- autosize: true,
- comfortZone: 20,
- inputPadding: 6*2
- }, options);
- this.each(function()
- {
- if(settings.hide)
- $(this).hide();
- var id=$(this).attr('id');
- var data=jQuery.extend({
- real_inputObj: $(this),
- pid: id,
- real_input: '#'+id,
- holder: '#'+id+'_tagsinput',
- input_wrapper: '#'+id+'_addTag',
- fake_input: '#'+id+'_tag'
- }, settings);
- tags_settings[id]={delimiter: data.delimiter, allowDelimiterInValue: data.allowDelimiterInValue};
- if(settings.onAddTag || settings.onRemoveTag || settings.onChange || settings.validateTag)
- {
- tags_callbacks[id] = new Array();
- tags_callbacks[id]['onAddTag'] = settings.onAddTag;
- tags_callbacks[id]['onRemoveTag'] = settings.onRemoveTag;
- tags_callbacks[id]['onChange'] = settings.onChange;
- tags_callbacks[id]['validateTag'] = settings.validateTag;
- }
- var markup='<div id="'+id+'_tagsinput" class="tagsinput"><div id="'+id+'_addTag">';
- if(settings.interactive)
- markup=markup+'<div class="input_container"><input id="'+id+'_tag" type="text" value=""'+(settings.useNativePlaceholder==true ? ' placeholder="'+settings.defaultText+'" data-default=""' : ' data-default="'+settings.defaultText+'"')+' /></div>';
- markup=markup+'</div><div class="tags_clear"></div></div>';
- var tmpMarkupObj=$(markup).insertAfter(this);
- if(settings.width!=null)
- tmpMarkupObj.css('width', settings.width);
- if(settings.height!=null)
- tmpMarkupObj.css('height', settings.height);
- if($(this).val()!='')
- $.fn.tagsInput.importTags($(this), $(this).val());
- if(settings.interactive)
- {
- tmpMarkupObj.val(tmpMarkupObj.attr('data-default'));
- tmpMarkupObj.css('color', settings.placeholderColor);
- tmpMarkupObj.resetAutosize(settings);
- tmpMarkupObj.bind('click', data, function(event)
- {
- $(this).find(event.data.fake_input).focus();
- });
- tmpMarkupObj.find(data.fake_input).bind('focus', data, function(event)
- {
- if($(this).val() == $(this).attr('data-default'))
- $(this).val('');
- $(this).css('color', settings.color);
- });
- if(settings.autocomplete_url!=undefined)
- {
- var autocomplete_options={source: settings.autocomplete_url};
- for(var attrname in settings.autocomplete)
- autocomplete_options[attrname]=settings.autocomplete[attrname];
- if(jQuery.Autocompleter!==undefined)
- {
- tmpMarkupObj.find(data.fake_input).autocomplete(settings.autocomplete_url, settings.autocomplete);
- tmpMarkupObj.find(data.fake_input).bind('result', data, function(event, data, formatted)
- {
- if(data)
- event.data.real_inputObj.addTag(data[0] + "", {focus: true, unique: settings.unique, trimInput: settings.trimInput});
- });
- }
- else if(jQuery.ui.autocomplete!==undefined)
- {
- tmpMarkupObj.find(data.fake_input).autocomplete(autocomplete_options);
- tmpMarkupObj.find(data.fake_input).bind('autocompleteselect', data, function(event,ui)
- {
- event.data.real_inputObj.addTag(ui.item.value, {focus: true, unique: settings.unique, trimInput: settings.trimInput});
- return false;
- });
- }
- // if a user tabs out of the field, create a new tag
- // this is only available if autocomplete is not used.
- tmpMarkupObj.find(data.fake_input).bind('blur', data, function(event)
- {
- var d=$(this).attr('data-default');
- if($(this).val()!='' && $(this).val()!=d)
- {
- if((event.data.minChars<=$(this).val().length) && (!event.data.maxChars || (event.data.maxChars>=$(this).val().length)))
- event.data.real_inputObj.addTag($(this).val(), {focus: true, unique: settings.unique, trimInput: settings.trimInput});
- }
- else
- $(this).val($(this).attr('data-default'));
- $(this).css('color', settings.placeholderColor);
- return false;
- });
- }
- // if user types a comma, create a new tag
- tmpMarkupObj.find(data.fake_input).bind('keypress', data, function(event)
- {
- if(settings.allowDelimiterInValue==false && event.which==event.data.delimiter.charCodeAt(0) || event.which==13)
- {
- event.preventDefault();
- if((event.data.minChars<=$(this).val().length) && (!event.data.maxChars || (event.data.maxChars>=$(this).val().length)))
- event.data.real_inputObj.addTag($(event.data.fake_input).val(), {focus: true, unique: settings.unique, trimInput: settings.trimInput});
- $(this).resetAutosize(settings);
- return false;
- }
- else if(event.data.autosize)
- $(this).doAutosize(settings);
- });
- //Delete last tag on backspace
- data.removeWithBackspace && tmpMarkupObj.find(data.fake_input).bind('keydown', data, function(event)
- {
- if($(this).closest('.tagsinput').hasClass('readonly')==false && event.keyCode==8 && $(this).val()=='')
- {
- event.preventDefault();
- var last_tag=$(this).closest('.tagsinput').find('.tag:last').text();
- var id=$(this).attr('id').replace(/_tag$/, '');
- last_tag=last_tag.replace(/x$/, '');
- event.data.real_inputObj.removeTag(last_tag);
- $(this).trigger('focus');
- }
- });
- tmpMarkupObj.find(data.fake_input).blur();
- //Removes the not_valid class when user changes the value of the fake input
- if(data.unique)
- {
- tmpMarkupObj.find(data.fake_input).keydown(function(event)
- {
- if(event.keyCode==8 || String.fromCharCode(event.which).match(/\w+|[áéíóúÁÉÍÓÚñÑ,/]+/))
- $(this).removeClass('not_valid');
- });
- }
- } // if settings.interactive
- // store settings
- $(this).data('tagsOptions', settings);
- return false;
- });
- return this;
- };
-
- $.fn.tagsInput.updateTagsField=function(obj, tagslist)
- {
- var id = $(obj).attr('id');
- if(tags_settings[id].allowDelimiterInValue==true)
- for(var i=0;i<tagslist.length;i++)
- tagslist[i]=tagslist[i].escapeCustom(tags_settings[id].delimiter);
- $(obj).val(tagslist.join(tags_settings[id].delimiter));
- };
- $.fn.tagsInput.importTags=function(obj, val)
- {
- var settings=jQuery.extend({
- trimInput: true,
- unique: true
- }, $(obj).data('tagsOptions'));
- $(obj).val('');
- var id=$(obj).attr('id');
- if(tags_settings[id].allowDelimiterInValue==true)
- var tags=val.splitCustom(tags_settings[id].delimiter);
- else
- var tags=val.split(delimiter[id]);
- for(var i=0; i<tags.length; i++)
- $(obj).addTag(tags[i], {focus: true, unique: settings.unique, trimInput: settings.trimInput, callback: false, imported: true});
- if(tags_callbacks[id] && tags_callbacks[id]['onChange'])
- {
- var f=tags_callbacks[id]['onChange'];
- f.call(obj, tags[i], true);
- }
- };
- })(jQuery);
|