JQ input输入框回车生成标签,可删除,并获取标签的值
程序员文章站
2022-07-04 22:26:23
在网上找的,效果如下 html代码 flat-ui标签
在网上找的,效果如下
html代码
<!doctype html> <html lang="zh-cn"> <head> <title>flat-ui标签</title> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width" /> <script src="js/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="css/css.css"/> <script src="js/tagsinput.js" type="text/javascript" charset="utf-8"></script> </head> <body> <div class="box"> <h1 style="text-align: center;margin: 20px 0;margin-top: 200px;">提取input中的标签</h1> <div class="tagsinput-primary form-group"> <input name="tagsinput" id="tagsinputval" class="tagsinput" data-role="tagsinput" value="faltui,这是一个标签" placeholder="输入后回车"/> <button class="btn" onclick="getinput()">获取输入的值</button> </div> </div> <script type="text/javascript"> function getinput(){ alert($('#tagsinputval').val()); } </script> </body> </html>
css代码:
*{margin: 0;padding: 0;list-style-type: none;text-decoration: none;} .box{width: 500px;margin: auto;} .bootstrap-tagsinput { background-color: white; border: 2px solid #ebedef; border-radius: 6px; margin-bottom: 18px; padding: 6px 1px 1px 6px; text-align: left; font-size: 0; } .bootstrap-tagsinput .badge { border-radius: 4px; background-color: #ebedef; color: #7b8996; font-size: 13px; cursor: pointer; display: inline-block; position: relative; vertical-align: middle; overflow: hidden; margin: 0 5px 5px 0; padding: 6px 28px 6px 14px; transition: .25s linear; } .bootstrap-tagsinput .badge > span { color: white; padding: 0 10px 0 0; cursor: pointer; font-size: 12px; position: absolute; right: 0; text-align: right; text-decoration: none; top: 0; width: 100%; bottom: 0; z-index: 2; } .bootstrap-tagsinput .badge > span:after { content: "x"; font-family: "flat-ui-pro-icons"; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; line-height: 27px; } @media (hover: hover) { .bootstrap-tagsinput .badge { padding: 6px 21px; } .bootstrap-tagsinput .badge > span { opacity: 0; filter: "alpha(opacity=0)"; transition: opacity .25s linear; } .bootstrap-tagsinput .badge:hover { background-color: #16a085; color: white; padding-right: 28px; padding-left: 14px; } .bootstrap-tagsinput .badge:hover > span { padding: 0 10px 0 0; opacity: 1; -webkit-filter: none; filter: none; } } .bootstrap-tagsinput input[type="text"] { font-size: 14px; border: none; box-shadow: none; outline: none; background-color: transparent; padding: 0; margin: 0; width: auto !important; max-width: inherit; min-width: 80px; vertical-align: top; height: 29px; color: #34495e; } .tagsinput-primary { margin-bottom: 18px; } .tagsinput-primary .bootstrap-tagsinput { border-color: #1abc9c; margin-bottom: 0; } .tagsinput-primary .badge { background-color: #1abc9c; color: white; } .btn{background: #1abc9c;border: none;color: #fff;padding: 10px;border-radius: 5px;margin-top: 10px;}
jq代码:
/* bootstrap-tagsinput v0.8.0 */ (function ($) { "use strict"; var defaultoptions = { tagclass: function(item) { return 'badge badge-info'; }, focusclass: 'focus', 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, triggerchange: true }; /** * 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(self.options.triggerchange); 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 = $(".badge", 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="badge ' + 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(self.options.triggerchange); // 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; $('.badge', 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(self.options.triggerchange); // 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; $('.badge', self.$container).remove(); $('option', self.$element).remove(); while(self.itemsarray.length > 0) self.itemsarray.pop(); self.pushval(self.options.triggerchange); }, /** * refreshes the tags so they match the text/value of their corresponding * item. */ refresh: function() { var self = this; $('.badge', 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('badge ' + 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); if (self.options.triggerchange) self.$element.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) { // determine if main configurations were passed or simply a dataset var typeaheadjs = self.options.typeaheadjs; if (!$.isarray(typeaheadjs)) { typeaheadjs = [null, typeaheadjs]; } $.fn.typeahead.apply(self.$input, typeaheadjs).on('typeahead:selected', $.proxy(function (obj, datum, name) { var index = 0; typeaheadjs.some(function(dataset, _index) { if (dataset.name === name) { index = _index; return true; } return false; }); // @todo dep: https://github.com/corejavascript/typeahead.js/issues/89 if (typeaheadjs[index].valuekey) { self.add(datum[typeaheadjs[index].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)); } // toggle the 'focus' css class on the container when it has focus self.$container.on({ focusin: function() { self.$container.addclass(self.options.focusclass); }, focusout: function() { self.$container.removeclass(self.options.focusclass); }, }); 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, size)); }, 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, size)); }, 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('.badge').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 * zmm2113@qq.com 2018.6.24 */ $(function() { $("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput(); }); })(window.jquery);