I want to combine the functions of jQueryUI autocmoplete and a tag input library (unfortunaly I don't remember where I got the library from, but the source code is inside the snippet).
A little documentation about the tag input library:
The tag input library basically hides the original <input/>
and adds a new <input class="tag-input" />
when initialized by new Tags('#testTags')
. New tags can be added with addTags("someTag");
What works so far:
When I receive some values from autocomplete and the user selects the value, I call addTags(ui.item.value);
- which is perfectly fine.
Where I have troubles:
Many users don't pick the value from the autocompleter, they rather just input a text and click on 'search'. I want to ensure that only values from the autocompleter are inserted. I understand, that only clicking on autocompleter values is not the best for user experience, so I want that if a user enters a text and click on 'search', a matching value from the autocompleter is automatically picked (if one exists).
I tried this little piece of code:
$('#search').on('click',function(){
if($( '.tag-input[placeholder="test1"]' ).val() != "") //user did not finish entry
{
testTags.addTags($( '.tag-input[placeholder="test1"]' ).val());
}
});
It checks on button click if the input contains a value, that isn't transformed into a tag yet. If so, I add this value as tag. My problem is, that this value should be matched against the autocompleter values before "transforming" to a tag.
How to access those autocompleter suggestions outside of .autocomplete({})
?
A related question would be this: How do I get the jQuery UI autocomplete value from outside an onchange event? The difference is, that I rather need the autocomplete suggestions instead of the selected value.
!function(){"use strict";function e(e,t){return"string"==typeof e?(t||document).querySelectorAll(e):[e]}function t(e,t){return"string"==typeof e?(t||document).querySelector(e):e}function n(e,t){var n=document.createElement(e);if(t)for(var i in t)void 0!==n[i]&&(n[i]=t[i]);return n}function i(){var e=document.documentElement,t={transition:"transitionend",WebkitTransition:"webkitTransitionEnd",MozTransition:"mozTransitionEnd",OTransition:"oTransitionEnd otransitionend"};for(var n in t)if(void 0!==e.style[n])return t[n];return!1}function r(e,t,n,i){i=i||!1,e.addEventListener(t,function t(r){n.call(this,r),e.removeEventListener(r.type,t,i)},i)}function a(e,t){return new RegExp("(^|\\s+)"+e+"(\\s+|$)").test(t.className)}function o(e,t){if(!a(e,t))return t.className+=""===t.className?e:" "+e}function s(e,t){t.className=t.className.replace(new RegExp("(^|\\s+)"+e+"(\\s+|$)"),"")}function u(u){function l(){y=n("div",{className:"tags-container"}),N=n("input",{type:"text",className:"tag-input",placeholder:h.placeholder||""}),y.appendChild(N),""!==h.value.trim()&&c(),h.type="hidden",h.parentNode.insertBefore(y,h.nextSibling),y.addEventListener("click",v,!1),y.addEventListener("keydown",d,!1),y.addEventListener("keyup",g,!1)}function c(){var e=h.value.trim().split(",");e.forEach(function(e){if(e=e.trim(),!~x.indexOf(e)){var t=f(e);x.push(e),y.insertBefore(t,N)}})}function f(e){var t=n("div",{className:"tag",innerHTML:'<span class="tag__name">'+e+'</span><button class="tag__remove">×</button>'});return t}function v(e){if(e.preventDefault(),"tag__remove"===e.target.className){var n=e.target.parentNode,i=t(".tag__name",n);y.removeChild(n),x.splice(x.indexOf(i.textContent),1),h.value=x.join(",")}N.focus()}function d(e){if("INPUT"===e.target.tagName&&"tag-input"===e.target.className){var t=e.target,n=e.which||e.keyCode;N.previousSibling&&n!==C.BACK&&s("tag--marked",N.previousSibling);var i=t.value.trim();n===C.ENTER?(t.blur(),m(i),E&&clearTimeout(E),E=setTimeout(function(){t.focus()},10)):n===C.BACK&&(""!==e.target.value||L||(L=!0,p()))}}function g(e){L=!1}function m(t){if(t=t.toString().replace(/,/g,"").trim(),""===t)return N.value="";if(~x.indexOf(t)){var n=e(".tag",y);return Array.prototype.forEach.call(n,function(e){e.firstChild.textContent===t&&(o("tag--exists",e),k?r(e,k,function(){s("tag--exists",e)}):s("tag--exists",e))}),N.value=""}var i=f(t);y.insertBefore(i,N),x.push(t),N.value="",h.value+=""===h.value?t:","+t}function p(){if(0!==x.length){var t=e(".tag",y),n=t[t.length-1];if(!a("tag--marked",n))return void o("tag--marked",n);x.pop(),y.removeChild(n),h.value=x.join(",")}}var h=t(u);if(!h.instance){h.instance=this;var E,y,N,T=h.type,k=i(),x=[],C={ENTER:13,BACK:8},L=!1;l(),this.getTags=function(){return x},this.clearTags=function(){h.instance&&(x.length=0,h.value="",y.innerHTML="",y.appendChild(N))},this.addTags=function(e){if(h.instance){if(Array.isArray(e))for(var t=0,n=e.length;t<n;t++)m(e[t]);else m(e);return x}},this.destroy=function(){h.instance&&(y.removeEventListener("click",v,!1),y.removeEventListener("keydown",d,!1),y.removeEventListener("keyup",d,!1),y.parentNode.removeChild(y),h.type=T,T=null,x=null,E=null,y=null,N=null,delete h.instance)}}}window.Tags=u}();
var testTags = new Tags('#testTags');
$( function() {
var availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
$( '.tag-input[placeholder="test1"]' ).autocomplete({
source: availableTags,
select: function(event, ui){
event.preventDefault();
event.stopPropagation();
testTags.addTags(ui.item.value);
return false;
}
});
$('#search').on('click',function(){
if($( '.tag-input[placeholder="test1"]' ).val() != "") //user did not finish entry
{
testTags.addTags($( '.tag-input[placeholder="test1"]' ).val());
}
});
});
*,:after,:before{box-sizing:border-box}.tags-container{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-bottom:15px;width:100%;min-height:34px;padding:2px 5px;font-size:14px;line-height:1.6;background-color:transparent;border:1px solid #ccc;border-radius:1px;overflow:hidden;word-wrap:break-word;box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}input.tag-input{-ms-flex:3;flex:3;border:0;outline:0}.tag{position:relative;margin:2px 6px 2px 0;padding:1px 20px 1px 8px;font-size:inherit;font-weight:400;text-align:center;color:#fff;background-color:#317caf;border-radius:3px;transition:background-color .3s ease;cursor:default}.tag:first-child{margin-left:0}.tag--marked{background-color:#6fadd7}.tag--exists{background-color:#edb5a1;-webkit-animation:a 1s linear;animation:a 1s linear}.tag__name{margin-right:3px}.tag__remove{position:absolute;right:0;bottom:0;width:20px;height:100%;padding:0 5px;font-size:16px;font-weight:400;transition:opacity .3s ease;opacity:.5;cursor:pointer;border:0;background-color:transparent;color:#fff;line-height:1}.tag__remove:hover{opacity:1}@-webkit-keyframes a{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}}@keyframes a{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.js"></script>
<input id="testTags" placeholder="test1">
<button id="search">search</button>