├── README.md ├── _config.yml ├── index.html ├── main.css └── main.js /README.md: -------------------------------------------------------------------------------- 1 | JavaScript Label creator is a very handy UI component for collecting options, search filters etc from users. It make it easy for users to make their selections and add or remove tags. 2 | You can add tags/labels, and also be able to delete them. 3 | The vanilla JavaScript code light and is heavily commented for easy understanding. 4 | I hope you find it useful. 5 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Label creator || Iyobosa Jefferson Osagie 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

HTML, CSS, Vanilla JS Label/tag creator

15 | You can also use the Enter key to create tag 16 |
17 | 18 |
19 |
20 | 21 |
22 | 23 |
24 |
With Love by Jefferson Iyobosa
25 |
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | position: relative; 3 | padding: 0px 3px; 4 | margin: 0px; 5 | font-family: nunito; 6 | } 7 | 8 | button{ 9 | cursor: pointer; 10 | outline: none; 11 | padding: 15px 20px; 12 | border-radius: 3px; 13 | border: none; 14 | box-shadow: 5px 5px 2px rgba(0,0,0,.08); 15 | background: #ff5555; 16 | width: 50%; 17 | margin: 8px auto; 18 | display: flex; 19 | justify-content: center; 20 | color: #fff; 21 | text-align: center; 22 | transition: .8s; 23 | font-size: 18px; 24 | } 25 | button:hover{ 26 | box-shadow: none; 27 | transition: .8s; 28 | } 29 | input{ 30 | outline: none; 31 | -webkit-appearance: none !important; 32 | height: 40px; 33 | padding: 10px; 34 | font-size: 16px; 35 | align-self: center; 36 | flex: 1; 37 | box-sizing: border-box; 38 | border: none !important; 39 | min-width: 80px; 40 | color: #aaa; 41 | } 42 | input:focus{ 43 | background: #fff !important; 44 | } 45 | 46 | .container{ 47 | margin: 10% auto; 48 | width: 100%; 49 | max-width: 400px; 50 | box-sizing: border-box; 51 | padding: 20px; 52 | border-radius: 3px; 53 | box-shadow: 0px 10px 30px rgba(0,0,0,.08) 54 | } 55 | .container > *{ 56 | border: 1px solid #ddd; 57 | padding: 20px; 58 | width: 100%; 59 | box-sizing: border-box; 60 | box-shadow: 0px 0px 30px rgba(0,0,0,.03) 61 | } 62 | .container > *:first-child, 63 | .container > *:last-child{ 64 | background: #f2f2f2; 65 | } 66 | .container > *:first-child{ 67 | border-bottom: none; 68 | border-top-right-radius: 3px; 69 | border-top-left-radius: 3px; 70 | } 71 | .container > *:last-child{ 72 | border-top: none; 73 | border-bottom-right-radius: 3px; 74 | border-bottom-left-radius: 3px; 75 | } 76 | .container .intro{ 77 | padding-top: 5px; 78 | text-align: center; 79 | font-size: 14px; 80 | } 81 | .container .intro h2, 82 | h3{ 83 | margin: 3px 0px; 84 | } 85 | .container a{ 86 | padding: 5px 8px; 87 | border-radius: 10px; 88 | color: #222; 89 | font-size: 14px; 90 | } 91 | .container .message{ 92 | width: 100%; 93 | padding: 10px; 94 | text-align: center; 95 | border-bottom: none; 96 | color: #ff5555; 97 | text-transform: capitalize; 98 | transform: scale(1); 99 | display: block; 100 | transition: .3s ease-out; 101 | } 102 | .container .message.hidden{ 103 | transform: scale(0); 104 | display: none; 105 | transition: .3s ease-out; 106 | } 107 | .container .archive{ 108 | width: 100%; 109 | box-sizing: border-box; 110 | margin: 0px auto !important; 111 | height: auto; 112 | padding: 3px; 113 | border: 1.2px solid #ddd; 114 | background: #fff; 115 | border-radius: 3px; 116 | display: flex; 117 | flex-wrap: wrap; 118 | align-items: flex-start; 119 | min-height: 40px; 120 | } 121 | .container .archive .label{ 122 | background: #f2f2f2; 123 | color: #222; 124 | font-size: 16px; 125 | box-sizing: border-box; 126 | display: flex; 127 | align-items: center; 128 | padding: 5px 8px; 129 | border-radius: 3px; 130 | border:1px solid #ddd; 131 | font-size: 12px; 132 | text-align: center; 133 | margin: 3px; 134 | animation: .3s tada ease-out; 135 | } 136 | .container .archive .label .delete-tag{ 137 | margin-left: 5px; 138 | font-size: 18px; 139 | cursor: pointer; 140 | font-weight: 800; 141 | } 142 | .container .archive .label #delete-tag:hover{ 143 | color: #000; 144 | } 145 | @keyframes tada{ 146 | from { 147 | transform: scale(0); 148 | } 149 | to { 150 | transform: scale(1); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | // DOM variables 2 | 3 | var form = document.querySelector("form"); 4 | var input = document.querySelector("#collect"); 5 | var container = document.querySelector(".archive"); 6 | var submit = document.querySelector("button"); 7 | var message = document.querySelector(".message"); 8 | // Adding event to the Add Label button 9 | 10 | 11 | // Array to hold the labels entered for backend export 12 | var labelsForExport = []; 13 | 14 | // To manipulate the DOM 15 | var labelsElements = []; 16 | 17 | // Process the value from the input 18 | function processInput(tag){ 19 | let inputValue = tag.value; 20 | // Get rid of white space 21 | let trimmedTag = inputValue.trim(); 22 | 23 | // Send the input to the export array 24 | labelsForExport.push(trimmedTag.toLowerCase()); 25 | return trimmedTag 26 | }; 27 | 28 | // Create the labels 29 | function createTag(tag){ 30 | // Create label Elements 31 | let div = document.createElement("div"); 32 | let textNode = document.createElement("span"); 33 | let deleteTag = document.createElement("span"); 34 | 35 | // Set elements' properties 36 | div.className = "label"; 37 | textNode.className = 'text'; 38 | deleteTag.className = "delete-tag"; 39 | 40 | textNode.innerText = tag; 41 | deleteTag.innerHTML = "×"; 42 | // Append the elements inside the label 43 | div.appendChild(deleteTag); 44 | div.prepend(textNode); 45 | // Add a unique data-attribute to the label 46 | div.setAttribute('data-tag', tag); 47 | deleteTag.setAttribute('data-target-tag', tag); 48 | // Add to the labelsELement array 49 | labelsElements.push(div); 50 | // return created element 51 | return div; 52 | } 53 | 54 | 55 | // Create tag on button click 56 | function newTagInstance(){ 57 | // Start a new instance of Making the tag 58 | let newTag = processInput(input); 59 | let createdTag = createTag(newTag); 60 | 61 | // Append the tag before the input 62 | container.insertBefore(createdTag, input); 63 | // Reset/clear the input field 64 | input.value = ""; 65 | 66 | } 67 | 68 | submit.addEventListener('click', ()=>{ 69 | // Preventing reloading of page when submitting 70 | form.addEventListener("submit", (e)=>{ 71 | e.preventDefault(); 72 | }); 73 | // Preventing submission of empty input and duplicate label 74 | if (input.value == "" ) { 75 | message.innerText = "Please input a value!" 76 | message.classList.remove("hidden"); 77 | }else if( labelsForExport.includes(input.value.toLowerCase()) ){ 78 | message.classList.remove("hidden"); 79 | message.innerText = "Label already exists!" 80 | } 81 | else{ 82 | message.classList.add("hidden"); 83 | newTagInstance(); 84 | } 85 | setTimeout(()=>{message.classList.add("hidden")}, 2000) 86 | }); 87 | 88 | 89 | // Delete the particular label when the delete icon on it is clicked 90 | document.addEventListener("click", deleteTag) 91 | function deleteTag(e){ 92 | // Check if the click was on the right tag 93 | if (e.target.className == 'delete-tag' ) { 94 | let purgeTag = e.target.getAttribute('data-target-tag'); 95 | // Loop through the array and match the selected label for deletion 96 | labelsElements.forEach((label)=>{ 97 | if (label.getAttribute("data-tag") === purgeTag) { 98 | let index = labelsElements.indexOf(label); 99 | // Remove and update the array of labels 100 | labelsForExport.splice(index, 1); 101 | labelsElements.splice(index, 1); 102 | // Remove the label from the DOM 103 | container.removeChild(label); 104 | } 105 | }) 106 | } 107 | 108 | } 109 | 110 | --------------------------------------------------------------------------------