UNPKG

bootstrap5-tags

Version:

Replace select[multiple] with nices badges for Bootstrap 5

1,454 lines 67.5 kB
<!DOCTYPE html>
<html lang="en" class="no-js" data-bs-theme="">

<head>
  <title>Bootstrap 5 tags demo</title>

  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="color-scheme" content="light dark" />

  <meta name="theme-color" content="#111111" media="(prefers-color-scheme: light)" />
  <meta name="theme-color" content="#eeeeee" media="(prefers-color-scheme: dark)" />

  <link rel="preconnect" href="https://fonts.googleapis.com" />
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
  <link href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro&display=swap" rel="stylesheet" />

  <!-- jquery is NOT required but it should work with it -->
  <script src="https://code.jquery.com/jquery-3.7.0.min.js" integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g="
    crossorigin="anonymous"></script>

  <!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.rtl.min.css" rel="stylesheet" /> -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
  <!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap-dark-5@1/dist/css/bootstrap-dark.min.css" rel="stylesheet" /> -->
  <!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css" rel="stylesheet" /> -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" type="module"></script>
  <script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js" type="module"></script>
  <script src="https://cdn.jsdelivr.net/npm/bs-companion@1.3.2/static/dist/bs-companion.min.js" type="module"></script>
  <script type="module">
    import Tags from "./tags.js";
    import JustValidate from "https://cdn.jsdelivr.net/npm/just-validate@4.2.0/+esm";

    window.myFilter = (str) => {
      return str.replace(/[^a-z0-9]/gi, '');
    }

    // callbacks can be nested
    window['app'] = {
      cityResponse: (promise, inst) => {
        const data = [
          { "state": "Texas", "city": "Houstan" },
          { "state": "Texas", "city": "San Antonio" },
          { "state": "California", "city": "Los Angeles" },
          { "state": "California", "city": "San Diego" }
        ];

        if (inst.config('labelField') == "state") {
          const unique = [];
          return data.filter((el, idx) => {
            if (unique.indexOf(el.state) === -1) {
              unique.push(el.state);
              return true
            }
            return false;
          })
        }
        return data;
      }
    }

    function confirmDialog(msg) {
      return new Promise(function (resolve, reject) {
        let confirmed = window.confirm(msg);

        return confirmed ? resolve(true) : reject(false);
      });
    }

    // These need to be define before init
    window["customItemFormat"] = function (item, label) {
      return label + " (" + item.value + ")";
    };
    window["customOnCreate"] = function (option, inst) {
      console.log("new item", option.value, inst);
      // attach tooltip dynamically
      option.setAttribute('title', 'this element is created dynamically');
    };

    window["emailRender"] = (item, label) => {
      return item.data.name + " &lt;" + label + "&gt;";
    };
    window["emailCanAdd"] = (text, data, inst) => {
      const name = data.name ?? null;
      const vals = inst.getSelectedValues();
      // Cannot email both of them
      if (text === "ms.x@mycompany.com" && vals.indexOf("mr.x@mycompany.com") !== -1) {
        toaster("Cannot email both of them");
        return false;
      }
      if (text === "mr.x@mycompany.com" && vals.indexOf("ms.x@mycompany.com") !== -1) {
        toaster("Cannot email both of them");
        return false;
      }
      return true;
    };
    window["emailConfirmClear"] = (text, inst) => {
      return confirmDialog("Are you sure you want to remove " + text + " ?");
    }
    window["emailConfirmAdd"] = (text, inst) => {
      return confirmDialog("Are you sure you want to add " + text + " ?");
    }

    const validator = new JustValidate("#just_form");
    validator.onSuccess((event) => {
      console.log("just validate", event);
      event.currentTarget.submit();
    });
    validator.onFail((fields) => {
      console.log("just validate", fields);
    });
    validator.addField(document.querySelector("#just_validate"), [
      {
        rule: "required",
      },
    ]);
    validator.addField("#basic_name", [
      {
        rule: "required",
      },
      {
        rule: "minLength",
        value: 3,
      },
      {
        rule: "maxLength",
        value: 15,
      },
    ]);

    Tags.init("select:not(.ignore-tags)", {
      clearLabel: "Clear tag",
      allowClear: true,
      suggestionThresold: 0,
      onDataLoaded: (src) => {
        console.log("Loaded", src);
      },
      onClearItem: (v) => {
        console.log(`Cleared ${v}`);
      },
      onSelectItem: (item) => {
        console.log("selected", item);
      },
    });

    function sortSelect(elem, sort) {
      var tmp = [];
      var selectedValue = elem[elem.selectedIndex].value;
      for (var i = 0; i < elem.options.length; i++) {
        tmp.push(elem.options[i]);
      }
      tmp.sort(function (a, b) {
        if (sort.indexOf(a.value) === -1) {
          return tmp.length;
        }
        return sort.indexOf(a.value) - sort.indexOf(b.value);
      });
      while (elem.options.length > 0) {
        elem.options[0] = null;
      }
      for (var i = 0; i < tmp.length; i++) {
        elem.options[i] = tmp[i];
      }
    }

    const validationTags = document.querySelector("#validationTags");
    const example1 = validationTags.parentElement.querySelector("div.form-control").querySelector("div");
    new Sortable(example1, {
      animation: 150,
      filter: "input",
      draggable: "span",
      ghostClass: "blue-background-class",
      onEnd: function (evt) {
        var itemEl = evt.item; // dragged HTMLElement
        var oldIndex = evt.oldIndex; // element's old index within old parent
        var newIndex = evt.newIndex; // element's new index within new parent

        // Sort options according to tag orders
        if (oldIndex != newIndex) {
          const indexes = Array.from(validationTags.parentElement.querySelectorAll("span.badge")).map((badge) => {
            return (badge.dataset && badge.dataset.value) || -1;
          });
          sortSelect(validationTags, indexes);
        }
      },
    });

    // Multiple inits should not matter
    Tags.init("select:not(.ignore-tags), .bs-tags");

    document.addEventListener("change", (event) => {
      console.log(`document listener: #${event.target.id}`);
    });

    // Reset does not fire a change input
    document.getElementById("regular").addEventListener("change", function (ev) {
      console.log(this.selectedOptions);
    });

    // Changed is fired properly and you can getInstance if needed
    document.getElementById("validationTags").addEventListener("change", function (ev) {
      /** @type {Tags} */
      let inst = Tags.getInstance(this);
      console.log(inst.getSelectedValues(), this.selectedOptions);
    });
    document.getElementById("singleTags").addEventListener("change", function (ev) {
      console.log(this.value);
    });

    document.querySelector(".toggle-enable").addEventListener("click", function (ev) {
      const el = document.getElementById("disabledTags");
      el.disabled = false;
      // It will automatically remove the disabled attr
      // if (el.hasAttribute("disabled")) {
      //   el.removeAttribute("disabled");
      // }
      Tags.getInstance(el).resetState();
      console.log("is disabled", Tags.getInstance(el).isDisabled());
    });
    document.querySelector(".toggle-disable").addEventListener("click", function (ev) {
      const el = document.getElementById("validationTags");
      if (el.hasAttribute("disabled")) {
        el.removeAttribute("disabled");
      } else {
        el.setAttribute("disabled", "");
      }
      let inst = Tags.getInstance(el);
      inst.resetState();
    });
    document.querySelector(".toggle-disable2").addEventListener("click", function (ev) {
      const el = document.getElementById("validationTagsClear");
      if (el.hasAttribute("disabled")) {
        el.removeAttribute("disabled");
      } else {
        el.setAttribute("disabled", "");
      }
      let inst = Tags.getInstance(el);
      inst.resetState();
    });
    document.querySelector(".toggle-setitem").addEventListener("click", function (ev) {
      const el = document.getElementById("validationTagsClear");
      let inst = Tags.getInstance(el);
      inst.setItem(9);
    });
    document.querySelector("#setitem3").addEventListener("click", function (ev) {
      const el = document.getElementById("serverSideTags");
      let inst = Tags.getInstance(el);
      inst.setItem("server2");
    });

    document.querySelector("#toggle_orange_disabled").addEventListener("click", (ev) => {
      const el = document.getElementById("showDisabled");
      let inst = Tags.getInstance(el);
      const orangeOption = el.querySelector("option[value='5']");
      if (orangeOption.hasAttribute("disabled")) {
        orangeOption.removeAttribute("disabled");
        toaster("Orange enabled");
      } else {
        orangeOption.setAttribute("disabled", "");
        toaster("Orange disabled");
        inst.removeItem(5); // maybe you want to remove it if it was added?
      }
      inst.resetSuggestions(); // rebuild
    });

    document.querySelector(".add-option").addEventListener("click", function (ev) {
      // add an option
      const el = document.getElementById("validationTags");
      const c = el.querySelectorAll("option").length + 1;
      let opt = document.createElement("option");
      opt.setAttribute("value", "new_" + c);
      opt.innerText = "Option " + c;
      el.appendChild(opt);
      console.log(el);

      // reset
      /** @type {Tags} */
      let inst = Tags.getInstance(el);
      inst.resetSuggestions();
    });

    document.querySelector('.add-item').addEventListener('click', function (ev) {
      const el = document.getElementById("validationTags");
      /** @type {Tags} */
      let inst = Tags.getInstance(el);
      inst.addItem('test item');
    })

    document.querySelector(".dispose").addEventListener("click", function (ev) {
      const el = document.getElementById("validationTags");
      /** @type {Tags} */
      let inst = Tags.getInstance(el);
      inst.dispose();
    });
    document.querySelector(".clear-all").addEventListener("click", function (ev) {
      const el = document.getElementById("validationTags");
      /** @type {Tags} */
      let inst = Tags.getInstance(el);
      inst.removeAll();
    });

    document.querySelector("#darkmode").addEventListener("click", function (ev) {
      if (document.documentElement.dataset.bsTheme == "dark") {
        document.documentElement.dataset.bsTheme = "light";
      } else {
        document.documentElement.dataset.bsTheme = "dark";
      }
    });

    document.querySelector("#makebodyscrollable").addEventListener("click", (ev) => {
      document.querySelector("#main").style.display = "block";
    });

    document.querySelector("#show_suggestions").addEventListener("click", (ev) => {
      ev.preventDefault();

      const el = document.getElementById("inputGroupTags");
      /** @type {Tags} */
      let inst = Tags.getInstance(el);
      inst.toggleSuggestions(false);
    });

    document.querySelector('#add_option').addEventListener("click", (ev) => {
      ev.preventDefault();

      const input = document.getElementById('new_option');
      const v = input.value;
      if (!v) {
        alert('No value');
        return;
      }
      const el = document.getElementById('validationTagsNew');
      const inst = Tags.getInstance(el);
      inst.addItem(v);
    })


    // multiple items

    let items = [
      { "value": 1, "label": "American" },
      { "value": 2, "label": "Russian" },
      { "value": 3, "label": "French" },
      { "value": 4, "label": "English" },
      {
        "group": "my group",
        "items": [
          { "value": 5, "label": "Other 1" },
          { "value": 6, "label": "Other 2" },
        ]
      }
    ];
    let selected = [3, 4, 5];

    Tags.init("#multipleItems",
      {
        items: items,
        selected: selected
      });


    let optGroupsItems = [
      { "value": 1, "label": "first item" },
      {
        "group": "my group",
        "items": [
          {
            "value": "g1",
            "label": "Group Item 1",
          },
          {
            "value": "g2",
            "label": "Group Item 2",
          },
        ]
      },
      {
        "group": "other group",
        "items": [
          {
            "value": "o1",
            "label": "Other Item 1",
          },
          {
            "value": "o2",
            "label": "Other Item 2",
          },
        ]
      },
      { "value": "zz", "label": "last item" },
    ];
    Tags.init("#optgroupsItems",
      {
        items: optGroupsItems,
      });

    // Use native addOnBlur setting
    // document.querySelector('#addOnBlur').addEventListener('tags.blur', function(ev) {
    //   // detail: {selection: 'ID', input: 'SOME_INPUT'}
    //   const el = document.getElementById("addOnBlur");
    //   /** @type {Tags} */
    //   let inst = Tags.getInstance(el);
    //   if(ev.detail.input && inst.canAdd(ev.detail.input)) {
    //     inst.addItem(ev.detail.input);
    //     inst.resetSearchInput();
    //   }
    // });

    // Test dark mode (emulate in dev console => rendering => emulate)
    if (window.matchMedia) {
      const darkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;
      if (darkMode) {
        console.log("Dark mode");
      } else {
        console.log("Light mode");
      }
      window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
        if (e.matches) {
          console.log("Dark mode");
        } else {
          console.log("Light mode");
        }
      });
    }

    // Bootstrap 5 validation script using bs-companion
    FormValidator.init();
  </script>
  <style type="text/css">
    .source-sans {
      font-family: "Source Sans Pro", sans-serif;
    }

    .mybadge {
      margin-right: 0.5rem;
      padding: 0.25 0.5rem;
      font-size: 0.85rem;
      background: #333;
    }

    .my.test {
      background: palegoldenrod;
    }

    #main {
      width: 120vw;
      height: 20px;
      background: #eee;
    }

    /* build this with sass instead, see _tags.scss */
    .form-control-focus,
    .form-control:focus {
      color: var(--bs-body-color, #212529);
      background-color: var(--bs-form-control-bg, var(--bs-body-bg, #fff));
      border-color: rgba(var(--bs-primary-rgb, 13, 110, 253), 0.5);
      outline: 0;
      box-shadow: 0 0 0 var(--bs-focus-ring-width) rgba(var(--bs-primary-rgb, 13, 110, 253), 0.25);
    }

    .was-validated :valid+.form-control-focus,
    .was-validated :valid+.form-control:focus {
      border-color: var(--bs-success, #198754);
      box-shadow: 0 0 0 var(--bs-focus-ring-width) rgba(var(--bs-success-rgb, 25, 135, 84), 0.25);
    }

    .was-validated :invalid+.form-control-focus,
    .was-validated :invalid+.form-control:focus {
      border-color: var(--bs-danger, #dc3545);
      box-shadow: 0 0 0 var(--bs-focus-ring-width, 0.25rem) rgba(var(--bs-danger-rgb, 220, 53, 69), 0.25);
    }

    .form-floating .form-control.form-placeholder-shown:not(.form-control-focus)~label {
      opacity: unset;
      transform: unset;
    }

    .form-floating .form-control~label {
      z-index: unset;
    }

    .form-control-disabled {
      background-color: var(--bs-form-control-disabled-bg, var(--bs-secondary-bg, #e9ecef));
      opacity: 1;
    }

    .tags-menu mark {
      text-decoration: underline;
      background: none;
      color: currentColor;
      padding: 0;
    }

    .form-control.is-max-reached {
      background-image: none;
    }
  </style>
</head>

<body>
  <div id="main" style="display: none"></div>
  <div class="container">
    <h1>Demo</h1>

    <button id="darkmode">Toggle dark mode</button>

    <form class="needs-validation" novalidate method="get" action="https://vercel-dumper.vercel.app/">
      <div class="py-3">
        <input type="reset" value="Reset" class="btn btn-outline-dark" /> click reset to see values restored to their original state
        (including same values)
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="validationTags" class="form-label">Tags (check console to see selected values). It's sortable thanks to SortableJS (in
            demo, it breaks text selection) !</label>
          <div class="position-relative has-validation">
            <select class="form-select" id="validationTags" name="tags[]" multiple data-allow-clear="dsfds" data-allow-html="1" required>
              <option selected="selected" disabled hidden value="">Choose a tag...</option>
              <option value="1" selected="selected">Apple</option>
              <option value="2" selected="selected">Banana</option>
              <option value="2" selected="selected">Banana</option>
              <option value="2">Banana again</option>
              <!-- use allow same because of identical values -->
              <option value="3">Orange</option>
              <option value="4" disabled="disabled">Disabled</option>
              <option value="5">This is a tag that should not overflow out of the window</option>
              <option value="6">abc&lt;i&gt;efg&lt;/i&gt;</option>
            </select>
            <div class="invalid-tooltip">Please select a valid tag.</div>
          </div>
        </div>
        <div class="col-md-4">
          <button type="button" class="add-option">Add option</button>
          <button type="button" class="add-item">Add item</button>
          <button type="button" class="toggle-disable">Enable/disable</button>
          <button type="button" class="dispose">Dispose</button>
          <button type="button" class="clear-all">Clear all</button>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="validationTagsClear" class="form-label">Tags (allow clear + optgroup + tooltips + fuzzy)</label>
          <select class="form-select" id="validationTagsClear" name="tagsClear[]" multiple data-allow-clear="true" data-fuzzy="true"
            required>
            <option disabled hidden value="">Choose a tag...</option>
            <optgroup label="fruits">
              <option value="1" selected="selected" title="my tooltip">Apple</option>
              <option value="2" title="my tooltip for banana">Banana</option>
              <option value="2" title="my tooltip for banana">Banana</option>
              <option value="2" title="my tooltip for banana">Banana 2 same value</option>
              <option value="3" title="my tooltip">Orange</option>
            </optgroup>
            <optgroup label="vegetables">
              <option value="4" title="my tooltip for disabled item" disabled>Broccoli</option>
              <option value="5" title="my tooltip">Lettuce</option>
              <option value="6" title="my tooltip">Onions</option>
            </optgroup>
            <optgroup label="berries">
              <option value="7" title="my tooltip">Raspberry</option>
              <option value="8" title="my tooltip">Cranberry</option>
              <option value="9" title="my tooltip">Blackberry</option>
            </optgroup>
          </select>
          <div class="invalid-feedback">Please select a valid tag.</div>
        </div>
        <div class="col-md-4">
          <button type="button" class="toggle-disable2">Enable/disable</button>
          <button type="button" class="toggle-setitem">Set item</button>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="showDisabled" class="form-label">Tags (show disabled + allow html)</label>
          <select class="form-select" id="showDisabled" name="showDisabled[]" multiple data-allow-clear="true" data-show-disabled="true"
            data-allow-html="1">
            <option disabled hidden value="">Choose a tag...</option>
            <option value="1" selected="selected">Apple</option>
            <option value="2">Banana</option>
            <option value="3" disabled selected="selected">Banana (disabled)</option>
            <option value="4">Orange</option>
            <option value="5" disabled>Orange (disabled)</option>
            <option value="6" selected="selected">abc&lt;i&gt;efg&lt;/i&gt;</option>
            <option value="7" selected="selected">a very long item that can be truncated</option>
          </select>
          <div class="invalid-feedback">Please select a valid tag.</div>
        </div>
        <div class="col-md-4">
          <button id="toggle_orange_disabled" type="button">Toggle orange disabled</button>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="validationTagsThreshold" class="form-label">Tags (allow clear + 1 threshold + custom active classes)</label>
          <select class="form-select" id="validationTagsThreshold" name="tagsClearThreshold[]" multiple data-allow-clear="true"
            data-active-classes="my,test,classes" data-suggestions-threshold="1">
            <option disabled hidden value="">Choose a tag...</option>
            <option value="1" selected="selected">Apple</option>
            <option value="2">Banana</option>
            <option value="3">Orange</option>
          </select>
          <div class="invalid-feedback">Please select a valid tag.</div>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="validationTagsShow" class="form-label">Tags (show all + custom colors)</label>
          <select class="form-select" id="validationTagsShow" name="tags_show[]" multiple data-show-all-suggestions="true">
            <option disabled hidden value="">Choose a tag...</option>
            <option value="1" selected="selected">Apple</option>
            <option value="2" data-badge-style="success" selected="selected">Banana</option>
            <option value="3" data-badge-style="warning" data-badge-class="text-dark another-class">Orange</option>
            <option value="4" data-badge-style="secondary">Blueberry with a very long label that pushes the menu</option>
            <option value="5">Strawberry</option>
            <option value="6">Cranberry</option>
            <option value="7">Huckleberry</option>
            <option value="8">Chokeberry</option>
            <option value="9">Elderberry</option>
            <option value="10">Gooseberry</option>
            <option value="11">Blackberry</option>
            <option value="12">Raspberry</option>
            <option value="13">Goji berry</option>
            <option value="14">Salmon berry</option>
            <option value="15">
              Sumac berry that doesn't even fit on a mobile screen because this labe is not reasonable and should be limited
            </option>
          </select>
          <div class="invalid-feedback">Please select a valid tag.</div>
        </div>
        <div class="col-md-4">
          You can also try with non ascii chars: <br />
          <code>ㅂㅈㄷㄱㅅㅁㄴㅇㄹㅎㅋㅌㅊ</code>
        </div>
      </div>
      <!-- you can change color with css variables ! -->
      <div class="row mb-3 g-3" style="--bs-primary-rgb: 25, 135, 84">
        <div class="col-md-4">
          <label for="validationTagsNew" class="form-label">Tags (allow new + green primary color + starts with + filter)</label>
          <select class="form-select" id="validationTagsNew" name="tags_new[]" multiple data-allow-new="true" data-starts-with="true"
            data-input-filter="myFilter" data-not-found-message="Type the start of the string">
            <option disabled hidden value="">Choose a tag...</option>
            <option value="1" selected="selected">Apple</option>
            <option value="2">Banana</option>
            <option value="3">Orange</option>
          </select>
          <div class="invalid-feedback">Please select a valid tag.</div>
        </div>
        <div class="col-md-4">
          <input type="text" id="new_option"> <button id="add_option">add option</button>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="itemsInput" class="form-label">Passing items in config</label>
          <select class="form-select bs-tags" id="itemsInput" data-allow-new="true"
            data-config='{"items": [{"value":1, "label": "Value 1", "selected": true}, {"value":2, "label": "Value 2", "disabled": true}]}'>
          </select>
        </div>
        <div class="col-md-4">
          <label for="multipleItems" class="form-label">Multiple items</label>
          <select class="form-select ignore-tags" id="multipleItems" name="tags[]" multiple>
            <option selected disabled hidden value="">Choose a tag...</option>
          </select>
        </div>
        <div class="col-md-4">
          <label for="optgroupsItems" class="form-label">Optgroups items</label>
          <select class="form-select ignore-tags" id="optgroupsItems" name="tags[]" multiple>
            <option selected disabled hidden value="">Choose a tag...</option>
          </select>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="itemsInputObj" class="form-label">Passing items + object as items</label>
          <select type="text" class="form-control bs-tags" id="itemsInputObj" data-allow-new="true"
            data-config='{"items": {"1": "v1", "2": "v2"}, "selected": "1"}'></select>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="validationTagsNewSame" class="form-label">Tags (allow new + same)</label>
          <select class="form-select" id="validationTagsNewSame" name="tags_new[]" multiple data-allow-new="true" data-allow-same="true">
            <option disabled hidden value="">Choose a tag...</option>
            <option value="1" selected="selected">Apple</option>
            <option value="2">Banana</option>
            <option value="3">Orange</option>
          </select>
          <div class="invalid-feedback">Please select a valid tag.</div>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="regexTags" class="form-label">Tags (allow new only if it matches regex) + confirm</label>
          <select class="form-select" id="regexTags" name="tags_regex[]" multiple data-allow-new="true" data-regex=".*@mycompany\.com$"
            data-on-render-item="emailRender" data-on-can-add="emailCanAdd" data-confirm-add="emailConfirmAdd"
            data-confirm-clear="emailConfirmClear" data-separator="|,|">
            <option disabled hidden value="">Add mail address</option>
            <option value="info@mycompany.com" data-name="info" selected="selected">info@mycompany.com</option>
            <option value="mr.x@mycompany.com" data-name="Mr. X">mr.x@mycompany.com</option>
            <option value="ms.x@mycompany.com" data-name="Ms. X">ms.x@mycompany.com</option>
            <option value="some_value" data-name="no name">Some invalid yet callable input</option>
          </select>
          <div class="invalid-feedback">Please select only @mycompany.com addresses.</div>
        </div>
        <div class="col-md-4">
          <label for="regexTagsNoNew" class="form-label">Tags (matches regex, don't allow new)</label>
          <select class="form-select" id="regexTagsNoNew" name="tags_regex_no_new[]" multiple data-regex=".*@mycompany\.com$">
            <option disabled hidden value="">Add mail address</option>
            <option value="1" selected="selected">info@mycompany.com</option>
            <option value="2">mr.x@mycompany.com</option>
            <option value="3">ms.x@mycompany.com</option>
          </select>
          <div class="invalid-feedback">Please select only @mycompany.com addresses.</div>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="separatorTags" class="form-label">Tags (with space and comma separator)</label>
          <select class="form-select" id="separatorTags" name="tags_separator[]" multiple data-allow-new="true" data-separator=" |,|  ">
            <option value="">Type a tag...</option>
            <!-- you need at least one option with the placeholder -->
          </select>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="maxTags" class="form-label">Tags (max 2 tags + clear)</label>
          <select class="form-select" id="maxTags" name="tags_max[]" multiple data-allow-new="true" data-max="2" data-allow-clear="1"
            data-suggestions-threshold="0">
            <option value="">ㅂㅈㄷㄱㅅㅁㄴㅇㄹㅎㅋㅌㅊ...</option>
            <!-- you need at least one option with the placeholder -->
            <option value="1">Apple</option>
            <option value="2">Banana</option>
            <option value="3">Orange</option>
          </select>
        </div>
        <div class="col-md-4">
          <label for="maxTags2" class="form-label">Tags (max 2 tags + clear - already set)</label>
          <select class="form-select" id="maxTags2" name="tags_max2[]" multiple data-allow-new="true" data-max="2" data-allow-clear="1"
            data-suggestions-threshold="0">
            <option value="">Type a tag...</option>
            <!-- you need at least one option with the placeholder -->
            <option value="1" selected>Apple</option>
            <option value="2" selected>Banana</option>
            <option value="3">Orange</option>
          </select>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="maxTagsBigger" class="form-label">Tags (max 2 tags + clear), but bigger!</label>
          <select class="form-select form-select-lg" id="maxTagsBigger" name="tags_max_bigger[]" multiple data-allow-new="true" data-max="2"
            data-allow-clear="1" data-suggestions-threshold="0">
            <option value="">ㅂㅈㄷㄱㅅㅁㄴㅇㄹㅎㅋㅌㅊ...</option>
            <!-- you need at least one option with the placeholder -->
            <option value="1">Apple</option>
            <option value="2">Banana</option>
            <option value="3">Orange</option>
          </select>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <label for="max1Tags" class="form-label">Tags (max 1 tag + clear)</label>
          <select class="form-select" id="max1Tags" name="tags_max1[]" multiple data-allow-new="true" data-max="1" data-allow-clear="1"
            data-suggestions-threshold="0">
            <option value="">Type a tag...</option>
            <!-- you need at least one option with the placeholder -->
            <option value="1">Apple</option>
            <option value="2">Banana</option>
            <option value="3">Orange</option>
          </select>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="addOnBlur" class="form-label">Add on blur (+ keep open)</label>
            <select class="form-select" id="addOnBlur" name="addOnBlur[]" multiple data-allow-new="true" data-allow-clear="1"
              data-add-on-blur="1" data-keep-open="1" data-suggestions-threshold="0">
              <option value="">Type a tag...</option>
              <!-- you need at least one option with the placeholder -->
              <option value="1">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
            </select>
            <div class="invalid-feedback">Please select a valid tag.</div>
          </div>
          <div class="col-md-4">
            <label for="addOnBlurValidation" class="form-label">Add on blur (validation)</label>
            <select class="form-select" id="addOnBlurValidation" name="addOnBlurValidation[]" multiple data-allow-clear="1"
              data-add-on-blur="1" data-separator=" |,|  " data-suggestions-threshold="0">
              <option value="">Type a tag...</option>
              <!-- you need at least one option with the placeholder -->
              <option value="1">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
            </select>
            <div class="invalid-feedback">Please select a valid tag.</div>
          </div>
          <div class="col-md-4">
            <label for="addOnBlurValidationRegex" class="form-label">Add on blur (validation + email regex)</label>
            <select class="form-select" id="addOnBlurValidationRegex" name="addOnBlurValidationRegex[]" multiple data-allow-new="true"
              data-add-on-blur="true" data-separator="| , |" data-allow-clear="1" data-badge-style="secondary"
              data-regex="^[^\s@]+@[^\s@]+\.[^\s@]+$" data-max="1">
              <option value="">Type a tag...</option>
            </select>
            <div class="invalid-feedback">Please select a valid tag.</div>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="updateOnSelect" class="form-label">Update on select + not found message + max 2 items displayed + custom format +
              custom
              create callback</label>
            <select class="form-select" id="updateOnSelect" name="updateOnSelect[]" multiple data-allow-new="true" data-allow-clear="1"
              data-add-on-blur="1" data-update-on-select="1" data-autoselect-first="0" data-not-found-message="Create a new tag '{{tag}}' ?"
              data-suggestions-threshold="0" data-maximum-items="2" data-on-render-item="customItemFormat"
              data-on-create-item="customOnCreate">
              <option value="">Type a tag...</option>
              <!-- you need at least one option with the placeholder -->
              <option value="1">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
              <option value="4">Orange 2</option>
              <option value="5">Orange 3</option>
              <option value="6">Orange 4</option>
              <option value="7">Orange 5</option>
            </select>
          </div>
        </div>
        <div class="py-3">
          <input type="reset" value="Reset" class="btn btn-outline-dark" /> click reset to see values restored to their original state
          (including same values)
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="tagsMaxReached" class="form-label">Tags (max 2 already reached)</label>
            <select class="form-control" id="tagsMaxReached" name="tagsMaxReached" multiple data-allow-clear="true"
              data-suggestions-threshold="0" data-max="2">
              <option selected disabled hidden value="">Choose</option>
              <option value="1" selected="selected">111</option>
              <option value="2" selected="selected">222</option>
              <option value="3" selected="selected">333</option>
              <option value="4">444</option>
              <option value="5">555</option>
            </select>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="serverSideTags" class="form-label">Tags (onload server side + preselected values + search fields)</label>
            <select class="form-select" id="serverSideTags" name="server_side_tags[]" multiple data-allow-new="true" data-server="demo.json"
              data-search-fields="value,label" data-selected="server1,server2">
              <option disabled hidden value="">Choose a tag...</option>
            </select>
          </div>
          <div class="col-md-4">
            <button id="setitem3">Set item with server</button>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="searchFieldsTags" class="form-label">Tags with custom search fields</label>
            <select class="form-select" id="searchFieldsTags" name="searchFieldsTags[]" placeholder="choose item">
            </select>
            <script type="module">
              import Tags from "./tags.js";

              const data = [
                { QIP_NO: "0001", QIP_NAME: "A", QIP_Product: "X" },
                { QIP_NO: "0002", QIP_NAME: "B", QIP_Product: "Y" },
                { QIP_NO: "0003", QIP_NAME: "C", QIP_Product: "Z" }
              ];

              // Init can reset instance
              Tags.init("#searchFieldsTags", {
                items: data,
                labelField: "QIP_NAME",
                valueField: "QIP_NO",
                searchFields: ["QIP_NO", "QIP_NAME", "QIP_Product"],
                onRenderItem: (item) => `${item.QIP_NO}-${item.QIP_NAME}-${item.QIP_Product}`
              }, true)

              document.querySelector('#setitem').addEventListener('click', (ev) => {
                Tags.getInstance(document.querySelector('#searchFieldsTags')).setItem(["0001"])
              })

            </script>
          </div>
          <div class="col-md-4">
            <button id="setitem">Set item</button>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="serverSideTagsSingle" class="form-label">Tags (onload server side + single value)</label>
            <select multiple name="person" data-placeholder="Start typing" id="serverSideTagsSingle" data-server="demo-single.json"
              data-show-all-suggestions="1" data-suggestions-threshold="0" data-allow-clear="1" data-max="1">
              <option disabled hidden value="">Choose a person</option>
            </select>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="serverSideTagsSelected" class="form-label">Tags (onload server side + selected value)</label>
            <select multiple name="person2" data-placeholder="Start typing" id="serverSideTagsSelected" data-server="demo-two.json"
              data-show-all-suggestions="1" data-suggestions-threshold="0" data-allow-clear="1">
              <option disabled hidden value="">Choose a person</option>
            </select>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="validationTagsJson" class="form-label">Tags (live server side + keep open + full width false)</label>
            <select class="form-select" id="validationTagsJson" name="tags_json[]" multiple data-allow-new="true" data-server="demo.json"
              data-live-server="1" data-server-params='{"key":"val"}' data-keep-open="1" data-full-width="0">
              <option disabled hidden value="">Choose a tag...</option>
              <!-- <option value="server1" selected>Server 1</option> -->
            </select>
          </div>
          <div class="col-md-4">
            <button type="button" id="upparams">Update params</button>
            <script type="module">
              document.getElementById('upparams').addEventListener('click', (e) => {
                let inst = document.getElementById('validationTagsJson');
                inst.dataset.serverParams = '{"key": "' + Date.now() + '"}';
              })
            </script>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="liveInitialValue" class="form-label">Tags (live server side + initial value)</label>
            <select class="form-select" id="liveInitialValue" name="tags_live_initial[]" multiple data-allow-new="true" data-allow-same="false"
              data-server="demo.json" data-live-server="1" data-items='{"some": "some", "value": "value"}' data-selected="some,value"
              data-server-params='{"key":"val"}'>
              <option disabled hidden value="">Choose a tag...</option>
            </select>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="liveInitialValueHtml" class="form-label">Tags (live server side + initial value from html)</label>
            <select class="form-select" id="liveInitialValue" name="tags_live_initial[]" multiple data-allow-new="true"
              data-server="demo.json" data-live-server="1"
              data-server-params='{"key":"val"}'>
              <option disabled hidden value="">Choose a tag...</option>
              <option value="some" selected="selected">some</option>
              <option value="value" selected="selected">value</option>
            </select>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="emptyTags" class="form-label">Tags (empty + hide drop icon is done automatically)</label>
            <select class="form-select" id="emptyTags" name="tags_empty[]" multiple data-allow-new="true" placeholder="Type a tag"></select>
            <!-- you can use the placeholder or data-placeholder attribute instead -->
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="disabledTags" class="form-label">Tags (disabled)</label>
            <select class="form-select" id="disabledTags" name="tags_disabled[]" multiple disabled data-allow-new="true"
              data-allow-clear="1">
              <option disabled hidden value="">Choose a tag...</option>
              <option value="1" selected="selected">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
            </select>
          </div>
          <div class="col-md-4">
            <button type="button" class="toggle-enable">Enable</button>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="singleTags" class="form-label">Tags (single - replace on select)</label>
            <select class="form-select" id="singleTags" name="tags_single" data-allow-clear="0">
              <option value="">Choose a tag...</option>
              <option value="1">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
            </select>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="tags_city" class="form-label">Tags (city)</label>
            <select class="form-select" id="tags_city" name="tags_city" data-allow-clear="1" data-suggestions-threshold="0"
              data-label-field="city" data-value-field="city" data-server="demo.json" data-on-server-response="app.cityResponse">
              <option value="">Choose a tag...</option>
            </select>
          </div>
          <div class="col-md-4">
            <label for="tags_state" class="form-label">Tags (state)</label>
            <select class="form-select" id="tags_state" name="tags_state" data-allow-clear="1" data-suggestions-threshold="0"
              data-label-field="state" data-value-field="state" data-server="demo.json" data-on-server-response="app.cityResponse">
              <option value="">Choose a tag...</option>
            </select>
          </div>
        </div>
        <div class="row mb-3 g-3 source-sans">
          <div class="col-md-4">
            <label for="sourceSansTags" class="form-label">Tags with custom font and custom class + clear end</label>
            <select class="form-select" id="sourceSansTags" name="sourceSansTags" multiple data-base-class="mybadge" data-clear-end="1"
              data-allow-clear="1" data-suggestions-threshold="0">
              <option value="">Choose a tag...</option>
              <option value="1" selected>Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
            </select>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="inputGroupTags" class="form-label">Tags in input group + highlight</label>
            <div class="input-group">
              <span class="input-group-text" id="basic-addon1">Tag</span>
              <select class="form-select" id="inputGroupTags" name="inputGroupTags[]" multiple data-allow-clear="1" data-highlight-typed="1"
                data-show-all-suggestions="1" required>
                <option value="">Choose a tag...</option>
                <option value="1">Apple</option>
                <option value="2">Banana</option>
                <option value="ban_2">Banana 2</option>
                <option value="ban_3">Banana 3</option>
                <option value="3">Orange</option>
                <option value="*crazy$<>value">*crazy$<>value</option>
                <option value="not=valid\">not=valid\</option>
              </select>
            </div>
          </div>
          <div class="col-md-4">
            <button id="show_suggestions">Show suggestions (external trigger)</button>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4">
            <label for="singleTagsFirst" class="form-label">Tags (single - first value selected by default)</label>
            <select class="form-select" id="singleTagsFirst" name="tags_single_first" data-allow-clear="1" data-suggestions-threshold="0"
              placeholder="Please select">
              <option value="1">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
            </select>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <div class="col-md-4" dir="rtl">
            <label for="rtlTags" class="form-label">Tags (rtl, not fixed)</label>
            <select class="form-select" id="rtlTags" name="rtlTags[]" multiple data-allow-clear="true" data-allow-new="true"
              data-clear-end="true">
              <option disabled hidden value="">Choose a tag...</option>
              <option value="1" selected="selected">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
              <option value="4">Orange 2</option>
              <option value="5">Orange 3</option>
              <option value="6">Orange 4</option>
              <option value="7">Orange 5</option>
              <option value="8">Orange 6</option>
            </select>
            <div class="invalid-feedback">Please select a valid tag.</div>
          </div>

          <div class="col-md-4" dir="rtl">
            <label for="rtlTags2" class="form-label">Tags (rtl, not fixed, full width false)</label>
            <select class="form-select" id="rtlTags2" name="rtlTags2[]" multiple data-allow-clear="true" data-full-width="0"
              data-allow-new="true">
              <option disabled hidden value="">Choose a tag...</option>
              <option value="1" selected="selected">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
              <option value="4">Orange 2</option>
              <option value="5">Orange 3</option>
              <option value="6">Orange 4</option>
              <option value="7">Orange 5</option>
              <option value="8">Orange 6</option>
            </select>
            <div class="invalid-feedback">Please select a valid tag.</div>
          </div>

          <div class="col-md-4" dir="rtl">
            <label for="rtlTags3" class="form-label">Tags (rtl, fixed)</label>
            <select class="form-select" id="rtlTags3" name="rtlTags3[]" multiple data-allow-clear="true" data-fixed="true">
              <option disabled hidden value="">Choose a tag...</option>
              <option value="1" selected="selected">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
            </select>
            <div class="invalid-feedback">Please select a valid tag.</div>
          </div>
        </div>
        <div class="row mb-3 g-3">
          <!-- it may NOT be positioned if it has a set position (relative, absolute, etc)-->
          <div class="col-md-4" style="height: 80px; background: #ccc; border: 1px solid #666; overflow: hidden">
            <label for="validationTagsClearInDiv" class="form-label">Tags (overflow, not fixed)</label>
            <select class="form-select" id="validationTagsClearInDiv" name="tagsClearInDiv[]" multiple data-allow-clear="true">
              <option disabled hidden value="">Choose a tag...</option>
              <option value="1" selected="selected">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
              <option value="4">Orange 2</option>
              <option value="5">Orange 3</option>
              <option value="6">Orange 4</option>
              <option value="7">Orange 5</option>
              <option value="8">Orange 6</option>
            </select>
            <div class="invalid-feedback">Please select a valid tag.</div>
          </div>
          <div class="col-md-4" style="height: 80px; background: #ccc; border: 1px solid #666; overflow: hidden; position: relative">
            <label for="tagsClearInFixedDiv" class="form-label">Tags fixed (overflow, fixed)</label>
            <select class="form-select" id="tagsClearInFixedDiv" name="tagsClearInFixedDiv[]" multiple data-allow-clear="true"
              data-fixed="true">
              <option disabled hidden value="">Choose a tag...</option>
              <option value="1" selected="selected">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
              <option value="4">Orange 2</option>
              <option value="5">Orange 3</option>
              <option value="6">Orange 4</option>
              <option value="7">Orange 5</option>
              <option value="8">Orange 6</option>
            </select>
            <div class="invalid-feedback">Please select a valid tag.</div>
          </div>
          <div class="col-md-4"
            style="height: 80px; width: 320px; background: #ccc; border: 1px solid #666; overflow: scroll; position: relative">
            <button id="makebodyscrollable">make body scrollable</button>
            <div style="margin: 25px 100px; width: 500px">
              <label for="tagsClearInFixedScrollingDiv" class="form-label">Tags fixed (scroll div)</label>
              <select class="form-select" id="tagsClearInFixedScrollingDiv" name="tagsClearInFixedScrollingDiv[]" multiple
                data-allow-clear="true" data-fixed="true" data-allow-new="true">
                <option disabled hidden value="">Choose a tag...</option>
                <option value="1" selected="selected">Apple</option>
                <option value="2">Banana</option>
                <option value="3">Orange</option>
                <option value="4">Orange 2</option>
                <option value="5">Orange 3</option>
                <option value="6">Orange 4</option>
                <option value="7">Orange 5</option>
                <option value="8">Orange 6</option>
              </select>
              <div class="invalid-feedback">Please select a valid tag.</div>
              <label for="tagsClearInFixedScrollingDivFullWidth" class="form-label">Tags fixed (scroll div full width false)</label>
              <select class="form-select" id="tagsClearInFixedScrollingDivFullWidth" name="tagsClearInFixedScrollingDivFullWidth[]" multiple
                data-allow-clear="true" data-fixed="true" data-full-width="false" data-allow-new="true">
                <option disabled hidden value="">Choose a tag...</option>
                <option value="1" selected="selected">Apple</option>
                <option value="2">Banana</option>
                <option value="3">Orange</option>
              </select>
              <div class="invalid-feedback">Please select a valid tag.</div>
            </div>
          </div>
        </div>
      </div>

      <!-- Button trigger modal -->
      <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">Works in modals too</button>

      <!-- Modal -->
      <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
        <div class="modal-dialog">
          <div class="modal-content">
            <div class="modal-body">
              <label for="scrollInModal" class="form-label">Scroll in modal</label>
              <select class="form-select" id="scrollInModal" name="scrollInModal[]" data-server="/some/url" data-server-params='{"id":"0"}'
                data-show-drop-icon="false" data-autoselect-first="false" data-allow-new="true" data-allow-clear="true"
                data-clear-end="true" data-show-disabled="true" data-add-on-blur="true" data-badge-style="secondary" multiple>
                <option disabled hidden value="">Choose a tag...</option>
                <option value="1" selected="selected">Apple</option>
                <option value="2">Banana</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
                <option value="3">Orange</option>
              </select>
              <div style="margin-left: 200px; margin-top: 200px">
                <table>
                  <tr>
                    <td><label for="tagsModals" class="form-label">Tags (allow clear)</label></td>
                    <td>
                      <select class="form-select" id="tagsModals" name="tagsModals[]" multiple data-allow-clear="true">
                        <option disabled hidden value="">Choose a tag...</option>
                        <option value="1" selected="selected">Apple</option>
                        <option value="2">Banana</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <option value="3">Orange</option>
                        <!-- should work for scroll -->
                      </select>
                      <div class="invalid-feedback">Please select a valid tag.</div>
                    </td>
                  </tr>
                </table>
              </div>
            </div>
          </div>
        </div>
      </div>

      <br />
      <br />

      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <div class="form-floating">
            <select class="form-select" id="tagsFloating" name="tagsFloating[]" multiple data-allow-clear="true">
              <option disabled hidden value=""><!-- don't use a placeholder!!! --></option>
              <option value="1" selected="selected">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
            </select>
            <!-- this needs to be placed just after the select !-->
            <label for="tagsFloating" class="form-label">Tags (floating label)</label>
            <div class="invalid-feedback">Please select a valid tag.</div>
          </div>
        </div>
      </div>
      <div class="row mb-3 g-3">
        <div class="col-md-4">
          <div class="form-floating">
            <select class="form-select" id="tagsFloatingInput" name="tagsFloatingInput[]" multiple data-allow-clear="true">
              <option disabled hidden value=""><!-- don't use a placeholder!!! --></option>
              <option value="1">Apple</option>
              <option value="2">Banana</option>
              <option value="3">Orange</option>
            </select>
            <label for="tagsFloatingInput" class="form-label">Tags (floating label)</label>
            <div class="invalid-feedback">Please select a valid tag.</div>
          </div>
        </div>
      </div>

      <br />
      <br />

      <input type="reset" value="Reset" class="btn btn-outline-dark" />
      <button class=" btn btn-primary" type="submit">Submit form</button>

      <hr />
      <p><label for="regular">A regular select below to test reset</label></p>
      <select class="form-select ignore-tags mb-2" id="regular" name="regular[]" multiple>
        <option disabled hidden value="">Choose a tag...</option>
        <option value="1" selected="selected">Apple</option>
        <option value="2">Banana</option>
        <option value="3">Orange</option>
      </select>
      <p><label for="regular_lg">A bigger select</label></p>
      <select class="form-select form-select-lg ignore-tags mb-2" id="regular_lg" name="regular_lg[]">
        <option disabled hidden value="">Choose a tag...</option>
        <option value="1" selected="selected">Apple</option>
        <option value="2">Banana</option>
        <option value="3">Orange</option>
      </select>
      <label for="validationCustom04" class="form-label">A regular select below to test required</label>
      <select class="form-select ignore-tags mb-2" id="validationCustom04" required>
        <option selected disabled value="">Choose...</option>
        <option>...</option>
      </select>
      <div class="invalid-feedback">Please select a valid state.</div>
      <p>A single select</p>
      <select class="form-select ignore-tags" id="single" name="single">
        <option disabled hidden value="">Choose a tag...</option>
        <option value="1" selected="selected">Apple</option>
        <option value="2">Banana</option>
        <option value="3">Orange</option>
      </select>
      <hr />
      <p>A disabled input for reference</p>
      <input class="form-control" type="text" placeholder="Disabled input" aria-label="Disabled input example" disabled />
      <hr />
      <div class="form-floating mb-3">
        <input type="email" class="form-control" id="floatingInput" placeholder="name@example.com" />
        <label for="floatingInput">Floating input demo</label>
      </div>
      <hr />
      <div class="form-floating mb-3">
        <select class="form-select ignore-tags" id="floatingSelect" aria-label="Floating label select example">
          <option selected>Open this select menu</option>
          <option value="1">One</option>
          <option value="2">Two</option>
          <option value="3">Three</option>
        </select>
        <label for="floatingSelect">Works with selects</label>
      </div>
    </form>

    <hr />

    <h2>Just validate</h2>

    <form id="just_form" autocomplete="off" method="post" action="https://vercel-dumper.vercel.app/">
      <div class="mb-3">
        <input id="basic_name" type="text" placeholder="Enter your name" />
      </div>
      <div class="mb-3">
        <label for="just_validate" class="form-label">Tags (just validate)</label>
        <select class="form-select" id="just_validate" name="just_validate" data-allow-clear="1" placeholder="Please select">
          <option value=""></option>
          <option value="1">Apple</option>
          <option value="2">Banana</option>
          <option value="3">Orange</option>
        </select>
      </div>

      <button class="btn btn-primary" type="submit">Submit form</button>
    </form>
    <hr />

    <h2>Regular form</h2>

    <p>This form use native html5 validation</p>

    <form id="regular_form" autocomplete="off" method="post" action="https://vercel-dumper.vercel.app/">
      <div class="mb-3">
        <label for="regular_validate" class="form-label">Tags (regular validate)</label>
        <select class="form-select" id="regular_validate" name="regular_validate" data-allow-clear="1" placeholder="Please select" required>
          <option value=""></option>
          <option value="1">Apple</option>
          <option value="2">Banana</option>
          <option value="3">Orange</option>
        </select>
        <div class="invalid-feedback">Please select a valid tag.</div>
      </div>
      <div class="mb-3">
        <label for="regular_validate_hide" class="form-label">Tags (regular validate + hide native validation)</label>
        <select class="form-select" id="regular_validate_hide" name="regular_validate_hide" data-allow-clear="1"
          data-hide-native-validation="1" placeholder="Please select" required>
          <option value=""></option>
          <option value="1">Apple</option>
          <option value="2">Banana</option>
          <option value="3">Orange</option>
        </select>
        <div class="invalid-feedback">Please select a valid tag.</div>
      </div>
      <div class="mb-3">
        <label for="regular_validate2" class="form-label">Tags (regular validate + allow new)</label>
        <select class="form-select" id="regular_validate2" name="regular_validate2" data-allow-clear="1" data-allow-new="1"
          placeholder="Please select" required>
          <option value=""></option>
          <option value="1">Apple</option>
          <option value="2">Banana</option>
          <option value="3">Orange</option>
        </select>
        <div class="invalid-feedback">Please select a valid tag.</div>
      </div>
      <div class="mb-3">
        <label for="inputGroupTagsRegular" class="form-label">Tags in input group + highlight</label>
        <div class="input-group">
          <span class="input-group-text" id="basic-addon1">Tag</span>
          <select class="form-select" id="inputGroupTagsRegular" name="inputGroupTagsRegular[]" multiple data-allow-clear="1"
            data-highlight-typed="1" data-show-suggestions-on-click="1" required>
            <option value="">Choose a tag...</option>
            <option value="1">Apple</option>
            <option value="2">Banana</option>
            <option value="ban_2">Banana 2</option>
            <option value="ban_3">Banana 3</option>
            <option value="3">Orange</option>
            <option value="*crazy$<>value">*crazy$<>value</option>
            <option value="not=valid\">not=valid\</option>
          </select>
        </div>
      </div>

      <button class="btn btn-primary" type="submit">Submit form</button>
    </form>

    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->
    <br /><!-- add a bit of space -->

    <!-- keep in mind that floating labels have a z-index: 2 -->
    <footer style="position: fixed; bottom: 0; left: 0; right: 0; z-index:3; padding: 1em; background: #eee">
      <div class="container">
        <select class="form-select" id="tagsBottom" name="tagsBottom[]" multiple data-allow-clear="true" data-allow-new="true">
          <option disabled hidden value="">Choose a tag...</option>
          <option value="1" selected="selected">Apple</option>
          <option value="2">Banana</option>
          <option value="3">Orange</option>
          <option value="4">Orange 2</option>
          <option value="5">Orange 3</option>
          <option value="6">Orange 4</option>
          <option value="7" data-badge-style="secondary">Blueberry with a very long label that pushes the menu</option>
        </select>
      </div>
    </footer>
  </div>
</body>

</html>