@ulu/frontend
Version:
A versatile SCSS and JavaScript component library offering configurable, accessible components and flexible integration into any project, with SCSS modules suitable for modern JS frameworks.
108 lines (100 loc) • 3.31 kB
JavaScript
/**
* @module events
*/
import { debounce } from "@ulu/utils/performance.js";
import { isBrowser } from "@ulu/utils/browser/dom.js";
// Setup global document events
if (isBrowser()) {
initResize();
initPrint();
}
/**
* Event object - called on dispatch
*/
const events = {
/**
* Event is dispatched when DOM in the page has changed, triggers updates from
* all modules listening for the change (init instances, etc)
* - Is triggered by modules that were responsible for modifying the page
*/
pageModified(context) {
context.dispatchEvent(createEvent("pageModified"));
},
/**
* Event called when page is resized
*/
pageResized(context) {
context.dispatchEvent(createEvent("pageResized"));
},
/**
* Event dispatched before page print begins (teardown/restructure/hide things)
*/
beforePrint(context) {
context.dispatchEvent(createEvent("beforePrint"));
},
/**
* Event dispatched after page print (cleanup)
*/
afterPrint(context) {
context.dispatchEvent(createEvent("afterPrint"));
}
};
/**
* Triggers one of our custom events (page/document level events)
* - UI components may dispatch their own events, this is just used for system wide events
* @param {String} type Type of event to dispatch
* @param {Node} context Element to trigger the event from
* @example
* if (updatedMarkup) {
* dispatch("pageModified", modalElement);
* }
*/
export function dispatch(type, context) {
if (events[type]) {
events[type](context);
} else {
console.warn(`Unable to dispatch site event: ${ type } in context:`, context);
}
}
/**
* Namespaced event
* - Should be used for all ulu script/component events
* @param {String} type Type of event to get the actual event name for
* @returns {String}
*/
export function getName(type) {
return "ulu:" + type;
}
/**
* Create ulu namespaced custom event
* @param {String} type Event base name (not prefixed)
* @param {any} data Custom data to pass with the event (will be available as `event.detail`)
* @param {Object} options CustomEvent options default `{ bubbles: true }`. If `detail` is also provided, it will be merged with this options object and will override the 'data' argument for this function
*/
export function createEvent(type, data = null, options = { bubbles: true }) {
return new CustomEvent(getName(type), { detail: data, ...options });
}
/**
* Setup resize handler/dispatch
*/
function initResize() {
window.addEventListener("resize", debounce(() => dispatch("pageResized", document), 250));
}
/**
* Setup print listeners
* - Note: Tested with matchMedia but these events are more consistent
* Experimented with normalizing both events but they fired
* strangely, using any delay won't work (ie setTimeout / RAF)
* chrome pauses immediately javascript after the initial event.
* Reverting to a straightforward method for now. If this ends up
* needing something more robust we can work that out on this side
* and it won't change how the custom events file.
*/
function initPrint() {
window.addEventListener("beforeprint", () => {
dispatch("beforePrint", document);
});
window.addEventListener("afterprint", () => {
dispatch("afterPrint", document);
});
}