πŸ”– lightweight, efficient Tags input component in Vanilla JS / React / Angular / Vue

Overview



Tagify - tags input component

Transforms an input field or a textarea into a Tags component, in an easy, customizable way, with great performance and small code footprint, exploded with features.
Vanilla ⚑ React ⚑ Vue ⚑ Angular

πŸ‘‰ See Many Examples πŸ‘ˆ

Table of Contents

Installation

Option 1 - import from CDN:

Place these lines before any other code which is (or will be) using Tagify (Example here)

<script src="https://cdn.jsdelivr.net/npm/@yaireo/tagify"></script>
<script src="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.polyfills.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.css" rel="stylesheet" type="text/css" />

Tagify will then be available globally. To load specific version use @ - for example: unpkg.com/@yaireo/[email protected]

option 2 - import as a Node module:

npm i @yaireo/tagify --save

Usage (in your bundle):

live demo using Parcel as bundler

import Tagify from '@yaireo/tagify'

var tagify = new Tagify(...)

Don't forget to include tagify.css file in your project. CSS location: @yaireo/tagify/dist/tagify.css SCSS location: @yaireo/tagify/src/tagify.scss See SCSS usecase & example

Features

  • Can be applied to input & textarea elements
  • Supports mix content (text and tags together)
  • Supports single-value mode (like <select>)
  • Supports whitelist/blacklist
  • Customizable HTML templates for the different areas of the component (wrapper, tags, dropdown, dropdown item, dropdown header, dropdown footer)
  • Shows suggestions list (flexiable settings & styling) at full (component) width or next to the typed texted (caret)
  • Allows setting suggestions' aliases for easier fuzzy-searching
  • Auto-suggest input as-you-type with the ability to auto-complete
  • Can paste in multiple values: tag 1, tag 2, tag 3 or even newline-separated tags
  • Tags can be created by Regex delimiter or by pressing the "Enter" key / focusing of the input
  • Validate tags by Regex pattern or by function
  • Tags may be editable (double-click)
  • ARIA accessibility support(Component too generic for any meaningful ARIA)
  • Supports read-only mode to the whole component or per-tag
  • Each tag can have any properties desired (class, data-whatever, readonly...)
  • Automatically disallow duplicate tags (vis "settings" object)
  • Has built-in CSS loader, if needed (Ex. AJAX whitelist pulling)
  • Tags can be trimmed via hellip by giving max-width to the tag element in your CSS
  • Easily change direction to RTL (via the SCSS file)
  • Internet Explorer - A polyfill script should be used: tagify.polyfills.min.js (in /dist) (IE support has been dropped)
  • Many useful custom events
  • Original input/textarea element values kept in sync with Tagify

Building the project

Simply run gulp in your terminal, from the project's path (Gulp should be installed first).

Source files are this path: /src/

Output files, which are automatically generated using Gulp, are in: /dist/

The rest of the files are most likely irrelevant.

Adding tags dynamically

var tagify = new Tagify(...);

tagify.addTags(["banana", "orange", "apple"])

// or add tags with pre-defined properties

tagify.addTags([{value:"banana", color:"yellow"}, {value:"apple", color:"red"}, {value:"watermelon", color:"green"}])

Output value

There are two possible ways to get the value of the tags:

  1. Access the tagify's instance's value prop: tagify.value (Array of tags)
  2. Access the original input's value: inputElm.value (Stringified Array of tags)

The most common way is to simply listen to the change event on the original input

var inputElm = document.querySelector,
    tagify = new Tagify (inputElm);

inputElm.addEventListener('change', onChange)

function onChange(e){
  // outputs a String
  console.log(e.target.value)
}

Modify original input value format

Default format is a JSON string:
'[{"value":"cat"}, {"value":"dog"}]'

I recommend keeping this because some situations might have values such as addresses (tags contain commas):
'[{"value":"Apt. 2A, Jacksonville, FL 39404"}, {"value":"Forrest Ray, 191-103 Integer Rd., Corona New Mexico"}]'

Another example for complex tags state might be disabled tags, or ones with custom identifier class:
(tags can be clicked, so delevopers can choose to use this to disable/enable tags)
'[{"value":"cat", "disabled":true}, {"value":"dog"}, {"value":"bird", "class":"color-green"}]'

To change the format, assuming your tags have no commas and are fairly simple:

var tagify = new Tagify(inputElm, {
  originalInputValueFormat: valuesArr => valuesArr.map(item => item.value).join(',')
})

Output:
"cat,dog"

Ajax whitelist

Dynamically-loaded suggestions list (whitelist) from the server (as the user types) is a frequent need to many.

Tagify comes with its own loading animation, which is a very lightweight CSS-only code, and the loading state is controlled by the method tagify.loading which accepts true or false as arguments.

Below is a basic example using the fetch API. I advise aborting the last request on any input before starting a new request.

Example:
var input = document.querySelector('input'),
    tagify = new Tagify(input, {whitelist:[]}),
    controller; // for aborting the call

// listen to any keystrokes which modify tagify's input
tagify.on('input', onInput)

function onInput( e ){
  var value = e.detail.value
  tagify.whitelist = null // reset the whitelist

  // https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort
  controller && controller.abort()
  controller = new AbortController()

  // show loading animation and hide the suggestions dropdown
  tagify.loading(true).dropdown.hide()

  fetch('http://get_suggestions.com?value=' + value, {signal:controller.signal})
    .then(RES => RES.json())
    .then(function(newWhitelist){
      tagify.whitelist = newWhitelist // update whitelist Array in-place
      tagify.loading(false).dropdown.show(value) // render the suggestions dropdown
    })
}

Persisted data

Sometimes the whitelist might be loaded asynchronously, and so any pre-filled value in the original input field will be removed if the enforceWhitelist is set to true.

Tagify can automatically restore the last used whitelist by setting a unique id to the Tagify instance, by using the localstorage to persist the whitelist & value data:

var input = document.querySelector('input'),
    tagify = new Tagify(input, {
      id: 'test1',  // must be unique (per-tagify instance)
      enforceWhitelist: true,
    }),

Edit tags

Tags that aren't read-only can be edited by double-clicking them (by default) or by changing the editTags setting to 1, making tags editable by single-clicking them.

The value is saved on blur or by pressing enter key. Pressing Escape will revert the change trigger blur. ctrlz will revert the change if an edited tag was marked as not valid (perhaps duplicate or blacklisted)

To prevent all tags from being allowed to be editable, set the editTags setting to false (or null).
To do the same but for specific tag(s), set those tags' data with editable property set to false:

<input value='[{"value":"foo", "editable":false}, {"value":"bar"}]'>

Validations

For "regular" tags (not mix-mode or select-mode) the easiest way is to use the pattern setting and use a Regex, or apply the pattern attribute directly on the input which will be "transformed" into a Tagify component (for vanilla code where the input tag is fully accessible to developers).

If the pattern setting does not meet your needs, use the validate setting, which recieves a tag data object as an argument and should return true if validaiton is passing, or false/string of not. A string may be returned as the reason of the validation failure so it would be printed as the title attribute of the invalid tag.

Here's an example for async validation for an added tag. The idea is to listen to "add" event, and when it fires, first set the tag to "loading" state, run an async call, and then set the loading state (of the tag) back to false. If the custom async validation failed, call the replaceTag Tagify method and set the __isValid tag data property to the error string which will be shown when hovering the tag.

Note - there is a setting to keep invalid tags (keepInvalidTags) and if it's set to true, the user can see the reason for the invalidation by hovering the tag and see the browser's native tooltip via the title attribute:

{
  empty      : "empty",
  exceed     : "number of tags exceeded",
  pattern    : "pattern mismatch",
  duplicate  : "already exists",
  notAllowed : "not allowed"
}

The texts for those (invalid tags) titles can be customized from the settings:

new Tagify(inputElement, {
  texts: {
    duplicate: "Duplicates are not allowed"
  }
})

Or by directly manipulating the Tagify function prototype:

Tagify.prototype.TEXTS = {...Tagify.prototype.TEXTS, {duplicate: "Duplicates are not allowed"}}

Drag & Sort

To be able to sort tags by dragging, a 3rd-party script is needed.

I have made a very simple drag & drop (~11kb unminified) script which uses HTML5 native API and it is available to download via NPM or Github but any other drag & drop script may work. I could not find on the whole internet a decent lightweight script.

Integration example:

var tagify = new Tagify(inputElement)

// bind "DragSort" to Tagify's main element and tell
// it that all the items with the below "selector" are "draggable"
var dragsort = new DragSort(tagify.DOM.scope, {
    selector: '.'+tagify.settings.classNames.tag,
    callbacks: {
        dragEnd: onDragEnd
    }
})

// must update Tagify's value according to the re-ordered nodes in the DOM
function onDragEnd(elm){
    tagify.updateValueByDOMTags()
}

DOM Templates

It's possible to control the templates for some of the HTML elements Tagify is using by modifying the settings.templates Object with your own custom functions which must return an HTML string.

Available templates are: wrapper, tag, dropdown, dropdownItem, dropdownContent, dropdownHeader, dropdownFooter and the optional dropdownItemNoMatch which is a special template for rendering a suggestion item (in the dropdown list) only if there were no matches found for the typed input, for example:

// ...more tagify settings...
templates: {
  dropdownItemNoMatch: data =>
    `<div class='${tagify.settings.classNames.dropdownItem}' value="noMatch" tabindex="0" role="option">
        No suggestion found for: <strong>${data.value}</strong>
    </div>`
}

View templates

Example of overriding the tag template:

Each template function is automatically binded with this pointing to the current Tagify instance. It is imperative to preserve the class names and also the this.getAttributes(tagData) for proper functionality.

new Tagify(inputElem, {
  templates: {
    tag(tagData, tagify){
      return `<tag title="${(tagData.title || tagData.value)}"
              contenteditable='false'
              spellcheck='false'
              tabIndex="${this.settings.a11y.focusableTags ? 0 : -1}"
              class="${this.settings.classNames.tag} ${tagData.class ? tagData.class : ""}"
              ${this.getAttributes(tagData)}>
      <x title='' class="${this.settings.classNames.tagX}" role='button' aria-label='remove tag'></x>
      <div>
          <span class="${this.settings.classNames.tagText}">${tagData[this.settings.tagTextProp] || tagData.value}</span>
      </div>
    </tag>`,

    dropdownFooter(suggestions){
      var hasMore = suggestions.length - this.settings.dropdown.maxItems;

      return hasMore > 0
        ? `<footer data-selector='tagify-suggestions-footer' class="${this.settings.classNames.dropdownFooter}">
            ${hasMore} more items. Refine your search.
          </footer>`
        : '';
    }
  }
})

Suggestions list

suggestions list dropdown

The suggestions list is a whitelist Array of Strings or Objects which was set in the settings Object when the Tagify instance was created, and can be set later directly on the instance: tagifyInstance.whitelist = ["tag1", "tag2", ...].

The suggestions dropdown will be appended to the document's <body> element and will be rendered by default in a position below (bottom of) the Tagify element. Using the keyboard arrows up/down will highlight an option from the list, and hitting the Enter key to select.

It is possible to tweak the list dropdown via 2 settings:

  • enabled - this is a numeral value that tells Tagify when to show the suggestions dropdown, when a minimum of N characters were typed.
  • maxItems - Limits the number of items the suggestions list will render
var input = document.querySelector('input'),
    tagify = new Tagify(input, {
        whitelist : ['aaa', 'aaab', 'aaabb', 'aaabc', 'aaabd', 'aaabe', 'aaac', 'aaacc'],
        dropdown : {
            classname     : "color-blue",
            enabled       : 0,              // show the dropdown immediately on focus
            maxItems      : 5,
            position      : "text",         // place the dropdown near the typed text
            closeOnSelect : false,          // keep the dropdown open after selecting a suggestion
            highlightFirst: true
        }
    });

Will render

<div class="tagify__dropdown tagify__dropdown--text" style="left:993.5px; top:106.375px; width:616px;">
    <div class="tagify__dropdown__wrapper">
      <div class="tagify__dropdown__item tagify__dropdown__item--active" value="aaab">aaab</div>
      <div class="tagify__dropdown__item" value="aaabb">aaabb</div>
      <div class="tagify__dropdown__item" value="aaabc">aaabc</div>
      <div class="tagify__dropdown__item" value="aaabd">aaabd</div>
      <div class="tagify__dropdown__item" value="aaabe">aaabe</div>
    </div>
</div>

By default searching the suggestions is using fuzzy-search (see settings).

If you wish to assign alias to items (in your suggestion list), add the searchBy property to whitelist items you wish to have an alias for.

In the below example, typing a part of a string which is included in the searchBy property, for example land midd" - the suggested item which matches the value "Israel" will be rendered in the suggestions (dropdown) list.

Example for a suggestion item alias

whitelist = [
    ...
    { value:'Israel', code:'IL', searchBy:'holy land, desert, middle east' },
    ...
]

Another handy setting is dropdown.searchKeys which, like the above dropdown.searchBy setting, allows expanding the search of any typed terms to more than the value property of the whitelist items (if items are a Collection).

Example whitelist:

[
  {
    value    : 123456,
    nickname : "foo",
    email    : "[email protected]"
  },
  {
    value    : 987654,
    nickname : "bar",
    email    : "[email protected]"
  },
  ...more..
]

Modified searchKeys setting to also search in other keys:

{
  dropdown: {
    searchKeys: ["nickname", "email"] //  fuzzy-search matching for those whitelist items' properties
  }
}

Mixed-Content

See demo here

This feature must be toggled using these settings:

{
  //  mixTagsInterpolator: ["{{", "}}"],  // optional: interpolation before & after string
  mode: 'mix',    // <--  Enable mixed-content
  pattern: /@|#/  // <--  Text starting with @ or # (if single, String can be used here instead of Regex)
}

When mixing text with tags, the original textarea (or input) element will have a value as follows:

[[cartman]]⁠ and [[kyle]]⁠ do not know [[Homer simpson]]⁠

If the initial value of the textarea or input is formatted as the above example, Tagify will try to automatically convert everything between [[ & ]] to a tag, if tag exists in the whitelist, so make sure when the Tagify instance is initialized, that it has tags with the correct value property that match the same values that appear between [[ & ]].

Applying the setting dropdown.position:"text" is encouraged for mixed-content tags, because the suggestions list weird when there is already a lot of content on multiple lines.

If a tag does not exist in the whitelist, it may be created by the user and all you should do is listen to the add event and update your local/remote state.

Single-Value

Similar to native <Select> element, but allows typing text as value.

React

See live demo for React integration examples. ⚠️ Tagify is not a controlled component.

A Tagify React component is exported from react.tagify.js:


Update regarding onChange prop:

I have changed how the onChange works internally within the Wrapper of Tagify so as of March 30, 2021 the e argument will include a detail parameter with the value as string. There is no more e.target, and to access the original DOM input element, do this: e.detail.tagify.DOM.originalInput.


Note: You will need to import Tagify's CSS also, either by JavaScript or by SCSS @import (which is preferable) Also note that you will need to use dart-sass and not node-sass in order to compile the file.

import Tags from "@yaireo/tagify/dist/react.tagify" // React-wrapper file
import "@yaireo/tagify/dist/tagify.css" // Tagify CSS

// on tag add/edit/remove
const onChange = useCallback((e) => {
  console.log("CHANGED:"
    , e.detail.tagify.value // Array where each tag includes tagify's (needed) extra properties
    , e.detail.tagify.getCleanValue() // Same as above, without the extra properties
    , e.detail.value // a string representing the tags
  )
}, [])

const App = () => {
  return (
    <Tags
      tagifyRef={tagifyRef} // optional Ref object for the Tagify instance itself, to get access to  inner-methods
      settings={settings}  // tagify settings object
      defaultValue="a,b,c"
      {...tagifyProps}   // dynamic props such as "loading", "showDropdown:'abc'", "value"
      onChange={onChange}
    />
  )
})

To gain full access to Tagify's (instance) inner methods, A custom ref can be used:

...
const tagifyRef = useRef()
...
<Tags tagifyRef={tagifyRef} ... />

// or mix-mode
<MixedTags
  settings={...}
  onChange={...}
  defaultValue={`This is a textarea which mixes text with [[{"value":"tags"}]].`}
/>

<MixedTags> component is a shorthand for <Tags InputMode="textarea">

Updating the component's state

The settings prop is only used once in the initialization process, please do not update it afterwards.


πŸ“– List of (React) props for the <Tags/> component
Prop Type Updatable Info
settings Object See settings section
name String βœ” <input>'s element name attribute
value String/Array βœ” Initial value.
defaultValue String/Array Same as `value prop
placeholder String βœ” placeholder text for the component
readOnly Boolean βœ” Toggles readonly state. With capital O.
tagifyRef Object useRef hook refference for the component inner instance of vailla Tagify (for methods access)
showFilteredDropdown Boolean/String βœ” if true shows the suggestions dropdown. if assigned a String, show the dropdown pre-filtered.
loading Boolean βœ” Toggles loading state for the whole component
whitelist Array βœ” Sets the whitelist which is the basis for the suggestions dropdown & autocomplete
className String Component's optional class name to be added
InputMode String "textarea" will create a <textarea> (hidden) element instead of the default <input> and automatically make Tagify act as "mix mode"
autoFocus Boolean Should the component have focus on mount. Must be unique, per-page.
children String/Array value/defaultValue props are prefered
onChange Function See events section
onInput Function See events section
onAdd Function See events section
onRemove Function See events section
onInvalid Function See events section
onClick Function See events section
onKeydown Function See events section
onFocus Function See events section
onBlur Function See events section
onEditInput Function See events section
onEditBeforeUpdate Function See events section
onEditUpdated Function See events section
onEditStart Function See events section
onEditKeydown Function See events section
onDropdownShow Function See events section
onDropdownHide Function See events section
onDropdownSelect Function See events section
onDropdownScroll Function See events section
onDropdownNoMatch Function See events section
onDropdownUpdated Function See events section

jQuery version

jQuery.tagify.js

A jQuery wrapper version is also available, but I advise not using it because it's basically the exact same as the "normal" script (non-jqueryfied) and all the jQuery's wrapper does is allowing to chain the event listeners for ('add', 'remove', 'invalid')

$('[name=tags]')
    .tagify()
    .on('add', function(e, tagData){
        console.log('added', ...tagData)  // data, index, and DOM node
    });

Accessing methods can be done via the .data('tagify'):

$('[name=tags]').tagify();
// get tags from the server (ajax) and add them:
$('[name=tags]').data('tagify').addTags('aaa, bbb, ccc')

HTML input & textarea attributes

The below list of attributes affect Tagify.
These can also be set by Tagify settings Object manually, and not declerativly (via attributes).

Attribute Example Info
pattern
<input pattern='^[A-Za-z_✲ ]{1,15}$'>
Tag Regex pattern which tag input is validated by.
placeholder
<input placeholder='please type your tags'>
This attribute's value will be used as a constant placeholder, which is visible unless something is being typed.
readOnly
<input readOnly>
No user-interaction (add/remove/edit) allowed.
autofocus
<input autofocus>
Automatically focus the the Tagify component when the component is loaded
required
<input required>
Adds a required attribute to the Tagify wrapper element. Does nothing more.

FAQ

List of questions & scenarios which might come up during development with Tagify:

Dynamic whitelist The whitelist initial value is set like so:
const tagify = new Tagify(tagNode, {
  whitelist: ["a", "b", "c"]
})

If changes to the whitelist are needed, they should be done like so:

Incorrect:

tagify.settings.whitelist = ["foo", "bar"]

Correct:

// set the whitelist directly on the instance and not on the "settings" property
tagify.whitelist = ["foo", "bar"]

tags/whitelist data structure

Tagify does not accept just any kind of data structure.
If a tag data is represented as an Object, it must contain a unique property value which Tagify uses to check if a tag already exists, among other things, so make sure it is present.

Incorrect:

[{ "id":1, "name":"foo bar" }]

Correct:

[{ "id":1, "value": 1, "name":"foo bar" }]
[{ "value":1, "name":"foo bar" }]
[{ "value":"foo bar" }]
// ad a simple array of Strings
["foo bar"]

Save changes (Ex. to a server)

In framework-less projects, the developer should save the state of the Tagify component (somewhere), and the question is:
when should the state be saved? On every change made to Tagify's internal state (tagify.value via the update() method).

var tagify = new Tagify(...)

// listen to "change" events on the "original" input/textarea element
tagify.DOM.originalInput.addEventListener('change', onTagsChange)

// This example uses async/await but you can use Promises, of course, if you prefer.
async function onTagsChange(e){
  const {name, value} = e.target
  // "imaginary" async function "saveToServer" should get the field's name & value
  await saveToServer(name, value)
}

If you are using React/Vue/Angular or any "modern" framework, then you already know how to attach "onChange" event listeners to your <input>/<textarea> elements, so the above is irrelevant.


Render tags in one single line

Stopping tags from wrapping to new lines, add this to your .tagify selector CSS Rule:

flex-wrap: nowrap;

Submit on `Enter` key

Tagify internally has state property, per Tagify instance and this may be useful for a variety of things when implementing a specific scenario.

var tagify = new Tagify(...)
var formElm = document.forms[0]; // just an example

tagify.on('keydown', onTagifyKeyDown)

function onTagifyKeyDown(e){
  if( e.key == 'Enter' &&         // "enter" key pressed
      !tagify.state.inputText &&  // assuming user is not in the middle oy adding a tag
      !tagify.state.editing       // user not editing a tag
    ){
    setTimeout(() => formElm.submit())  // put some buffer to make sure tagify has done with whatever, to be on the safe-side
  }

}

CSS Variables

Learn more about CSS Variables) (custom properties)

Tagify's utilizes CSS variables which allow easy customization without the need to manually write CSS. If you do wish to heavily style your Tagify components, then you can (and should) use the below variables within your modified styles as much as you can.

For a live example, see the demos page.

Name Info
--tags-disabled-bg Tag background color when disabled
--tags-border-color The outer border color which surrounds tagify
--tags-hover-border-color hover state
--tags-focus-border-color focus state
--tag-border-radius Tag border radius
--tag-bg Tag background color
--tag-hover Tag background color on hover (mouse)
--tag-text-color Tag text color
--tag-text-color--edit Tag text color when a Tag is being edited
--tag-pad Tag padding, from all sides. Ex. .3em .5em
--tag--min-width Minimum Tag width
--tag--max-width Maximum tag width, which gets trimmed with hellip after
--tag-inset-shadow-size This is the inner shadow size, which dictates the color of the Tags.
It's important the size fits exactly to the tag.
Change this if you change the --tag-pad or fontsize.
--tag-invalid-color For border color of edited tags with invalid value being typed into them
--tag-invalid-bg Background color for invalid Tags.
--tag-remove-bg Tag background color when hovering the Γ— button.
--tag-remove-btn-color Remove (Γ—) button text color
--tag-remove-btn-bg Remove (Γ—) button background color
--tag-remove-btn-bg--hover Remove (Γ—) button hover background color
--input-color Input text color
--tag-hide-transition Controls the transition property when a tag is removed. default is '.3s'
--placeholder-color Placeholder text color
--placeholder-color-focus Placeholder text color when Tagify has focus and no input was typed
--loader-size Loading animation size. 1em is pretty big, default is a bit less.
--readonly-striped Either a value 1 or 0 can be used to toggle the striped diagonal background in readonly

Suggestions Dropdown CSS variables

should be appiled on the :root {...} selector

Name Info
--tagify-dd-color-primary The suggestion's dropdown background color
--tagify-dd-bg-color Sugegstion's background color on hover
--tagify-dd-item--hidden-duration When selecting a suggestion, this is the duration for it to become hidden (shrink)
--tagify-dd-item-pad Suggestion item padding

Full list of Tagify's SCSS variables

Methods

Tagify is prototype based and There are many methods, but I've chosen to list the most relevant ones:

Name Parameters Info
destroy Reverts the input element back as it was before Tagify was applied
removeAllTags Removes all tags and resets the original input tag's value property
addTags
  1. Array/String/Object tag(s) to add
  2. Boolean clear input after adding
  3. Boolean - skip adding invalids
    Accepts a String (word, single or multiple with a delimiter), an Array of Objects (see above) or Strings.
    addMixTags Array/String Bypasses the normalization process in addTags, forcefully adding tags at the last caret location or at the end, if there's no last caret location saved (at tagify.state.selection)
    removeTags
    1. Array/HTMLElement/String tag(s) to remove
    2. silent does not update the component's value
    3. tranDuration Transition duration (in ms)
    (#502) Remove single/multiple Tags. When nothing passed, removes last tag.
    • silent - A flag, which when turned on, does not remove any value and does not update the original input value but simply removes the tag from tagify
    • tranDuration - delay for animation, after which the tag will be removed from the DOM
    addEmptyTag Object (tagData) Create an empty tag (optionally with pre-defined data) and enters "edit" mode directly. See demo
    loadOriginalValues String/Array Converts the input's value into tags. This method gets called automatically when instansiating Tagify. Also works for mixed-tags
    getWhitelistItemsByValue Object {value} - return an Array of found matching items (case-insensitive)
    getTagIndexByValue String Returns the index of a specific tag, by value
    getTagElmByValue String Returns the first matched tag node, if found
    isTagDuplicate String Returns how many tags already exists with that value
    parseMixTags String Converts a String argument ([[foo]]⁠ and [[bar]]⁠ are..) into HTML with mixed tags & texts
    getTagElms Returns a DOM nodes list of all the tags
    getTagElmByValue String Returns a specific tag DOM node by value
    tagData HTMLElement, Object set/get tag data on a tag element (has.tagify__tag class by default)
    editTag HTMLElement Goes to edit-mode in a specific tag
    getTagTextNode HTMLElement Get the node which has the actual tag's content
    setTagTextNode HTMLElement, String Sets the text of a tag (DOM only, does not affect actual data)
    replaceTag tagElm, Object (tagData) Exit a tag's edit-mode. if "tagData" exists, replace the tag element with new data and update Tagify value
    loading Boolean toggle loading state on/off (Ex. AJAX whitelist pulling)
    tagLoading HTMLElement, Boolean same as above but for a specific tag element
    createTagElem Object (tagData) Returns a tag element from the supplied tag data
    injectAtCaret HTMLElement (injectedNode), Object (range) Injects text or HTML node at last caret position. range parameter is optional
    placeCaretAfterNode HTMLElement Places the caret after a given node
    insertAfterTag HTMLElement (tag element), HTMLElement/String (whatever to insert after)
    toggleClass Boolean Toggles class on the main tagify container (scope)
    dropdown.selectAll Add all whitelist items as tags and close the suggestion dropdown
    dropdown.show String Shows the sugegstions list dropdown. A string paramater allows filtering the results
    dropdown.hide Boolean Hides the suggestions list dropdown (if it's not managed manually by the developer)
    dropdown.toggle Boolean Toggles dropdown show/hide. the boolean parameter will force-show
    updateValueByDOMTags Iterate tag DOM nodes and re-build the tagify.value array (call this if tags get sorted manually)
    parseTemplate String/Function (template name or function), Array (data) converts a template string (by selecting one from the settings.templates by name or supplying a template function which returns a String) into a DOM node
    setReadonly Boolean Toggles "readonly" mode on/off
    setDisabled Boolean Toggles "disabled" mode on/off
    getPersistedData String Get data for the specific instance by parameter
    setPersistedData *, String Set data for the specific instance. Must supply a second parameter which will be the key to save the data in the localstorage (under the tagify namespace)
    clearPersistedData String Clears data for the specific instance, by parameter. If the parameter is ommited, clears all persisted data related to this instance (by its id which was set in the instance's settings)

    Events

    All triggered events return the instance's scope (tagify).
    See e.detail for custom event additional data.

    Example 1
    var tagify = new Tagify(...)
    
    // events can be chainable, and multiple events may be binded for the same callback
    tagify
      .on('input', e => console.log(e.detail))
      .on('edit:input edit:updated edit:start edit:keydown', e => console.log(e.type, e.detail))
    Example 2
    var tagify = new Tagify(inputNode, {
      callbacks: {
        "change": (e) => console.log(e.detail),
        "dropdown:show": (e) => console.log(e.detail)
      }
    })
    Name Info
    change Any change to the value has occurred. e.details.value callback listener argument is a String
    add A tag has been added
    remove A tag has been removed (use removeTag instead with jQuery)
    invalid A tag has been added but did not pass validation. See event detail
    input Input event, when a tag is being typed/edited. e.detail exposes value, inputElm & isValid
    click Clicking a tag. Exposes the tag element, its index & data
    dblclick Double-clicking a tag
    keydown When Tagify input has focus and a key was pressed
    focus The component currently has focus
    blur The component lost focus
    edit:input Typing inside an edited tag
    edit:beforeUpdate Just before a tag has been updated, while still in "edit" mode
    edit:updated A tag as been updated (changed view editing or by directly calling the replaceTag() method)
    edit:start A tag is now in "edit mode"
    edit:keydown keydown event while an edited tag is in focus
    dropdown:show Suggestions dropdown is to be rendered. The dropdown DOM node is passed in the callback, see demo.
    dropdown:hide Suggestions dropdown has been removed from the DOM
    dropdown:select Suggestions dropdown item selected (by mouse/keyboard/touch)
    dropdown:scroll Tells the percentage scrolled. (event.detail.percentage)
    dropdown:noMatch No whitelist suggestion item matched for the typed input. At this point it is possible to manually set tagify.suggestedListItems to any possible custom value, for example: [{ value:"default" }]
    dropdown:updated Fired when the dropdown list is re-filtered while suggestions list is visible and a tag was removed so it was re-added as a suggestion

    Hooks

    Promise-based hooks for async program flow scenarios.

    Allows to "hook" (intervene) at certain points of the program, which were selected as a suitable place to pause the program flow and wait for further instructions on how/if to proceed.

    For example, if a developer wishes to add a (native) confirmation popup before a tag is removed (by a user action):
    var input = document.querySelector('input')
    var tagify = new Tagify(input,{
        hooks: {
            /**
             * Removes a tag
             * @param  {Array}  tags [Array of Objects [{node:..., data:...}, {...}, ...]]
             */
            beforeRemoveTag : function( tags ){
                return new Promise((resolve, reject) => {
                    confirm("Remove " + tags[0].data.value + "?")
                        ? resolve()
                        : reject()
                })
            }
        }
    })
    Name Parameters Info
    beforeRemoveTag Array (of Objects) Example
    suggestionClick Object (click event data) Example
    beforePaste tagify, pastedText, clipboardData Before pasted text was added to Tagify. Resolve with new paste value if needed

    Settings

    Name Type Default Info
    id String See Persisted data
    tagTextProp String "value" Tag data Object property which will be displayed as the tag's text. Remember to keep "value" property unique. See Also: dropdown.mapValueTo, dropdown.searchKeys
    placeholder String Placeholder text. If this attribute is set on an input/textarea element it will override this setting
    delimiters String "," [RegEx string] split tags by any of these delimiters. Example delimeters: ",|.| " (comma, dot or whitespace)
    pattern String/RegEx null Validate input by RegEx pattern (can also be applied on the input itself as an attribute) Ex: /[1-9]/
    mode String null Use select for single-value dropdown-like select box. See mix as value to allow mixed-content. The 'pattern' setting must be set to some character.
    mixTagsInterpolator Array ['[[', ']]'] Interpolation for mix mode. Everything between these will become a tag
    mixTagsAllowedAfter RegEx /,|\.|\:|\s/ Define conditions in which typed mix-tags content is allowing a tag to be created after.
    duplicates Boolean false Should duplicate tags be allowed or not
    trim Boolean true If true trim the tag's value (remove before/after whitespaces)
    enforceWhitelist Boolean false Should ONLY use tags allowed in whitelist.
    In mix-mode, setting it to false will not allow creating new tags.
    userInput Boolean true Disable manually typing/pasting/editing tags (tags may only be added from the whitelist). Can also use the disabled attribute on the original input element.
    autoComplete.enabled Boolean true Tries to suggest the input's value while typing (match from whitelist) by adding the rest of term as grayed-out text
    autoComplete.rightKey Boolean false If true, when β†’ is pressed, use the suggested value to create a tag, else just auto-completes the input. In mixed-mode this is ignored and treated as "true"
    whitelist Array [] An array of allowed tags (Strings or Objects). When using Objects in the whitelist array a value property is a must & should be unique.
    Also, the *whitelist used for auto-completion when autoCompletion.enabled is true
    blacklist Array [] An array of tags which aren't allowed
    addTagOnBlur Boolean true Automatically adds the text which was inputed as a tag when blur event happens
    onChangeAfterBlur Boolean true By default, the native way of inputs' onChange events is kept, and it only fires when the field is blured.
    pasteAsTags Boolean true Automatically converts pasted text into tags
    callbacks Object {} Exposed callbacks object to be triggered on events: 'add' / 'remove' tags
    maxTags Number Infinity Maximum number of allowed tags. when reached, adds a class "tagify--hasMaxTags" to <Tags>
    editTags Object/Number {} false or null will disallow editing
    editTags.clicks Number 2 Number of clicks to enter "edit-mode": 1 for single click. Any other value is considered as double-click
    editTags.keepInvalid Boolean true keeps invalid edits as-is until esc is pressed while in focus
    templates Object wrapper, tag, dropdownItem Object consisting of functions which return template strings
    validate Function If the pattern setting does not meet your needs, use this function, which receives tag data object as an argument and should return true if validation passed or false/string if not. A string may be returned as the reason for the validation failure.
    transformTag Function Takes a tag data as argument and allows mutating it before a tag is created or edited and also before validation.
    Should not return anything, only mutate the argument.
    keepInvalidTags Boolean false If true, do not remove tags which did not pass validation
    createInvalidTags Boolean true If true, create invalid-tags. Otherwise, keep the editable input and do not create tags from it
    skipInvalid Boolean false If true, do not add invalid, temporary, tags before automatically removing them
    backspace * true On pressing backspace key:
    true - remove last tag
    edit - edit last tag
    false - do nothing (useful for outside style)
    originalInputValueFormat Function If you wish your original input/textarea value property format to other than the default (which I recommend keeping) you may use this and make sure it returns a string.
    mixMode.insertAfterTag Node/String \u00A0 node or string to add after a tag added
    a11y.focusableTags Boolean false allows tags to get focus, and also to be deleted via Backspace
    dropdown.enabled Number 2 Minimum characters input for showing a suggestions list. false will not render a suggestions list.
    dropdown.caseSensitive Boolean false if true, match exact item when a suggestion is selected (from the dropdown) and also more strict matching for dulpicate items. Ensure fuzzySearch is false for this to work.
    dropdown.maxItems Number 10 Maximum items to show in the suggestions list
    dropdown.classname String "" Custom classname for the dropdown suggestions list
    dropdown.fuzzySearch Boolean true Enables filtering dropdown items values' by string containing and not only beginning
    dropdown.sortby String/Function If set as startsWith string, the suggestions list will be sorted with matched items which starts with the query shown first, and exact matches shown before all.

    If this setting is defined as a function, it recieves two arguments: the array of filtered items and the query and it must return an Array.

    (default sorting order is same as the whitelist's)
    dropdown.accentedSearch Boolean true Enable searching for accented items in the whitelist without typing exact match (#491)
    dropdown.includeSelectedTags Boolean false Should the suggestions list Include already-selected tags (after filtering)
    dropdown.position String "all"
    • manual - will not render the dropdown, and you would need to do it yourself. See demo
    • text - places the dropdown next to the caret
    • input - places the dropdown next to the input (useful in rare situations)
    • all - normal, full-width design
    dropdown.highlightFirst Boolean false When a suggestions list is shown, highlight the first item, and also suggest it in the input (The suggestion can be accepted with β†’ key)
    dropdown.closeOnSelect Boolean true close the dropdown after selecting an item, if enabled:0 is set (which means always show dropdown on focus)
    dropdown.clearOnSelect Boolean true Keep typed text after selecting a suggestion
    dropdown.mapValueTo Function/String If whitelist is an Array of Objects:
    Ex. [{value:'foo', email:'[email protected]'},...])
    this setting controlls which data key will be printed in the dropdown.
    Ex.1: mapValueTo: data => "To:" + data.email
    Ex.2: mapValueTo: "email"
    dropdown.searchKeys Array ["value", "searchBy"] When a user types something and trying to match the whitelist items for suggestions, this setting allows matching other keys of a whitelist objects
    dropdown.appendTarget HTMLNode document.body Target-Node which the suggestions dropdown is appended to (only when rendered)
    dropdown.placeAbove Boolean If defined, will force the placement of the dropdown in respect to the Boolean value: true will always show the suggestions dropdown above the input field and false will always show it below. By default this setting it not defined and the placement of the dropdown is automatically decided according to the space availble, where opening it below the input is preferred.
    Comments
    • Can't delete tags just added, by clicking on the cross button

      Can't delete tags just added, by clicking on the cross button

      Prerequisites

      • [x ] I am running the latest version
      • [ x] I checked the documentation and found no answer
      • [ x] I checked to make sure that this issue has not already been filed

      Demo Page

      https://jsbin.com/hatepopege/1/edit?html,js,output

      Explanation

      Hi! Thanks for this library! I am fetching the tags with AJAX and I am having a weird issue. If I type some text and select a tag from the dropdown, then I can only remove that tag by pressing backspace; clicking on the "x" button doesn't do anything. However if I disable the onInput callback and just use a static whitelist, I can remove tags soon after adding them. I tried to reproduce it in a jsbin (https://jsbin.com/hatepopege/1/edit?html,js,output) but with that jsbin I can delete the tag soon after adding it even when it comes from an AJAX request. So I am not sure it is a bug or if there is something in my code that somehow interferes with Tagify, although I don't have much else going on.

      Could you give me some pointers on how to investigate / find the cause of this issue?

      Thanks!

      ps. I don't see any errors in the console. It just seems that the click event on the x button doesn't work.

      Cannot Reproduce 
      opened by vitobotta 26
    • Enter tags without any delimiters in mix mode / Empty Pattern

      Enter tags without any delimiters in mix mode / Empty Pattern

      Hi @yairEO ,

      I loved your library and would like to use it for all my projects which would have this requirement of Tags, but on my tryouts I have encountered an issue which may totally be due to my lack of understanding, but to clarify does this library support empty pattern?

      I tried out a scenario with mode: 'mix' and added values for white-listing, and pattern to null etc. But if i don't set a valid pattern I am not getting the drop-down suggestions.

      const tagify = new Tagify(document.querySelector('input[name=search-bar]'), {
                  delimiters: null,
                  tagTemplate: function (value, tagData) {
                      return `
                      <tag title='${value}'>
                          <x title=''></x>
                          <div>
                              <span class='tagify__tag-text'>${value}</span>
                          </div>
                      </tag>`;
                  },
                  mode: 'mix',
                  pattern    : /@/,
                  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' },
                      { value: 'Austria', code: 'AT' },
                      { value: 'Azerbaijan', code: 'AZ' }
                  ],
                  dropdown: {
                      enabled: 1,
                      classname: 'extra-properties',
                      itemTemplate: function (tagData) {
                          return `<div class='tagify__dropdown__item ${tagData.class ? tagData.class : ""}'>
                              <span>${tagData.value}</span>
                          </div>`
                      }
                  },
                  mapValueToProp: "code", // map tags' values to this property name, so this property will be the actual value and not the printed value on the screen
              });
      
      Suggestion 
      opened by KiranRW1 23
    • Going back (history) in Chrome doesn't keep input data

      Going back (history) in Chrome doesn't keep input data

      Issue

      When you post the data of the form that contains the Tagify input element, if you go back with the browser after posting the control content is not persisted when using Chrome (while it works with Firefox).

      πŸ’₯ Demo Page (your original/unmodified Codepen link)

      It's not demostrable using Codepen only, as there must be a <form> element inside, anyway it happens also with your original Codepen link here:

      https://codepen.io/vsync/pen/OJNVyQR

      Steps to reproduce

      1. Download the HTML from the Codepen link above
      2. Edit the HTML file, enclosing the <input> element in a form and adding a Submit button. So:
      <body translate="no" >
      <form method="get" action="not-exists"> <!-- ADDED LINE -->
        <input name='tags'
        class='some_class_name'            
        placeholder='write some tags'      
        value='css, html, javascript, css' of Objects)
        data-blacklist='.NET,PHP'>
       <input type="submit" value="Submit"> <!-- ADDED LINE -->
      </form> <!-- ADDED LINE -->
          <script src [...]
      
      1. Open the modified page in Firefox, type some tags, push the Submit button (it leads to an error of course) then go back. Your tags are still there. CORRECT
      2. Do the same with Chrome: after going back, the typed tags are not there and they're replaced with the <input> element original values. WRONG

      Video demonstration

      Go back: Firefox works, Chrome does not

      Bug 
      opened by virtualdj 22
    • Can't make pattern regex work in MixMode

      Can't make pattern regex work in MixMode

      Prerequisites

      • [x] I am running the latest version
      • [X] I checked the documentation and found no answer
      • [X] I checked to make sure that this issue has not already been filed

      πŸ’₯ Demo Page

      https://jsbin.com/nenoduxeli/edit?html,js,console,output

      Explanation

      • What is the expected behavior? Tags should match my regex

      • What is happening instead? The plugin don't detect tag

      • What error message are you getting? No one

      Clarification required 
      opened by syrm 22
    • Click

      Click "enter" on suggested list, only when data comes from external function, duplicate the tag

      I got this code

      <script>
        var controller;
        var input = document.getElementById('element-tags-list');
        var tagify = new Tagify(input, {
            whitelist : [],
            duplicates: false,
            dropdown : {
                classname : "color-blue",
                enabled   : 3,
                maxItems  : 5
            }
        });
      
        tagify.on('input', onInput);
      
        function onInput( e ){
            var value = e.detail.value;
            tagify.settings.whitelist.length = 0;
            controller && controller.abort();
            controller = new AbortController();
            tagify.settings.whitelist = ['aaabc', 'aaacb', 'aaabb', 'bbbbc', 'cccbd', 'dddbe', 'eeec', 'fffcc'];
            tagify.dropdown.show.call(tagify, value);
        }
      </script>
      

      Explanation

      When I press enter on a suggested item the library creates 2 tags and not one. Es.

      • I write aa
      • It suggest aaabc, aaacb and aaabb
      • I use arrow key to choose aaabb and press Enter
      • the library adds 2 tags: my original aa and the choosed aaabb

      The same error if in the "onInput" function I use a more complex ajax call like:

      fetch('ajax/tags-list.php?prefix=' + value, {signal:controller.signal})
        .then(RES => RES.json())
        .then(function(whitelist){
          tagify.settings.whitelist = whitelist;
          tagify.dropdown.show.call(tagify, value); // render the suggestions dropdown
        })
      

      If I click the suggested item with mouse everything works well. If I put the suggested words directly in the object creation everything works well (with Enter key too).

      Bug: high priority 
      opened by gspawn 19
    • Extra `⁠` HTML code in mix mode

      Extra `⁠` HTML code in mix mode

      Hello,

      I'm behind a strange behaviour with the jQuery file.

      After some investigation, I found this part of code in dist/jQuery.tagify.min.js file

              replaceMixStringWithTag: function(t, e, i, n) {
                  return i && t && -1 != t.indexOf(e) && (n = this.createTagElem(i), this.value.push(i), t = t.replace(e, n.outerHTML + "&#8288;")), {
                      s: t,
                      tagElm: n
                  }
              }
      

      And I can't find why in the mix mode, the originalInput tags are rendered as tags + &#8288;.

      I think that &#8288; is used only in replaceMixStringWithTag() and addMixTag() methods and it's not used in another method. So I don't think that it's usefull somewhere.

      The strange thing that I found is when I call loadOriginalValues()

              loadOriginalValues: function() {
                  var t = this.DOM.originalInput.value;
                  if (t) {
                      try {
                          t = JSON.parse(t)
                      } catch (t) {}
                      "mix" == this.settings.mode ? this.parseMixTags(t) : this.addTags(t).forEach(function(t) {
                          t && t.classList.add("tagify--noAnim")
                      })
                  }
              }
      

      Since the mix mode is enabled, the parseMixTags(t) method will be called

              parseMixTags: function(n) {
                  var s = this;
                  return n.split(this.settings.mixTagsAllowedAfter).filter(function(t) {
                      return t.match(s.settings.pattern)
                  }).forEach(function(t) {
                      var e, i = t.replace(s.settings.pattern, "");
                      s.isTagWhitelisted(i) && (e = s.normalizeTags.call(s, i)[0], n = s.replaceMixStringWithTag(n, t, e).s)
                  }), this.DOM.input.innerHTML = n, this.update(), n
              }
      

      In which, if we are using whitelisted tags, each tag text will be normalized in a JSON object and it will be rendered as a HTML tag using replaceMixStringWithTag(n, t, e) method.

      Until now everything is OK.

      Before continuing, let's take an example:

      Input="Hello @homer how are you ?"

      The rendered input will be Hello [Homer](x)&#8288; how are ?.

      This output will be set in DOM.input.innerHTML

      Now the update() method will be called

              update: function() {
                  this.DOM.originalInput.value = "mix" == this.settings.mode ? this.DOM.input.textContent : JSON.stringify(this.value)
              }
      

      Since we are operating in mix mode, DOM.originalInput.value will take the DOM.input.textContent value.

      But using the previous example, DOM.input.textContent value is Hello Homer&#8288; how are ?. To be more precise it's value will be seen as "Hello Homer how are ?" but in hexadecimal (for the non visible characeters) it's "Hello Homer%20%60 how are ?"

      And that's what's confusing me.

      Because in my use-case, I managed to use a custom template

              tagTemplate : function(v, tagData){
                return `<tag title='${v}' contenteditable='false' spellcheck='false' value='${v}'>
                          <x title=''></x>
                          <div>
                              <span class='d-none'>@</span>
                              <span class='tagify__tag-text'>${v}</span>
                          </div>
                      </tag>`;
              }
      

      To keep the pattern character (@) in DOM.originalInput. So everytime I render the tags using loadOriginalValues() method, I will never lost my previously rendered tags.

      But after seeing this strange behaviour, when loadOriginalValues() method is called the first time it will render the tags normally, but the second time loadOriginalValues() method is called, the previously rendered tags will be deleted and they will never be rendered because of that extra HTML code &#8288;. And this is normal because Homer&#8288; is not whitelisted.

      From Wikipedia:

      U+2060 WORD JOINER (HTML &#8288; Β· WJ): encoded in Unicode since version 3.2. The word-joiner does not produce any space, and prohibits a line break at its position.

      So can I have any answer ?

      Thank you

      Best regards

      opened by mohamedaymenkarmous 18
    • Angular usage

      Angular usage

      Can someone please explain how to use this library with Angular.

      When I add <tagify></tagify> inside component HTML I'm getting next error: `error NG8001: 'tagify' is not a known element:

      1. If 'tagify' is an Angular component, then verify that it is part of this module.
      2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ` I tried to import Tagify and TagifyService into modules and providers inside app.module.ts but still the same. I've searched the documentation and other issues but still don't see how to start using it in Angular app.
      Help wanted 
      opened by skined90 17
    • Mix Mode - Safari caret position after new tag

      Mix Mode - Safari caret position after new tag

      Hi,

      In Safari for Mac, when adding a new tag, the cursor jumps to the start of the tag opposed to the end. This means when you start typing it actually types before the tag not after.

      I don't mind doing a bit of self diag, but could you point me in the right direction? Might need some sort of timeout before re-positioning the cursor after the tag add function has completed.

      --

      It would also be great if you can add the option in mix mode of forcing a space after a tag when added. I know currently it adds a zero width space, but it would be of benefit to have a visual space to maintain formatting when tags are used within a sentence.

      Thanks.

      Bug 
      opened by coding-tech-guy 17
    • Using Mixed Tags: How to add new Tags that are not listed in the whitelist?

      Using Mixed Tags: How to add new Tags that are not listed in the whitelist?

      Ì'm trying to create new Tags, which should be pushed thereafter into the whitelist.

      where does the check happen whether my new input is part of the white list or not? I'd have to change the code here.

      Question Suggestion 
      opened by Issabln 17
    • How to deal with originalInputValueFormat, enforceWhitelist, AJAX and browser going back (history)

      How to deal with originalInputValueFormat, enforceWhitelist, AJAX and browser going back (history)

      Prerequisites

      • [x] I am running the latest version
      • [x] I checked the documentation and found no answer
      • [x] I checked to make sure that this issue has not already been filed

      πŸ’₯ Demo Page

      https://jsbin.com/qucuzehuwa/1/edit?html,js,output

      Explanation

      • What I'm going to do?

        I would like to use AJAX to load a lot of tags from a database when the user starts typing, allowing him to choose only from existing tags (hence with enforceWhitelist enabled) and, at the same time, post only a numeric ID of the selected tags back to the server with a custom separator, when the form is submitted.

        So if the whitelist is: [{value: 1, name: "Apple"},{value: 2, name: "Banana"},{value: 3, name: "Lemon"}] and my typed tags are Apple and Lemon, I would like the original text input value to be 1|3 (with the | separator).

        This works perfectly with a code similar to the linked demo page above (where I introduced a delay on the whitelist populating, to simulate the AJAX call). But there are some issues with this approach.

      • What is happening instead?

      1. With enforceWhitelist set to true I could initialize the textbox value with the value saved on the DB (e.g. Apple only) but to avoid tagify to autoremove the tag, I have to pre-populate the whitelist at the same time with at least the saved value (e.g. [{value: 1, name: "Apple"}]). This could be done, but the numeric value is not parsed by tagify and neither its separator (see this example variation); in a nutshell value="1|2" doesn't work while value="Apple,Banana" does.
      2. ~Even if we don't consider the previous issue if I start with a blank whitelist (like the one in the JSBIN above), type a tag (which is accepted thanks to AJAX) post the form and then I go back using the browser, the tag is cleared because the whitelist starts blank. In this case I cannot apply #465 because I don't store the tags the user typed... how can this situation be handled? I see that Firefox v91 autocompletion works correctly by keeping the tags, while Microsoft Edge v92 / Chrome v93 when going back displays 1|3 for a brief moment and then the input is cleared of course, due to the empty whitelist.~ (EDIT: removed and opened a separate thread #898)
      • What is the expected behavior?
      1. Tagify should respect the originalInputValueFormat or provide another callback for the inverse function during the initialization. So tagify must be able to convert 1|3 into Apple, Lemon on its own using the whitelist (which still I must populate in advance; since it's not possible with AJAX probably I could pull it from the DB during the page initialization).
      2. Tagify should implement an event to be handled (like add) that is fired only on the initialization of the control? This way I could ask the DB if for example 2|3 are valid tags and then populate the whitelist as a consequence? ~Another thing to consider is that you cannot initialize tagify with enforceWhitelist: false and then set it to true programmatically; this would allow to start with enforceWhitelist turned off, load the information about the tags and set it to true after the whitelist has been populated~. (EDIT: use tagify.settings.enforceWhitelist to enable it afterward; see example here)

      Sorry for being quite long but I hope it's clear... basically the issues are during initialization of the tag values when using non-standard values (numeric ID instead of the names) and dealing with the browser going back with the input control already filled-in that gets cleared due to the missing whitelist (that cannot be fully loaded).

      opened by virtualdj 16
    • Pasted text separated with new line symbol doesn't process correct

      Pasted text separated with new line symbol doesn't process correct

      I have the latest version (2.22.3) and I have a code to initialize tagify:

      this.tagify = new Tagify(emails, {
                      delimiters          : ",| |:", 
                      suggestionsMinChars : 3,
                      maxTags             : 100,
                      keepInvalidTags     : true,
                      duplicates: false
                  }
              );
      

      If I paste lines like these, separated by new line symbol ('\n'):

      [email protected]
      [email protected]
      [email protected]
      [email protected]
      

      And then click enter - it doesn't process text in a correct way: Screen Shot 2019-06-26 at 12 10 50 As you can see it adds "||" symbols.

      Pasting works fine if I paste text separated by comma or whitespace.

      Thanks.

      Bug 
      opened by nikbo 16
    • Adding tags in mix-mode always puts caret at end of input

      Adding tags in mix-mode always puts caret at end of input

      Prerequisites

      • [x] I am running the latest version
      • [x] I checked the documentation and found no answer
      • [x] I checked to make sure that this issue has not already been filed

      πŸ’₯ Demo Page

      You can see this behavior on the demo page itself when adding tags in the middle of a sentence in the mix-mode example. The caret position after a tag is added is always at the end of the input no matter where the tag is

      https://yaireo.github.io/tagify/

      I believe this behavior was broken by the change made for this previous issue as I tested on different versions to confirm.

      https://github.com/yairEO/tagify/issues/1109 https://github.com/yairEO/tagify/commit/3860722afdc971ab58545d9c8f663af4d324dfd7

      Previously, this was working correctly when selecting a suggestion with keyboard and not working when selecting using a mouse

      Explanation

      • What is the expected behavior? The caret position appears immediately after the added tag when selecting a suggestion either using a keyboard or a mouse

      • What is happening instead? The caret position is always at end of input when adding a tag in mixed-mode

      opened by lohit8846 0
    • Pasted data into empty tag created via addEmptyTag automatically disappears on lost focus.

      Pasted data into empty tag created via addEmptyTag automatically disappears on lost focus.

      Prerequisites

      • [X] I am running the latest version
      • [X] I checked the documentation and found no answer
      • [X] I checked to make sure that this issue has not already been filed

      πŸ’₯ Demo Page

      You can see this behavior on your own demo page (https://yaireo.github.io/tagify). Under your 'Easy to customize' demo, click the + to create an empty tag and paste some data into it. Then simply make the tag lose focus and the tag is cleared.

      Explanation

      • What is the expected behavior? Pasted data should become a valid tag.

      • What is happening instead? Pasted data disappears.

      • What error message are you getting? None

      Bug: high priority 
      opened by gitgitwhat 1
    • Focus issues in firefox

      Focus issues in firefox

      Prerequisites

      • [x] I am running the latest version
      • [x] I checked the documentation and found no answer
      • [x] I checked to make sure that this issue has not already been filed

      πŸ’₯ Demo Page

      Can be done on the unmodified template as well, I've added extra padding and a border to show it better. https://jsbin.com/ruhotomezi/1/edit?html,js,output

      Steps to reproduce

      1. Open the above jsbin in firefox
      2. click anywhere in .tagify to focus it
      3. click again on .tagify but not on .tagify__input (aka the space between the actual input box and the outer .tagify)
      4. Observe that .tagify__input lost its focus while .tagify is still focused
      5. click anywhere else on the page to unfocus it
      6. Observer that the .tagify--focus is still present on the .tagify element

      Explanation

      • What is the expected behavior? Clicking anywhere on the .tagify should focus the input

      • What is happening instead? In Firefox, clicking on .tagify removes focus from .tagify__input, and the .tagify--focus class remains in the element even after losing focus.

      • What error message are you getting? none

      Notes

      On browsers other than firefox clicking on .tagify keeps the focus on .tagify__input.

      This can be especially annoying when .tagify__input doesn't take up the whole length of the input.

      opened by dumbasPL 0
    • On Safari 'Enter' button doesn't add new lines

      On Safari 'Enter' button doesn't add new lines

      Prerequisites

      • [x] I am running the latest version
      • [x] I checked the documentation and found no answer
      • [x] I checked to make sure that this issue has not already been filed

      πŸ’₯ Demo Page

      https://jsbin.com/rugeqoleri/1/edit?html,js,output

      Explanation

      Open in Safari 1.Type any text 2.Press Enter key - cursor moves to the next line 3.Press Enter key one more time or even more times - nothing happens

      • What is the expected behavior? Empty lines added to a text
      • What is happening instead? Nothing happens, cursor stays at the same position
      • What error message are you getting? No errors

      I think issue related with this part of code image when I remove underlined string error gone

      opened by pavel-nitka 1
    • Tagify settings option 'Callbacks' work on js version, but not on jquery version

      Tagify settings option 'Callbacks' work on js version, but not on jquery version

      Prerequisites

      • [x] I am running the latest version
      • [x] I checked the documentation and found no answer
      • [x] I checked to make sure that this issue has not already been filed

      Hi Yair, just confirming whether the callback{} setting is supposed to work with the Jquery version or not? (as it currently doesn't).

      This works new Tagify(inputId, {whitelist: blah, callback:{add: ()=>{console.log('blah')}}});

      But this doesn't work $('#id').tagify({whitelist: blah, callback:{add: ()=>{console.log('blah')}}});

      I realise you're not keen on the jquery version, but I'm preferring the jquery version as it permits access to the whitelist directly by whitelistTags = ($(inputId).data()).tagify.whitelist, instead of using a global variable var tagify = new Tagify and accessing tagify later.

      Unfortunately using jquery callback with bind/on('change',callback) will trigger the callback twice, whereas using the javascript callback methodology works correctly.

      Alternatively, is there a way to prevent the jquery callback on tag change triggering twice?

      Cheers

      opened by gidzr 1
    • Access tags list of tags which are added in text area

      Access tags list of tags which are added in text area

      Prerequisites

      • [x] I am running the latest version
      • [x] I checked the documentation and found no answer
      • [x] I checked to make sure that this issue has not already been filed

      React issue template: https://codesandbox.io/s/tagify-react-issue-template-4ub1r?file=/src/index.js

      I am implementing tagify in my react app and I am building my custom dropdown and I want to add tags onClick on tags from my custom dropdown.

      If this is not possible to add tags from custom dropdown then How can I access the tags list or array in which I can append on click in my custom dropdown.

      Clarification required 
      opened by Yawan-1 1
    Releases(v4.17.6)
    • v4.17.6(Dec 4, 2022)

    • v4.17.5(Dec 3, 2022)

      • Undoing #384 fix as it seems. This also fixes #1153 4224eb9

      • changes React file from js to jsx 5556c33

      • fixes #1155 - should again take inco consideration the dropdown might be open when the timeout fires 7f6f787

      • fixes #1154 - "isCaretAfterTag" is sometimes "true" and not an element, so make sure it's an element before continuing 6317fc7

      • mix-mode is better initialized by default with dropdown.position as text 903444c

      • added missing argument in function's comment 1ec88c3

      • added pnpm lock file 17e2884

      https://github.com/yairEO/tagify/compare/v4.17.4...v4.17.5

      Source code(tar.gz)
      Source code(zip)
    • v4.17.4(Nov 19, 2022)

      • for auto-complete, should be mapped b6bdcea
      • suggested text must be a string and not number, and also should be initialized if data is empty so value is an empty string ac7e5f8
      • Deepscan errors fixes 63a8934
      • fixes #1150 - autosuggest should use getMappedValue in order to find the best match for the string f0f9529

      https://github.com/yairEO/tagify/compare/v4.17.3...v4.17.4

      Source code(tar.gz)
      Source code(zip)
    • v4.17.3(Nov 17, 2022)

      • fixes #1149 - Caret placement is at begining (and not end) after calls to editTag 22c90ec
      • fixes #1148 - calling setRangeAtStartEnd with wrong 2nd parameter 869f1da

      https://github.com/yairEO/tagify/compare/v4.17.2...v4.17.3

      Source code(tar.gz)
      Source code(zip)
    • v4.17.2(Nov 16, 2022)

      • fixes #1147 - Accessing to the settings' dropdown property without it existing 2c53c57

      https://github.com/yairEO/tagify/compare/v4.17.1...v4.17.2

      Source code(tar.gz)
      Source code(zip)
    • v4.17.1(Nov 15, 2022)

      • removed exports from package.json as it seemed to have caused problems with importing the package due to misconfiguration. Will work on that more. cc93ccc
      • moved tagData from the prototype to the "helpers" file, and renamed it getSetTagData 3acff13

      https://github.com/yairEO/tagify/compare/v4.17.0...v4.17.1

      Source code(tar.gz)
      Source code(zip)
    • v4.17.0(Nov 12, 2022)

      • fixes #1115 - setRangeAtStartEnd should not unfocus another focused element which is not the current tagified component. d112fa7
      • fixes #1129 - dropdown.enabled setting should be considered in select-mode 41f227e
      • refactor after moving methods to helpers file 0ebabd1
      • fixes #1131 - when editing a tag, pasted content should be sanitized 49b83f9
      • moved methods to helpers.js file: injectAtCaret, setRangeAtStartEnd, getCaretGlobalPosition 99b9c48
      • added "exports" property for proper ESM consumption 6528772
      • fixes #1137 - never automatically trim original value (in mix mode) and let the author handle any trimming from outside 8631d68
      • fixes #1142 - introeduced deboucning mechanism to the update method to avoid cases when it is called succeedingly, so only the last call should be executed. cff6a1b
      • Fixes #1143 - Removed InstallTrigger Firefox detected due to annoying console warning in Firefox saying it is deprecated. Replaced with user-agent parsing 278cca8
      • packages update 298654e

      https://github.com/yairEO/tagify/compare/v4.16.4...v4.17.0

      Source code(tar.gz)
      Source code(zip)
    • v4.16.4(Sep 3, 2022)

      • fixes #1103 - Enter/tab don't work as delimiters for dropdown position 'manual' d16145f
      • improved custom suggestions list demo when nothing is found 9378853
      • fixes #1113 - support disallowing user input in select-mode 3d50e58

      https://github.com/yairEO/tagify/compare/v4.16.3...v4.16.4

      Source code(tar.gz)
      Source code(zip)
    • v4.16.3(Sep 1, 2022)

      • fixed typo 02aae13
      • improved demo to be more complex 6a93257
      • fixes #1108 - Dropdown position is incorrect when element enters fullscreen mode b019c41
      • fixes #1109 - when selecting a suggestion with the mouse, in mix-mode, the caret appears at the start after the tag was added 3860722
      • changed author to the short version 1a9ffae

      https://github.com/yairEO/tagify/compare/v4.16.2...v4.16.3

      Source code(tar.gz)
      Source code(zip)
    • v4.16.2(Aug 19, 2022)

      • fixes #1101 - Suggestion list position not updated when tagify is in a scrollable container (other than &lt;body&gt;) 2380363
      • fixes #1099 - incorrect suggestions-autocomplete when suggestions are highlighted e2f0bed

      https://github.com/yairEO/tagify/compare/v4.16.0...v4.16.2

      Source code(tar.gz)
      Source code(zip)
    • v4.16.0(Aug 15, 2022)

      • fixes #1098 - Added new dropdown setting includeSelectedTags which allows showing already-selected tags in the suggestions dropdown defcedf

      https://github.com/yairEO/tagify/compare/v4.15.4...v4.16.0

      Source code(tar.gz)
      Source code(zip)
    • v4.15.4(Aug 13, 2022)

      • fixes #1094 - Suggestions dropdown does not highlight first item 229af64
      • improved CSS selectors for the users-list example 13e311a
      • fixes #1022 - 'Event.path' is deprecated 4ca3a2d
      • renamed originalEvent to event in multiple events - removed cloneEvent in EventDispatcher.js since it was already defined apparently in tagify.js 897561f

      https://github.com/yairEO/tagify/compare/v4.15.3...v4.15.4

      Source code(tar.gz)
      Source code(zip)
    • v4.15.3(Aug 5, 2022)

      • fixes #1032 - Delete key deletes tags in other Tagify instances when dropdown.enabled is set to false 948c2d0
      • fixes #1059 - in FF 47, let keyword in a for loop does not creates a scope c0aea5e
      • fixes #1091 - dropdown setting mapValueTo breaks previous changes which deprecated tagifySuggestionIdx in favor of value (which is unique and should not be mapped when applied to the template) 23811c0

      https://github.com/yairEO/tagify/compare/v4.15.2...v4.15.3

      Source code(tar.gz)
      Source code(zip)
    • v4.15.2(Jul 31, 2022)

      urgent bugfix - suggestions can also be an array of strings (and not objects) bada36e

      https://github.com/yairEO/tagify/compare/v4.15.1...v4.15.2

      Source code(tar.gz)
      Source code(zip)
    • v4.15.1(Jul 30, 2022)

      • fix navigation issues when selecting an item with the arrows keys or ENTER key 14763e9
      • fixed keyboard navigation for complex suggestions dropdowns and changed tagifySuggestionIdx to point to the unique value rather than the index in the suggestions array ec82221

      https://github.com/yairEO/tagify/compare/v4.15.0...v4.15.1

      Source code(tar.gz)
      Source code(zip)
    • v4.15.0(Jul 30, 2022)

      • added support for sending the original event to the "trigger" events method cd70179
      • added support for transitioning-out the selected suggestion item 2199473
      • when removing all tags, the dropdown should re-filter, because that action might have been triggered from inside the dropdown, and it might still be open e9534ad
      • added dropdown variables to knobs in the examples page 34b4c5f
      • refactored users-list CSS example to use --tagify-dd-item-pad variable instead of hard-coded property setter 7fae41a
      • minor improvements to the horizontal tags hidden transition e6139c9
      • attach a custom property __tagify`` reference to the Tagify instance on the original input and is now returning that instance if the same original input is re-tagified (for some reason) 02902be
      • chore - added README info for some new CSS variables + ones which were not mentioned before regarding the suggestions dropdown f290462
      • fixes #1054 - underlying Tagify shoud not get focused when selecting a suggestion from a Tagify sugegstion dropdown which is rendered over it. b2aa6a7
      • chore - added an item to the FAQ in README 0dbbfc9
      • fixes #1074 - do not create tags from invalid input. Added the new createInvalidTags setting e446b1d
      • fixes #1082 - add an easy was to set tags border-radius using CSS variables 8b6e00c
      • Update index.html for a problematic HTML markup (#1083) 2246bc4

      https://github.com/yairEO/tagify/compare/v4.14.1...v4.15.0

      Source code(tar.gz)
      Source code(zip)
    • v4.14.1(Jul 25, 2022)

      • fixes a bug where select-mode was marked as invalid on first load, if was empty 7622f32
      • fixes #1080 - in select-mode with mapValueTo if the more than one mapped property is identical, a mismatch is happening during blur event. Also normalizeTags should not try to match items from the whitelist if the argument is a collection ef6abff
      • fixes #1081 - in "select" mode, manually removing the value and re-selecting an option is stuck as "invalid - empty" c03e594
      • fixes #1076 - CDN links updated from unpkg to jsdeliver 3b84145

      https://github.com/yairEO/tagify/compare/v4.14.0...v4.14.1

      Source code(tar.gz)
      Source code(zip)
    • v4.14.0(Jul 20, 2022)

      • improved the explenation for the Tags with properties section in the examples page d893323
      • fixes #1055 - added new setting onChangeAfterBlur which when set to false, fires the onChange event on every change and not only when the field is blured 2dad0de
      • fixes #1068 - memory leak when interval was not cleared when the instance is destroyed or the original input is no longer in the DOM 5b4b69f
      • Fixes typos in 'Tags with Properties' section (#1070) a4fc91a

      https://github.com/yairEO/tagify/compare/v4.13.3...v4.14.0

      Source code(tar.gz)
      Source code(zip)
    • v4.13.3(Jul 13, 2022)

      • fixes #1064 - Tagify input box is focused when clicking outside beside/below the input box 4060b04
      • fixes #1067 - select-mode ignores setReadonly(true) method f1f89e5
      • fixes #1062 - edited tag with only changed casing is wrongfully marked as dulpicate 9f30756

      https://github.com/yairEO/tagify/compare/v4.13.2...v4.13.3

      Source code(tar.gz)
      Source code(zip)
    • v4.13.2(Jul 11, 2022)

      • #1062 - When editing a tag, "__tagId" is needed so validation will skip current tag when checking for dups 5593105

      https://github.com/yairEO/tagify/compare/v4.13.1...v4.13.2

      Source code(tar.gz)
      Source code(zip)
    • v4.13.1(Jul 9, 2022)

      • fixes #1050 - added the this instance scope as the second parameter to the tag template react 757e179

      https://github.com/yairEO/tagify/compare/v4.13.0...v4.13.1

      Source code(tar.gz)
      Source code(zip)
    • v4.13.0(Jul 9, 2022)

      • Filter only the dropdown-item elements (not header/footer/custom ones) when moving with up/down arrows c97aecd
      • Refactored and fixed the escape scenario when editing tags, so the original tag is now being replaced back correctly 008f10e
      • Changed "__originalHTML" to point to a cloned element instead of innerHTML, so when pressing escape, it will be replaced back to that, as-is 81d49b9
      • Fixes #1056 - Selected tag disappears after the input loses focus when in select mode. a8b5d2a
      • Merge branch 'master' of https://github.com/yairEO/tagify dde8fbc
      • Update templates.js (#1060) b51c690
      • Merge branch 'master' of https://github.com/yairEO/tagify 6efcc53
      • Update tagify.test.js (#1061) 86f0bc7
      • Improved users-list demo 03fb265
      • Added function comment 87e916a
      • Added some new methods 1da2156
      • Refactored editTag method and added 3 new methods: editTagChangeDetected, getTagTextNode & setTagTextNode 820f5f4
      • Fixes #1044 - add missing css color variable to the suggested text 184ad0f
      • Mentioned more templates recently added d792c48
      • Fixes #1042 - Tag doesn't get added on selecting value from custom template dropdownItemNoMatch 987af67
      • Fixed typo acd2b6b
      • Fixed some typos and added async validation example 776a9eb
      • Fixes #1046 - clicking an uneditable tag when the editTags settings is set to clicks: 1 gives focus to the Tagify field which cannot be unfocused by clicking outside cfd3e0c
      • Removed data-editable attribute for tags done in previous commit. better its added by the developer and not automatically by Tagify bdc22bd
      • Refactored. removed all CSS variables fallbacks to SCSS variables because they already have fallbacks... 3dedfbe
      • Added "data-editable" for tags (default is undefined which means "true") bca7bae
      • Removed unneeded left-trim because the the returned value is already trimmed 516c2b2
      • Updated eslintrc file eea6e21
      • Removed unused package gulp-eslint 00766e0
      • Updated eslintrc file 21c9ae9
      • Fixes #1037 - support originalInputValueFormat setting in mix-mode 5a0de8f
      • Fixed some mix-mode issues with new line before/after tags in FF/Chrome. Still a bug for new line before a tag in FF causes double BRs ec6444a
      • Fixed placeCaretAfterNode after last change in the function 4da5ef4
      • Packages versions bump a14a1f6
      • Fixes #1035 - Editing a tag, allows you to have duplicated tags (case insenstitve) c3502e4
      • Removed the fix done for #653 as it seems fixed in Chrome 7ab28fd
      • Fixes #1036 - injecting a tag node using injectAtCaret without prior focus results in an error 041e727
      • Fix yairEO/tagify#1038 Changed order of if clauses in iterateChildren function (#1039) 1da6bce
      • Fixing typo (#1021) def256f

      https://github.com/yairEO/tagify/compare/v4.12.0...v4.13.0

      Source code(tar.gz)
      Source code(zip)
    • v4.12.0(Apr 25, 2022)

      • editing existing valid tag by adding spaces before or after, should not affect validation, unless the trim setting is false 7125bab
      • fixes #1019 - transformTag setting can make a tag invalid when editing 32b3eb6
      • exposed the helpers for outside usage acf4a88
      • added a comment 381ee1d
      • fixes #1013 - dropdownFooter shows "Refine your search" when maxItems = 0 (which shows all items) 9723e6e
      • added an example to the manual tests 2cd4c6a
      • Fixed anchor link in index.html (#1014) 43b7e20

      https://github.com/yairEO/tagify/compare/v4.11.0...v4.12.0

      Source code(tar.gz)
      Source code(zip)
    • v4.11.0(Apr 10, 2022)

      • improved the example for the users-list. it now uses the new dropdown header template instead of the hacky way it used to work 35d4b7a
      • stop adding a tag when blured in select-mode - when typing a tag and blurring, if the typed text is not included in the whitelist, it will be cleared 4ad26d8
      • do not render the dropdown header template if there's nothing in it d4bfee4
      • added 2 new templates for dropdown header & footer 45b902c
      • fixes #986 - keyboard shortcut for bold and italic interfere with mix-mode output c5fbcae
      • for "select" mode - if text value is not in the whitelist, clear it once the input is blured 0365d68
      • fixes #1001 - Tagify can change a tag value to its tagTextProp under mysterious circumstances 776c063
      • fixes #1008 - destroy() method throws DOM not defined exception 53610f2

      https://github.com/yairEO/tagify/compare/v4.10.0...v4.11.0

      Source code(tar.gz)
      Source code(zip)
    • v4.10.0(Apr 5, 2022)

      • now same styles as applied for "readonly" will also apply to "disabled", mainly so the X button will not be rendered d4c6cfd06e
      • docs(README): grammar and spelling (#1006) 4857567
      • fixes #996 - use the same license all across 7014d7d
      • fixes #998 - Grammarly is messing with the tag input 263975b
      • fixes #1000 - Changing writing direction in mix-mode removes that line from the original input's value 81a1ca7
      • fixes #1004 - Disable spellcheck for select-mode 49819e1
      • fixes #1003 - disallow tab focus to the original input cba082c
      • fixes #1002 - setDisabled doesn't completely disable the input [should not allow click to tab focus] 492bd08

      https://github.com/yairEO/tagify/compare/v4.9.8...v4.10.0

      Source code(tar.gz)
      Source code(zip)
    • v4.9.8(Feb 17, 2022)

      • fixes #989 - fix XSS 198c045
      • removed unneeded line after recent change which moved this to another onEditDone 93f729c
      • fixes #984 - Readonly tags can be deleted by Backspace d675c3f
      • bugfix - in mix-mode, place the caret after a tag which was just edited, instead of before it 9d0787d
      • fixes #987 - edit tag bug 0f1ebbc

      https://github.com/yairEO/tagify/compare/v4.9.7...v4.9.8

      Source code(tar.gz)
      Source code(zip)
    • v4.9.7(Feb 13, 2022)

      • fixes #982 - "strim" setting has no affect on "loadOriginalValues" when in mix-mode 95aab51
      • fix syntax error in README example (#981) 80d623f

      https://github.com/yairEO/tagify/compare/v4.9.6...v4.9.7

      Source code(tar.gz)
      Source code(zip)
    • v4.9.6(Feb 6, 2022)

      • minor syntax and comments changes c2a9951
      • added "help with something" issue templates 88ab9c4
      • fixes #972 - Unable to edit tags when they reached to maxTags cd9e13a
      • fixes #974 - make the striped background on readonly an opt-out feature 4894c53
      • re-ordered classNames cf2be53
      • added "readonly" to be able to be configured from the settings and not only as an attribute on the original input f3ad3a6
      • fixes #978 - dropdown.enabled:false has no effect 45b2a8a
      • Fix typo (#977) e91e0f7

      https://github.com/yairEO/tagify/compare/v4.9.5...v4.9.6

      Source code(tar.gz)
      Source code(zip)
    • v4.9.5(Jan 24, 2022)

      • fixes #925 - Don't trigger onChange event for loadOriginalValues 48c166f
      • [bugfix] mock tagify methods when input element does not exists 155c3fc
      • -fixed icons links - changed placeholder text for "outside" example 317ac66
      • fixes #958 - unable to type after calling tagify.removeAllTags() in select-mode ab5ec31
      • fixes #949 -Tagify recieves focus when clicking outside, on the same line. The extra unicode was causing height probelms 35ea533
      • fixes #910 - backspace removes previous item when there are extra spaces fe8833f
      • fixes #949 -Tagify recieves focus when clicking outside, on the same line. see https://stackoverflow.com/a/34445203/104380 f74c157

      https://github.com/yairEO/tagify/compare/v4.9.2...v4.9.5

      Source code(tar.gz)
      Source code(zip)
    • v4.9.2(Nov 27, 2021)

      • fixes #951 - add callback moved to be triggered after DOM has been modified b70061a
      • fixes #950 - tag is set as readonly even though tagData has key readonly:false 4fbc41c

      https://github.com/yairEO/tagify/compare/v4.9.1...v4.9.2

      Source code(tar.gz)
      Source code(zip)
    Owner
    Yair Even Or
    As a programmer I very much enjoy making front-end things like Components, CSS stuff, and beautiful javascript code. I also love growing plants very much
    Yair Even Or
    jQuery tags input plugin based on Twitter Bootstrap.

    Bootstrap Tags Input Bootstrap Tags Input is a jQuery plugin providing a Twitter Bootstrap user interface for managing tags. Current stable version: v

    null 26 Dec 21, 2022
    This is a JQuery plugin for input tags with auto complete suggestion.

    Jquery Suggestags This is a JQuery plugin for input tags with auto complete suggestion. $('input').amsifySuggestags(); npm installation npm i suggesta

    Amsify42 60 Nov 16, 2022
    A Pure JavaScript Solution to create Tags Input Element.

    JavaScript Tags Input Library Native JavaScript library to make Tags Input Element in DOM. There isn't any dependency for this library, add it straigh

    Qamar ALi 11 Jun 27, 2022
    EggyJS is a Javascript micro Library for simple, lightweight toast popups focused on being dependency-less, lightweight, quick and efficient.

    EggyJS EggyJS is a Javascript micro Library for simple, lightweight toast popups. The goal of this library was to create something that meets the foll

    Sam 10 Jan 8, 2023
    Grayce Muthui 8 Jun 16, 2022
    A Bootstrap plugin to create input spinner elements for number input

    bootstrap-input-spinner A Bootstrap / jQuery plugin to create input spinner elements for number input. Demo page with examples Examples with floating-

    Stefan Haack 220 Nov 7, 2022
    dynamic-component-app is an angular application for dynamic component template creation

    MyApp This project was generated with Angular CLI version 14.1.0. Development server Run ng serve for a dev server. Navigate to http://localhost:4200/

    Aniket Muruskar 7 Aug 26, 2022
    Lightweight vanilla js modal component (just 2kb) , pure javascript Modal

    Lightweight vanilla js modal component (just 2kb) pure javascript Modal , This is just 2kb Lightweight vanilla js modal component with zero dependenci

    Salah Eddine Lalami 12 Dec 12, 2022
    Create sticky element in flexbox sidebars. it can use in Vanilla JS and frameworks like Vue and React

    js sticky side simple sticky side with js that can use in frameworks like vue and react. notes it can be used just in flexbox grids. target element sh

    milad nazari 10 Mar 3, 2022
    A fast, vanilla JS customisable select box/text input plugin for modern browsers ⚑

    choices A fast, vanilla, lightweight (~16kb gzipped ?? ), configurable select plugin for modern browsers. Similar to Select2 and Selectize but without

    null 9 Aug 9, 2022
    vanilla javascript input mask

    imaskjs vanilla javascript input mask Features get and set raw and unmasked values easily no external dependencies supports overwrite mode supports we

    Alexey Kryazhev 4.1k Dec 30, 2022
    A simple easy to use vanilla JavaScript library for creating input fields that accept multiple email addresses

    MeiMei - Multiple Email Input MeiMei: A simple easy to use vanilla JavaScript library for creating input fields that accept multiple email addresses.

    Lars Straathof 1 Apr 13, 2022
    🌐 Text Input Component for validating and formatting international phone numbers.

    React Native Intl Phone Field Try the Expo Snack ?? ??️ Demo It's a javascript-only (no native code) component that can run in iOS, Android, Expo & Re

    Ivanka Todorova 24 Jul 8, 2022
    Beautiful UI-Range input component, highly customisable, based on CSS variables.

    Beautiful UI-Range input component, highly customisable, based on CSS variables. including a floating output value, min & max values on the sides & ticks according to the steps

    Yair Even Or 73 Dec 27, 2022
    A Masked Input Component based on Ant Design.

    antd-input-mask A Masked Input Component based on Ant Design. Usage Example Contributing How to run PR template Issue template Developed by bem-te-vi

    bem.te.vi 6 Oct 24, 2022
    Firebase Storage with Angular 14 example: Upload File, Retrieve, Display, Download Url & Delete using @angular/fire AngularFireStorage

    Angular 14 File Upload to Firebase Storage example I will show you how to make Angular 14 Firebase Storage: File Upload/Display/Delete Application usi

    null 7 Sep 7, 2022
    Angular JWT refresh token with Interceptor, handle token expiration in Angular 14 - Refresh token before expiration example

    Angular 14 JWT Refresh Token example with Http Interceptor Implementing Angular 14 Refresh Token before Expiration with Http Interceptor and JWT. You

    null 8 Nov 30, 2022
    A package to toggle properties of your HTML tags.

    Toggler A package(atleast the code) to toggle properties of tags. I mostly use toggle classes while making a switch theme method, button interaction e

    chandra sekhar pilla 6 Jan 9, 2022
    Bootstrap5-tags - Replace select[multiple] with nices badges

    Tags for Bootstrap 4/5 How to use An ES6 native replacement for select using standards Bootstrap 5 (and 4) styles. No additional CSS needed! Supports

    Thomas Portelange 75 Jan 9, 2023