UNPKG

stimulus_reflex

Version:

Build reactive applications with the Rails tooling you already know and love.

80 lines (63 loc) 2.66 kB
import Schema from './schema' import { attributeValues, attributeValue } from './attributes' import { debounce, dispatch } from './utils' import { findControllerByReflexName, allReflexControllers } from './controllers' import { reflexes } from './reflexes' // Sets up declarative reflex behavior. // Any elements that define data-reflex will automatically be wired up with the default StimulusReflexController. // const scanForReflexes = debounce(() => { const reflexElements = document.querySelectorAll(`[${Schema.reflex}]`) reflexElements.forEach(element => scanForReflexesOnElement(element)) }, 20) const scanForReflexesOnElement = (element, controller = null) => { const controllerAttribute = element.getAttribute(Schema.controller) const controllers = attributeValues(controllerAttribute).filter( controller => controller !== 'stimulus-reflex' ) const reflexAttribute = element.getAttribute(Schema.reflex) const reflexAttributeNames = attributeValues(reflexAttribute) const actionAttribute = element.getAttribute(Schema.action) const actions = attributeValues(actionAttribute).filter( action => !action.includes('#__perform') ) reflexAttributeNames.forEach(reflexName => { const potentialControllers = [controller].concat(allReflexControllers(element)) controller = findControllerByReflexName( reflexName, potentialControllers ) const controllerName = controller ? controller.identifier : 'stimulus-reflex' actions.push(`${reflexName.split('->')[0]}->${controllerName}#__perform`) const parentControllerElement = element.closest(`[data-controller~=${controllerName}]`) const elementPreviouslyHadStimulusReflexController = (element === parentControllerElement && controllerName === 'stimulus-reflex') if (!parentControllerElement || elementPreviouslyHadStimulusReflexController) { controllers.push(controllerName) } }) const controllerValue = attributeValue(controllers) const actionValue = attributeValue(actions) let emitReadyEvent = false if ( controllerValue && element.getAttribute(Schema.controller) != controllerValue ) { element.setAttribute(Schema.controller, controllerValue) emitReadyEvent = true } if (actionValue && element.getAttribute(Schema.action) != actionValue) { element.setAttribute(Schema.action, actionValue) emitReadyEvent = true } if (emitReadyEvent) { dispatch(element, 'stimulus-reflex:ready', { reflex: reflexAttribute, controller: controllerValue, action: actionValue, element }) } } export { scanForReflexes, scanForReflexesOnElement }