Build a jQuery Tagify Youtube Like Tag Input Fields to Take Input From User in Browser Using HTML5 & Javascript Full Project For Beginners

 

 

 

index.html

 

 

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Tagify - Tags input Component</title>
        <meta name="description" content="Converts HTML input/textarea into Tags component">
        <meta name="author" content="Yair Even-Or">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="keywords" content="tag, tags, tagging, tagify, javascript, component, web">
        <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🔖</text></svg>">
        <link rel="stylesheet" href="dist/tagify.css">
        <link rel="stylesheet" href="https://unpkg.com/@yaireo/dragsort/dist/dragsort.css" media="print" onload="this.media='all'">
        <style>
          html, body{ min-height:100%; scroll-behavior: smooth; }
          body{
            font:14px Arial;
            margin:0;
            overflow-x:hidden;
          } /* display:flex; flex-flow: column nowrap; align-items:center; justify-content:center; */

          .forkLink{ position:fixed; z-index:100; border:0; top:0; width:70px; right:0; opacity:.8; transition:.15s ease-out; }
          .forkLink:hover{ opacity:1; }
          .forkLink img{ width:100%; }

          section{ display:flex; }
          aside{ padding:4rem; box-sizing:border-box; width:50%; }
          section > .leftSide{
            max-width: 700px;
            border-right: 1px solid #CDE6FF;
            background:#F5FAFF;
            font-size: 1.1em;
          }
          section > .rightSide{  }

          .leftSide style {
            display: block;
            background: #333;
            color: white;
            font: 13px/1.8 Monaco, monospace;
            padding: 1.1em;
            margin-right: -2rem;
            white-space: pre;
            position:relative;
            border-radius: 5px;
          }

          style[contenteditable]::before{
            content: "Editable";
            position: absolute;
            top: 2px;
            right: 8px;
            color: salmon;
          }

          .leftSide{ padding-top:0; }
          .leftSide > header{ padding-top:4rem; position:relative; }
          .leftSide .demoLink{ float:right; width:38px; transform:translateX(calc(4rem + 50%)) translateY(-1px); position:relative; z-index:5; }
          .leftSide .demoLink svg{ box-shadow: 0 0 0 3px black inset; border-radius:50%; transition:.12s ease-out; }
          .leftSide .demoLink:hover svg{ box-shadow: 0 0 0 0 black inset; transform:scale(1.2); }
          .leftSide > header > h3{ margin-top:.5rem; }
          .leftSide h2{ color:salmon; text-transform:capitalize; font-size:1.6em; font-size:calc(1.3em + .5vw); line-height:1.2; margin-top:0; margin-bottom:0; }
          .leftSide h2 > a{
             color:inherit;
             text-decoration: none;
          }
          .leftSide h2 > a::before{
              content: '#';
              position:absolute; color:inherit; opacity:0; font-weight:normal;
              transform: translatex(-75%);
              transition: .1s ease-out;
          }
          .leftSide h2 > a:hover::before{ opacity:.6; transform:translateX(-150%); }

          .rightSide > .demoLink{
            position: absolute;
            left: 0;
            width: 38px;
            transform: translateX(-50%);
          }

          .rightSide .demoLink svg{ box-shadow: 0 0 0 3px black inset; border-radius:50%; transition:.12s ease-out; }
          .rightSide .demoLink:hover svg{ box-shadow: 0 0 0 0 black inset; transform:scale(1.2); }

          h3{ color:#388ffe; font-size:1.2em; margin:2rem 0 .5em; text-transform:capitalize; }
          h3:first-child{ margin-top:4.3rem; }
          xmp, pre{ white-space:normal; padding:8px; background:white; color:navy; border-radius:8px; }
          pre{ white-space:pre; overflow:auto; border:1px solid #eef5fa; box-shadow:0 8px 15px #388ffe25; }


          p{ line-height:1.4; }
          code{ padding:2px 5px; background:lightyellow; border-radius:8px; }
          pre code{ background:none; padding:0; }

          body :not(pre)>code[class*=language-], body pre[class*=language-]{ background:white; font-size:12px; margin-right:-2rem; }

          p{ line-height:1.4; }
          code{ padding:2px 3px; background:lightyellow; }
          pre code{ background:none; padding:0; }
          pre[class*=language-]{ max-height:1000px; }

          /* details expander */
          summary{ outline: none; font-size:1.3em; color: #333; cursor:pointer; margin:1em 0 0 0; user-select:none; transition: .15s ease-out; }
          summary::after{ content:"Code"; }
          details[open] summary{ margin-bottom: 1em; }

          .forkLink{ display:none; position:absolute; top:.7em; right:50%; transform:translateX(50%); }
          body > header{
              position: sticky;
              z-index: 100;
              top: -1px;
              left: 0;
              right: 0;
              display: flex;
              align-items: center;
              background:white;
              border-bottom: 1px solid #DDD;
              box-shadow: 0 0 6px rgba(0,0,0,.1);
              padding: .8em 1em .8em 3em;
          }

          header.isSticky .repoLink{
            height: 50px;
            margin: -.5em 0 -1.6em 0;
            transition: .55s cubic-bezier(.5,0,.5,1.075);
          }

          header.isSticky .repoLink svg{ filter: none; }

         .repoLink{
            height: 70px;
            margin: -1em 0 -1.5em 0;
            transform: translateX(calc(50vw - 50%));
            transition: .2s ease-out;
         }
         .repoLink svg{
            filter: drop-shadow(0px 4px 0px white)
                    drop-shadow(-4px 0px 0px white)
                    drop-shadow(4px 0px 0px white)
                    drop-shadow(0px 3px 1px rgba(0,0,0,.15));
          }
          body > header .liveLink{ color:#333; text-decoration:none; font-size:1.4em; position:relative; line-height:1; }
          body > header .liveLink::before{ content:'✎'; text-decoration:none; transform:translateX(-150%); position:absolute; top:1px; left:0; }
          body > header .liveLink:hover{ text-decoration: underline; }

          ul > li{
            margin: .8em 0;
          }
        </style>

        <script>
            // if IE, add IE tagify's polyfills
            !function( d ) {
                if( !d.currentScript ){
                    var s = d.createElement( 'script' );
                    s.src = 'dist/tagify.polyfills.min.js';
                    d.head.appendChild( s );
                }
            }(document)
        </script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
        <script src="dist/jQuery.tagify.min.js"></script>
        <script src="https://unpkg.com/@yaireo/dragsort"></script>

        <script>
            var isIE = !document.currentScript;

            function renderPRE(currentScript, codeScriptName){
                if( isIE ) return;

                function removeLast(s, r){
                    s = s.split(r)
                    return s.slice(0,-1).join(r) + s.pop()
                }

                setTimeout(function(){
                    var jsCode = document.querySelector("[data-name='"+ codeScriptName +"']").innerHTML;

                    // cleanup closure wraper
                    jsCode = jsCode.replace("(function(){", "").trim();
                    jsCode = removeLast(jsCode, "})()").replace(/</g, "&lt" )
                                                        .replace(/>/g, "&gt" )
                                                        .trim();

                    currentScript.insertAdjacentHTML('afterend', "<pre class='language-js'><code>" + jsCode + "</code></pre>");
                }, 500);
            }

            // detect modern browser and enhance console logs with colors
            if( typeof(Intl) )
                try{
                   // console.log = ((_c) => (...args) => args.length > 1 ? _c("%c "+ args[0], 'background:indianred; color:white; border-radius:3px; padding:1px;', ...args.slice(1)) : _c(...args))(console.log);
                }
                catch(err){}
        </script>

        <style>
            section > .rightSide{
                position: sticky;
                top: 0;
                align-self: start;
            }

            .tagify{
                min-width:400px;
                max-width:600px;
                margin: 0 0 1em 0;
            }

            label{ cursor:pointer; }
            .disabled tags{
                max-width:none;
                min-width:0;
                border:0;
                display: none;
            }

            .disabled tags tag,
            .disabled tags div{ display:none !important; }

            .showOriginal tags + input,
            .showOriginal tags + textarea{
                position: initial !important;
                left: 0 !important;
                transform: none !important;
                width:100%; padding:6px; border:2px solid #999;
                margin-bottom: 1em;
                border-radius: 5px;
                background: #F1F1F1;
            }

            /* .tagify.readonlyMix > tag:not([readonly]) div::before{ background:#d3e2e2; } */

            .tagify__input .borderd-blue > div::before{ border:2px solid #8DAFFA; }

            header label[for="toggle__tagifyStyleSettings"]{
                margin-left: auto;
                font-size: 1.5em;
                line-height: 1;
                position: relative;
                animation: 1s settingsIconFrames 3;
            }

            header label[for="toggle__tagifyStyleSettings"]::before{
              content: '';
              position: absolute;
              z-index: -1;
              top: -2px;
              left: 0;
              width: 100%;
              height: 120%;
              border-radius: 50%;
              pointer-events: none;
              animation: 1s settingsIconShockwavesFrames 3;
            }

            @keyframes settingsIconFrames {
              30%{ transform: scale(1.2);  }
            }

            @keyframes settingsIconShockwavesFrames {
              0%{ transform: scale(.6); box-shadow: 0 0 10px 2px red; }
              90%{ transform: scale(10); box-shadow: 0 0 40px 2px yellow; }
              100%{ transform: scale(12); opacity:0; }
            }
/*
            header label[for="toggle__tagifyStyleSettings"]::before{
              content: "☝";
              position: absolute;
              font-size: 3rem;
              left: -15px;
              top: .5em;
              pointer-events: none;
            }
*/
            #toggle__tagifyStyleSettings:checked + .tagifyStyleSettings{
                transform: none;
            }

            .tagifyStyleSettings > label[for="toggle__tagifyStyleSettings"]{
                float: right;
            }

            .tagifyStyleSettings{
                position: fixed;
                z-index: 999;
                top: 0;
                right: 0;
                background: black;
                padding: 1em;
                color: white;
                border-bottom-left-radius: 6px;
                transform: translatex(100.5%);
                transition: .45s cubic-bezier(.65,0,.35,1);
            }

            .tagifyStyleSettings > div{
                display: flex;
                align-items: center;
                margin: 5px 0;
            }

            .tagifyStyleSettings > div > span{
                flex: 1;
                margin-right:1em;
            }

            @media only screen and (max-device-width: 600px){
                body{
                    font-size: 12px;
                }

                body > header {
                    position: relative;
                    top: 0;
                    margin-bottom: 3em;
                }

                section{
                    flex-flow: column-reverse;
                }

                section > .leftSide{
                    padding: 1.5rem;
                    width: auto;
                }

                .leftSide > header{
                    padding-top: 0;
                }

                section > .rightSide{
                    width: 100%;
                    padding: 1.5em;
                    background: white;
                    border-bottom: 1px solid #CDE6FF;
                }

                .tagify{
                    min-width: auto;
                    width: 100%;
                }

                .rightSide > .demoLink {
                    display: none;
                }

            }
        </style>
    </head>

    <body>
        <header>
            <a class='repoLink' title='Go To Repo' href='https://github.com/yairEO/tagify'>
                <svg height="100%" viewBox="0 0 280 150" fill-rule="evenodd" fill="#444" xmlns="http://www.w3.org/2000/svg">
                    <path d="m86.601,17.001q3.1,0.6 4.65,2.1a5.288,5.288 0 0 1 1.073,1.435a4.56,4.56 0 0 1 0.477,2.065a9.273,9.273 0 0 1 -0.161,1.79q-0.198,1.007 -0.641,1.776a4.402,4.402 0 0 1 -1.048,1.234a4.933,4.933 0 0 1 -1.566,0.832q-1.69,0.563 -4.284,0.368q-6.891,-0.536 -11.466,-0.808a261.493,261.493 0 0 0 -2.584,-0.142q-4.517,-0.223 -11.555,-0.327a671.4,671.4 0 0 0 -1.695,-0.023q-3.7,18.4 -6.8,37q-1.1,6.8 -2.3,15.75q-1.073,8.006 -1.507,13.252a122.559,122.559 0 0 0 -0.093,1.198a6.511,6.511 0 0 1 -0.477,2.097a5.419,5.419 0 0 1 -1.923,2.353a8.433,8.433 0 0 1 -3.705,1.439a11.101,11.101 0 0 1 -1.595,0.111q-3.3,0 -5.1,-1.6a5.269,5.269 0 0 1 -1.789,-3.8a7.187,7.187 0 0 1 -0.011,-0.4q0,-1.809 0.426,-5.409a156.38,156.38 0 0 1 0.324,-2.541q0.75,-5.55 1.75,-11.65a316.042,316.042 0 0 0 0.755,-4.35q0.285,-1.719 0.521,-3.281a171.143,171.143 0 0 0 0.424,-2.969q1.1,-7.6 2.5,-15.1q1.4,-7.5 2.8,-14.2q0.3,-1.5 0.7,-3.45q0.4,-1.95 0.9,-4.35a138.602,138.602 0 0 0 -5.715,0.285q-5.22,0.377 -8.851,1.132a36.936,36.936 0 0 0 -0.834,0.183a30.163,30.163 0 0 0 -2.893,0.815q-2.915,0.992 -4.572,2.391a7.794,7.794 0 0 0 -0.485,0.444a7.93,7.93 0 0 0 -2.298,4.982a10.773,10.773 0 0 0 -0.052,1.068a11.586,11.586 0 0 0 1.531,5.721a14.176,14.176 0 0 0 0.469,0.779q0.4,0.7 0.4,1.5a3.407,3.407 0 0 1 -0.596,1.89q-0.347,0.53 -0.896,1.038a8.6,8.6 0 0 1 -0.758,0.622a9.129,9.129 0 0 1 -1.997,1.128a7.073,7.073 0 0 1 -2.653,0.522a4.734,4.734 0 0 1 -1.316,-0.174a3.7,3.7 0 0 1 -1.484,-0.826q-1.812,-1.54 -3.05,-4.272a18.514,18.514 0 0 1 -0.25,-0.578a16.991,16.991 0 0 1 -1.117,-4.269a21.937,21.937 0 0 1 -0.183,-2.881a21.081,21.081 0 0 1 0.881,-6.241a16.64,16.64 0 0 1 4.669,-7.409q5.55,-5.15 16.9,-7.55q11.35,-2.4 29.15,-2.4q9.389,0 15.536,0.292a148.328,148.328 0 0 1 2.014,0.108a121.637,121.637 0 0 1 5.415,0.446q2.459,0.261 4.624,0.611a67.021,67.021 0 0 1 1.411,0.243z"/>
                    <path d="m72.595,99.73a13.778,13.778 0 0 0 4.706,0.771q7.9,0 13.1,-8.4a16.672,16.672 0 0 0 1.021,2.303a12.716,12.716 0 0 0 3.129,3.847a11.7,11.7 0 0 0 0.433,0.338a9.221,9.221 0 0 0 5.617,1.912a10.999,10.999 0 0 0 2.045,-0.194q1.837,-0.347 3.728,-1.313a20.867,20.867 0 0 0 3.127,-1.993a44.987,44.987 0 0 0 3.38,-2.85a54.085,54.085 0 0 0 5.32,-5.75a6.749,6.749 0 0 0 0.903,-1.349q0.997,-1.953 0.997,-4.851q0,-1.23 -0.257,-2.152a4.376,4.376 0 0 0 -0.493,-1.148a3.165,3.165 0 0 0 -0.301,-0.408a2.225,2.225 0 0 0 -1.749,-0.792a3.137,3.137 0 0 0 -1.86,0.618a4.764,4.764 0 0 0 -0.84,0.782a181.098,181.098 0 0 1 -1.496,1.767q-3.559,4.146 -5.804,6.183q-2.7,2.45 -4.6,2.45a3.041,3.041 0 0 1 -0.221,-0.008a2.394,2.394 0 0 1 -1.729,-0.892a2.866,2.866 0 0 1 -0.202,-0.274q-0.318,-0.489 -0.451,-1.125a4.872,4.872 0 0 1 -0.097,-1.001a19.067,19.067 0 0 1 0.003,-0.32q0.057,-3.429 1.318,-10.52a245.902,245.902 0 0 1 0.979,-5.16a306.979,306.979 0 0 0 0.187,-0.991q1.313,-7.044 1.313,-9.009a4.851,4.851 0 0 0 -0.002,-0.141q-0.098,-3.359 -4.898,-3.359q-2.3,0 -4.4,0.4a16.337,16.337 0 0 0 -0.167,-0.672q-0.453,-1.664 -1.083,-2.378a1.767,1.767 0 0 0 -0.381,-0.321q-0.833,-0.529 -2.569,-0.529a21.082,21.082 0 0 0 -6.202,0.924a24.014,24.014 0 0 0 -6.848,3.426q-6.15,4.35 -9.85,11.5q-3.7,7.15 -3.7,15.15a28.402,28.402 0 0 0 0.002,0.359q0.089,7.052 3.698,11.441a11.86,11.86 0 0 0 5.194,3.729zm15.406,-18.829l3.7,-18.4a11.707,11.707 0 0 0 -6.51,2.189a15.265,15.265 0 0 0 -1.24,0.961a19.709,19.709 0 0 0 -4.116,4.979a25.263,25.263 0 0 0 -1.534,3.071q-2.1,5 -2.1,10.6a12.33,12.33 0 0 0 0.099,1.617q0.25,1.888 1.135,2.964a3.841,3.841 0 0 0 0.016,0.019a4.086,4.086 0 0 0 2.786,1.464a5.852,5.852 0 0 0 0.664,0.036q2.2,0 4.2,-2.6q2,-2.6 2.9,-6.9z"/>
                    <path d="m150.501,96.801l-6.4,4.3q-2.484,13.529 -5.971,23.278a75.028,75.028 0 0 1 -3.979,9.272a32.613,32.613 0 0 1 -3.394,5.323q-2.196,2.754 -4.72,4.346a13.857,13.857 0 0 1 -7.536,2.181a13.461,13.461 0 0 1 -3.83,-0.52a10.533,10.533 0 0 1 -4.47,-2.63a10.575,10.575 0 0 1 -3.087,-6.406a14.662,14.662 0 0 1 -0.113,-1.844a21.012,21.012 0 0 1 1.22,-6.857q0.948,-2.751 2.631,-5.64a43.813,43.813 0 0 1 1.749,-2.753a46.804,46.804 0 0 1 3.925,-4.881q6.006,-6.616 17.075,-15.169l0.6,-3.9q-1.7,2.7 -4.45,4.15q-2.75,1.45 -5.45,1.45a13.778,13.778 0 0 1 -4.706,-0.771a11.86,11.86 0 0 1 -5.194,-3.729q-3.609,-4.389 -3.698,-11.441a28.402,28.402 0 0 1 -0.002,-0.359q0,-8 3.7,-15.15q3.7,-7.15 9.85,-11.5a24.014,24.014 0 0 1 6.848,-3.426a21.082,21.082 0 0 1 6.202,-0.924q1.736,0 2.569,0.529a1.767,1.767 0 0 1 0.381,0.321q0.63,0.714 1.083,2.378a16.337,16.337 0 0 1 0.167,0.672q1.742,-0.367 3.989,-0.397a30.328,30.328 0 0 1 0.411,-0.003q2.5,0 3.55,0.75q1.001,0.715 1.048,2.748a8.802,8.802 0 0 1 0.002,0.202q0,1.113 -0.086,1.796a6.337,6.337 0 0 1 -0.014,0.104q-0.4,3.1 -2.5,15.7q-0.4,2.4 -0.85,5.25q-0.45,2.85 -0.95,6.05q7.7,-6 14.8,-10.6a7.207,7.207 0 0 1 0.783,-0.422q0.83,-0.378 1.517,-0.378a2.186,2.186 0 0 1 1.736,0.81a3.273,3.273 0 0 1 0.314,0.44q0.75,1.25 0.75,3.15q0,1.497 -0.297,2.571a4.943,4.943 0 0 1 -0.403,1.029q-0.7,1.3 -2.2,2.3q-8.6,5.8 -12.6,8.6zm-15.2,-17.2l3.2,-17.1a11.292,11.292 0 0 0 -6.139,2.023a14.986,14.986 0 0 0 -1.461,1.127a19.815,19.815 0 0 0 -3.986,4.835a25.642,25.642 0 0 0 -1.614,3.215q-2.1,5 -2.1,10.6a12.33,12.33 0 0 0 0.099,1.617q0.25,1.888 1.135,2.964a3.841,3.841 0 0 0 0.016,0.019a4.086,4.086 0 0 0 2.786,1.464a5.852,5.852 0 0 0 0.664,0.036a4.113,4.113 0 0 0 2.179,-0.655q0.657,-0.405 1.297,-1.058a10.912,10.912 0 0 0 0.924,-1.087q1.54,-2.053 2.435,-5.398a29.644,29.644 0 0 0 0.565,-2.602zm-15.7,56.2a2.805,2.805 0 0 0 1.542,-0.529q1.712,-1.132 3.688,-4.691a38.125,38.125 0 0 0 0.42,-0.78q3.15,-6 6.05,-19.1q-7.615,6.527 -11.024,11.783a27.437,27.437 0 0 0 -0.076,0.117q-2.151,3.353 -2.941,6.186a11.603,11.603 0 0 0 -0.459,3.114q0,1.7 0.65,2.8q0.65,1.1 2.15,1.1z" />
                    <path d="m168.485,100.052a14.405,14.405 0 0 0 3.716,0.449a13.017,13.017 0 0 0 2.983,-0.354q5.115,-1.201 10.667,-6.47a57.215,57.215 0 0 0 4.85,-5.276a6.749,6.749 0 0 0 0.903,-1.349q0.997,-1.953 0.997,-4.851q0,-1.23 -0.257,-2.152a4.376,4.376 0 0 0 -0.493,-1.148a3.165,3.165 0 0 0 -0.301,-0.408a2.225,2.225 0 0 0 -1.749,-0.792a3.137,3.137 0 0 0 -1.86,0.618a4.764,4.764 0 0 0 -0.84,0.782a184.196,184.196 0 0 1 -1.465,1.737q-2.309,2.703 -4.074,4.528a42.627,42.627 0 0 1 -1.661,1.635q-2.7,2.5 -4.5,2.5a3.986,3.986 0 0 1 -0.537,-0.035q-0.802,-0.109 -1.37,-0.559a2.931,2.931 0 0 1 -0.793,-1.006q-0.8,-1.6 -0.8,-4.6a18.033,18.033 0 0 1 0.045,-1.205q0.213,-3.139 1.42,-9.222a243.091,243.091 0 0 1 0.935,-4.473a333.394,333.394 0 0 0 0.054,-0.257q1.444,-6.943 1.758,-9.964a13.831,13.831 0 0 0 0.088,-1.379q0,-2.736 -3.302,-3.27a11.317,11.317 0 0 0 -1.798,-0.13q-2.114,0 -3.489,0.493a4.516,4.516 0 0 0 -1.311,0.707a4.047,4.047 0 0 0 -0.275,0.242q-0.903,0.867 -1.571,2.516a15.701,15.701 0 0 0 -0.554,1.642a96.723,96.723 0 0 0 -1.259,4.709a115.141,115.141 0 0 0 -1.691,8.441q-0.755,4.627 -1.014,8.155a46.575,46.575 0 0 0 -0.136,3.395a35.4,35.4 0 0 0 0.086,2.505q0.417,5.88 2.864,9.695a9.47,9.47 0 0 0 5.734,4.151zm2.207,-53.423a14.478,14.478 0 0 0 2.309,0.172a12.934,12.934 0 0 0 2.784,-0.284a8.852,8.852 0 0 0 4.116,-2.066a7.555,7.555 0 0 0 2.219,-3.529a9.921,9.921 0 0 0 0.381,-2.821a8.542,8.542 0 0 0 -0.056,-0.994a5.858,5.858 0 0 0 -2.244,-4.106a7.5,7.5 0 0 0 -0.488,-0.351q-1.281,-0.846 -2.946,-1.198a12.408,12.408 0 0 0 -2.566,-0.251a12.993,12.993 0 0 0 -1.617,0.098a9.725,9.725 0 0 0 -5.233,2.252a9.427,9.427 0 0 0 -0.413,0.374a7.313,7.313 0 0 0 -2.337,5.476a9.57,9.57 0 0 0 0.205,2.036a6.381,6.381 0 0 0 1.895,3.414q1.477,1.371 3.991,1.778z"/>
                    <path d="m225.87,72.406a2.564,2.564 0 0 0 -1.469,-0.405q-0.9,0 -1.8,0.1q-0.9,0.1 -1.7,0.2q-4.9,0.7 -8.9,0.7a27.307,27.307 0 0 1 -0.332,-0.002q-0.995,-0.012 -1.768,-0.098a99.703,99.703 0 0 0 -1.269,-0.083q-2,-0.117 -3.531,-0.117a1.775,1.775 0 0 0 -0.4,0.047q-0.66,0.153 -1.419,0.797a8.2,8.2 0 0 0 -0.681,0.656a12.714,12.714 0 0 0 -0.601,0.693a14.05,14.05 0 0 0 -1.749,2.807a14.72,14.72 0 0 0 -0.07,0.15q-0.876,1.899 -0.78,3.15a231.116,231.116 0 0 1 1.245,5.963a193.785,193.785 0 0 1 1.605,9.437a98.157,98.157 0 0 1 0.065,0.457a106.247,106.247 0 0 1 0.985,14.643a56.187,56.187 0 0 1 -0.076,3.047q-0.252,4.62 -1.342,6.338a1.861,1.861 0 0 1 -1.582,1.015q-1.35,0 -2.059,-7.724a116.118,116.118 0 0 1 -0.241,-3.126a359.188,359.188 0 0 1 -0.011,-0.169a328.402,328.402 0 0 1 -0.689,-20.981q0,-7.4 1,-17.2a179.38,179.38 0 0 0 2.296,-2.304q25.804,-26.376 25.804,-48.896a33.422,33.422 0 0 0 -0.118,-2.866q-0.196,-2.281 -0.72,-4.204a15.529,15.529 0 0 0 -1.812,-4.23a11.636,11.636 0 0 0 -0.486,-0.711q-1.209,-1.635 -2.792,-2.503a8.323,8.323 0 0 0 -4.072,-0.986a11.515,11.515 0 0 0 -2.712,0.323q-5.148,1.243 -9.76,7.268a44.915,44.915 0 0 0 -3.478,5.359a80.564,80.564 0 0 0 -2.972,5.879q-2.701,5.91 -4.88,12.965a155.054,155.054 0 0 0 -3.548,13.856q-4.15,19.75 -4.15,38.95q0,20.6 3.05,30.8q1.18,3.945 2.98,6.364a8.709,8.709 0 0 0 7.27,3.836a9.618,9.618 0 0 0 6.798,-2.694a14.408,14.408 0 0 0 2.402,-3.006a15.999,15.999 0 0 0 0.125,-0.207q2.355,-3.968 3.067,-10.33a53.781,53.781 0 0 0 0.308,-5.963a72.868,72.868 0 0 0 -0.091,-3.501q-0.092,-1.893 -0.275,-4.071a173.83,173.83 0 0 0 -0.484,-4.878q-0.85,-7.55 -2.15,-13.75a78.893,78.893 0 0 0 1.457,0.278q3.447,0.622 5.443,0.622a36.857,36.857 0 0 0 0.881,-0.01q4.937,-0.118 7.757,-1.584a6.603,6.603 0 0 0 3.762,-6.306a9.695,9.695 0 0 0 -0.081,-1.309q-0.248,-1.809 -1.25,-2.486zm-11.569,-56.505q-1.8,0 -4.45,6.1q-2.65,6.1 -5.25,16.15a247.056,247.056 0 0 0 -3.506,15.722a282.802,282.802 0 0 0 -0.994,5.528a78.429,78.429 0 0 0 8.466,-11.518a65.753,65.753 0 0 0 3.834,-7.432a58.244,58.244 0 0 0 2.959,-8.379q1.277,-4.824 1.424,-9.313a35.708,35.708 0 0 0 0.017,-0.758a22.746,22.746 0 0 0 -0.074,-1.916q-0.356,-4.184 -2.426,-4.184z"/>
                    <path d="m272.701,88.201l-19.2,12.9q-2.484,13.529 -5.971,23.278a75.028,75.028 0 0 1 -3.979,9.272a32.613,32.613 0 0 1 -3.394,5.323q-2.196,2.754 -4.72,4.346a13.857,13.857 0 0 1 -7.536,2.181a13.461,13.461 0 0 1 -3.83,-0.52a10.533,10.533 0 0 1 -4.47,-2.63a10.575,10.575 0 0 1 -3.087,-6.406a14.662,14.662 0 0 1 -0.113,-1.844q0,-4.7 2.15,-9.6a26.719,26.719 0 0 1 1.915,-3.54q2.246,-3.543 6.085,-7.71a84.129,84.129 0 0 1 4.595,-4.584q4.933,-4.585 11.955,-9.966l0.3,-2.3q0.536,-2.833 1.189,-7.541a380.176,380.176 0 0 0 0.411,-3.059q-1.446,5.207 -3.729,8.609a17.233,17.233 0 0 1 -1.871,2.341q-2.806,2.923 -5.856,3.568a8.413,8.413 0 0 1 -1.744,0.182a8.258,8.258 0 0 1 -6.413,-2.947a12.208,12.208 0 0 1 -0.937,-1.203a15.755,15.755 0 0 1 -2.398,-5.735a22.346,22.346 0 0 1 -0.452,-4.615a98.01,98.01 0 0 1 0.299,-7.829a75.931,75.931 0 0 1 0.701,-5.921a78.663,78.663 0 0 1 1.646,-7.686a98.87,98.87 0 0 1 1.654,-5.564q0.706,-2.118 1.811,-3.389a5.856,5.856 0 0 1 0.989,-0.911a5.57,5.57 0 0 1 1.486,-0.74q1.655,-0.56 4.214,-0.56q1.743,0 2.639,0.44a2.096,2.096 0 0 1 0.411,0.26q0.827,0.681 0.849,2.024a4.518,4.518 0 0 1 0.001,0.076a3.471,3.471 0 0 1 -0.039,0.434q-0.137,1.008 -0.764,3.706a198.933,198.933 0 0 1 -0.297,1.26a124.01,124.01 0 0 0 -0.875,3.42q-0.39,1.625 -0.686,3.086a74.279,74.279 0 0 0 -0.039,0.194q-0.8,4.1 -1.4,7.85a63.407,63.407 0 0 0 -0.316,2.212q-0.284,2.288 -0.284,3.938a10.271,10.271 0 0 0 0.074,1.292q0.32,2.508 2.026,2.508q1.452,0 3.606,-2.81a22.589,22.589 0 0 0 0.144,-0.19a23.883,23.883 0 0 0 1.436,-2.178q1.384,-2.344 2.874,-5.771a89.066,89.066 0 0 0 0.49,-1.151q1.952,-4.67 3.817,-10.982a175.362,175.362 0 0 0 1.133,-4.018a12.336,12.336 0 0 1 0.583,-1.709q0.378,-0.875 0.862,-1.536a5.37,5.37 0 0 1 1.005,-1.055a5.254,5.254 0 0 1 1.595,-0.835q1.383,-0.465 3.355,-0.465q1.787,0 2.729,0.362a2.402,2.402 0 0 1 0.471,0.238a1.919,1.919 0 0 1 0.794,1.132q0.093,0.339 0.104,0.749a4.199,4.199 0 0 1 0.002,0.119q0,2.5 -2.6,17.2l-2.6,16.1q7.7,-5.8 15,-10.6a7.207,7.207 0 0 1 0.783,-0.422q0.83,-0.378 1.517,-0.378a2.186,2.186 0 0 1 1.736,0.81a3.273,3.273 0 0 1 0.314,0.44q0.75,1.25 0.75,3.15q0,1.497 -0.297,2.571a4.943,4.943 0 0 1 -0.403,1.029q-0.7,1.3 -2.2,2.3zm-38.506,42.54a36.133,36.133 0 0 0 0.406,-0.74q2.4,-4.49 4.8,-13.595a184.128,184.128 0 0 0 1.4,-5.705a90.074,90.074 0 0 0 -4.397,3.95q-4.381,4.222 -6.753,7.9q-2.176,3.374 -2.979,6.211a11.534,11.534 0 0 0 -0.471,3.139q0,1.7 0.65,2.8q0.65,1.1 2.15,1.1q2.335,0 5.194,-5.06z"/>
                </svg>
            </a>
            <a class='forkLink' title='Go To Repo' href='https://github.com/yairEO/tagify'>
                <img src='https://github.githubassets.com/images/modules/logos_page/GitHub-Logo.png' alt='GitHub Repo'>
            </a>
        </header>

        <!-- SVG codeopen logo template -->
        <svg style='display:none' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
            <g id='codepen-logo' viewBox="0 0 120 120">
                <path class="inner-box" d="M97 48v-1a3 3 0 00-1-1L62 23h-4L24 46a3 3 0 00-1 1v26a4 4 0 001 0v1l34 23a3 3 0 004 0l34-23a3 3 0 001-1v-1-23-1zM63 32l25 17-11 7-14-9V32zm-6 0v15l-14 9-11-7 25-17zM29 55l8 5-8 5V55zm28 33L32 71l11-7 14 9v15zm3-20l-11-8 11-8 11 8-11 8zm3 20V73l14-9 11 7-25 17zm28-23l-8-5 8-5v10z"/>
            </g>
        </svg>
        <!-- template end -->

        <form>
            <section id='section-basic'>
                <aside class='leftSide'>
                    <header>

                        <h2><a href='#section-basic'>Basic example</a></h2>
                    </header>
                    <p>
                      Passing the input element as a parameter to <em>Tagify</em> will transform it into a tags-component. Without any settings, the user will be allowed to create any tags they want, without a count limit.
                    </p>
                    <p>
                      If the input element has a pre-defined <code>value</code> attribute, tags will be created from it.
                    </p>
                    <p>
                      (<strong>Try <em>Double-clicking</em> a tag to edit it</strong>)
                    </p>
                    <details>
                      <summary></summary>
                      <h3>HTML</h3>
<pre class="language-markup"><code><input name='basic' value='tag1, tag2 autofocus'></code></pre>
                      <h3>JAVASCRIPT</h3>
                      <script>renderPRE(document.currentScript, "basic")</script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/PoNqYVY'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='basic' value='tag1, tag2' autofocus>
                </aside>
            </section>



            <section id='section-input'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-input'>text input</a></h2>
                    </header>
                    <h3>In this example:</h3>
                    <ul>
                        <li>Tagify instance with initial <em>settings</em> Object</li>
                        <li>Only allow tags from the whitelist to exist</li>
                        <li>Manually create initial <em>whitelist</em> from the original input's value</li>
                        <li>Simulate fetching <em>whitelist</em> (from a server) as the user is typing</li>
                        <li><em>"Remove all tags"</em> by an extrenal button</li>
                        <li>Listen to various Tagify <a href='https://github.com/yairEO/tagify#events'>events</a></li>
                        <li>Un-listen to specific event (see <code>onAddTag</code> function)</li>
                    </ul>
                    <h3>Intro:</h3>
                    <p>
                        The input element is pre-ocupied with <strong>4</strong> tags. The <em>last</em> tag, <em>"CSS"</em>, has the same value as the <em>first</em> tag,
                        and will be <em>removed</em>, because the <code>duplicates</code> setting is set to <code>true</code>.
                    </p>
                    <p>
                        Note that <code>whitelist</code> & <code>blacklist</code> may also be set on to <i>Tagify</i> as <code>data-</code> attributes on the input tag itself
                        as a list of tags seperated by the same delimeter defined in the Tagify's configuration. Default is comma (<code>,</code>)
                    </p>
                    <p>As text is typed, the <code>onInput</code> Tagify event is fired, on each key stroke. Reseting the current whitelist and fetching a new one (from <code>mockAjax()</code>)</p>
                    <p>In real-life scenarios, a developer might wish to use different <em>whitelists</em> suggested to the user, according to the typed text, asusming the possibilities are too large to load at-once as the inital <em>whitelist</em>.</p>

                    <details>
                      <summary></summary>
                      <h3>HTML</h3>
<pre class="language-markup"><code><input
  name='input'
  class='some_class_name'            // This class will be copied to the Tagify component
  placeholder='write some tags'      // This text will be shown after the last tag
  value='css, html, javascript, css' // initial values, as String (can also be an Array of Objects)
  data-blacklist='.NET,PHP'>         // list of invaild tags, which cannot be added
</code></pre>
                      <h3>JAVASCRIPT</h3>
                      <script>renderPRE(document.currentScript, "input")</script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/OJNVyQR'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='input' class='some_class_name' placeholder='write some tags' value='css, html, javascript, css' data-blacklist='.NET,PHP'>
                    <button class='tags--removeAllBtn' type='button'>Remove all these tags ⬆</button>
                </aside>
            </section>



            <section id='section-dropdown-tags'>
              <aside class='leftSide'>
                  <header>
                        <h3>Same using custom suggestions:</h3>
                  </header>
                  <p>The dropdown will appear immediately when Tagify has focus.</p>
                  <p>The suggestions are styled as tags this time. Clicking on a suggested it, it will be added to <em>Tagify</em></p>
                  <details>
                    <summary></summary>
                    <h3>HTML</h3>
<pre class="language-markup"><code><​input name='input-custom-dropdown' class='some_class_name' placeholder='write some tags' value='css, html, javascript'>
</code></pre>
                    <h3>JAVASCRIPT</h3>
                    <script>renderPRE(document.currentScript, "dropdown-tags")</script>
                    <h3>CSS</h3>
<style contenteditable>
.tags-look .tagify__dropdown__item{
  display: inline-block;
  border-radius: 3px;
  padding: .3em .5em;
  border: 1px solid #CCC;
  background: #F3F3F3;
  margin: .2em;
  font-size: .85em;
  color: black;
  transition: 0s;
}

.tags-look .tagify__dropdown__item--active{
  color: black;
}

.tags-look .tagify__dropdown__item:hover{
  background: lightyellow;
  border-color: gold;
}
</style>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/bGpdVMW'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='input-custom-dropdown' class='tagify--custom-dropdown' placeholder='write some tags' value='css, html, javascript'>
                </aside>
            </section>



            <section id='section-textarea'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-textarea'>textarea</a></h2>
                    </header>
                    <p>
                        In this example, the field is pre-ocupied with 3 tags, and last tag is <strong>not included</strong> in the whitelist,
                        and will be <em>removed</em> because the <code>enforceWhitelist</code> <em>setting flag</em> is set to <code>true</code>
                    </p>
                    <p>
                        🚩 This example is very interesting because it shows another layer of complexity - Films' names might include commas (<code>,</code>),
                        and therefore it is <strong>very important</strong> to load initial values as Object <em>Collection</em> (Array of Objects)
                        where each Object is proper JSON as shown in the example below, or else initial tags will not get parsed well if they include commas.
                    </p>
                    <p>
                        🚩 <strong>Another important</strong> thing to keep in mind is that the default <code>delimiters</code> setting of Tagify is to split tags by commas, and
                        when tags (might) contain commas inside them, this setting should be changed to <code>null</code>, so when a user is typing,
                        for example, a movie name which contains commans, a tag will <em>not</em> be created as soon as comma was inputed.
                    </p>
                    <details>
                      <summary></summary>
                      <h3>HTML</h3>
<pre class="language-markup"><code><textarea name='tags2' placeholder='Movie names'>
    [{"value":"The Good, the Bad and the Ugly"}, {"value":"The Matrix"}]
</textarea></code></pre>
                      <h3>JAVASCRIPT</h3>
                      <script>renderPRE(document.currentScript, "textarea")</script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/dyMoYKb'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <textarea name='tags2' placeholder='Movie names'> [{"value":"The Good, the Bad and the Ugly"}, {"value":"The Matrix"}]</textarea>
                </aside>
            </section>



            <section id='section-different-look'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-different-look'>Easy to customize</a></h2>
                    </header>
                    <p>
                        The easiest way to customize styles <em>(colors, borders, spacing, radii, etc.)</em> is by using <a href='https://github.com/yairEO/tagify#css-variables'>CSS variables</a>.
                    </p>
                    <p>
                        No placeholder, and no way of adding tags from within the component, but only
                        by clicking the (+) button, which is not related to Tagify in anyway, but in this example
                        it is shown how combining a few simple things make customization easy.
                    </p>
                    <p>
                        (This example also shows how to implement minimum-allowed tags)
                    </p>
                    <details>
                      <summary></summary>
                      <h3>HTML</h3>
<pre class="language-markup"><code><input class='customLook' value='some.name@website.com'>
<button type="button">+</button>
</code></pre>
                      <h3>JAVASCRIPT</h3>
                      <script>renderPRE(document.currentScript, "customLook")</script>
                      <h3>CSS</h3>
<style contenteditable>.customLook{
  --tag-bg                  : #0052BF;
  --tag-hover               : #CE0078;
  --tag-text-color          : #FFF;
  --tags-border-color       : silver;
  --tag-text-color--edit    : #111;
  --tag-remove-bg           : var(--tag-hover);
  --tag-pad                 : .6em 1em;
  --tag-inset-shadow-size   : 1.35em;
  --tag-remove-btn-bg--hover: black;

  display: inline-block;
  min-width: 0;
  border: none;
}

.customLook .tagify__tag{
  margin-top: 0;
}

.customLook .tagify__tag > div{
  border-radius: 25px;
}

/* Do not show the "remove tag" (x) button when only a single tag remains */
.customLook .tagify__tag:only-of-type .tagify__tag__removeBtn{
  display: none;
}

.customLook .tagify__tag__removeBtn{
  opacity: 0;
  transform: translateX(-6px) scale(.5);
  margin-left: -3ch;
  transition: .12s;
}

.customLook .tagify__tag:hover .tagify__tag__removeBtn{
  transform: none;
  opacity: 1;
  margin-left: -1ch;
}

.customLook + button{
  color: #0052BF;
  font: bold 1.4em/1.65 Arial;
  border: 0;
  background: none;
  box-shadow: 0 0 0 2px inset currentColor;
  border-radius: 50%;
  width: 1.65em;
  height: 1.65em;
  cursor: pointer;
  outline: none;
  transition: .1s ease-out;
  margin: 0 0 0 5px;
  vertical-align: top;
}

.customLook + button:hover{
  box-shadow: 0 0 0 5px inset currentColor;
}

.customLook .tagify__input{
  display: none;
}
</style>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/wvGaKxd'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input class='customLook' value='some.name@website.com'><button type="button">+</button>
                </aside>
            </section>

            <section id='section-mix'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-mix'>Mix text & tags</a></h2>
                    </header>
                    <p>
                        It is possible to configure Tagify to supoprt mixed content.
                        A common example would be <em>tagging</em> people while writing a comment on a social website.
                    </p>
                    <p>
                        To allow mix content, simply pass the setting <code>mode : 'mix'</code>
                    </p>
                    <p>
                        In this example, there are a few <em>Southpark</em> character names and a few <em>Simpsons</em> ones.
                        when <code>@</code> is typed, following 1 more character, suggestions dropdown will show <em>Southpark</em>-only items,
                        and when starting with <code>#</code>, <i>Simpsons</i> items list.
                    </p>
                    <p>
                        Note that the two whitelists are very different from eachother in teams of structure. The first is quite complex,
                        as it uses numeric IDs as <code>value</code> ("value" prop is always unique), and the rendered text is placed in a custom
                        property named "text". <br>
                        The other whitelist, <em>Simpsons</em> is very basic, just a flat array of strings.
                    </p>
                    <p>
                        Note that "homer simpson" tag is set to <code>readonly</code> in this example. If tried to select all text and delete
                        everything, <em>readonly</em> tags will remain.
                    </p>
                    <p>
                        When a <code>textarea</code> already has mixed-content and it wasn't pre-configured using a whitelist, the tags will ignored, so keep
                        that in mind when populating a textarea with server data and expecting tags to "magically" appear. Whitelist <strong><em>must</em></strong> exist because not
                        everything that starts with <code>@</code> or <code>#</code> (or whatever was defined as <code>pattern</code>) is meant to be rendered as a tag.
                    </p>
                    <h4>Creating new tags:</h4>
                    <p>
                        To create new tags (ones not included in your <code>whitelist</code> collection), simply make sure
                        to keep the <code>enforceWhitelist</code> setting as <code>false</code>, which is the <em>default</em>.
                        After a new tags has been added, you should listen to the <code>add</code> and probably update your local state (Ex. server request).
                    </p>
                    <details>
                      <summary></summary>
                    <h3>HTML</h3>
<pre class="language-markup"><code><textarea name='mix'>
    [[{"id":200, "value":"cartman", "title":"Eric Cartman"}]] and [[kyle]] do not know [[{"value":"homer simpson", "readonly":true}]] because he's a relic.
</textarea>
</code></pre>
                    <h3>JAVASCRIPT</h3>
                    <script>renderPRE(document.currentScript, "mix")</script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/KKzpdxQ'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <textarea name='mix'>[[{"id":101, "value":"cartman", "title":"Eric Cartman"}]] and [[kyle]] do not know [[{"value":"homer simpson", "readonly":true}]] because he's a relic.</textarea>
                </aside>
            </section>

            <section id='outside-of-the-box'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#outside-of-the-box'>outside-of-the-box</a></h2>
                    </header>
                    <p>
  Some designs might require showing the tags outside of the input box, so to set this up
  some manual CSS changes has to be made, and also the <code>dropdown.position</code> <em>setting</em>
  should be set to <code>"input"</code> so the suggestions dropdown will be rendered right next to <em>input</em>
  element and not relative to the whole component (which is the default)
                    </p>
                    <details>
                      <summary></summary>
                    <h3>HTML</h3>
 <pre class="language-markup"><code><input name='tags-outside' class='tagify--outside' placeholder='write some tags'></code></pre>
                    <h3>JAVASCRIPT</h3>
                    <script>renderPRE(document.currentScript, "outside-of-the-box")</script>
                    <h3>CSS</h3>
<style contenteditable>.tagify--outside{
    border: 0;
}

.tagify--outside .tagify__input{
  order: -1;
  flex: 100%;
  border: 1px solid var(--tags-border-color);
  margin-bottom: 1em;
  transition: .1s;
}

.tagify--outside .tagify__input:hover{ border-color:var(--tags-hover-border-color); }
.tagify--outside.tagify--focus .tagify__input{
  transition:0s;
  border-color: var(--tags-focus-border-color);
}</style>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/oNxXjav'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='tags-outside' class='tagify--outside' value='tag1, tag2, tag3' placeholder='write some tags'>
                </aside>
            </section>

            <section id='section-manual-suggestions'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-manual-suggestions'>Render suggestions list manually</a></h2>
                    </header>
                    <p>
                        Renders the suggestions list <strong>manually</strong> - useful for situations where it is wished showing the suggestions list
                        inside a modal or your own popup implementaion, or even always show it. In this example the list is always shown.
                    </p>
                    <details>
                      <summary></summary>
                    <h3>HTML</h3>
<pre class="language-markup"><code><input name='tags-manual-suggestions' placeholder='write some tags'></code></pre>
                    <h3>JAVASCRIPT</h3>
                    <script>renderPRE(document.currentScript, "manualSuggestions")</script>
                    <h3>CSS</h3>
<style contenteditable>.customSuggestionsList > div{
  max-height: 300px;
  border: 2px solid pink;
  overflow: auto;
}
</style>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/QWNbjZO'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='tags-manual-suggestions' placeholder='write some tags'>
                    <h3>☝ Add items from below list:</h3>
                </aside>
            </section>


            <section id='section-no-user-input'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-no-user-input'>Disabled user input</a></h2>
                    </header>
                    <p>
                        User cannot type or paste any input not edit already-exiting tags.<br>
                        Tags can only be selected from the suggestions list (<em>whitelist</em>) dropdown.
                    </p>
                    <details>
                      <summary></summary>
                    <h3>HTML</h3>
<pre class="language-markup"><code><input name='tags-disabled-user-input' placeholder='Select tags from the list''></code></pre>
                    <h3>JAVASCRIPT</h3>
                    <script>renderPRE(document.currentScript, "noUserInput")</script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/PomMMwp'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120"><use class="logo-use" xlink:href="#codepen-logo"/></svg>
                    </a>
                    <input name='tags-disabled-user-input' placeholder='Select tags from the list'>
                </aside>
            </section>


            <section id="users-list">
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#users-list'>Users list</a></h2>
                    </header>
                    <p>
                        This example shows how to customize <em>Tagify</em> further. It also includes an <code>Add All</code> option as the first
                        item in the suggestions dropdown list.
                    </p>
                    <p>
                        <code>tagTextProp</code> is very interesting in this example as it allows inputing both a <code>value</code>
                        or a <code>name</code> and have them both match against the whitelist items. First the "value" is looked for,
                        and if failed, then <em>prop</em> which was defined by the <code>tagTextProp</code> setting.
                    </p>
                    <details>
                      <summary></summary>
                    <h3>HTML</h3>
<pre class="language-markup"><code><input name='users-list-tags' value='abatisse2@nih.gov, Justinian Hattersley'></code></pre>
                    <h3>JAVASCRIPT</h3>
                    <script>renderPRE(document.currentScript, "users-list")</script>
                    <h3>CSS</h3>
<style contenteditable>/* Suggestions items */
.tagify__dropdown.users-list .tagify__dropdown__item{
    padding: .5em .7em;
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0 1em;
    grid-template-areas: "avatar name"
                         "avatar email";
}

.tagify__dropdown.users-list .tagify__dropdown__item:hover .tagify__dropdown__item__avatar-wrap{
    transform: scale(1.2);
}

.tagify__dropdown.users-list .tagify__dropdown__item__avatar-wrap{
    grid-area: avatar;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    overflow: hidden;
    background: #EEE;
    transition: .1s ease-out;
}

.tagify__dropdown.users-list img{
    width: 100%;
    vertical-align: top;
}

.tagify__dropdown.users-list strong{
    grid-area: name;
    width: 100%;
    align-self: center;
}

.tagify__dropdown.users-list span{
    grid-area: email;
    width: 100%;
    font-size: .9em;
    opacity: .6;
}

.tagify__dropdown.users-list .addAll{
    border-bottom: 1px solid #DDD;
    gap: 0;
}


/* Tags items */
#users-list .tagify__tag{
    white-space: nowrap;
}

#users-list .tagify__tag:hover .tagify__tag__avatar-wrap{
    transform: scale(1.6) translateX(-10%);
}

#users-list .tagify__tag .tagify__tag__avatar-wrap{
    width: 16px;
    height: 16px;
    white-space: normal;
    border-radius: 50%;
    background: silver;
    margin-right: 5px;
    transition: .12s ease-out;
}

#users-list .tagify__tag img{
    width: 100%;
    vertical-align: top;
    pointer-events: none;
}
</style>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/qBZdOJe'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='users-list-tags' value='abatisse2@nih.gov, Justinian Hattersley'>
                </aside>
            </section>


            <section id="section-advance-options">
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-advance-options'>Advance options</a></h2>
                    </header>
                    <p>
                        In this example, the <code>dropdown.enabled</code> <em>setting</em> is set (minimum charactes typed to show the dropdown) to <code>3</code>.
                        <br>
                        Maximum number of tags is set to <code>6</code>
                    </p>
                    <p>
                        Each (valid) tag gets a random color, via the <code>transformTag</code> callback which modifies the tag's data object before creating the tag element.
                        Another way of giving colors to tags is <a href='https://github.com/yairEO/tagify/issues/644'>discussed here</a>.
                        Clicking a tag <strong>once</strong> will change its color.
                    </p>
                    <p>
                        HTML5 <code>pattern</code> attribute is automatically used to validate tags.<br>
                        Also, the <code>delimiters</code> <em>setting</em> using both <code>comma</code> or <code>space</code> as tags seperators.
                    </p>
                    <p>
                        The <code>keepInvalidTags</code> <em>setting</em> flag is switched <em>on</em> to <code>true</code> so invaild tags are not removed but are only marked.
                    </p>
                    <p>
                        If there is no match for the typed text, a special dropdown item will be renderd using the optional <em>settings</em>: <code>templates.dropdownItemNoMatch</code>
                    </p>
                    <details>
                        <summary></summary>
                    <h3>HTML</h3>
<pre class="language-markup"><code><input name='tags3' value='[{"value":"point"}, {"value":"soft"}]' pattern='^[A-Za-z_✲ ]{1,15}$'></code></pre>
                    <h3>JAVASCRIPT</h3>
                    <script>renderPRE(document.currentScript, "advance-options")</script>
                    <h3>CSS</h3>
                    <style contenteditable>.advance .tagify__tag{
    --tag-hover: var(--tag-bg);
}
</style>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/bGpdVOr'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='tags3' class='advance' value='[{"value":"point"}, {"value":"soft"}]' pattern='^[A-Za-z_✲ ]{1,15}$'>
                </aside>
            </section>

            <section id="section-extra-properties">
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-extra-properties'>Tags with properties</a></h2>
                    </header>
                    <p>
                        Some cases requires more control per-tag, for exmaple, sending a different value to the server than the textual value
                        the user sees/entered. Another example, would be different colors for different tags or tags' groups.
                        it's possible to add any number of properties per tag, the only constant is the <code>value</code> property which
                        must be declared per-tag, and that will be the rendered text.
                    </p>
                    <p>
                        The propeties shown in the example below, declared in the <code>allowedTags</code> Array, will be transformed into
                        HTML attributes for each tag element rendered from the allowed <code>whitelist</code> settings, so naturally
                        some attributes are in the specs and the made-up ones should technically be prefixed with <code>data-</code>.
                    </p>
                    <details>
                        <summary></summary>
                    <h3>HTML</h3>
                    <xmp><input name='tags3-1' class='countries' placeholder="Try to add tags from the list"></xmp>
                    <h3>Javascript</h3>
                    <script>
                        renderPRE(document.currentScript, "extra-properties")
                    </script>
                    <h3>CSS</h3>
<style contenteditable>.tagify__dropdown.extra-properties .tagify__dropdown__item > img{
    display: inline-block;
    vertical-align: middle;
    height: 20px;
    transform: scale(.75);
    margin-right: 5px;
    border-radius: 2px;
    transition: .12s ease-out;
}

.tagify__dropdown.extra-properties .tagify__dropdown__item--active > img,
.tagify__dropdown.extra-properties .tagify__dropdown__item:hover > img{
    transform: none;
    margin-right: 12px;
}

.tagify.countries .tagify__input{ min-width:175px; }

.tagify.countries tag{ white-space:nowrap; }
.tagify.countries tag img{
    display: inline-block;
    height: 16px;
    margin-right: 3px;
    border-radius: 2px;
    pointer-events: none;
}
</style>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/ExKjVJJ'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input class='countries' name='tags3-1' placeholder="Try to add tags from the list">
                </aside>
            </section>


            <section id='section-readonly'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-readonly'>readonly</a></h2>
                    </header>
                    <p>
                        If the original input field has a <code>readonly</code> attribute, then, via CSS, Tagify blocks interactions with <code>pointer-events: none;</code>
                    </p>
                    <details>
                      <summary></summary>
                    <h3>HTML</h3>
                    <xmp><input name='tags4' readonly value='tag1, tag 2, another tag'></xmp>
                    <h3>Javascript</h3>
                    <script>
                        renderPRE(document.currentScript, "readonly")
                    </script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/RwaPWmR'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='tags4' readonly value='tag1, tag 2, another tag'>
                </aside>
            </section>

            <section id='section-readonly-mixed'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-readonly'>Readonly mix</a></h2>
                    </header>
                    <p>
                        Tags that are read-only mixed with removable tags
                    </p>
                    <details>
                      <summary></summary>
                    <h3>HTML</h3>
                    <pre class="language-markup"><code><input
    name='tags-readonly-mix'
    class='readonlyMix'
    placeholder="Type something"
    value='[
        {
            "value"    : "foo",
            "readonly" : true,
            "title"    : "read-only tag"
        },
        {
            "value"    : "bar"
        },
        {
            "value"    : "Locked tag",
            "readonly" : true,
            "title"    : "Another readonly tag"
        }
    ]'/>
</code></pre>
                    <h3>Javascript</h3>
                    <script>
                        renderPRE(document.currentScript, "readonly-mixed")
                    </script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/KKzpdLR'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input
                        name='tags-readonly-mix'
                        class='readonlyMix'
                        placeholder="Type something"
                        value='[
                            {
                                "value"    : "foo",
                                "readonly" : true,
                                "title"    : "read-only tag"
                            },
                            {
                                "value"    : "bar"
                            },
                            {
                                "value"    : "Locked tag",
                                "readonly" : true,
                                "title"    : "Another readonly tag"
                            }
                        ]' />
                </aside>
            </section>

            <section id='section-disabled'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-disabled'>disabled</a></h2>
                    </header>
                    <p>
                        If the original input field has a <code>disabled</code> attribute, then, via CSS, Tagify blocks interactions with <code>pointer-events: none;</code>
                    </p>
                    <details>
                        <summary></summary>
                    <h3>HTML</h3>
                    <xmp><input name='disabledInput' disabled value='tag1, tag 2, another tag'></xmp>
                    <h3>Javascript</h3>
                    <script>
                        renderPRE(document.currentScript, "disabled")
                    </script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/dyWYJbX'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='disabledInput' disabled value='tag1, tag 2, another tag'>
                </aside>
            </section>

            <section id='section-drag-sort'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-mode-select'>Drag & Sort</a></h2>
                    </header>
                    <p>
                        To be able to sort tags by draging, a 3rd-party script is needed. In this example I will be using my own -
                        lightweight & simple native HTML5 <a href='https://www.npmjs.com/package/@yaireo/dragsort' target='_blank'><em>dragsort</em></a> script.
                    </p>
                    <p>
                        Any <em>drag & drop</em> script would do that is able to also sort the elements. The only requirement is that when
                        the sorting it done, <code>tagify.updateValueByDOMTags()</code> must be called to sync Tagify with the change.
                    </p>
                    <details>
                      <summary></summary>
                    <h3>HTML</h3>
<pre class="language-markup"><code><input name='drag-sort' value='tag 1, tag 2, tag 3, tag 4, tag 5, tag 6' /></code></pre>
                    <h3>Javascript</h3>
                    <script>renderPRE(document.currentScript, "drag-sort")</script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/jOqYOVJ'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='drag-sort' value='tag 1, tag 2, tag 3, tag 4, tag 5, tag 6'/>
                </aside>
            </section>

            <section id='section-mode-select'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-mode-select'>single-value select</a></h2>
                    </header>
                    <p>
                        Similar to native <code><Select></code> element, but allows free text as value.
                    </p>
                    <p>
                        If the `enforceWhitelist` setting is set to `true` and a tag is currently selected,
                        user text input will be disabled, so altering the currently selected tag is forbidden.
                    </p>
                    <details>
                      <summary></summary>
                    <h3>HTML</h3>
<pre class="language-markup"><code><input name='tags-select-mode' class='selectMode' placeholder="Please select" /></code></pre>
                    <h3>Javascript</h3>
                    <script>renderPRE(document.currentScript, "mode-select")</script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/yLONYdx'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='tags-select-mode' class='selectMode' placeholder="Please select" />
                </aside>
            </section>


            <section id='section-jquery'>
                <aside class='leftSide'>
                    <header>
                        <h2><a href='#section-jquery'>jQuery plugin version</a></h2>
                    </header>
                    <p>
                        Tagify can also be used as a jQuery plugin
                    </p>
                    <details>
                      <summary></summary>
                    <h3>HTML</h3>
                    <pre class="language-markup"><code><input name='tags-jquery' value='try, adding, a tag'>
<button class='tags-jquery--removeAllBtn' type='button'>Remove all tags</button></code></pre>
                    <h3>JAVASCRIPT</h3>
                    <script>renderPRE(document.currentScript, "jQuery")</script>
                    </details>
                </aside>
                <aside class='rightSide'>
                    <a class='demoLink' title='View in Codepen' target='_blank' href='https://codepen.io/vsync/pen/abNOmWz'>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
                            <use class="logo-use" xlink:href="#codepen-logo"/>
                        </svg>
                    </a>
                    <input name='tags-jquery' value='try, adding, a tag'>
                    <button class='tags-jquery--removeAllBtn' type='button'>Remove all tags</button>
                </aside>
            </section>
        </form>








        <!-- Initialize Tagify for both Input and Textaera -->
        <script>
            document.forms[0].reset();

            // get the sticky element
            const stickyElm = document.querySelector('header')

            const observer = new IntersectionObserver(
                ([e]) => e.target.classList.toggle('isSticky', e.intersectionRatio < 1),
                {threshold: [1]}
            );

            observer.observe(stickyElm)
        </script>


<script data-name="basic">
(function(){
// The DOM element you wish to replace with Tagify
var input = document.querySelector('input[name=basic]');

// initialize Tagify on the above input node reference
new Tagify(input)
})()
</script>



<script data-name="input">
(function(){
var inputElm = document.querySelector('input[name=input]'),
    whitelist = ["A# .NET", "A# (Axiom)", "A-0 System", "A+", "A++", "ABAP", "ABC", "ABC ALGOL", "ABSET", "ABSYS", "ACC", "Accent", "Ace DASL", "ACL2", "Avicsoft", "ACT-III", "Action!", "ActionScript", "Ada", "Adenine", "Agda", "Agilent VEE", "Agora", "AIMMS", "Alef", "ALF", "ALGOL 58", "ALGOL 60", "ALGOL 68", "ALGOL W", "Alice", "Alma-0", "AmbientTalk", "Amiga E", "AMOS", "AMPL", "Apex (Salesforce.com)", "APL", "AppleScript", "Arc", "ARexx", "Argus", "AspectJ", "Assembly language", "ATS", "Ateji PX", "AutoHotkey", "Autocoder", "AutoIt", "AutoLISP / Visual LISP", "Averest", "AWK", "Axum", "Active Server Pages", "ASP.NET", "B", "Babbage", "Bash", "BASIC", "bc", "BCPL", "BeanShell", "Batch (Windows/Dos)", "Bertrand", "BETA", "Bigwig", "Bistro", "BitC", "BLISS", "Blockly", "BlooP", "Blue", "Boo", "Boomerang", "Bourne shell (including bash and ksh)", "BREW", "BPEL", "B", "C--", "C++ – ISO/IEC 14882", "C# – ISO/IEC 23270", "C/AL", "Caché ObjectScript", "C Shell", "Caml", "Cayenne", "CDuce", "Cecil", "Cesil", "Céu", "Ceylon", "CFEngine", "CFML", "Cg", "Ch", "Chapel", "Charity", "Charm", "Chef", "CHILL", "CHIP-8", "chomski", "ChucK", "CICS", "Cilk", "Citrine (programming language)", "CL (IBM)", "Claire", "Clarion", "Clean", "Clipper", "CLIPS", "CLIST", "Clojure", "CLU", "CMS-2", "COBOL – ISO/IEC 1989", "CobolScript – COBOL Scripting language", "Cobra", "CODE", "CoffeeScript", "ColdFusion", "COMAL", "Combined Programming Language (CPL)", "COMIT", "Common Intermediate Language (CIL)", "Common Lisp (also known as CL)", "COMPASS", "Component Pascal", "Constraint Handling Rules (CHR)", "COMTRAN", "Converge", "Cool", "Coq", "Coral 66", "Corn", "CorVision", "COWSEL", "CPL", "CPL", "Cryptol", "csh", "Csound", "CSP", "CUDA", "Curl", "Curry", "Cybil", "Cyclone", "Cython", "Java", "Javascript", "M2001", "M4", "M#", "Machine code", "MAD (Michigan Algorithm Decoder)", "MAD/I", "Magik", "Magma", "make", "Maple", "MAPPER now part of BIS", "MARK-IV now VISION:BUILDER", "Mary", "MASM Microsoft Assembly x86", "MATH-MATIC", "Mathematica", "MATLAB", "Maxima (see also Macsyma)", "Max (Max Msp – Graphical Programming Environment)", "Maya (MEL)", "MDL", "Mercury", "Mesa", "Metafont", "Microcode", "MicroScript", "MIIS", "Milk (programming language)", "MIMIC", "Mirah", "Miranda", "MIVA Script", "ML", "Model 204", "Modelica", "Modula", "Modula-2", "Modula-3", "Mohol", "MOO", "Mortran", "Mouse", "MPD", "Mathcad", "MSIL – deprecated name for CIL", "MSL", "MUMPS", "Mystic Programming L"];


// initialize Tagify on the above input node reference
var tagify = new Tagify(inputElm, {
    enforceWhitelist: true,
    whitelist: inputElm.value.trim().split(/\s*,\s*/) // Array of values. stackoverflow.com/a/43375571/104380
})



// "remove all tags" button event listener
document.querySelector('.tags--removeAllBtn')
    .addEventListener('click', tagify.removeAllTags.bind(tagify))

// Chainable event listeners
tagify.on('add', onAddTag)
      .on('remove', onRemoveTag)
      .on('input', onInput)
      .on('edit', onTagEdit)
      .on('invalid', onInvalidTag)
      .on('click', onTagClick)
      .on('focus', onTagifyFocusBlur)
      .on('blur', onTagifyFocusBlur)
      .on('dropdown:hide dropdown:show', e => console.log(e.type))
      .on('dropdown:select', onDropdownSelect)

var mockAjax = (function mockAjax(){
    var timeout;
    return function(duration){
        clearTimeout(timeout); // abort last request
        return new Promise(function(resolve, reject){
            timeout = setTimeout(resolve, duration || 700, whitelist)
        })
    }
})()

// tag added callback
function onAddTag(e){
    console.log("onAddTag: ", e.detail);
    console.log("original input value: ", inputElm.value)
    tagify.off('add', onAddTag) // exmaple of removing a custom Tagify event
}

// tag remvoed callback
function onRemoveTag(e){
    console.log("onRemoveTag:", e.detail, "tagify instance value:", tagify.value)
}

// on character(s) added/removed (user is typing/deleting)
function onInput(e){
    console.log("onInput: ", e.detail);
    tagify.whitelist = null; // reset current whitelist
    tagify.loading(true) // show the loader animation

    // get new whitelist from a delayed mocked request (Promise)
    mockAjax()
        .then(function(result){
            tagify.settings.whitelist = result.concat(tagify.value) // add already-existing tags to the new whitelist array

            tagify
                .loading(false)
                // render the suggestions dropdown.
                .dropdown.show(e.detail.value);
        })
        .catch(err => tagify.dropdown.hide())
}

function onTagEdit(e){
    console.log("onTagEdit: ", e.detail);
}

// invalid tag added callback
function onInvalidTag(e){
    console.log("onInvalidTag: ", e.detail);
}

// invalid tag added callback
function onTagClick(e){
    console.log(e.detail);
    console.log("onTagClick: ", e.detail);
}

function onTagifyFocusBlur(e){
    console.log(e.type, "event fired")
}

function onDropdownSelect(e){
    console.log("onDropdownSelect: ", e.detail)
}
})()
</script>


<script data-name="dropdown-tags">
(function(){

var input = document.querySelector('input[name="input-custom-dropdown"]'),
    // init Tagify script on the above inputs
    tagify = new Tagify(input, {
      whitelist: ["A# .NET", "A# (Axiom)", "A-0 System", "A+", "A++", "ABAP", "ABC", "ABC ALGOL", "ABSET", "ABSYS", "ACC", "Accent", "Ace DASL", "ACL2", "Avicsoft", "ACT-III", "Action!", "ActionScript", "Ada", "Adenine", "Agda", "Agilent VEE", "Agora", "AIMMS", "Alef", "ALF", "ALGOL 58", "ALGOL 60", "ALGOL 68", "ALGOL W", "Alice", "Alma-0", "AmbientTalk", "Amiga E", "AMOS", "AMPL", "Apex (Salesforce.com)", "APL", "AppleScript", "Arc", "ARexx", "Argus", "AspectJ", "Assembly language", "ATS", "Ateji PX", "AutoHotkey", "Autocoder", "AutoIt", "AutoLISP / Visual LISP", "Averest", "AWK", "Axum", "Active Server Pages", "ASP.NET", "B", "Babbage", "Bash", "BASIC", "bc", "BCPL", "BeanShell", "Batch (Windows/Dos)", "Bertrand", "BETA", "Bigwig", "Bistro", "BitC", "BLISS", "Blockly", "BlooP", "Blue", "Boo", "Boomerang", "Bourne shell (including bash and ksh)", "BREW", "BPEL", "B", "C--", "C++ – ISO/IEC 14882", "C# – ISO/IEC 23270", "C/AL", "Caché ObjectScript", "C Shell", "Caml", "Cayenne", "CDuce", "Cecil", "Cesil", "Céu", "Ceylon", "CFEngine", "CFML", "Cg", "Ch", "Chapel", "Charity", "Charm", "Chef", "CHILL", "CHIP-8", "chomski", "ChucK", "CICS", "Cilk", "Citrine (programming language)", "CL (IBM)", "Claire", "Clarion", "Clean", "Clipper", "CLIPS", "CLIST", "Clojure", "CLU", "CMS-2", "COBOL – ISO/IEC 1989", "CobolScript – COBOL Scripting language", "Cobra", "CODE", "CoffeeScript", "ColdFusion", "COMAL", "Combined Programming Language (CPL)", "COMIT", "Common Intermediate Language (CIL)", "Common Lisp (also known as CL)", "COMPASS", "Component Pascal", "Constraint Handling Rules (CHR)", "COMTRAN", "Converge", "Cool", "Coq", "Coral 66", "Corn", "CorVision", "COWSEL", "CPL", "CPL", "Cryptol", "csh", "Csound", "CSP", "CUDA", "Curl", "Curry", "Cybil", "Cyclone", "Cython", "Java", "Javascript", "M2001", "M4", "M#", "Machine code", "MAD (Michigan Algorithm Decoder)", "MAD/I", "Magik", "Magma", "make", "Maple", "MAPPER now part of BIS", "MARK-IV now VISION:BUILDER", "Mary", "MASM Microsoft Assembly x86", "MATH-MATIC", "Mathematica", "MATLAB", "Maxima (see also Macsyma)", "Max (Max Msp – Graphical Programming Environment)", "Maya (MEL)", "MDL", "Mercury", "Mesa", "Metafont", "Microcode", "MicroScript", "MIIS", "Milk (programming language)", "MIMIC", "Mirah", "Miranda", "MIVA Script", "ML", "Model 204", "Modelica", "Modula", "Modula-2", "Modula-3", "Mohol", "MOO", "Mortran", "Mouse", "MPD", "Mathcad", "MSIL – deprecated name for CIL", "MSL", "MUMPS", "Mystic Programming L"],
      maxTags: 10,
      dropdown: {
        maxItems: 20,           // <- mixumum allowed rendered suggestions
        classname: "tags-look", // <- custom classname for this dropdown, so it could be targeted
        enabled: 0,             // <- show suggestions on focus
        closeOnSelect: false    // <- do not hide the suggestions dropdown once an item has been selected
      }
    })
})()
</script>

<script data-name="manualSuggestions">
(function(){

var input = document.querySelector('input[name=tags-manual-suggestions]'),
    // init Tagify script on the above inputs
    tagify = new Tagify(input, {
        whitelist : ["A# .NET", "A# (Axiom)", "A-0 System", "A+", "A++", "ABAP", "ABC", "ABC ALGOL", "ABSET", "ABSYS", "ACC", "Accent", "Ace DASL", "ACL2", "Avicsoft", "ACT-III", "Action!", "ActionScript", "Ada", "Adenine", "Agda", "Agilent VEE", "Agora", "AIMMS", "Alef", "ALF", "ALGOL 58", "ALGOL 60", "ALGOL 68", "ALGOL W", "Alice", "Alma-0", "AmbientTalk", "Amiga E", "AMOS", "AMPL", "Apex (Salesforce.com)", "APL", "AppleScript", "Arc", "ARexx", "Argus", "AspectJ", "Assembly language", "ATS", "Ateji PX", "AutoHotkey", "Autocoder", "AutoIt", "AutoLISP / Visual LISP", "Averest", "AWK", "Axum", "Active Server Pages", "ASP.NET", "B", "Babbage", "Bash", "BASIC", "bc", "BCPL", "BeanShell", "Batch (Windows/Dos)", "Bertrand", "BETA", "Bigwig", "Bistro", "BitC", "BLISS", "Blockly", "BlooP", "Blue", "Boo", "Boomerang", "Bourne shell (including bash and ksh)", "BREW", "BPEL", "B", "C--", "C++ – ISO/IEC 14882", "C# – ISO/IEC 23270", "C/AL", "Caché ObjectScript", "C Shell", "Caml", "Cayenne", "CDuce", "Cecil", "Cesil", "Céu", "Ceylon", "CFEngine", "CFML", "Cg", "Ch", "Chapel", "Charity", "Charm", "Chef", "CHILL", "CHIP-8", "chomski", "ChucK", "CICS", "Cilk", "Citrine (programming language)", "CL (IBM)", "Claire", "Clarion", "Clean", "Clipper", "CLIPS", "CLIST", "Clojure", "CLU", "CMS-2", "COBOL – ISO/IEC 1989", "CobolScript – COBOL Scripting language", "Cobra", "CODE", "CoffeeScript", "ColdFusion", "COMAL", "Combined Programming Language (CPL)", "COMIT", "Common Intermediate Language (CIL)", "Common Lisp (also known as CL)", "COMPASS", "Component Pascal", "Constraint Handling Rules (CHR)", "COMTRAN", "Converge", "Cool", "Coq", "Coral 66", "Corn", "CorVision", "COWSEL", "CPL", "CPL", "Cryptol", "csh", "Csound", "CSP", "CUDA", "Curl", "Curry", "Cybil", "Cyclone", "Cython", "Java", "Javascript", "M2001", "M4", "M#", "Machine code", "MAD (Michigan Algorithm Decoder)", "MAD/I", "Magik", "Magma", "make", "Maple", "MAPPER now part of BIS", "MARK-IV now VISION:BUILDER", "Mary", "MASM Microsoft Assembly x86", "MATH-MATIC", "Mathematica", "MATLAB", "Maxima (see also Macsyma)", "Max (Max Msp – Graphical Programming Environment)", "Maya (MEL)", "MDL", "Mercury", "Mesa", "Metafont", "Microcode", "MicroScript", "MIIS", "Milk (programming language)", "MIMIC", "Mirah", "Miranda", "MIVA Script", "ML", "Model 204", "Modelica", "Modula", "Modula-2", "Modula-3", "Mohol", "MOO", "Mortran", "Mouse", "MPD", "Mathcad", "MSIL – deprecated name for CIL", "MSL", "MUMPS", "Mystic Programming L"],
        dropdown: {
            position: "manual",
            maxItems: Infinity,
            enabled: 0,
            classname: "customSuggestionsList"
        },
        enforceWhitelist: true
    })

    tagify.on("dropdown:show", onSuggestionsListUpdate)
          .on("dropdown:hide", onSuggestionsListHide)
          .on('dropdown:scroll', onDropdownScroll)

    renderSuggestionsList()

    // ES2015 argument destructuring
    function onSuggestionsListUpdate({ detail:suggestionsElm }){
        console.log(  suggestionsElm  )
    }

    function onSuggestionsListHide(){
        console.log("hide dropdown")
    }

    function onDropdownScroll(e){
        console.log(e.detail)
      }

    // https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement
    function renderSuggestionsList(){
        tagify.dropdown.show() // load the list
        tagify.DOM.scope.parentNode.appendChild(tagify.DOM.dropdown)
    }
})()
</script>


<script data-name="noUserInput">
(function(){

var input = document.querySelector('input[name=tags-disabled-user-input]');

new Tagify(input, {
    whitelist: [1,2,3,4,5],
    userInput: false
})
})()
</script>


<script data-name="textarea">
(function(){
var input = document.querySelector('textarea[name=tags2]'),
    tagify = new Tagify(input, {
        enforceWhitelist : true,
        delimiters       : null,
        whitelist        : ["The Shawshank Redemption", "The Godfather", "The Godfather: Part II", "The Dark Knight", "12 Angry Men", "Schindler's List", "Pulp Fiction", "The Lord of the Rings: The Return of the King", "The Good, the Bad and the Ugly", "Fight Club", "The Lord of the Rings: The Fellowship of the Ring", "Star Wars: Episode V - The Empire Strikes Back", "Forrest Gump", "Inception", "The Lord of the Rings: The Two Towers", "One Flew Over the Cuckoo's Nest", "Goodfellas", "The Matrix", "Seven Samurai", "Star Wars: Episode IV - A New Hope", "City of God", "Se7en", "The Silence of the Lambs", "It's a Wonderful Life", "The Usual Suspects", "Life Is Beautiful", "Léon: The Professional", "Spirited Away", "Saving Private Ryan", "La La Land", "Once Upon a Time in the West", "American History X", "Interstellar", "Casablanca", "Psycho", "City Lights", "The Green Mile", "Raiders of the Lost Ark", "The Intouchables", "Modern Times", "Rear Window", "The Pianist", "The Departed", "Terminator 2: Judgment Day", "Back to the Future", "Whiplash", "Gladiator", "Memento", "Apocalypse Now", "The Prestige", "The Lion King", "Alien", "Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb", "Sunset Boulevard", "The Great Dictator", "Cinema Paradiso", "The Lives of Others", "Paths of Glory", "Grave of the Fireflies", "Django Unchained", "The Shining", "WALL·E", "American Beauty", "The Dark Knight Rises", "Princess Mononoke", "Aliens", "Oldboy", "Once Upon a Time in America", "Citizen Kane", "Das Boot", "Witness for the Prosecution", "North by Northwest", "Vertigo", "Star Wars: Episode VI - Return of the Jedi", "Reservoir Dogs", "M", "Braveheart", "Amélie", "Requiem for a Dream", "A Clockwork Orange", "Taxi Driver", "Lawrence of Arabia", "Like Stars on Earth", "Double Indemnity", "To Kill a Mockingbird", "Eternal Sunshine of the Spotless Mind", "Toy Story 3", "Amadeus", "My Father and My Son", "Full Metal Jacket", "The Sting", "2001: A Space Odyssey", "Singin' in the Rain", "Bicycle Thieves", "Toy Story", "Dangal", "The Kid", "Inglourious Basterds", "Snatch", "Monty Python and the Holy Grail", "Hacksaw Ridge", "3 Idiots", "L.A. Confidential", "For a Few Dollars More", "Scarface", "Rashomon", "The Apartment", "The Hunt", "Good Will Hunting", "Indiana Jones and the Last Crusade", "A Separation", "Metropolis", "Yojimbo", "All About Eve", "Batman Begins", "Up", "Some Like It Hot", "The Treasure of the Sierra Madre", "Unforgiven", "Downfall", "Raging Bull", "The Third Man", "Die Hard", "Children of Heaven", "The Great Escape", "Heat", "Chinatown", "Inside Out", "Pan's Labyrinth", "Ikiru", "My Neighbor Totoro", "On the Waterfront", "Room", "Ran", "The Gold Rush", "The Secret in Their Eyes", "The Bridge on the River Kwai", "Blade Runner", "Mr. Smith Goes to Washington", "The Seventh Seal", "Howl's Moving Castle", "Lock, Stock and Two Smoking Barrels", "Judgment at Nuremberg", "Casino", "The Bandit", "Incendies", "A Beautiful Mind", "A Wednesday", "The General", "The Elephant Man", "Wild Strawberries", "Arrival", "V for Vendetta", "Warrior", "The Wolf of Wall Street", "Manchester by the Sea", "Sunrise", "The Passion of Joan of Arc", "Gran Torino", "Rang De Basanti", "Trainspotting", "Dial M for Murder", "The Big Lebowski", "The Deer Hunter", "Tokyo Story", "Gone with the Wind", "Fargo", "Finding Nemo", "The Sixth Sense", "The Thing", "Hera Pheri", "Cool Hand Luke", "Andaz Apna Apna", "Rebecca", "No Country for Old Men", "How to Train Your Dragon", "Munna Bhai M.B.B.S.", "Sholay", "Kill Bill: Vol. 1", "Into the Wild", "Mary and Max", "Gone Girl", "There Will Be Blood", "Come and See", "It Happened One Night", "Life of Brian", "Rush", "Hotel Rwanda", "Platoon", "Shutter Island", "Network", "The Wages of Fear", "Stand by Me", "Wild Tales", "In the Name of the Father", "Spotlight", "Star Wars: The Force Awakens", "The Nights of Cabiria", "The 400 Blows", "Butch Cassidy and the Sundance Kid", "Mad Max: Fury Road", "The Maltese Falcon", "12 Years a Slave", "Ben-Hur", "The Grand Budapest Hotel", "Persona", "Million Dollar Baby", "Amores Perros", "Jurassic Park", "The Princess Bride", "Hachi: A Dog's Tale", "Memories of Murder", "Stalker", "Nausicaä of the Valley of the Wind", "Drishyam", "The Truman Show", "The Grapes of Wrath", "Before Sunrise", "Touch of Evil", "Annie Hall", "The Message", "Rocky", "Gandhi", "Harry Potter and the Deathly Hallows: Part 2", "The Bourne Ultimatum", "Diabolique", "Donnie Darko", "Monsters, Inc.", "Prisoners", "8½", "The Terminator", "The Wizard of Oz", "Catch Me If You Can", "Groundhog Day", "Twelve Monkeys", "Zootopia", "La Haine", "Barry Lyndon", "Jaws", "The Best Years of Our Lives", "Infernal Affairs", "Udaan", "The Battle of Algiers", "Strangers on a Train", "Dog Day Afternoon", "Sin City", "Kind Hearts and Coronets", "Gangs of Wasseypur", "The Help"],
        callbacks        : {
            add    : console.log,  // callback when adding a tag
            remove : console.log   // callback when removing a tag
        }
    });
})()
</script>

<script data-name="customLook">
(function(){
  // generate random whilist items (for the demo)
var randomStringsArr = Array.apply(null, Array(100)).map(function() {
  return Array.apply(null, Array(~~(Math.random() * 10  + 3))).map(function() {
    return String.fromCharCode(Math.random() * (123 - 97) + 97)
  }).join('') + '@gmail.com'
})

var input = document.querySelector('.customLook'),
    tagify = new Tagify(input, {
      // email address validation (https://stackoverflow.com/a/46181/104380)
      pattern: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
      whitelist: randomStringsArr,
      callbacks: {
        "invalid": onInvalidTag
      },
      dropdown : {
        position: 'text',
        enabled: 1 // show suggestions dropdown after 1 typed character
      }
    }),
    button = input.nextElementSibling;  // "add new tag" action-button

button.addEventListener("click", onAddButtonClick)

function onAddButtonClick(){
    tagify.addEmptyTag()
}

function onInvalidTag(e){
  console.log("invalid", e.detail)
}
})()
</script>


<script data-name='mix'>
(function(){
// Define two types of whitelists, each used for the dropdown suggestions menu,
// depending on the prefix pattern typed (@/#). See settings below.
  var whitelist_1 = [
    { value: 100, text: 'kenny', title: 'Kenny McCormick' },
    { value: 200, text: 'cartman', title: 'Eric Cartman' },
    { value: 300, text: 'kyle', title: 'Kyle Broflovski' },
    { value: 400, text: 'token', title: 'Token Black' },
    { value: 500, text: 'jimmy', title: 'Jimmy Valmer' },
    { value: 600, text: 'butters', title: 'Butters Stotch' },
    { value: 700, text: 'stan', title: 'Stan Marsh' },
    { value: 800, text: 'randy', title: 'Randy Marsh' },
    { value: 900, text: 'Mr. Garrison', title: 'POTUS' },
    { value: 1000, text: 'Mr. Mackey', title: "M'Kay" }
  ]

// Second whitelist, which is shown only when starting to type "#".
// Thiw whitelist is the most simple one possible.
var whitelist_2 = ['Homer simpson', 'Marge simpson', 'Bart', 'Lisa', 'Maggie', 'Mr. Burns', 'Ned', 'Milhouse', 'Moe'];


// initialize Tagify
var input = document.querySelector('[name=mix]'),
    // init Tagify script on the above inputs
    tagify = new Tagify(input, {
    //  mixTagsInterpolator: ["{{", "}}"],
        mode: 'mix',  // <--  Enable mixed-content
        pattern: /@|#/,  // <--  Text starting with @ or # (if single, String can be used here)
        tagTextProp: 'text',  // <-- the default property (from whitelist item) for the text to be rendered in a tag element.
        // Array for initial interpolation, which allows only these tags to be used
        whitelist: whitelist_1.concat(whitelist_2).map(function(item){
            return typeof item == 'string' ? {value:item} : item
        }),
        dropdown : {
            enabled: 1,
            position: 'text', // <-- render the suggestions list next to the typed text ("caret")
            mapValueTo: 'text', // <-- similar to above "tagTextProp" setting, but for the dropdown items
            highlightFirst: true  // automatically highlights first sugegstion item in the dropdown
        },
        callbacks: {
            add: console.log,  // callback when adding a tag
            remove: console.log   // callback when removing a tag
        }
    })


// A good place to pull server suggestion list accoring to the prefix/value
tagify.on('input', function(e){
    var prefix = e.detail.prefix;

    // first, clean the whitlist array, because the below code, while not, might be async,
    // therefore it should be up to you to decide WHEN to render the suggestions dropdown
    // tagify.settings.whitelist.length = 0;

    if( prefix ){
        if( prefix == '@' )
            tagify.whitelist = whitelist_1;

        if( prefix == '#' )
            tagify.whitelist = whitelist_2;

        if( e.detail.value.length > 1 )
            tagify.dropdown.show(e.detail.value);
    }

    console.log( tagify.value )
    console.log('mix-mode "input" event value: ', e.detail)
})

tagify.on('add', function(e){
    console.log(e)
})

})()
</script>


<script data-name="outside-of-the-box">
(function(){

var input = document.querySelector('input[name=tags-outside]')
// init Tagify script on the above inputs
var tagify = new Tagify(input, {
  whitelist: ["foo", "bar", "baz"],
  dropdown: {
    position: "input",
    enabled : 0 // always opens dropdown when input gets focus
  }
})
})()
</script>


<script data-name="advance-options">
(function(){
var input = document.querySelector('input[name=tags3]'),
    tagify = new Tagify(input, {
        pattern             : /^.{0,20}$/,  // Validate typed tag(s) by Regex. Here maximum chars length is defined as "20"
        delimiters          : ",| ",        // add new tags when a comma or a space character is entered
        keepInvalidTags     : true,         // do not remove invalid tags (but keep them marked as invalid)
        editTags            : {
            clicks: 2,              // single click to edit a tag
            keepInvalid: false      // if after editing, tag is invalid, auto-revert
        },
        maxTags             : 6,
        blacklist           : ["foo", "bar", "baz"],
        whitelist           : ["temple","stun","detective","sign","passion","routine","deck","discriminate","relaxation","fraud","attractive","soft","forecast","point","thank","stage","eliminate","effective","flood","passive","skilled","separation","contact","compromise","reality","district","nationalist","leg","porter","conviction","worker","vegetable","commerce","conception","particle","honor","stick","tail","pumpkin","core","mouse","egg","population","unique","behavior","onion","disaster","cute","pipe","sock","dialect","horse","swear","owner","cope","global","improvement","artist","shed","constant","bond","brink","shower","spot","inject","bowel","homosexual","trust","exclude","tough","sickness","prevalence","sister","resolution","cattle","cultural","innocent","burial","bundle","thaw","respectable","thirsty","exposure","team","creed","facade","calendar","filter","utter","dominate","predator","discover","theorist","hospitality","damage","woman","rub","crop","unpleasant","halt","inch","birthday","lack","throne","maximum","pause","digress","fossil","policy","instrument","trunk","frame","measure","hall","support","convenience","house","partnership","inspector","looting","ranch","asset","rally","explicit","leak","monarch","ethics","applied","aviation","dentist","great","ethnic","sodium","truth","constellation","lease","guide","break","conclusion","button","recording","horizon","council","paradox","bride","weigh","like","noble","transition","accumulation","arrow","stitch","academy","glimpse","case","researcher","constitutional","notion","bathroom","revolutionary","soldier","vehicle","betray","gear","pan","quarter","embarrassment","golf","shark","constitution","club","college","duty","eaux","know","collection","burst","fun","animal","expectation","persist","insure","tick","account","initiative","tourist","member","example","plant","river","ratio","view","coast","latest","invite","help","falsify","allocation","degree","feel","resort","means","excuse","injury","pupil","shaft","allow","ton","tube","dress","speaker","double","theater","opposed","holiday","screw","cutting","picture","laborer","conservation","kneel","miracle","brand","nomination","characteristic","referral","carbon","valley","hot","climb","wrestle","motorist","update","loot","mosquito","delivery","eagle","guideline","hurt","feedback","finish","traffic","competence","serve","archive","feeling","hope","seal","ear","oven","vote","ballot","study","negative","declaration","particular","pattern","suburb","intervention","brake","frequency","drink","affair","contemporary","prince","dry","mole","lazy","undermine","radio","legislation","circumstance","bear","left","pony","industry","mastermind","criticism","sheep","failure","chain","depressed","launch","script","green","weave","please","surprise","doctor","revive","banquet","belong","correction","door","image","integrity","intermediate","sense","formal","cane","gloom","toast","pension","exception","prey","random","nose","predict","needle","satisfaction","establish","fit","vigorous","urgency","X-ray","equinox","variety","proclaim","conceive","bulb","vegetarian","available","stake","publicity","strikebreaker","portrait","sink","frog","ruin","studio","match","electron","captain","channel","navy","set","recommend","appoint","liberal","missile","sample","result","poor","efflux","glance","timetable","advertise","personality","aunt","dog"],
        transformTag        : transformTag,
        backspace           : "edit",
        placeholder         : "Type something",
        dropdown : {
            enabled: 1,            // show suggestion after 1 typed character
            fuzzySearch: false,    // match only suggestions that starts with the typed characters
            position: 'text',      // position suggestions list next to typed text
            caseSensitive: true,   // allow adding duplicate items if their case is different
        },
        templates: {
            dropdownItemNoMatch: function(data) {
                return `<div class='${this.settings.classNames.dropdownItem}' tabindex="0" role="option">
                    No suggestion found for: <strong>${data.value}</strong>
                </div>`
            }
        }
    })

// generate a random color (in HSL format, which I like to use)
function getRandomColor(){
    function rand(min, max) {
        return min + Math.random() * (max - min);
    }

    var h = rand(1, 360)|0,
        s = rand(40, 70)|0,
        l = rand(65, 72)|0;

    return 'hsl(' + h + ',' + s + '%,' + l + '%)';
}

function transformTag( tagData ){
    tagData.color = getRandomColor();
    tagData.style = "--tag-bg:" + tagData.color;

    if( tagData.value.toLowerCase() == 'shit' )
        tagData.value = 's✲✲t'
}

tagify.on('add', function(e){
    console.log(e.detail)
})

tagify.on('invalid', function(e){
    console.log(e, e.detail);
})

var clickDebounce;

tagify.on('click', function(e){
    const {tag:tagElm, data:tagData} = e.detail;

    // a delay is needed to distinguish between regular click and double-click.
    // this allows enough time for a possible double-click, and noly fires if such
    // did not occur.
    clearTimeout(clickDebounce);
    clickDebounce = setTimeout(() => {
        tagData.color = getRandomColor();
        tagData.style = "--tag-bg:" + tagData.color;
        tagify.replaceTag(tagElm, tagData);
    }, 200);
})

tagify.on('dblclick', function(e){
    // when souble clicking, do not change the color of the tag
    clearTimeout(clickDebounce);
})


})()
</script>

<script data-name="users-list">
// https://www.mockaroo.com/
(function(){

var inputElm = document.querySelector('input[name=users-list-tags]');

function tagTemplate(tagData){
    return `
        <tag title="${tagData.email}"
                contenteditable='false'
                spellcheck='false'
                tabIndex="-1"
                class="tagify__tag ${tagData.class ? tagData.class : ""}"
                ${this.getAttributes(tagData)}>
            <x title='' class='tagify__tag__removeBtn' role='button' aria-label='remove tag'></x>
            <div>
                <div class='tagify__tag__avatar-wrap'>
                    <img onerror="this.style.visibility='hidden'" src="${tagData.avatar}">
                </div>
                <span class='tagify__tag-text'>${tagData.name}</span>
            </div>
        </tag>
    `
}

function suggestionItemTemplate(tagData){
    return `
        <div ${this.getAttributes(tagData)}
            class='tagify__dropdown__item ${tagData.class ? tagData.class : ""}'
            tabindex="0"
            role="option">
            ${ tagData.avatar ? `
            <div class='tagify__dropdown__item__avatar-wrap'>
                <img onerror="this.style.visibility='hidden'" src="${tagData.avatar}">
            </div>` : ''
            }
            <strong>${tagData.name}</strong>
            <span>${tagData.email}</span>
        </div>
    `
}

// initialize Tagify on the above input node reference
var tagify = new Tagify(inputElm, {
    tagTextProp: 'name', // very important since a custom template is used with this property as text
    enforceWhitelist: true,
    skipInvalid: true, // do not remporarily add invalid tags
    dropdown: {
        closeOnSelect: false,
        enabled: 0,
        classname: 'users-list',
        searchKeys: ['name', 'email']  // very important to set by which keys to search for suggesttions when typing
    },
    templates: {
        tag: tagTemplate,
        dropdownItem: suggestionItemTemplate
    },
    whitelist: [
        {
            "value": 1,
            "name": "Justinian Hattersley",
            "avatar": "https://i.pravatar.cc/80?img=1",
            "email": "jhattersley0@ucsd.edu"
        },
        {
            "value": 2,
            "name": "Antons Esson",
            "avatar": "https://i.pravatar.cc/80?img=2",
            "email": "aesson1@ning.com"
        },
        {
            "value": 3,
            "name": "Ardeen Batisse",
            "avatar": "https://i.pravatar.cc/80?img=3",
            "email": "abatisse2@nih.gov"
        },
        {
            "value": 4,
            "name": "Graeme Yellowley",
            "avatar": "https://i.pravatar.cc/80?img=4",
            "email": "gyellowley3@behance.net"
        },
        {
            "value": 5,
            "name": "Dido Wilford",
            "avatar": "https://i.pravatar.cc/80?img=5",
            "email": "dwilford4@jugem.jp"
        },
        {
            "value": 6,
            "name": "Celesta Orwin",
            "avatar": "https://i.pravatar.cc/80?img=6",
            "email": "corwin5@meetup.com"
        },
        {
            "value": 7,
            "name": "Sally Main",
            "avatar": "https://i.pravatar.cc/80?img=7",
            "email": "smain6@techcrunch.com"
        },
        {
            "value": 8,
            "name": "Grethel Haysman",
            "avatar": "https://i.pravatar.cc/80?img=8",
            "email": "ghaysman7@mashable.com"
        },
        {
            "value": 9,
            "name": "Marvin Mandrake",
            "avatar": "https://i.pravatar.cc/80?img=9",
            "email": "mmandrake8@sourceforge.net"
        },
        {
            "value": 10,
            "name": "Corrie Tidey",
            "avatar": "https://i.pravatar.cc/80?img=10",
            "email": "ctidey9@youtube.com"
        },
        {
            "value": 11,
            "name": "foo",
            "avatar": "https://i.pravatar.cc/80?img=11",
            "email": "foo@bar.com"
        },
        {
            "value": 12,
            "name": "foo",
            "avatar": "https://i.pravatar.cc/80?img=12",
            "email": "foo.aaa@foo.com"
        },
    ]
})

tagify.on('dropdown:show dropdown:updated', onDropdownShow)
tagify.on('dropdown:select', onSelectSuggestion)

var addAllSuggestionsElm;

function onDropdownShow(e){
    var dropdownContentElm = e.detail.tagify.DOM.dropdown.content;

    if( tagify.suggestedListItems.length > 1 ){
        addAllSuggestionsElm = getAddAllSuggestionsElm();

        // insert "addAllSuggestionsElm" as the first element in the suggestions list
        dropdownContentElm.insertBefore(addAllSuggestionsElm, dropdownContentElm.firstChild)
    }
}

function onSelectSuggestion(e){
    if( e.detail.elm == addAllSuggestionsElm )
        tagify.dropdown.selectAll();
}

// create a "add all" custom suggestion element every time the dropdown changes
function getAddAllSuggestionsElm(){
    // suggestions items should be based on "dropdownItem" template
    return tagify.parseTemplate('dropdownItem', [{
            class: "addAll",
            name: "Add all",
            email: tagify.whitelist.reduce(function(remainingSuggestions, item){
                return tagify.isTagDuplicate(item.value) ? remainingSuggestions : remainingSuggestions + 1
            }, 0) + " Members"
        }]
      )
}
})()
</script>


<script data-name="extra-properties">
(function(){

var tagify = new Tagify(document.querySelector('input[name=tags3-1]'), {
    delimiters : null,
    templates : {
        tag : function(tagData){
            try{
                return `<tag title='${tagData.value}' contenteditable='false' spellcheck="false" class='tagify__tag ${tagData.class ? tagData.class : ""}' ${this.getAttributes(tagData)}>
                        <x title='remove tag' class='tagify__tag__removeBtn'></x>
                        <div>
                            ${tagData.code ?
                            `<img onerror="this.style.visibility='hidden'" src='https://lipis.github.io/flag-icon-css/flags/4x3/${tagData.code.toLowerCase()}.svg'>` : ''
                            }
                            <span class='tagify__tag-text'>${tagData.value}</span>
                        </div>
                    </tag>`
            }
            catch(err){}
        },

        dropdownItem : function(tagData){
            try{
                return `<div class='tagify__dropdown__item ${tagData.class ? tagData.class : ""}' tagifySuggestionIdx="${tagData.tagifySuggestionIdx}">
                            <img onerror="this.style.visibility = 'hidden'"
                                src='https://lipis.github.io/flag-icon-css/flags/4x3/${tagData.code.toLowerCase()}.svg'>
                            <span>${tagData.value}</span>
                        </div>`
            }
            catch(err){}
        }
    },
    enforceWhitelist : true,
    whitelist : [
      { value:'Afghanistan', code:'AF' },
      { value:'Åland Islands', code:'AX' },
      { value:'Albania', code:'AL' },
      { value:'Algeria', code:'DZ' },
      { value:'American Samoa', code:'AS' },
      { value:'Andorra', code:'AD' },
      { value:'Angola', code:'AO' },
      { value:'Anguilla', code:'AI' },
      { value:'Antarctica', code:'AQ' },
      { value:'Antigua and Barbuda', code:'AG' },
      { value:'Argentina', code:'AR' },
      { value:'Armenia', code:'AM' },
      { value:'Aruba', code:'AW' },
      { value:'Australia', code:'AU', searchBy:'beach, sub-tropical' },
      { value:'Austria', code:'AT' },
      { value:'Azerbaijan', code:'AZ' },
      { value:'Bahamas', code:'BS' },
      { value:'Bahrain', code:'BH' },
      { value:'Bangladesh', code:'BD' },
      { value:'Barbados', code:'BB' },
      { value:'Belarus', code:'BY' },
      { value:'Belgium', code:'BE' },
      { value:'Belize', code:'BZ' },
      { value:'Benin', code:'BJ' },
      { value:'Bermuda', code:'BM' },
      { value:'Bhutan', code:'BT' },
      { value:'Bolivia', code:'BO' },
      { value:'Bosnia and Herzegovina', code:'BA' },
      { value:'Botswana', code:'BW' },
      { value:'Bouvet Island', code:'BV' },
      { value:'Brazil', code:'BR' },
      { value:'British Indian Ocean Territory', code:'IO' },
      { value:'Brunei Darussalam', code:'BN' },
      { value:'Bulgaria', code:'BG' },
      { value:'Burkina Faso', code:'BF' },
      { value:'Burundi', code:'BI' },
      { value:'Cambodia', code:'KH' },
      { value:'Cameroon', code:'CM' },
      { value:'Canada', code:'CA' },
      { value:'Cape Verde', code:'CV' },
      { value:'Cayman Islands', code:'KY' },
      { value:'Central African Republic', code:'CF' },
      { value:'Chad', code:'TD' },
      { value:'Chile', code:'CL' },
      { value:'China', code:'CN' },
      { value:'Christmas Island', code:'CX' },
      { value:'Cocos (Keeling) Islands', code:'CC' },
      { value:'Colombia', code:'CO' },
      { value:'Comoros', code:'KM' },
      { value:'Congo', code:'CG' },
      { value:'Congo, The Democratic Republic of the', code:'CD' },
      { value:'Cook Islands', code:'CK' },
      { value:'Costa Rica', code:'CR' },
      { value:'Cote D\'Ivoire', code:'CI' },
      { value:'Croatia', code:'HR' },
      { value:'Cuba', code:'CU' },
      { value:'Cyprus', code:'CY' },
      { value:'Czech Republic', code:'CZ' },
      { value:'Denmark', code:'DK' },
      { value:'Djibouti', code:'DJ' },
      { value:'Dominica', code:'DM' },
      { value:'Dominican Republic', code:'DO' },
      { value:'Ecuador', code:'EC' },
      { value:'Egypt', code:'EG' },
      { value:'El Salvador', code:'SV' },
      { value:'Equatorial Guinea', code:'GQ' },
      { value:'Eritrea', code:'ER' },
      { value:'Estonia', code:'EE' },
      { value:'Ethiopia', code:'ET' },
      { value:'Falkland Islands (Malvinas)', code:'FK' },
      { value:'Faroe Islands', code:'FO' },
      { value:'Fiji', code:'FJ' },
      { value:'Finland', code:'FI' },
      { value:'France', code:'FR' },
      { value:'French Guiana', code:'GF' },
      { value:'French Polynesia', code:'PF' },
      { value:'French Southern Territories', code:'TF' },
      { value:'Gabon', code:'GA' },
      { value:'Gambia', code:'GM' },
      { value:'Georgia', code:'GE' },
      { value:'Germany', code:'DE' },
      { value:'Ghana', code:'GH' },
      { value:'Gibraltar', code:'GI' },
      { value:'Greece', code:'GR' },
      { value:'Greenland', code:'GL' },
      { value:'Grenada', code:'GD' },
      { value:'Guadeloupe', code:'GP' },
      { value:'Guam', code:'GU' },
      { value:'Guatemala', code:'GT' },
      { value:'Guernsey', code:'GG' },
      { value:'Guinea', code:'GN' },
      { value:'Guinea-Bissau', code:'GW' },
      { value:'Guyana', code:'GY' },
      { value:'Haiti', code:'HT' },
      { value:'Heard Island and Mcdonald Islands', code:'HM' },
      { value:'Holy See (Vatican City State)', code:'VA' },
      { value:'Honduras', code:'HN' },
      { value:'Hong Kong', code:'HK' },
      { value:'Hungary', code:'HU' },
      { value:'Iceland', code:'IS' },
      { value:'India', code:'IN' },
      { value:'Indonesia', code:'ID' },
      { value:'Iran, Islamic Republic Of', code:'IR' },
      { value:'Iraq', code:'IQ' },
      { value:'Ireland', code:'IE' },
      { value:'Isle of Man', code:'IM' },
      { value:'Israel', code:'IL', searchBy:'holy land, desert' },
      { value:'Italy', code:'IT' },
      { value:'Jamaica', code:'JM' },
      { value:'Japan', code:'JP' },
      { value:'Jersey', code:'JE' },
      { value:'Jordan', code:'JO' },
      { value:'Kazakhstan', code:'KZ' },
      { value:'Kenya', code:'KE' },
      { value:'Kiribati', code:'KI' },
      { value:'Korea, Democratic People\'S Republic of', code:'KP' },
      { value:'Korea, Republic of', code:'KR' },
      { value:'Kuwait', code:'KW' },
      { value:'Kyrgyzstan', code:'KG' },
      { value:'Lao People\'S Democratic Republic', code:'LA' },
      { value:'Latvia', code:'LV' },
      { value:'Lebanon', code:'LB' },
      { value:'Lesotho', code:'LS' },
      { value:'Liberia', code:'LR' },
      { value:'Libyan Arab Jamahiriya', code:'LY' },
      { value:'Liechtenstein', code:'LI' },
      { value:'Lithuania', code:'LT' },
      { value:'Luxembourg', code:'LU' },
      { value:'Macao', code:'MO' },
      { value:'Macedonia, The Former Yugoslav Republic of', code:'MK' },
      { value:'Madagascar', code:'MG' },
      { value:'Malawi', code:'MW' },
      { value:'Malaysia', code:'MY' },
      { value:'Maldives', code:'MV' },
      { value:'Mali', code:'ML' },
      { value:'Malta', code:'MT' },
      { value:'Marshall Islands', code:'MH' },
      { value:'Martinique', code:'MQ' },
      { value:'Mauritania', code:'MR' },
      { value:'Mauritius', code:'MU' },
      { value:'Mayotte', code:'YT' },
      { value:'Mexico', code:'MX' },
      { value:'Micronesia, Federated States of', code:'FM' },
      { value:'Moldova, Republic of', code:'MD' },
      { value:'Monaco', code:'MC' },
      { value:'Mongolia', code:'MN' },
      { value:'Montserrat', code:'MS' },
      { value:'Morocco', code:'MA' },
      { value:'Mozambique', code:'MZ' },
      { value:'Myanmar', code:'MM' },
      { value:'Namibia', code:'NA' },
      { value:'Nauru', code:'NR' },
      { value:'Nepal', code:'NP' },
      { value:'Netherlands', code:'NL' },
      { value:'Netherlands Antilles', code:'AN' },
      { value:'New Caledonia', code:'NC' },
      { value:'New Zealand', code:'NZ' },
      { value:'Nicaragua', code:'NI' },
      { value:'Niger', code:'NE' },
      { value:'Nigeria', code:'NG' },
      { value:'Niue', code:'NU' },
      { value:'Norfolk Island', code:'NF' },
      { value:'Northern Mariana Islands', code:'MP' },
      { value:'Norway', code:'NO' },
      { value:'Oman', code:'OM' },
      { value:'Pakistan', code:'PK' },
      { value:'Palau', code:'PW' },
      { value:'Palestinian Territory, Occupied', code:'PS' },
      { value:'Panama', code:'PA' },
      { value:'Papua New Guinea', code:'PG' },
      { value:'Paraguay', code:'PY' },
      { value:'Peru', code:'PE' },
      { value:'Philippines', code:'PH' },
      { value:'Pitcairn', code:'PN' },
      { value:'Poland', code:'PL' },
      { value:'Portugal', code:'PT' },
      { value:'Puerto Rico', code:'PR' },
      { value:'Qatar', code:'QA' },
      { value:'Reunion', code:'RE' },
      { value:'Romania', code:'RO' },
      { value:'Russian Federation', code:'RU' },
      { value:'RWANDA', code:'RW' },
      { value:'Saint Helena', code:'SH' },
      { value:'Saint Kitts and Nevis', code:'KN' },
      { value:'Saint Lucia', code:'LC' },
      { value:'Saint Pierre and Miquelon', code:'PM' },
      { value:'Saint Vincent and the Grenadines', code:'VC' },
      { value:'Samoa', code:'WS' },
      { value:'San Marino', code:'SM' },
      { value:'Sao Tome and Principe', code:'ST' },
      { value:'Saudi Arabia', code:'SA' },
      { value:'Senegal', code:'SN' },
      { value:'Serbia and Montenegro', code:'CS' },
      { value:'Seychelles', code:'SC' },
      { value:'Sierra Leone', code:'SL' },
      { value:'Singapore', code:'SG' },
      { value:'Slovakia', code:'SK' },
      { value:'Slovenia', code:'SI' },
      { value:'Solomon Islands', code:'SB' },
      { value:'Somalia', code:'SO' },
      { value:'South Africa', code:'ZA' },
      { value:'South Georgia and the South Sandwich Islands', code:'GS' },
      { value:'Spain', code:'ES' },
      { value:'Sri Lanka', code:'LK' },
      { value:'Sudan', code:'SD' },
      { value:'Suriname', code:'SR' },
      { value:'Svalbard and Jan Mayen', code:'SJ' },
      { value:'Swaziland', code:'SZ' },
      { value:'Sweden', code:'SE' },
      { value:'Switzerland', code:'CH' },
      { value:'Syrian Arab Republic', code:'SY' },
      { value:'Taiwan, Province of China', code:'TW' },
      { value:'Tajikistan', code:'TJ' },
      { value:'Tanzania, United Republic of', code:'TZ' },
      { value:'Thailand', code:'TH' },
      { value:'Timor-Leste', code:'TL' },
      { value:'Togo', code:'TG' },
      { value:'Tokelau', code:'TK' },
      { value:'Tonga', code:'TO' },
      { value:'Trinidad and Tobago', code:'TT' },
      { value:'Tunisia', code:'TN' },
      { value:'Turkey', code:'TR' },
      { value:'Turkmenistan', code:'TM' },
      { value:'Turks and Caicos Islands', code:'TC' },
      { value:'Tuvalu', code:'TV' },
      { value:'Uganda', code:'UG' },
      { value:'Ukraine', code:'UA' },
      { value:'United Arab Emirates', code:'AE' },
      { value:'United Kingdom', code:'GB' },
      { value:'United States', code:'US' },
      { value:'United States Minor Outlying Islands', code:'UM' },
      { value:'Uruguay', code:'UY' },
      { value:'Uzbekistan', code:'UZ' },
      { value:'Vanuatu', code:'VU' },
      { value:'Venezuela', code:'VE' },
      { value:'Viet Nam', code:'VN' },
      { value:'Virgin Islands, British', code:'VG' },
      { value:'Virgin Islands, U.S.', code:'VI' },
      { value:'Wallis and Futuna', code:'WF' },
      { value:'Western Sahara', code:'EH' },
      { value:'Yemen', code:'YE' },
      { value:'Zambia', code:'ZM' },
      { value:'Zimbabwe', code:'ZW' }
    ],
    dropdown : {
        enabled: 1, // suggest tags after a single character input
        classname : 'extra-properties' // custom class for the suggestions dropdown
    } // map tags' values to this property name, so this property will be the actual value and not the printed value on the screen
})

tagify.on('click', function(e){
    console.log(e.detail);
});

tagify.on('remove', function(e){
    console.log(e.detail);
});

tagify.on('add', function(e){
    console.log( "original Input:", tagify.DOM.originalInput);
    console.log( "original Input's value:", tagify.DOM.originalInput.value);
    console.log( "event detail:", e.detail);
});

// add the first 2 tags and makes them readonly
var tagsToAdd = tagify.whitelist.slice(0, 2)
tagify.addTags(tagsToAdd)

})()
</script>


<script data-name='readonly'>
(function(){
var input = document.querySelector('input[name=tags4]'),
    tagify = new Tagify(input);
})()
</script>


<script data-name='readonly-mixed'>
(function(){
var input = document.querySelector('input[name=tags-readonly-mix]'),
    tagify = new Tagify(input);
})()
</script>

<script data-name='disabled'>
    (function(){
    var input = document.querySelector('input[name=disabledInput]'),
        tagify = new Tagify(input);
    })()
</script>


<script data-name='drag-sort'>
(function(){
var input = document.querySelector('input[name=drag-sort]'),
    tagify = new Tagify(input);

// using 3-party script "dragsort"
// https://github.com/yairEO/dragsort
var dragsort = new DragSort(tagify.DOM.scope, {
    selector:'.'+tagify.settings.classNames.tag,
    callbacks: {
        dragEnd: onDragEnd
    }
})

function onDragEnd(elm){
    tagify.updateValueByDOMTags()
}
})()
</script>




<script data-name='mode-select'>
(function(){
var input = document.querySelector('input[name=tags-select-mode]'),
    tagify = new Tagify(input, {
        enforceWhitelist: true,
        mode : "select",
        whitelist: ["first option", "second option", "third option"],
        blacklist: ['foo', 'bar'],
    })

// bind events
tagify.on('add', onAddTag)
tagify.DOM.input.addEventListener('focus', onSelectFocus)

function onAddTag(e){
    console.log(e.detail)
}

function onSelectFocus(e){
    console.log(e)
}
})()
</script>




<script data-name='jQuery'>
(function(){
var $input = $('input[name=tags-jquery]')
    .tagify({
            whitelist : [
                {"id":1, "value":"some string"}
            ]
        })
        .on('add', function(e, tagName){
            console.log('JQEURY EVENT: ', 'added', tagName)
        })
        .on("invalid", function(e, tagName) {
            console.log('JQEURY EVENT: ',"invalid", e, ' ', tagName);
        });

// get the Tagify instance assigned for this jQuery input object so its methods could be accessed
var jqTagify = $input.data('tagify');

// bind the "click" event on the "remove all tags" button
$('.tags-jquery--removeAllBtn').on('click', jqTagify.removeAllTags.bind(jqTagify))
})()
</script>
    <script>
        window.Prism = window.Prism || {};
        window.Prism.manual = true;
        setTimeout(function(){
            Prism.highlightAll();
        }, 500)
    </script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism.min.css">
    <script src='https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/prism.min.js'></script>


    <script src='https://unpkg.com/@yaireo/knobs'></script>
    <script>
     (function(){
        var settings = {
            theme: {
                flow: "compact"
            },
            live: false,
            // 0 - starts as hidden, 1 - starts as visible, 2 - always visible
            visible: 1,
            CSSVarTarget: document.querySelectorAll('.tagify'),
            knobs: [
                {
                    label: 'Show Original Input Element',
                    type: 'checkbox',
                    checked: false,
                    onChange(e){
                        document.body.classList[e.target.checked ? 'add' : 'remove']('showOriginal')
                    }
                },
                "Sizes",
                {
                    cssVar: ['tag-pad', 'em'],
                    label: 'tag-pad',
                    type: 'range',
                    value: .5, min: 0, max: 1.5, step: 0.01,
                },
                {
                    cssVar: ['tag-inset-shadow-size', 'em'],
                    label: 'tag-inset-shadow-size',
                    type: 'range',
                    min: 0, max: 2 , step:.1,
                },
                {
                    cssVar: ['tag--min-width', 'ch'],
                    label: 'tag--min-width',
                    type: 'range',
                    value: 1,
                    min: 0,
                    max: 20,
                },
                {
                    cssVar: ['tag--max-width', 'ch'],
                    label: 'tag--max-width',
                    type: 'range',
                    value: 'auto',
                    min: 1,
                    max: 20,
                },
                {
                    cssVar: ['loader-size', 'em'],
                    label: 'loader-size',
                    type: 'range',
                    value: 'auto',
                    min:.1,
                    max: 1.4,
                    step: 0.05
                },
                "Colors",
                {
                    cssVar: ['tag-bg'],
                    label: 'tag-bg',
                    type: 'color',
                    value: '#E5E5E5',
                },
                {
                    cssVar: ['tag-hover'],
                    label: 'tag-hover',
                    type: 'color',
                    value: '#D3E2E2',
                },
                {
                    cssVar: ['tags-border-color'],
                    label: 'tags-border-color',
                    type: 'color',
                    value: '#E5E5E5',
                },
                {
                    cssVar: ['tags-hover-border-color'],
                    label: 'tags-hover-border-color',
                    type: 'color',
                    value: '#CCCCCC',
                },
                {
                    cssVar: ['tags-focus-border-color'],
                    label: 'tags-focus-border-color',
                    type: 'color',
                    value: '#85C8EA',
                },
                {
                    cssVar: ['tag-text-color'],
                    label: 'tag-text-color',
                    type: 'color',
                    value: '#000000',
                },
                {
                    cssVar: ['tag-text-color--edit'],
                    label: 'tag-text-color--edit',
                    type: 'color',
                    value: '#000000',
                },
                {
                    cssVar: ['tag-remove-bg'],
                    label: 'tag-remove-bg',
                    type: 'color',
                    value: '#D39494',
                },
                {
                    cssVar: ['tag-remove-btn-bg'],
                    label: 'tag-remove-btn-bg',
                    type: 'color',
                    value: 'none',
                },
                {
                    cssVar: ['tag-remove-btn-bg--hover'],
                    label: 'tag-remove-btn-bg--hover',
                    type: 'color',
                    value: '#C77777',
                },
                {
                    cssVar: ['tag-invalid-color'],
                    label: 'tag-invalid-color',
                    type: 'color',
                    value: '#D39494',
                },
                {
                    cssVar: ['tag-invalid-bg'],
                    label: 'tag-invalid-bg',
                    type: 'color',
                    value: '#D39494',
                },
                {
                    cssVar: ['placeholder-color'],
                    label: 'placeholder-color',
                    type: 'color',
                    value: 'rgba(0,0,0,.4)',
                },
                {
                    cssVar: ['placeholder-color-focus'],
                    label: 'placeholder-color-focus',
                    type: 'color',
                    value: 'rgba(0,0,0,.25)',
                },
                {
                    cssVar: ['input-color'],
                    label: 'input-color',
                    type: 'color',
                    value: '#000000',
                },
            ]
        }

        var knobs = new Knobs(settings)

        knobs.settings.live = true

        setTimeout(knobs.toggle.bind(knobs), 2000)
     })()
    </script>
    </body>
</html>

 

See also  Koa.js Tutorial to Send or Download a File inside Browser Using Javascript Full Project For Beginners

 

DOWNLOAD FULL SOURCE CODE

 

 

Leave a Reply