From 281439a5bb09d3a7a4999ba48a478c120b364cf1 Mon Sep 17 00:00:00 2001 From: vupham Date: Thu, 13 Apr 2023 15:28:25 +0700 Subject: [PATCH 1/7] fix(active-section): add activatedActiveSection flag for checking animating status to open multiple active section in default --- src/_index.js | 5 +++++ src/helpers.js | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/_index.js b/src/_index.js index 8e3fbd2..ae83c4d 100644 --- a/src/_index.js +++ b/src/_index.js @@ -141,6 +141,9 @@ export class EasyTabAccordion{ if(this.enabled && !this.hasInitialized) initSetup(this); if(!this.enabled && this.hasInitialized) this.destroy(); + // activated flag + this.hasActivatedSection = false; + // toggle via hash if(this.enabled){ if(isValidHash(this)){ @@ -150,6 +153,8 @@ export class EasyTabAccordion{ } } + this.hasActivatedSection = true; + // watch for resize/load events window.addEventListener('resize', debounce(e => onResize(this, e), 300)); window.addEventListener('load', e => onLoad(this, e)); diff --git a/src/helpers.js b/src/helpers.js index 777c037..e91f7f2 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -27,7 +27,7 @@ export function getToggleState(context, id){ // exit: 0 // check if option is avoid double click - if(context.options.avoidDoubleClick){ + if(context.options.avoidDoubleClick && context.hasActivatedSection){ if(context.isAnimating){ log(context, 'warn', `Block [${id}] to avoid double click on animating item.`); return 0; From 7c2111c8b03c1c581dbc998935959456d4cc750f Mon Sep 17 00:00:00 2001 From: vuquangpham Date: Tue, 20 Jun 2023 10:47:51 +0700 Subject: [PATCH 2/7] fix(active-section): rename flag variable --- src/_index.js | 4 ++-- src/helpers.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_index.js b/src/_index.js index ae83c4d..e71e087 100644 --- a/src/_index.js +++ b/src/_index.js @@ -142,7 +142,7 @@ export class EasyTabAccordion{ if(!this.enabled && this.hasInitialized) this.destroy(); // activated flag - this.hasActivatedSection = false; + this.hasInitializedActiveSections = false; // toggle via hash if(this.enabled){ @@ -153,7 +153,7 @@ export class EasyTabAccordion{ } } - this.hasActivatedSection = true; + this.hasInitializedActiveSections = true; // watch for resize/load events window.addEventListener('resize', debounce(e => onResize(this, e), 300)); diff --git a/src/helpers.js b/src/helpers.js index e91f7f2..aba05e8 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -27,7 +27,7 @@ export function getToggleState(context, id){ // exit: 0 // check if option is avoid double click - if(context.options.avoidDoubleClick && context.hasActivatedSection){ + if(context.options.avoidDoubleClick && context.hasInitializedActiveSections){ if(context.isAnimating){ log(context, 'warn', `Block [${id}] to avoid double click on animating item.`); return 0; From 42ed5a3147c56865a9af9ae02eee9d1c1becdc40 Mon Sep 17 00:00:00 2001 From: vuquangpham Date: Tue, 20 Jun 2023 15:19:05 +0700 Subject: [PATCH 3/7] refactor: refactor code structure --- src/_index.js | 14 -------------- src/helpers.js | 8 +++++--- src/methods.js | 16 ++++++++++++++-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/_index.js b/src/_index.js index e71e087..e7131ad 100644 --- a/src/_index.js +++ b/src/_index.js @@ -141,20 +141,6 @@ export class EasyTabAccordion{ if(this.enabled && !this.hasInitialized) initSetup(this); if(!this.enabled && this.hasInitialized) this.destroy(); - // activated flag - this.hasInitializedActiveSections = false; - - // toggle via hash - if(this.enabled){ - if(isValidHash(this)){ - this.toggle(getHash().id, 'hash'); - }else{ - defaultActiveSections(this); - } - } - - this.hasInitializedActiveSections = true; - // watch for resize/load events window.addEventListener('resize', debounce(e => onResize(this, e), 300)); window.addEventListener('load', e => onLoad(this, e)); diff --git a/src/helpers.js b/src/helpers.js index aba05e8..c2602c5 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -24,10 +24,12 @@ export function getToggleState(context, id){ if(!validID(context, id)) return false; // close: -1 // open: 1 - // exit: 0 + // exit: 0 // prevent open or close - // check if option is avoid double click - if(context.options.avoidDoubleClick && context.hasInitializedActiveSections){ + // exit if it is animating, and + // when has not initialized, allow to run multiple animation due to possible multiple active sections + if(context.hasInitialized && context.options.avoidDoubleClick){ + // avoid multiple animation at the same time if(context.isAnimating){ log(context, 'warn', `Block [${id}] to avoid double click on animating item.`); return 0; diff --git a/src/methods.js b/src/methods.js index f936edb..b57ee9d 100644 --- a/src/methods.js +++ b/src/methods.js @@ -1,12 +1,12 @@ import {responsive} from "./responsive"; import {setCSS, setTransition} from "./animation"; -import {getHash} from "./hash"; +import {getHash, isValidHash} from "./hash"; +import {defaultActiveSections} from "./helpers"; export function initSetup(context){ // event: onBeforeInit context.options.onBeforeInit(context); - context.hasInitialized = true; context.wrapper.classList.add(context._class.enabled); // loop through triggers @@ -50,8 +50,20 @@ export function initSetup(context){ assignTriggerElements(context); + // toggle via hash + if(context.enabled){ + if(isValidHash(context)){ + context.toggle(getHash().id, 'hash'); + }else{ + defaultActiveSections(context); + } + } + // event: onAfterInit context.options.onAfterInit(context); + + // initialized flag + context.hasInitialized = true; } function assignTriggerElements(context){ From 3f4dc3996e48230b85f5c4aec6462c890459982e Mon Sep 17 00:00:00 2001 From: vuquangpham Date: Tue, 20 Jun 2023 15:45:21 +0700 Subject: [PATCH 4/7] chore: refactor code structure --- src/_index.js | 2 +- src/methods.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_index.js b/src/_index.js index e7131ad..3859d4b 100644 --- a/src/_index.js +++ b/src/_index.js @@ -1,6 +1,6 @@ import {slideDown, slideUp, destroySlide, updateSlide} from "./slide"; import {fadeIn, fadeOut, destroyFade, updateFade} from "./fade"; -import {getHash, isValidHash, hashScroll, updateURL} from "./hash"; +import {hashScroll, updateURL} from "./hash"; import { validID, getToggleState, diff --git a/src/methods.js b/src/methods.js index b57ee9d..4bd04d8 100644 --- a/src/methods.js +++ b/src/methods.js @@ -59,11 +59,11 @@ export function initSetup(context){ } } - // event: onAfterInit - context.options.onAfterInit(context); - // initialized flag context.hasInitialized = true; + + // event: onAfterInit + context.options.onAfterInit(context); } function assignTriggerElements(context){ From eef2a59d6bcbb6beb526436fe08507077e19de4b Mon Sep 17 00:00:00 2001 From: vuquangpham Date: Tue, 20 Jun 2023 15:45:51 +0700 Subject: [PATCH 5/7] chore: refactor code structure --- src/_index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_index.js b/src/_index.js index 3859d4b..2b2113c 100644 --- a/src/_index.js +++ b/src/_index.js @@ -6,7 +6,7 @@ import { getToggleState, getIndexById, getElements, - removeActiveClass, addActiveClass, getIdByIndex, defaultActiveSections, log, getOptions + removeActiveClass, addActiveClass, getIdByIndex, log, getOptions } from "./helpers"; import {debounce, uniqueId} from "./utils"; import {initSetup, onLoad, onResize} from "./methods"; From 07feeee380f7189a3deafd735862612fa4af1cfe Mon Sep 17 00:00:00 2001 From: Phuc Bui Date: Thu, 3 Aug 2023 18:24:24 +0700 Subject: [PATCH 6/7] use EventsManager & add configs.js (#45) * Use events manger (#44) * feat: use events manger * fix: remove redundant code * fix: add bracket for data-ea in DEFAULTS variable * fix: format code * fix: return default back * fix: add comma * fix: add comma * fix: remove configs file and add on method * fix: add comma * fix: add comma * fix: add bracket for target * docs: update README.md * Add config file (#43) * feat: add config file * fix: format code * fix: add defaults to configs.js * fix: add comma * fix: add comma * fix: replace fire event and add eventsManager * fix: add on method --------- Co-authored-by: Pau15122 <77733880+vandangnhathung@users.noreply.github.com> --- README.md | 4 ++ package.json | 3 ++ src/_index.js | 111 +++++++++++++------------------------------------ src/configs.js | 60 ++++++++++++++++++++++++++ src/helpers.js | 12 +++--- src/methods.js | 11 ++--- 6 files changed, 109 insertions(+), 92 deletions(-) create mode 100644 src/configs.js diff --git a/README.md b/README.md index ffd842d..76899c0 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,7 @@ Add these attributes on the wrapper element. | `destroy` | `eta.destroy()` | Remove all style and events | | `init` | `eta.init()` | Could be use after destroy | | `update` | `eta.update()` | Update styling | +| `on` | `eta.on()` | Assign events | Get the instance with JS init @@ -229,6 +230,9 @@ const eta = ETA.get('my-eta'); // use methods eta.update(); +eta.on("open", () => { + // do something +}); ``` ## Deployment diff --git a/package.json b/package.json index eecf963..788c74f 100644 --- a/package.json +++ b/package.json @@ -58,5 +58,8 @@ "webpack-cli": "^4.9.0", "webpack-dev-server": "^4.3.1", "webpack-merge": "^5.8.0" + }, + "dependencies": { + "@phucbm/os-util": "^0.0.4" } } diff --git a/src/_index.js b/src/_index.js index 2b2113c..f7e82ac 100644 --- a/src/_index.js +++ b/src/_index.js @@ -8,80 +8,19 @@ import { getElements, removeActiveClass, addActiveClass, getIdByIndex, log, getOptions } from "./helpers"; -import {debounce, uniqueId} from "./utils"; +import {debounce} from "./utils"; import {initSetup, onLoad, onResize} from "./methods"; import {isLive, validBreakpoints} from "./responsive"; import {scrollIntoView} from "./animation"; +import {CLASSES, ATTRS, DEFAULTS} from './configs'; +import {EventsManager} from "@phucbm/os-util"; export class EasyTabAccordion{ constructor(options){ - this._class = { - enabled: 'easy-tab-accordion-enabled', - active: 'active', - hasAssignedTriggerEvent: 'assigned-trigger-event' - }; - this._attr = { - container: 'data-eta', - trigger: 'data-eta-trigger', - receiver: 'data-eta-receiver', - hash: 'data-eta-hash', - hashScroll: 'data-eta-hash-scroll', - animation: 'data-eta-animation', - }; - this.defaultOptions = { - // selectors - el: document.querySelector(`[${this._attr.container}]`), // DOM element - id: uniqueId('eta-'), - trigger: `[${this._attr.trigger}]`, // string selector - triggerAttr: this._attr.trigger, // attribute name - receiver: `[${this._attr.receiver}]`, // string selector - receiverAttr: this._attr.receiver, // attribute name - activeClass: this._class.active, - - // animation - animation: 'slide', // slide, fade - duration: 450, - scrollIntoView: false, // scroll panel into view when open - - // hash - hash: false, // update hash URL - hashScroll: false, // scroll into view when page loaded with a valid hash - - // responsive - liveBreakpoint: [], // [1920, 1024] => destroy if window.width if bigger than 1920 or less than 1024 - - // avoid double click - avoidDoubleClick: true, - - // dev mode => enable console.log - dev: false, - - // open/close - activeSection: 0, // default opening sections, will be ignored if there's a valid hash, allow array of index [0,1,2] for slide animation only - allowCollapseAll: false, // for slide animation only - allowExpandAll: false, // for slide animation only - - // prevent default when click to trigger element - isPreventDefault: true, - - // events - onBeforeInit: (data) => { - }, - onAfterInit: (data) => { - }, - onBeforeOpen: (data, el) => { - }, - onBeforeClose: (data, el) => { - }, - onAfterOpen: (data, el) => { - }, - onAfterClose: (data, el) => { - }, - onDestroy: (data) => { - }, - onUpdate: (data) => { - }, - }; + // init events manager + this.events = new EventsManager(this, { + names: ['onBeforeInit', 'onAfterInit', 'onBeforeOpen', 'onBeforeClose', 'onAfterOpen', 'onAfterClose', 'onDestroy', 'onUpdate'], + }) // save options this.originalOptions = options; @@ -92,9 +31,19 @@ export class EasyTabAccordion{ this.isAnimating = false; } + /****************************** + * EVENTS + ******************************/ + /** + * Assign late-events + */ + on(eventName, callback){ + this.events.add(eventName, callback); + }; + init(){ // setup - this.options = {...this.defaultOptions, ...this.originalOptions}; + this.options = {...DEFAULTS, ...this.originalOptions}; if(!this.options.el){ log(this, 'warn', 'ETA Error, target not found!'); @@ -111,7 +60,7 @@ export class EasyTabAccordion{ this.count = this.wrapper.querySelectorAll(this.options.trigger).length; // check if ETA has already initialized - if(this.wrapper.classList.contains(this._class.enabled)){ + if(this.wrapper.classList.contains(CLASSES.enabled)){ log(this, 'ETA has initialized'); return; } @@ -120,17 +69,17 @@ export class EasyTabAccordion{ this.isFirst = true; // update hash from attribute - this.options.hash = this.wrapper.hasAttribute(this._attr.hash) === true ? true : this.options.hash; - this.options.hashScroll = this.wrapper.hasAttribute(this._attr.hashScroll) === true ? true : this.options.hashScroll; + this.options.hash = this.wrapper.hasAttribute(ATTRS.hash) === true ? true : this.options.hash; + this.options.hashScroll = this.wrapper.hasAttribute(ATTRS.hashScroll) === true ? true : this.options.hashScroll; // update animation from attribute - const animationValue = this.wrapper.getAttribute(this._attr.animation); + const animationValue = this.wrapper.getAttribute(ATTRS.animation); this.options.animation = animationValue !== null ? animationValue : this.options.animation; // get options init by data attribute (JSON format) this.options = getOptions(this); // assign id to wrapper - this.wrapper.setAttribute(this._attr.container, this.id); + this.wrapper.setAttribute(ATTRS.container, this.id); if(this.count < 1){ log(this, 'warn', 'Quit init due to child panels not found', this); @@ -148,7 +97,7 @@ export class EasyTabAccordion{ destroy(){ this.hasInitialized = false; - this.wrapper.classList.remove(this._class.enabled); + this.wrapper.classList.remove(CLASSES.enabled); // loop through triggers this.wrapper.querySelectorAll(this.options.trigger).forEach(trigger => { @@ -169,7 +118,7 @@ export class EasyTabAccordion{ } // event: onDestroy - this.options.onDestroy(this); + this.events.fire('onDestroy'); } update(){ @@ -183,7 +132,7 @@ export class EasyTabAccordion{ } // event: onUpdate - this.options.onUpdate(this); + this.events.fire('onUpdate'); } openPanel(id = this.current_id){ @@ -197,7 +146,7 @@ export class EasyTabAccordion{ updateURL(this, id); // events - this.options.onBeforeOpen(this); + this.events.fire('onBeforeOpen'); }; // event: on Before Open @@ -216,7 +165,7 @@ export class EasyTabAccordion{ this.isAnimating = false; log(this, 'log', 'Stop animation.'); - this.options.onAfterOpen(this, target); + this.events.fire('onAfterOpen', {target}); // log log(this, 'log', 'after open', id); @@ -253,12 +202,12 @@ export class EasyTabAccordion{ if(!validID(this, id)) return; // event: on Before Close - this.options.onBeforeClose(this); + this.events.fire('onBeforeClose'); // event: on After Close this.dataset[getIndexById(this, id)].active = false; const afterClose = (target) => { - this.options.onAfterClose(this, target); + this.events.fire('onAfterClose', {target}); // toggle animating status this.isAnimating = false; diff --git a/src/configs.js b/src/configs.js new file mode 100644 index 0000000..c4bda38 --- /dev/null +++ b/src/configs.js @@ -0,0 +1,60 @@ +import {uniqueId} from './utils' + +/** + * Classes + * */ +export const CLASSES = { + enabled: 'easy-tab-accordion-enabled', + active: 'active', + hasAssignedTriggerEvent: 'assigned-trigger-event', +}; +/** + * Attributes + * */ +export const ATTRS = { + container: 'data-eta', + trigger: 'data-eta-trigger', + receiver: 'data-eta-receiver', + hash: 'data-eta-hash', + hashScroll: 'data-eta-hash-scroll', + animation: 'data-eta-animation', +}; +/** + * Defaults + * */ +export const DEFAULTS = { + // selectors + el: document.querySelector('[data-eta]'), // DOM element + id: uniqueId('eta-'), + trigger: '[data-eta-trigger]', // string selector + triggerAttr: 'data-eta-trigger', // attribute name + receiver: '[data-eta-receiver]', // string selector + receiverAttr: 'data-eta-receiver', // attribute name + activeClass: 'active', + + // animation + animation: 'slide', // slide, fade + duration: 450, + scrollIntoView: false, // scroll panel into view when open + + // hash + hash: false, // update hash URL + hashScroll: false, // scroll into view when page loaded with a valid hash + + // responsive + liveBreakpoint: [], // [1920, 1024] => destroy if window.width if bigger than 1920 or less than 1024 + + // avoid double click + avoidDoubleClick: true, + + // dev mode => enable console.log + dev: false, + + // open/close + activeSection: 0, // default opening sections, will be ignored if there's a valid hash, allow array of index [0,1,2] for slide animation only + allowCollapseAll: false, // for slide animation only + allowExpandAll: false, // for slide animation only + + // prevent default when click to trigger element + isPreventDefault: true, +}; \ No newline at end of file diff --git a/src/helpers.js b/src/helpers.js index c2602c5..dae4654 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,5 +1,5 @@ import {arrayUnique} from "./utils"; - +import {CLASSES, ATTRS} from './configs' /** * Has valid id @@ -166,8 +166,8 @@ export function removeActiveClass(context, id){ const {current, currentTrigger} = getElements(context, id); // update classes - current.forEach(item => item.classList.remove(context._class.active)); - currentTrigger.forEach(item => item.classList.remove(context._class.active)); + current.forEach(item => item.classList.remove(CLASSES.active)); + currentTrigger.forEach(item => item.classList.remove(CLASSES.active)); } @@ -181,8 +181,8 @@ export function addActiveClass(context, id){ const {current, currentTrigger} = getElements(context, id ? id : context.current_id); // update classes - if(current) current.forEach(item => item.classList.add(context._class.active)); - if(currentTrigger) currentTrigger.forEach(item => item.classList.add(context._class.active)); + if(current) current.forEach(item => item.classList.add(CLASSES.active)); + if(currentTrigger) currentTrigger.forEach(item => item.classList.add(CLASSES.active)); } export function log(context, status, ...message){ @@ -207,7 +207,7 @@ export function getOptions(context, defaultOptions){ const wrapper = context.wrapper; // options from attribute - let dataAttribute = wrapper.getAttribute(context._attr.container); + let dataAttribute = wrapper.getAttribute(ATTRS.container); let options = {}; // data attribute doesn't exist or not JSON format -> string diff --git a/src/methods.js b/src/methods.js index 4bd04d8..ca0d313 100644 --- a/src/methods.js +++ b/src/methods.js @@ -2,12 +2,13 @@ import {responsive} from "./responsive"; import {setCSS, setTransition} from "./animation"; import {getHash, isValidHash} from "./hash"; import {defaultActiveSections} from "./helpers"; +import {CLASSES} from './configs'; export function initSetup(context){ // event: onBeforeInit - context.options.onBeforeInit(context); + context.events.fire("onBeforeInit"); - context.wrapper.classList.add(context._class.enabled); + context.wrapper.classList.add(CLASSES.enabled); // loop through triggers context.wrapper.querySelectorAll(context.options.trigger).forEach(trigger => { @@ -15,7 +16,7 @@ export function initSetup(context){ trigger.addEventListener('click', e => manualTriggerFunction(context, e)); // add a class to check if the trigger has assigned an event - trigger.classList.add(context._class.hasAssignedTriggerEvent); + trigger.classList.add(CLASSES.hasAssignedTriggerEvent); }); // loop through receivers @@ -63,7 +64,7 @@ export function initSetup(context){ context.hasInitialized = true; // event: onAfterInit - context.options.onAfterInit(context); + context.events.fire("onAfterInit"); } function assignTriggerElements(context){ @@ -77,7 +78,7 @@ function assignTriggerElements(context){ context.dataset.forEach(item => { if(item.id === id){ // already assigned trigger event - if(trigger.classList.contains(context._class.hasAssignedTriggerEvent)) return; + if(trigger.classList.contains(CLASSES.hasAssignedTriggerEvent)) return; // valid trigger trigger.addEventListener('click', e => { From 8f063512d268103fa862630d78d5f9c67934963d Mon Sep 17 00:00:00 2001 From: Pau15122 <77733880+vandangnhathung@users.noreply.github.com> Date: Fri, 4 Aug 2023 11:37:08 +0700 Subject: [PATCH 7/7] Add getOptionsFromAttribute() (#46) * feat: add getOptionsFromAttrs and remove old getOptions * feat: change this.options position * fix: move this.options before init * fix: replace this.originalOptions for options --- src/_index.js | 21 ++++++++++++-------- src/helpers.js | 53 -------------------------------------------------- 2 files changed, 13 insertions(+), 61 deletions(-) diff --git a/src/_index.js b/src/_index.js index f7e82ac..7a37ec4 100644 --- a/src/_index.js +++ b/src/_index.js @@ -6,14 +6,14 @@ import { getToggleState, getIndexById, getElements, - removeActiveClass, addActiveClass, getIdByIndex, log, getOptions + removeActiveClass, addActiveClass, getIdByIndex, log } from "./helpers"; import {debounce} from "./utils"; import {initSetup, onLoad, onResize} from "./methods"; import {isLive, validBreakpoints} from "./responsive"; import {scrollIntoView} from "./animation"; import {CLASSES, ATTRS, DEFAULTS} from './configs'; -import {EventsManager} from "@phucbm/os-util"; +import {EventsManager, getOptionsFromAttribute} from "@phucbm/os-util"; export class EasyTabAccordion{ constructor(options){ @@ -24,6 +24,17 @@ export class EasyTabAccordion{ // save options this.originalOptions = options; + + // get options init by data attribute (JSON format) + this.options + = getOptionsFromAttribute({ + target: this.wrapper, + defaultOptions: {...DEFAULTS, ...options}, + attributeName: ATTRS.container, + numericValues: ['duration', 'activeSection'], + dev: DEFAULTS.dev + }); + // init this.init(); @@ -42,9 +53,6 @@ export class EasyTabAccordion{ }; init(){ - // setup - this.options = {...DEFAULTS, ...this.originalOptions}; - if(!this.options.el){ log(this, 'warn', 'ETA Error, target not found!'); return; @@ -75,9 +83,6 @@ export class EasyTabAccordion{ const animationValue = this.wrapper.getAttribute(ATTRS.animation); this.options.animation = animationValue !== null ? animationValue : this.options.animation; - // get options init by data attribute (JSON format) - this.options = getOptions(this); - // assign id to wrapper this.wrapper.setAttribute(ATTRS.container, this.id); diff --git a/src/helpers.js b/src/helpers.js index dae4654..948bd19 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -191,59 +191,6 @@ export function log(context, status, ...message){ } } - -/** - * Get JSON options - * ID priority: data-attribute > selector#id > unique id - * @version 0.0.1 - * @returns {object} - */ -export function getOptions(context, defaultOptions){ - if(!defaultOptions){ - defaultOptions = context.options || context.config || {}; - } - - const numeric = ['duration', 'activeSection']; // convert these props to float - const wrapper = context.wrapper; - - // options from attribute - let dataAttribute = wrapper.getAttribute(ATTRS.container); - let options = {}; - - // data attribute doesn't exist or not JSON format -> string - const attributeIsNotJSON = !dataAttribute || !isJSON(dataAttribute); - - // data attribute is not json format or string - if(attributeIsNotJSON){ - options = {...defaultOptions}; - - // data attribute exist => string - if(dataAttribute) options.id = dataAttribute; - else options.id = ''; - }else{ - options = JSON.parse(dataAttribute); - - for(const [key, value] of Object.entries(options)){ - // convert boolean string to real boolean - if(value === "false") options[key] = false; - else if(value === "true") options[key] = true; - // convert string to float - else if(numeric.includes(key) && typeof value === 'string' && value.length > 0) options[key] = parseFloat(value); - else options[key] = value; - } - } - - // reassign id - const id = options.id || wrapper.id || defaultOptions.id; - context.id = id; - options.id = id; - - options = {...defaultOptions, ...options}; - - return options; -} - - /** * Is JSON string * https://stackoverflow.com/a/32278428/6453822