tags (pure js)

by slawe

HTML

<div class="tags-wrapper">
  <input type="text" id="input-tags" data-name="tags" placeholder="Enter article tags separate with comma..." />
</div>

CSS

.tags-wrapper{
  float:left;
  border:1px solid #ccc;
  padding:5px;
  font-family:Arial;
}
.tags-wrapper span.tag{
  cursor:pointer;
  display:block;
  float:left;
  padding:5px;
  padding-right:25px;
  margin:4px;
  color:#ffffff;
  background:#0082FE;
}
.tags-wrapper span.tag:hover{
  opacity:0.7;
}
.tags-wrapper span.tag:after{
 position:absolute;
 content:"x";
 border:1px solid;
 padding:0 4px;
 margin:3px 0 10px 5px;
 font-size:10px;
}
.tags-wrapper input{
  background:#eee;
  border:0;
  margin:4px;
  padding:7px;
  width:auto;
}

JavaScript

let tags = {

	input: document.getElementById('input-tags'),
  hidden: null,
	
  init: function() {
  	let that = this,
    		field = that.input,
        hiddenInput = document.createElement('input');
    
    hiddenInput.setAttribute('type', 'hidden');
    hiddenInput.setAttribute('name', that.input.getAttribute('data-name'));
    that.hidden = hiddenInput;
    
  	that.makeTag(field);
    field.addEventListener('keydown', function(e) {
    	let keyCode = e.which || e.keyCode,
      		tags = document.querySelectorAll('.tag');
          
    	if (keyCode === 8 && this.value.length === 0 && tags.length > 0) {
        [...tags].at(-1).remove();
        that.update();
      }

      if([13, 188].includes(keyCode) && this.value.length > 0) {
      	e.preventDefault();
    		that.makeTag(this, false);
        return;
      }
    });
  },
  
  clear: function(el, commaAllowed = true) {
  	let reg = commaAllowed ? /[^a-z0-9,]/gi : /[^a-z0-9]/gi;
  	let text = el.value.replace(reg,'');
    return text.toLowerCase();
  },
  
  makeTag: function(el, commaAllowed) {
  	let val = this.clear(el, commaAllowed);
    
  	if(val) {
    	let arr = val.split(',');
      
      for(let i in arr) {
        let parentNode = el.parentNode;
        let tagNode = this.htmlToNode('<span class="tag">'+arr[i]+'</span>');
        parentNode.insertBefore(tagNode, el);
      }
    }
    
    el.value = '';
    this.removeTag();
    this.update();
  },
  
  removeTag: function() {
  	let that = this;
  	document.querySelectorAll('.tag').forEach(tag => {
    	tag.addEventListener('click', function(e) {
      	this.remove();
    		that.update();
      });
    });
  },
  
  update: function() {
  	let array = Array.from(document.querySelectorAll('.tag')).map(function(e, i) {
    	return e.innerHTML;
    });
    this.hidden.value = array.join(',');
  },
  
  htmlToNode: function(htmlString) {
    let div = document.createElement('div');
    div.innerHTML = htmlString.trim();
    return...