Skip to content

Commit

Permalink
jsdocs for dynamicImports
Browse files Browse the repository at this point in the history
  • Loading branch information
Oksydan committed Oct 22, 2023
1 parent 384173b commit 4f9bd6b
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 76 deletions.
24 changes: 15 additions & 9 deletions _dev/js/theme/utils/dynamicImports/componentProxyFactory.js
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 = [],
Expand Down Expand Up @@ -42,6 +59,10 @@ const useBootstrapComponentDynamicImport = (importFiles, {

const getJQueryComponentName = () => componentName.toLowerCase();

/**
* Handles the loading of component files.
* @returns {Promise<void>} - 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];
Expand All @@ -56,6 +77,10 @@ const useBootstrapComponentDynamicImport = (importFiles, {
filesLoading = false;
});

/**
* Executes component initialization and callback calls.
* @returns {void}
*/
const executeComponentInitializationAndCallbackCalls = () => {
const instances = getAllInstancesForComponent();

Expand Down Expand Up @@ -105,6 +130,10 @@ const useBootstrapComponentDynamicImport = (importFiles, {
}
};

/**
* Handles the loading of the component.
* @returns {Promise<void>} - A Promise that resolves when the component is loaded.
*/
const handleComponentLoad = async () => {
if (filesLoaded || filesLoading) {
return;
Expand All @@ -118,6 +147,11 @@ const useBootstrapComponentDynamicImport = (importFiles, {
executeComponentInitializationAndCallbackCalls();
};

/**
* Handles events triggered during dynamic loading.
* @param {Event} e - The event object.
* @returns {Promise<void>} - A Promise that resolves when the event is handled.
*/
const handleEvent = async (e) => {
e.preventDefault();

Expand All @@ -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);

Expand All @@ -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);
Expand All @@ -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);

Expand All @@ -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 || {};
Expand All @@ -185,6 +256,10 @@ const useBootstrapComponentDynamicImport = (importFiles, {
};
}

/**
* Initializes the dynamic loading of the Bootstrap component.
* @returns {void}
*/
const init = () => {
bindEvents();
};
Expand Down
44 changes: 14 additions & 30 deletions _dev/js/theme/utils/dynamicImports/useDynamicImportEventsHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
};

Expand Down
63 changes: 39 additions & 24 deletions _dev/js/theme/utils/dynamicImports/useFunctionCallstackMap.js
Original file line number Diff line number Diff line change
@@ -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) => {
Expand All @@ -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) {
Expand All @@ -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)) {
Expand All @@ -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) => {
Expand All @@ -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)) {
Expand All @@ -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)) {
Expand All @@ -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);

Expand Down
Loading

0 comments on commit 4f9bd6b

Please sign in to comment.