diff --git a/_dev/js/theme/utils/dynamicImports/componentProxyFactory.js b/_dev/js/theme/utils/dynamicImports/componentProxyFactory.js index fe99a797..2eaf6bbe 100644 --- a/_dev/js/theme/utils/dynamicImports/componentProxyFactory.js +++ b/_dev/js/theme/utils/dynamicImports/componentProxyFactory.js @@ -1,8 +1,11 @@ /** - * @method handleProxyGet - * @param element - * @param proxyMethodHandler - * @return {(function(*, *, *): (*))|*} + * Handles the proxy get operation for a component. + * + * @function + * @name handleProxyGet + * @param {HTMLElement} element - The component element. + * @param {function} proxyMethodHandler - The proxy method handler. + * @returns {function(*, *, *): (*)|*} - The proxy handler function. */ const handleProxyGet = (element, proxyMethodHandler) => (target, prop, receiver) => { if (target[prop] !== undefined) { @@ -13,11 +16,14 @@ const handleProxyGet = (element, proxyMethodHandler) => (target, prop, receiver) }; /** - * @method componentProxyFactory - * @param element {HTMLElement} - component element - * @param options {object} - component options - * @param proxyMethodHandler {function} - proxy method handler - * @return {{_options, _element}} - component proxy + * Creates a proxy for a component. + * + * @function + * @name componentProxyFactory + * @param {HTMLElement} element - The component element. + * @param {object} options - The component options. + * @param {function} proxyMethodHandler - The proxy method handler. + * @returns {{_options, _element}} - The component proxy. */ const componentProxyFactory = ( element, diff --git a/_dev/js/theme/utils/dynamicImports/useBootstrapComponentDynamicImport.js b/_dev/js/theme/utils/dynamicImports/useBootstrapComponentDynamicImport.js index edddd6ac..7a01d469 100644 --- a/_dev/js/theme/utils/dynamicImports/useBootstrapComponentDynamicImport.js +++ b/_dev/js/theme/utils/dynamicImports/useBootstrapComponentDynamicImport.js @@ -3,6 +3,13 @@ import useDynamicImportEventsHandler from './useDynamicImportEventsHandler'; import useFunctionCallstackMap from './useFunctionCallstackMap'; import componentProxyFactory from './componentProxyFactory'; +/** + * Checks if jQuery is enabled. + * + * @function + * @name isJQueryEnabled + * @returns {boolean} - Whether jQuery is enabled or not. + */ const isJQueryEnabled = () => { try { return !!window.jQuery; @@ -11,6 +18,16 @@ const isJQueryEnabled = () => { } }; +/** + * Dynamically loads and initializes Bootstrap components with optional jQuery support. + * + * @param {Function[]} importFiles - Array of functions that import the necessary files for the component. + * @param {Object} options - Configuration options. + * @param {string} options.componentName - Name of the Bootstrap component. + * @param {string[]} [options.events=[]] - List of events to bind for dynamic loading. + * @returns {Object} - Object with an `init` function for initializing the dynamic loading. + * @throws {Error} - Throws an error if the component name is not provided. + */ const useBootstrapComponentDynamicImport = (importFiles, { componentName, events = [], @@ -42,6 +59,10 @@ const useBootstrapComponentDynamicImport = (importFiles, { const getJQueryComponentName = () => componentName.toLowerCase(); + /** + * Handles the loading of component files. + * @returns {Promise} - A Promise that resolves when files are loaded. + */ const loadFiles = () => Promise.all(importFiles()).then((files) => { for (let i = 0; i < files.length; i += 1) { const file = files[i]; @@ -56,6 +77,10 @@ const useBootstrapComponentDynamicImport = (importFiles, { filesLoading = false; }); + /** + * Executes component initialization and callback calls. + * @returns {void} + */ const executeComponentInitializationAndCallbackCalls = () => { const instances = getAllInstancesForComponent(); @@ -105,6 +130,10 @@ const useBootstrapComponentDynamicImport = (importFiles, { } }; + /** + * Handles the loading of the component. + * @returns {Promise} - A Promise that resolves when the component is loaded. + */ const handleComponentLoad = async () => { if (filesLoaded || filesLoading) { return; @@ -118,6 +147,11 @@ const useBootstrapComponentDynamicImport = (importFiles, { executeComponentInitializationAndCallbackCalls(); }; + /** + * Handles events triggered during dynamic loading. + * @param {Event} e - The event object. + * @returns {Promise} - A Promise that resolves when the event is handled. + */ const handleEvent = async (e) => { e.preventDefault(); @@ -128,10 +162,30 @@ const useBootstrapComponentDynamicImport = (importFiles, { delegateTarget.dispatchEvent(new Event(type)); }; + /** + * Binds events for dynamic loading. + * @type {Object} + * @property {Function} bindEvents - Binds events. + * @property {Function} unbindEvents - Unbinds events. + */ const { bindEvents, unbindEvents } = useDynamicImportEventsHandler(events, handleEvent); + /** + * Gets the component instance associated with an element. + * @param {HTMLElement} element - The HTML element. + * @returns {Object|null} - The component instance or null if not found. + */ const getComponentInstance = (element) => getInstanceFromMap(element); + /** + * Handles proxy method calls for the component. + * @param {Object} target - The target object. + * @param {string} prop - The property being accessed. + * @param {Object} receiver - The receiver object. + * @param {HTMLElement} element - The HTML element associated with the component. + * @param {Array} args - The arguments passed to the method. + * @returns {Object} - The receiver object. + */ const proxyMethodCallHandler = (target, prop, receiver, element, args) => { const instance = getInstanceFromMap(element); @@ -152,6 +206,12 @@ const useBootstrapComponentDynamicImport = (importFiles, { return receiver; }; + /** + * Constructor function for creating Bootstrap component instances. + * @param {string|HTMLElement} selectorOrElement - Selector or HTML element. + * @param {Object} [options={}] - Component options. + * @returns {Object} - The component instance proxy. + */ function ComponentObjectConstructorFunction(selectorOrElement, options = {}) { const element = selectorOrElement instanceof Element ? selectorOrElement : document.querySelector(selectorOrElement); const componentInstanceProxy = componentProxyFactory(element, options, proxyMethodCallHandler); @@ -161,6 +221,12 @@ const useBootstrapComponentDynamicImport = (importFiles, { return componentInstanceProxy; } + /** + * Gets or creates a component instance for a given element. + * @param {HTMLElement} element - The HTML element. + * @param {Object} options - Component options. + * @returns {Object} - The component instance. + */ ComponentObjectConstructorFunction.getOrCreateInstance = (element, options) => { const componentInstance = getComponentInstance(element); @@ -171,6 +237,11 @@ const useBootstrapComponentDynamicImport = (importFiles, { return new ComponentObjectConstructorFunction(element, options); }; + /** + * Gets an existing component instance for a given element. + * @param {HTMLElement} element - The HTML element. + * @returns {Object|null} - The existing component instance or null if not found. + */ ComponentObjectConstructorFunction.getInstance = getComponentInstance; window.bootstrap = window.bootstrap || {}; @@ -185,6 +256,10 @@ const useBootstrapComponentDynamicImport = (importFiles, { }; } + /** + * Initializes the dynamic loading of the Bootstrap component. + * @returns {void} + */ const init = () => { bindEvents(); }; diff --git a/_dev/js/theme/utils/dynamicImports/useDynamicImportEventsHandler.js b/_dev/js/theme/utils/dynamicImports/useDynamicImportEventsHandler.js index 85d757d7..161b070b 100644 --- a/_dev/js/theme/utils/dynamicImports/useDynamicImportEventsHandler.js +++ b/_dev/js/theme/utils/dynamicImports/useDynamicImportEventsHandler.js @@ -3,56 +3,40 @@ import useEvent from '../../components/event/useEvent'; const { on, off } = useEvent(); /** - * Use dynamic import events handler - * @param {array} events - Array of events - * @param {function} handler - Event handler - * @return {{ - * bindEvents: function(): (void), - * unbindEvents: (function(): (void)), + * Handles dynamic import events by binding and unbinding specified events on the document. + * @param {Array} events - An array of event configurations, each containing a name and selector. + * @param {Function} handler - The event handler function. + * @returns {{ + * bindEvents: Function, + * unbindEvents: Function, * }} */ const useDynamicImportEventsHandler = (events, handler) => { /** - * Bind events - * @return {void} + * Binds the specified events on the document. + * @returns {void} */ const bindEvents = () => { - events.forEach(({ - name = '', - selector = '', - }) => { + events.forEach(({ name = '', selector = '' }) => { if (!name || !selector) { throw new Error('Event name and selector are required'); } - on( - document, - name, - selector, - handler, - ); + on(document, name, selector, handler); }); }; /** - * Unbind events - * @return {void} + * Unbinds the specified events on the document. + * @returns {void} */ const unbindEvents = () => { - events.forEach(({ - name = '', - selector = '', - }) => { + events.forEach(({ name = '', selector = '' }) => { if (!name || !selector) { throw new Error('Event name and selector are required'); } - off( - document, - name, - selector, - handler, - ); + off(document, name, selector, handler); }); }; diff --git a/_dev/js/theme/utils/dynamicImports/useFunctionCallstackMap.js b/_dev/js/theme/utils/dynamicImports/useFunctionCallstackMap.js index df40b20b..0ddd371c 100644 --- a/_dev/js/theme/utils/dynamicImports/useFunctionCallstackMap.js +++ b/_dev/js/theme/utils/dynamicImports/useFunctionCallstackMap.js @@ -1,15 +1,17 @@ const callbackMap = new Map(); /** + * Manages a map for function callbacks associated with specific elements or keys. + * * @module useFunctionCallstackMap - * @description create instance map - * @param {string} key - map key + * @description Creates and manages a callback map for function callstacks. + * @param {string} key - The key for the function callbacks map. * @return {{ - * getCallbacksForElement: (function(any): (null|array)), - * setCallbackForElement: (function(any, object): (void)), - * removeCallbacksForElement: (function(any): (void)), - * getAllCallbacksForComponent: (function(): (any|null)), - * createCallbackObject: (function(string, ...args): (CallbackObject)) + * getCallbacksForElement: function(any): (array|null), + * setCallbackForElement: function(any, object): void, + * removeCallbacksForElement: function(any): void, + * getAllCallbacksForComponent: function(): (any|null), + * createCallbackObject: function(string, ...args): CallbackObject * }} */ const useFunctionCallstackMap = (key) => { @@ -18,9 +20,11 @@ const useFunctionCallstackMap = (key) => { } /** + * Represents a callback object containing a property and arguments. + * * @class CallbackObject - * @param prop - * @param args + * @param {string} prop - The callback function property. + * @param {...any} args - The callback function arguments. * @constructor */ function CallbackObject(prop, args) { @@ -29,11 +33,13 @@ const useFunctionCallstackMap = (key) => { } /** + * Retrieves the functions callback map for a specific element or key. + * * @method getCallbacksForElement - * @description get functions callback map for elementKey - * @param {any} elementKey - map elementKey + * @description Gets the functions callback map for a specified element key. + * @param {any} elementKey - The element or key to retrieve callbacks for. * @public - * @return {array|null} - functions callback map for key or null + * @return {array|null} - An array of callbacks or null if not found. */ const getCallbacksForElement = (elementKey) => { if (!callbackMap.has(key)) { @@ -50,12 +56,14 @@ const useFunctionCallstackMap = (key) => { }; /** + * Sets a callback for a specific element or key. + * * @method setCallbackForElement - * @description set callback for elementKey + * @description Sets a callback for a specified element key. * @public - * @param {any} elementKey - component elementKey - * @param {CallbackObject} callback - callback object - * @throws {Error} - if callback is not instance of CallbackObject + * @param {any} elementKey - The element or key to set the callback for. + * @param {CallbackObject} callback - The callback object to set. + * @throws {Error} - If the callback is not an instance of CallbackObject. * @return {void} */ const setCallbackForElement = (elementKey, callback) => { @@ -77,10 +85,13 @@ const useFunctionCallstackMap = (key) => { }; /** + * Removes callbacks associated with a specific element or key. + * * @method removeCallbacksForElement - * @description remove component instance from map + * @description Removes callbacks associated with a specified element key. * @public - * @param {any} elementKey - component elementKey + * @param {any} elementKey - The element or key to remove callbacks for. + * @return {void} */ const removeCallbacksForElement = (elementKey) => { if (!callbackMap.has(key)) { @@ -101,10 +112,12 @@ const useFunctionCallstackMap = (key) => { }; /** + * Retrieves all callbacks for the component. + * * @method getAllCallbacksForComponent - * @description get all callbacks for component + * @description Gets all callbacks associated with the component. * @public - * @return {any|null} + * @return {any|null} - All callbacks for the component or null if none. */ const getAllCallbacksForComponent = () => { if (!callbackMap.has(key)) { @@ -115,12 +128,14 @@ const useFunctionCallstackMap = (key) => { }; /** + * Creates a callback object with a property and arguments. + * * @method createCallbackObject - * @description create callback object + * @description Creates a callback object with a specified property and arguments. * @public - * @param prop {string} - callback function - * @param args {...args} - callback arguments - * @return {CallbackObject} - callback object + * @param {string} prop - The callback function property. + * @param {...any} args - The callback function arguments. + * @return {CallbackObject} - The created callback object. */ const createCallbackObject = (prop, args) => new CallbackObject(prop, args); diff --git a/_dev/js/theme/utils/dynamicImports/useInstanceMap.js b/_dev/js/theme/utils/dynamicImports/useInstanceMap.js index f295ccbf..aac00013 100644 --- a/_dev/js/theme/utils/dynamicImports/useInstanceMap.js +++ b/_dev/js/theme/utils/dynamicImports/useInstanceMap.js @@ -1,13 +1,16 @@ const componentsInstancesMap = new Map(); /** + * Manages a map for component instances associated with specific elements or keys. + * * @module useInstanceMap - * @description create instance map - * @param {string} key - map key + * @description Creates and manages an instance map for component instances. + * @param {string} key - The key for the component instances map. * @return {{ - * getInstanceFromMap: (function(HTMLElement): (null|object)), - * setInstanceInMap: (function(HTMLElement, object): (void)), - * removeInstanceFromMap: (function(HTMLElement): (void)) + * getInstanceFromMap: function(HTMLElement): (object|null), + * setInstanceInMap: function(HTMLElement, object): void, + * removeInstanceFromMap: function(HTMLElement): void, + * getAllInstancesForComponent: function(): (object|null) * }} */ const useInstanceMap = (key) => { @@ -16,11 +19,13 @@ const useInstanceMap = (key) => { } /** + * Retrieves the component instance from the map for a specific element. + * * @method getInstanceFromMap - * @description get component instance from map + * @description Gets the component instance from the map for a specified element. * @public - * @param {HTMLElement} element - component element - * @return {object|null} - component instance or null + * @param {HTMLElement} element - The component element. + * @return {object|null} - The component instance or null if not found. */ const getInstanceFromMap = (element) => { if (!componentsInstancesMap.has(key)) { @@ -37,11 +42,13 @@ const useInstanceMap = (key) => { }; /** + * Sets the component instance in the map for a specific element. + * * @method setInstanceInMap - * @description set component instance in map + * @description Sets the component instance in the map for a specified element. * @public - * @param {HTMLElement} element - component element - * @param {object} instance - component instance + * @param {HTMLElement} element - The component element. + * @param {object} instance - The component instance. * @return {void} */ const setInstanceInMap = (element, instance) => { @@ -55,10 +62,13 @@ const useInstanceMap = (key) => { }; /** + * Removes the component instance from the map for a specific element. + * * @method removeInstanceFromMap - * @description remove component instance from map + * @description Removes the component instance from the map for a specified element. * @public - * @param {HTMLElement} element - component element + * @param {HTMLElement} element - The component element. + * @return {void} */ const removeInstanceFromMap = (element) => { if (!componentsInstancesMap.has(key)) { @@ -78,6 +88,14 @@ const useInstanceMap = (key) => { } }; + /** + * Retrieves all component instances for the component. + * + * @method getAllInstancesForComponent + * @description Gets all component instances associated with the component. + * @public + * @return {object|null} - All component instances for the component or null if none. + */ const getAllInstancesForComponent = () => { if (!componentsInstancesMap.has(key)) { return null;