<div>
    <div class="acl-tag-input__container">
        <div class="acl-tag-input__display"></div>
    </div>
</div>

<script>
    const tagEl = document.querySelector('.acl-tag-input__container');
    const tagsInput = new acl.ACLTagInput(tagEl, {
        tags: ['Tag 1', 'Tag 2', 'Tag 3']
    });
    tagEl.addEventListener('tagadded', event => {
        console.log(`tagadded => ${event.detail}`);
    });
    tagEl.addEventListener('tagremoved', event => {
        console.log(`tagremoved => ${event.detail}`);
    });
</script>
<div>
	<div class="acl-tag-input__container">
		<div class="acl-tag-input__display"></div>
	</div>
</div>

<script>
	const tagEl = document.querySelector('.acl-tag-input__container');
	const tagsInput = new acl.ACLTagInput(tagEl, { tags: ['Tag 1', 'Tag 2', 'Tag 3']});

	tagEl.addEventListener('tagadded', event => {
		console.log(`tagadded => ${event.detail}`);
	});

	tagEl.addEventListener('tagremoved', event => {
		console.log(`tagremoved => ${event.detail}`);
	});
</script>
/* No context defined. */
  • Content:
    
    .acl-tag-input {
        border: none;
        flex: 1;
        background-color: rgba(0, 0, 0, 0);
    
        &__container {
            display: flex;
            border: 1px solid #e0e0e0;
            padding: 10px;
            flex-wrap: wrap;
            border-radius: 5px;
            cursor: text;
            min-height: 23px;
        }
    
    
        &__display {
            display: flex;
            flex-wrap: wrap;
            flex: 1;
            gap: 5px;
        }
    
        &__tag {
            display: flex;
            color: white;
            align-items: center;
            border-radius: 3px;
            padding: 2px 7px;
            background: #35c3aa;
    
            &-title {
                margin-right: 3px;
                font-size: 14px;
            }
    
            &-icon {
                font-size: 14px;
                max-width: 14px;
            }
    
            &-close-btn {
                display: flex;
                cursor: pointer;
            }
        }
    }
  • URL: /components/raw/tag-input/acl-tag-input.scss
  • Filesystem Path: src/components/tag-input/acl-tag-input.scss
  • Size: 848 Bytes
  • Content:
    class ACLTagInput {
    	constructor(tagsEl, tagInputOptions) {
    		this.className = Object.freeze({
    			CLOSE_BTN: 'acl-tag-input__tag-close-btn',
    			ACL_TAGS_INPUT: 'acl-tag-input',
    			ACL_TAGS_INPUT_TAG: 'acl-tag-input__tag',
    			FLASH: 'flash',
    			ANIMATED: 'animated',
    		});
    
    		this.selector = Object.freeze({
    			INPUT: 'input',
    			DIV: 'div',
    			ACL_TAGS_INPUT_DISPLAY: '.acl-tag-input__display',
    		});
    
    		this.eventName = Object.freeze({
    			BLUR: 'blur',
    			KEYDOWN: 'keydown',
    			CLICK: 'click',
    			TAG_ADDED: 'tagadded',
    			TAG_REMOVED: 'tagremoved',
    		});
    
    		this.keys = Object.freeze({
    			ENTER: 'Enter',
    			INSERT: 'Insert',
    			BACKSPACE: 'Backspace',
    		});
    
    		this.tags =
    			tagInputOptions && tagInputOptions.tags && tagInputOptions.tags.length > 0 ? tagInputOptions.tags : [];
    		this.submitKeys = [this.keys.ENTER, this.keys.INSERT];
    
    		this.tagsEl = tagsEl;
    
    		this.inputElement = document.createElement(this.selector.INPUT);
    		this.inputElement.classList.add(this.className.ACL_TAGS_INPUT);
    
    		this.renderTags();
    		this.handleEventListeners();
    	}
    
    	handleEventListeners() {
    		this.tagsEl.addEventListener(this.eventName.CLICK, () => {
    			this.inputElement.focus();
    		});
    
    		const tagInputSelector = `.${this.className.ACL_TAGS_INPUT}`;
    		this.tagsEl.querySelector(tagInputSelector).addEventListener(this.eventName.KEYDOWN, event => {
    			if (this.submitKeys.includes(event.key)) this.tagifyInput();
    
    			if (event.key === this.keys.BACKSPACE) {
    				const tagsInput = this.tagsEl.querySelector(`.${this.className.ACL_TAGS_INPUT}`);
    				if (tagsInput.value.length == 0 && this.tags.length > 0) {
    					this.removeTag(this.tags[this.tags.length - 1]);
    				}
    			}
    		});
    
    		this.tagsEl.querySelector(tagInputSelector).addEventListener(this.eventName.BLUR, () => {
    			this.tagifyInput();
    		});
    	}
    
    	updateTags(tags) {
    		this.tags = tags;
    		this.renderTags();
    	}
    
    	tagifyInput() {
    		const tagsInput = this.tagsEl.querySelector(`.${this.className.ACL_TAGS_INPUT}`);
    		if (!tagsInput.value.trim()) {
    			return;
    		}
    
    		if (this.tags.includes(tagsInput.value)) {
    			this.flashTag(tagsInput.value);
    			return;
    		}
    
    		this.tags.push(tagsInput.value);
    		this.renderTags();
    		this.tagsEl.dispatchEvent(
    			new CustomEvent(this.eventName.TAG_ADDED, {
    				detail: tagsInput.value,
    			})
    		);
    		tagsInput.value = '';
    	}
    
    	renderTags() {
    		const tagsDisplay = this.tagsEl.querySelector(this.selector.ACL_TAGS_INPUT_DISPLAY);
    
    		const tagElements = [];
    		this.tags.forEach(tag => {
    			tagElements.push(this.renderTag(tag));
    		});
    
    		while (tagsDisplay.firstChild) {
    			tagsDisplay.firstChild.remove();
    		}
    
    		tagElements.forEach(tagElement => {
    			tagsDisplay.appendChild(tagElement);
    		});
    
    		tagsDisplay.appendChild(this.inputElement);
    
    		tagElements.forEach(tagElement => {
    			tagElement.querySelector(`.${this.className.CLOSE_BTN}`).addEventListener(this.eventName.CLICK, () => {
    				this.removeTag(tagElement.dataset.tag);
    			});
    		});
    
    		this.inputElement.focus();
    	}
    
    	renderTag(tag) {
    		const tagWrapper = document.createElement(this.selector.DIV);
    		tagWrapper.classList.add(this.className.ACL_TAGS_INPUT_TAG);
    		tagWrapper.dataset.tag = tag;
    		const template = `<span class="acl-tag-input__tag-title">${tag}</span> <div class="${this.className.CLOSE_BTN}"><i class="aforza-icons acl-tag-input__tag-icon">acl_close_small</i></div>`;
    		tagWrapper.innerHTML = template;
    
    		return tagWrapper;
    	}
    
    	removeTag(tag) {
    		this.tags = this.tags.filter(currentTag => currentTag != tag);
    		this.tagsEl.dispatchEvent(
    			new CustomEvent(this.eventName.TAG_REMOVED, {
    				detail: tag,
    			})
    		);
    		this.renderTags();
    	}
    
    	flashTag(tag) {
    		const tagElement = this.tagsEl.querySelector(`[data-tag="${tag}"]`);
    		if (tagElement) {
    			tagElement.classList.remove(this.className.FLASH);
    
    			setTimeout(() => {
    				tagElement.classList.add(this.className.ANIMATED, this.className.FLASH);
    			});
    		}
    	}
    }
    
    export { ACLTagInput };
    
  • URL: /components/raw/tag-input/index.js
  • Filesystem Path: src/components/tag-input/index.js
  • Size: 3.9 KB

No notes defined.