Home > Software engineering >  How to access jQuery UI autocomplete suggestions outside of the autocomplete callback?
How to access jQuery UI autocomplete suggestions outside of the autocomplete callback?

Time:05-30

I want to combine the functions of enter image description here


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 >' e '</span><button >&times;</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>

CodePudding user response:

It's very unclear what you are trying to accomplish. I am guessing, that if the User enter "apple", moves away from the input, and clicks the search button, you want to grab the first match from availableTags that might work?

Consider the following.

  $('#search').on('click', function() {
    if ($('.tag-input[placeholder="test1"]').val() != "") {
      //user did not finish entry
      var partialTag = $('.tag-input[placeholder="test1"]').val();
      var tag = $.ui.autocomplete.filter(availableTags, partialTag)[0];
      testTags.addTags(tag);
    }
  });

The use of $.ui.autocomplete.filter() can help filter the results in the same way Autocomplete would. It returns an Array of results. It is demonstrated in the following: https://jqueryui.com/autocomplete/#multiple

It is not heavily documented, yet you can find a bit more here: https://api.jqueryui.com/autocomplete/

Here is a full example.

! 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 >'   e   '</span><button >&times;</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
      var partialTag = $('.tag-input[placeholder="test1"]').val();
      var tag = $.ui.autocomplete.filter(availableTags, partialTag)[0];
      testTags.addTags(tag);
    }
  });

});
*,
: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>

  • Related