Skip to content

Instantly share code, notes, and snippets.

@disgusting-dev
Last active September 6, 2023 09:49
Show Gist options
  • Select an option

  • Save disgusting-dev/8d45aebff8a536af1cba39b0fcd203e3 to your computer and use it in GitHub Desktop.

Select an option

Save disgusting-dev/8d45aebff8a536af1cba39b0fcd203e3 to your computer and use it in GitHub Desktop.

Revisions

  1. disgusting-dev revised this gist Apr 6, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion vue-directive-clickOutside.js
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,7 @@ function processArgs(value) {

    return {
    handler: isFunction ? value : value.handler,
    middleware: value.middleware || (() => {}),
    middleware: value.middleware || (() => true),
    }
    }

  2. disgusting-dev revised this gist Apr 6, 2021. 1 changed file with 2 additions and 8 deletions.
    10 changes: 2 additions & 8 deletions vue-directive-clickOutside.js
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,4 @@
    const isTouch =
    typeof window !== 'undefined'
    && ('ontouchstart' in window || navigator.msMaxTouchPoints > 0);

    const events = isTouch
    ? ['touchstart', 'click']
    : ['click'];
    const events = ['click'];

    function onClickOutside({ event, el, handler, middleware }) {
    const isClickOutside =
    @@ -39,7 +33,7 @@ function processArgs(value) {

    return {
    handler: isFunction ? value : value.handler,
    middleware: value.middleware || ((isClickOutside) => isClickOutside),
    middleware: value.middleware || (() => {}),
    }
    }

  3. disgusting-dev revised this gist Mar 16, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion vue-directive-clickOutside.js
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@ function onClickOutside({ event, el, handler, middleware }) {
    event.target !== el
    && !el.contains(event.target);

    if (!isClickOutside && !middleware(event, el)) {
    if (!isClickOutside || !middleware(event, el)) {
    return null;
    }

  4. disgusting-dev revised this gist Mar 14, 2021. 1 changed file with 45 additions and 30 deletions.
    75 changes: 45 additions & 30 deletions vue-directive-clickOutside.js
    Original file line number Diff line number Diff line change
    @@ -6,59 +6,74 @@ const events = isTouch
    ? ['touchstart', 'click']
    : ['click'];

    function onClickOutside({ event, el, handler }) {
    function onClickOutside({ event, el, handler, middleware }) {
    const isClickOutside =
    event.target !== el
    && !el.contains(event.target);

    return isClickOutside ? handler(event, el) : null;
    if (!isClickOutside && !middleware(event, el)) {
    return null;
    }

    return handler(event, el);
    }

    const instances = new Map();

    function bind(el, { value: handler }) {
    const eventHandler = event => onClickOutside({ el, event, handler});

    toggleEventListeners('add', eventHandler);

    instances.set(
    el,
    eventHandler
    );
    //Requires loop to toggle events for several listeners of an element
    function toggleEventListeners(eventHandlers) {
    return (action) => {
    eventHandlers.forEach(({ event, handler }) => {
    document[`${action}EventListener`](event, handler, true);
    })
    }
    }

    function update(el) {
    const eventHandler = instances.get(el);
    //Validator function
    function processArgs(value) {
    const isFunction = typeof value === 'function';

    toggleEventListeners('remove', eventHandler);
    toggleEventListeners('add', eventHandler);
    }
    if (!isFunction && typeof value !== 'object') {
    throw new Error(`v-click-outside: Binding value should be a function or an object, ${typeof bindingValue} given`)
    }

    function unbind(el) {
    const eventHandler = instances.get(el);
    return {
    handler: isFunction ? value : value.handler,
    middleware: value.middleware || ((isClickOutside) => isClickOutside),
    }
    }

    toggleEventListeners('remove', eventHandler);
    //Now need adapter to handle several events for one Map element
    function eventAdapter(events, { el, handler, middleware }) {
    return events.map((eventName) => ({
    event: eventName,
    handler: (event) => onClickOutside({ event, el, handler, middleware })
    }));
    }

    function processArgs(value) {
    function bind(el, { value }) {
    const { handler, middleware } = processArgs(value);
    const eventHandlers = eventAdapter(events, { el, handler, middleware });

    }
    instances.set(
    el,
    eventHandlers,
    );

    function toggleEventListeners(action, eventHandler) {
    document[`${action}EventListener`]('click', eventHandler);
    toggleEventListeners(eventHandlers)('add');
    }

    function eventAdapter(events) {
    return events.map((eventName) => ({
    event: eventName,
    handler: (event) => onEvent({ event, el, handler, middleware })
    }));
    function unbind(el) {
    const eventHandlers = instances.get(el);

    toggleEventListeners(eventHandlers)('remove');

    instances.delete(el);
    }

    const directive = {
    bind,
    update,
    unbind,
    };

    export default directive;
    export default directive;
  5. disgusting-dev revised this gist Mar 14, 2021. 1 changed file with 15 additions and 34 deletions.
    49 changes: 15 additions & 34 deletions vue-directive-clickOutside.js
    Original file line number Diff line number Diff line change
    @@ -1,16 +1,11 @@
    /* Define event listeners to work with */
    const isTouch =
    typeof window !== 'undefined'
    && ('ontouchstart' in window || navigator.msMaxTouchPoints > 0);

    const events = isTouch
    ? ['touchstart', 'click']
    : ['click'];
    /* End of events definition */

    const instances = [];

    //1.
    function onClickOutside({ event, el, handler }) {
    const isClickOutside =
    event.target !== el
    @@ -19,52 +14,38 @@ function onClickOutside({ event, el, handler }) {
    return isClickOutside ? handler(event, el) : null;
    }

    //2.
    document.addEventListener('click', (event) => onClickOutside({ event }))

    //3.
    const instances = [];
    const instances = new Map();

    //4.
    function bind(el, { value: handler }) {
    //5.
    const instance = {
    el,
    eventHandlers: eventAdapter(events),
    };
    const eventHandler = event => onClickOutside({ el, event, handler});

    //6.
    toggleEventListeners(instance);
    toggleEventListeners('add', eventHandler);

    instances.push(instance);
    instances.set(
    el,
    eventHandler
    );
    }

    function update(el, { value }) {
    //7.
    const instance = instances.find(item => item.el === el);
    function update(el) {
    const eventHandler = instances.get(el);

    //8.
    removeIstanceListeners(instance);
    //9.
    instance.eventHandlers = eventAdapter(events)
    //10.
    toggleEventListeners(instance, 'add');
    toggleEventListeners('remove', eventHandler);
    toggleEventListeners('add', eventHandler);
    }

    function unbind(el) {
    const instance = instances.find(item => item.el === el);
    const eventHandler = instances.get(el);

    toggleEventListeners(instance, 'remove');
    toggleEventListeners('remove', eventHandler);
    }

    function processArgs(value) {

    }

    function toggleEventListeners(instance, action) {
    instance.eventHandlers.forEach(({ event, handler }) =>
    document[`${action}EventListener`](event, handler),
    );
    function toggleEventListeners(action, eventHandler) {
    document[`${action}EventListener`]('click', eventHandler);
    }

    function eventAdapter(events) {
  6. disgusting-dev created this gist Mar 13, 2021.
    83 changes: 83 additions & 0 deletions vue-directive-clickOutside.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,83 @@
    /* Define event listeners to work with */
    const isTouch =
    typeof window !== 'undefined'
    && ('ontouchstart' in window || navigator.msMaxTouchPoints > 0);

    const events = isTouch
    ? ['touchstart', 'click']
    : ['click'];
    /* End of events definition */

    const instances = [];

    //1.
    function onClickOutside({ event, el, handler }) {
    const isClickOutside =
    event.target !== el
    && !el.contains(event.target);

    return isClickOutside ? handler(event, el) : null;
    }

    //2.
    document.addEventListener('click', (event) => onClickOutside({ event }))

    //3.
    const instances = [];

    //4.
    function bind(el, { value: handler }) {
    //5.
    const instance = {
    el,
    eventHandlers: eventAdapter(events),
    };

    //6.
    toggleEventListeners(instance);

    instances.push(instance);
    }

    function update(el, { value }) {
    //7.
    const instance = instances.find(item => item.el === el);

    //8.
    removeIstanceListeners(instance);
    //9.
    instance.eventHandlers = eventAdapter(events)
    //10.
    toggleEventListeners(instance, 'add');
    }

    function unbind(el) {
    const instance = instances.find(item => item.el === el);

    toggleEventListeners(instance, 'remove');
    }

    function processArgs(value) {

    }

    function toggleEventListeners(instance, action) {
    instance.eventHandlers.forEach(({ event, handler }) =>
    document[`${action}EventListener`](event, handler),
    );
    }

    function eventAdapter(events) {
    return events.map((eventName) => ({
    event: eventName,
    handler: (event) => onEvent({ event, el, handler, middleware })
    }));
    }

    const directive = {
    bind,
    update,
    unbind,
    };

    export default directive;