All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.dist.module-debug.event.js Maven / Gradle / Ivy

The newest version!

import { EventOptions } from "./type.js";
import Mikado from "./mikado.js";

/** @type {Object} */
const events = {},
      event_options = {},
      routes = Object.create(null),
      options = Object.create(null),
      doc = document.documentElement || document.body.parentNode,
      has_touch = "ontouchstart" in window,
      has_pointer = !has_touch && window.PointerEvent && navigator.maxTouchPoints;
/** @type {Object} */

/** @type {Object} */

/** @type {Object} */


// The most outer element which is covered by Mikado event system is document.body

/** @type {boolean} */
Mikado.eventCache = !1;
/** @type {boolean} */
Mikado.eventBubble = !1;


let tap_fallback;

/**
 * @param {!Event} event
 * @param {string=} type
 */

export function handler(event, type) {

    const event_target = event.target;
    // we just handle events which are defined somewhere in the DOM
    // do we need handle events on documentElement?
    if (event_target === window || event_target === doc) return;

    const use_event_cache = Mikado.eventCache,
          use_bubble = Mikado.eventBubble;

    type || (type = event.type);

    let cache;

    // When the "eventCache" option is enabled, all the assigned event route names and all the event targets exposed by bubbling
    // are being cached, and therefore they can't be changed dynamically after its creation.
    // Instead of: 
you will need then just apply logic inside the handler. // Alternatively a route can re-defined dynamically by register a new function to it by calling Mikado.route(name, fn, options) again. // Delete a route by Mikado.route(name, null, null) if (use_event_cache) { cache = event_target["_mke" + type]; } if ("undefined" == typeof cache) { let target = event_target; // bubble up the dom tree to find element which has assigned a handler while (target && target !== doc) { let route; if ("click" === type && tap_fallback) { route = target.getAttribute("tap"); } if (!route) { route = target.getAttribute(type); } if (route) { const delimiter = route.indexOf(":"); // when continue bubble it needs the original target let root = target; // it has a custom target, bubbling needs to continue if (-1 < delimiter) { const handler = route.substring(0, delimiter), attr = route.substring(delimiter + 1); route = ""; // continue bubble up the dom tree to find the custom defined root element while ((root = root.parentElement) !== doc) { if ("root" === attr ? root._mkr : root.hasAttribute(attr)) { route = handler; break; } } if (!route) { console.warn("Event root '" + attr + "' was not found for the event: '" + handler + "'."); } } if (route) { if (!cache) { cache = []; if (use_event_cache) { event_target["_mke" + type] = cache; } } cache.push([route, root]); const option = options[route]; if (!use_bubble || option && (option.stop || option.cancel)) { // stop bubbling break; } } } // continue bubble up target = target.parentElement; } if (use_event_cache) { cache || (event_target["_mke" + type] = null); } } else {} if (cache) for (let i = 0, tmp; i < cache.length; i++) { tmp = cache[i]; const route = tmp[0], fn = routes[route]; if (fn) { const target = tmp[1], option = options[route]; if (option) { option.prevent && event.preventDefault(); option.stop && event.stopImmediatePropagation(); if (option.once) { routes[route] = null; if (use_event_cache) { event_target["_mke" + type] = null; } } } //fn(target, event, event_target); fn(target, event); } else { console.warn("The route '" + route + "' is not defined for the event '" + type + "'."); } } } /** * @param {!string} route * @param {Function|null} fn * @param {EventOptions=} option */ export function route(route, fn, option) { if (!route) { throw new Error("Missing route name."); } if (!fn) { throw new Error("The route '" + route + "' has no function assigned to it."); } if (routes[route]) { console.info("A new handler was re-assigned to the route '" + route + "'."); } routes[route] = fn; options[route] = option || null; return this; } /** * @param {!string} route * @param {Element=} target * @param {Event=} event */ export function dispatch(route, target, event) { if (!route) { throw new Error("Missing route name."); } if (!routes[route]) { throw new Error("Undefined route '" + route + "'."); } routes[route](target || this, event || window.event); return this; } /** * @param {!string} event * @param {EventListenerOptions|boolean=} options */ export function listen(event, options) { if (!events[event]) { register_event(1, event, handler, options); events[event] = 1; event_options[event] = options || null; } return this; } /** * @param {string} event * @returns {Mikado} */ export function unlisten(event) { if (events[event]) { register_event(0, event, handler, event_options[event]); events[event] = 0; event_options[event] = null; } return this; } let touch_x, touch_y, register_tap; if (has_touch || has_pointer) { /** * @param {TouchEvent|PointerEvent} event */ function handler_down(event) { pointer(event, event.touches); } /** * @param {TouchEvent|PointerEvent} event */ function handler_end(event) { const last_x = touch_x, last_y = touch_y; pointer(event, event.changedTouches); if (15 > Math.abs(touch_x - last_x) && 15 > Math.abs(touch_y - last_y)) { handler(event, "tap"); } } /** * @param {TouchEvent|PointerEvent|Touch} event * @param {TouchList} touches */ function pointer(event, touches) { if (touches) { event = touches[0]; } touch_x = event.clientX; touch_y = event.clientY; } /** * @type {EventListenerOptions} */ const opt = { // Note: the default click behavior should not force passive handling passive: !1, // Capturing by default, since we need the event dispatched from window capture: !0 }; register_tap = function (add_or_remove) { register_event(add_or_remove, has_pointer ? "pointerdown" : "touchstart", handler_down, opt); //register_event(add_or_remove, "touchmove", handler_move, false); register_event(add_or_remove, has_pointer ? "pointerup" : "touchend", handler_end, opt); }; } /** * @param {boolean|number} add_or_remove * @param {string} type * @param {Function} handler * @param {EventListenerOptions|boolean=} options */ function register_event(add_or_remove, type, handler, options) { if ("tap" === type) { if (has_touch || has_pointer) { register_tap(add_or_remove); return; } else { tap_fallback = !0; type = "click"; } } window[(add_or_remove ? "add" : "remove") + "EventListener"](type, handler, // Capturing by default, since we need the event dispatched from window options || !1 === options ? options : !0); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy