wj-elements
Version:
WebJET Elements is a modern set of user interface tools harnessing the power of web components designed to simplify web application development.
151 lines (150 loc) • 5.29 kB
JavaScript
const routerLinksData = Symbol("routerLinksData");
const linkContainers = /* @__PURE__ */ new Set();
let router;
const delegate = function(el, eventName, selector, listener, context) {
const handler = function(e) {
let node = e.target;
for (; node && node !== el; node = node.parentNode) {
if (node.matches && node.matches(selector)) {
e.selectorTarget = node;
listener.call(context, e);
}
}
};
handler.eventName = eventName;
el.addEventListener(eventName, handler, false);
return handler;
};
function isModifiedEvent(event) {
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
}
const undelegate = function(el, handler) {
const eventName = handler.eventName;
el.removeEventListener(eventName, handler, false);
};
const camelize = (str) => {
if (str.indexOf("-") === -1) return str;
const words = str.split("-");
let result = "";
for (let i = 0; i < words.length; i++) {
const word = words[i];
result += i ? word.charAt(0).toUpperCase() + word.slice(1) : word;
}
return result;
};
function mutationHandler(mutations, observer) {
mutations.forEach(function(mutation) {
if (mutation.type === "attributes") {
const attr = mutation.attributeName;
if (attr.indexOf("param-") === 0 || attr.indexOf("query-") === 0) {
updateLink(mutation.target, observer.rootEl);
}
} else {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) {
if (node.getAttribute("route")) updateLink(node, observer.rootEl);
createLinks(observer.rootEl);
}
});
}
});
}
const elementsObserverConfig = { childList: true, subtree: true, attributes: true };
function getAttributeValues(el, prefix, result) {
const attributes = el.attributes;
for (let i = 0; i < attributes.length; i++) {
const attr = attributes[i];
if (attr.name.indexOf(prefix) === 0) {
const paramName = camelize(attr.name.slice(prefix.length));
result[paramName] = attr.value;
}
}
return result;
}
function getDefaults(rootEl, routeName, propName, routeEl, options) {
let result = options[propName];
if (typeof result === "function") result = result.call(rootEl, routeName, routeEl);
return result || {};
}
function getRouteProp(rootEl, routeName, routeEl, propName, attrPrefix) {
const options = rootEl[routerLinksData].options;
const defaults = getDefaults(rootEl, routeName, propName, routeEl, options);
getAttributeValues(rootEl, attrPrefix, defaults);
return getAttributeValues(routeEl, attrPrefix, defaults);
}
function updateActiveClass(el, routeName, params, query) {
const activeClass = el.hasAttribute("active-class") ? el.getAttribute("active-class") : "active";
if (activeClass) {
const isActive = router.isActive(routeName, params, query, el.hasAttribute("exact"));
el.classList.toggle(activeClass, isActive);
}
}
function updateLink(el, rootEl) {
const routeName = el.getAttribute("route");
if (!routeName) return;
const params = getRouteProp(rootEl, routeName, el, "params", "param-");
const query = getRouteProp(rootEl, routeName, el, "query", "query-");
try {
const href = router.generate(routeName, params, query);
const anchorEl = el.tagName === "A" ? el : el.querySelector("a");
if (anchorEl) anchorEl.setAttribute("href", href);
if (!router.state.activeTransition) {
updateActiveClass(el, routeName, params, query);
}
} catch (error) {
console.warn(`Error generating link for "${routeName}": ${error}`);
}
}
function createLinks(rootEl) {
const routeEls = rootEl.querySelectorAll("[route]");
routeEls.forEach((el) => {
updateLink(el, rootEl);
});
}
function linkClickHandler(e) {
if (e.button !== 0 || isModifiedEvent(e)) return;
e.preventDefault();
const el = e.selectorTarget;
const routeName = el.getAttribute("route");
if (!routeName) return;
const params = getRouteProp(this, routeName, el, "params", "param-");
const query = getRouteProp(this, routeName, el, "query", "query-");
const method = el.hasAttribute("replace") ? "replaceWith" : "transitionTo";
router[method](routeName, params, query);
}
function bindRouterLinks(rootEl, options = {}) {
const observer = new MutationObserver(mutationHandler);
observer.rootEl = rootEl;
rootEl[routerLinksData] = { options, observer };
const eventHandler = delegate(rootEl, "click", "[route]", linkClickHandler, rootEl);
createLinks(rootEl);
observer.observe(rootEl, elementsObserverConfig);
linkContainers.add(rootEl);
return function() {
linkContainers.delete(rootEl);
undelegate(rootEl, eventHandler);
};
}
function create(instance) {
router = instance;
}
function done() {
linkContainers.forEach((rootEl) => {
rootEl.querySelectorAll("[route]").forEach((el) => {
const routeName = el.getAttribute("route");
if (!routeName) return;
const params = getRouteProp(rootEl, routeName, el, "params", "param-");
const query = getRouteProp(rootEl, routeName, el, "query", "query-");
updateActiveClass(el, routeName, params, query);
});
});
}
const routerLinks = {
create,
done
};
export {
bindRouterLinks as b,
routerLinks as r
};
//# sourceMappingURL=router-links-CJnOdbas.js.map