diff --git a/reactions.js b/reactions.js index 450c8fc..45df7e0 100644 --- a/reactions.js +++ b/reactions.js @@ -1,20 +1,19 @@ /** -* @typedef {object} ReactionsConfig -* @property {string} title - Text in text area -* @property {string} wrapperBlockSelector - Module holder -* -*/ + * @typedef {object} ReactionsConfig + * @property {string} title - Text in text area + * @property {string} wrapperBlockSelector - Module holder + * @property {string[]} emojiCodes - unicodes of emoji to buttons + */ /** -* Creating blocks, adding emoji, text and buttons to general block -*/ + * Creating blocks, adding emoji, text and buttons to general block + */ class Reactions { /** - * @param {ReactionsConfig} settings - module configuration object - * @return {void} - */ + * @param {ReactionsConfig} settings - module configuration obj + */ constructor(settings) { this.nodes = { wrapper: document.querySelector(settings.wrapperBlockSelector), @@ -23,18 +22,20 @@ class Reactions { emojiWrapper: [], buttonWrapper: [], button: [], - unicode: [], countBlock: [] } - this.nodes.unicode = settings.emojiCodes; + + this.itemActive= null; + this.wrapperActive= null; + this.count = []; + this.unicode = settings.emojiCodes; this.titleText = settings.title; this.appendElementsToWrapper(); - this.count=0; } /** - * CSS classes of elements in class Reactions - */ + * CSS classes of elements in class Reactions + */ static get CSS(){ return { titleClass : 'reactions__text', @@ -49,131 +50,214 @@ class Reactions { } /** - * Create a general block - * @param {CSSClass} CSSClass - CSS class for block - * @returns {HTMLElement} div - */ + * Create blocks and give CSS class + * @param {string} tagName + * @param {string} className - CSS class for block + * @returns {HTMLElement} element + */ make(tagName, className) { - let div = document.createElement(tagName); + const element = document.createElement(tagName); - div.classList.add(className); + element.classList.add(className); - return div; + return element; } - /** - * Append emojiblock, buttons and counter to general block - */ + /** + * Append emojiblock, emojiwrapper, buttons and counter to general block + */ appendElementsToWrapper() { + /** - * Append title - */ + * Append title + */ this.nodes.title = this.make('div', Reactions.CSS.titleClass); this.nodes.wrapper.appendChild(this.nodes.title); this.nodes.title.innerHTML = this.titleText; /** - * Append emoji wrapper - * @type {HTMLElement} emojiBlock - */ + * Append emoji wrapper + * @type {HTMLElement} emojiBlock + */ this.nodes.emojiBlock = this.make('div', Reactions.CSS.emojiClass); this.nodes.wrapper.appendChild(this.nodes.emojiBlock); /** - * Append button - * @type {HTMLElement} button - */ - for (let i = 0; i < this.nodes.unicode.length; i++){ + * Create and append blocks to wrapper + * @type {HTMLElement} + */ + for (let i = 0; i < this.unicode.length; i++){ + + /** + * Append wrapper to button and count clicks block + * @type {HTMLElement} emojiWrapper + */ this.nodes.emojiWrapper[i] = this.make('div', Reactions.CSS.emojiWrapperClass); this.nodes.wrapper.appendChild(this.nodes.emojiWrapper[i]); + /** + * Append buttons + * @type {HTMLElement} button + */ this.nodes.button[i] = this.make('div', Reactions.CSS.buttonClass); this.nodes.wrapper.appendChild(this.nodes.button[i]); /** - * Append wrapper for button - * @type {HTMLElement} buttonWrapper - */ - this.nodes.buttonWrapper[i] = this.make('div', Reactions.CSS.buttonWrapperClass); - this.nodes.wrapper.appendChild(this.nodes.buttonWrapper[i]); + * Append wrappers for button + * @type {HTMLElement} buttonWrapper + */ + this.nodes.buttonWrapper[i] = this.make('div', Reactions.CSS.buttonWrapperClass); + this.nodes.wrapper.appendChild(this.nodes.buttonWrapper[i]); /** - * Append clicks counter - * @type {HTMLElement} countBlock - */ + * Append blocks for clicks counter + * @type {HTMLElement} countBlock + */ this.nodes.countBlock[i] = this.make('div', Reactions.CSS.countClicksClass); this.nodes.wrapper.appendChild(this.nodes.countBlock[i]); - } + + this.count[i] = '0'; + } this.appendElementsToEmojiBlock() } - /** - * Append emoji and counter to emojiBlock - */ + /** + * Append emoji and counter to emojiBlock + */ appendElementsToEmojiBlock(){ - /** - * Append button wrapper to emojiBlock - */ - for (let i = 0; i < this.nodes.unicode.length; i++){ - this.nodes.emojiBlock.appendChild(this.nodes.buttonWrapper[i]); + /** + * Append emojiwrapper to emojiblock and append button and counter in emojiwrapper + */ + for (let i = 0; i < this.unicode.length; i++){ - this.nodes.emojiBlock.appendChild(this.nodes.emojiWrapper[i]); - - this.nodes.emojiWrapper[i].appendChild(this.nodes.buttonWrapper[i]); + /** + * Append buttonWrapper to emojiBlock + */ + this.nodes.emojiBlock.appendChild(this.nodes.buttonWrapper[i]); - this.nodes.emojiWrapper[i].appendChild(this.nodes.countBlock[i]); + /** + * Append emojiWrapper to emojiBlock + */ + this.nodes.emojiBlock.appendChild(this.nodes.emojiWrapper[i]); + + /** + * Append buttonWrapper to emojiWrapper + */ + this.nodes.emojiWrapper[i].appendChild(this.nodes.buttonWrapper[i]); - this.nodes.buttonWrapper[i].appendChild(this.nodes.button[i]); + /** + * Append countBlock to emojiWrapper + */ + this.nodes.emojiWrapper[i].appendChild(this.nodes.countBlock[i]); - this.nodes.button[i].innerText = String.fromCodePoint(this.nodes.unicode[i]); + /** + * Append button to buttonWrapper + */ + this.nodes.buttonWrapper[i].appendChild(this.nodes.button[i]); - this.nodes.countBlock[i].innerText = '0'; + /** + * Add emoji to button + * @type {string} + */ + this.nodes.button[i].textContent = String.fromCodePoint(this.unicode[i]); + /** + * Get 0 count to countBlock + * @type {String} + */ + this.nodes.countBlock[i].textContent = '0'; } /** - * Transfer to counting clicks - * @param {HTMLElement} 'click' add CSS class, count clicks - * @return {void} - */ - for (let i = 0; i < this.nodes.unicode.length; i++) { + * Transfer to counting clicks after click on button + */ + for (let i = 0; i < this.unicode.length; i++) { this.nodes.buttonWrapper[i].addEventListener('click', () => { - this.countClicksToButton(this.nodes.buttonWrapper[i],this.nodes.emojiWrapper[i],i); - }) - ;} - }; + this.countClicksToButton(i); + }); + } + } /** - * Increase or decrease counter after click - * @param {HTMLElement} buttonWrapper - * @param {HTMLElement} count of clicks - */ - countClicksToButton(buttonWrapper,emojiWrapper,i){ - let itemActive = document.querySelector('.reactions__button--active'); - let wrapperActive = document.querySelector('.reactions__emoji-wrapper--active'); - if (itemActive === null){ - buttonWrapper.classList.add(Reactions.CSS.activeButtonClass); - emojiWrapper.classList.add(Reactions.CSS.activeButtonWrapper); - this.nodes.countBlock[i].innerHTML = ++this.count; - }else{ - if(itemActive === buttonWrapper){ - buttonWrapper.classList.remove(Reactions.CSS.activeButtonClass); - emojiWrapper.classList.remove(Reactions.CSS.activeButtonWrapper); - this.nodes.countBlock[i].innerHTML = --this.count; - }else{ - let countActive = wrapperActive.querySelector('.reactions__count'); - countActive.innerHTML = --this.count; - itemActive.classList.remove(Reactions.CSS.activeButtonClass); - wrapperActive.classList.remove(Reactions.CSS.activeButtonWrapper); - buttonWrapper.classList.add(Reactions.CSS.activeButtonClass); - emojiWrapper.classList.add(Reactions.CSS.activeButtonWrapper); - this.nodes.countBlock[i].innerHTML = ++this.count; + * Increase or decrease counter after click, add or remove active CSS class + * @param {HTMLElement} buttonWrapper + * @param {HTMLElement} emojiWrapper + * @param {HTMLElement} counter + */ + countClicksToButton(i){ + + /** + * If there is no active button, add active CSS class + */ + if (this.wrapperActive === null){ + this.addReaction(i); + + } else { + + /** + * If clicked button is active, remove active CSS class + */ + if (this.wrapperActive === i){ + this.removeReaction(i); + + /** + * Remove active CSS class for active button and add for clicked button + */ + } else { + + /** + * Count block of active button + * @type {HTMLElement} + */ + + this.removeReaction(this.wrapperActive); + + this.addReaction(i); + } } - }; + } + /** + * Add CSS active class and increase counter + * @param {HTMLElement} buttonWrapper + * @param {HTMLElement} emojiWrapper + * @param {HTMLElement} counter + */ + addReaction(i){ + this.nodes.buttonWrapper[i].classList.add(Reactions.CSS.activeButtonClass); + this.nodes.emojiWrapper[i].classList.add(Reactions.CSS.activeButtonWrapper); + this.wrapperActive = i; + + /** + * Increase counter + * @type {string} + */ + this.count[i] = parseInt(this.count[i]) + 1 + this.nodes.countBlock[i].textContent = this.count[i]; + } + + /** + * Remove CSS active class and decrease counter + * @param {HTMLElement} buttonWrapper + * @param {HTMLElement} emojiWrapper + * @param {HTMLElement} counter + * @param {HTMLElement} countActive + */ + removeReaction(i){ + this.nodes.buttonWrapper[i].classList.remove(Reactions.CSS.activeButtonClass); + this.nodes.emojiWrapper[i].classList.remove(Reactions.CSS.activeButtonWrapper); + this.wrapperActive = null; + + /** + * Decrease counter + * @type {string} + */ + this.count[i] = parseInt(this.count[i]) - 1 + this.nodes.countBlock[i].textContent = this.count[i]; + } }