<commit_before>import {isFunction, toArray, find, noop} from '../utils.js';
import {Builder} from './Builder.js';

/**
 * The on builder.
 * Its goal is to provide a way to listen events coming from the custom element.
 * @extends {Builder}
 */
export class OnBuilder extends Builder {

    /**
     * @param {!string} events a list of tuple 'event target' separated by comas, the target is optional
     */
    constructor(events) {
        super();
        /**
         * @ignore
         */
        this.data = {events, invoke: noop};
    }

    /**
     * To do something when events occurred.
     * The target arugment is by default the custom element.
     * When the delegate feature is used, target is the matched element.
     * @param {!function(el: HTMLElement, evt: DOMEvent, target: HTMLElement)} fn the event's logic
     * @returns {OnBuilder} the builder
     */
    invoke(fn) {
        if (isFunction(fn)) {
            this.data.invoke = fn;
        }
        return this;
    }

    /**
     * To attach the event on the capture phase instread of on the bubble phase.
     * @returns {OnBuilder} the builder
     */
    capture() {
        this.data.capture = true;
        return this;
    }

    /**
     * To delegate the event.
     * @param {!string} selector the selector
     * @returns {OnBuilder} the builder
     */
    delegate(selector) {
        this.data.selector = selector;
        return this;
    }

    /**
     * To prevent the default behavior.
     * @returns {OnBuilder} the builder
     */
    prevent() {
        this.data.preventDefault = true;
        return this;
    }

    /**
     * To stop the event propagation.
     * @returns {OnBuilder} the builder
     */
    stop() {
        this.data.stopPropagation = true;
        return this;
    }

    /**
     * To prevent the default behavior and to stop the event propagation.
     * @returns {OnBuilder} the builder
     */
    skip() {
        return this.prevent().stop();
    }

    /**
     * @ignore
     */
    build(proto, on) {
        let events = this.data.events.split(',').map(event => event.trim().split(' ')),
            capture = !!this.data.capture,
            invoke = this.data.invoke,
            selector = this.data.selector,
            stopPropagation = this.data.stopPropagation,
            preventDefault = this.data.preventDefault;

        on('before:createdCallback').invoke((el) => {
            el._cebOnHandlers = [];
        });

        on('before:attachedCallback').invoke((el) => {
            let listener = evt => {
                if (stopPropagation) {
                    evt.stopPropagation();
                }
                if (preventDefault) {
                    evt.preventDefault();
                }

                if (selector) {
                    let target = find(
                        toArray(el.querySelectorAll(selector)),
                            el => el === evt.target || el.contains(evt.target)
                    );
                    if (target) {
                        invoke(el, evt, target);
                    }
                } else {
                    invoke(el, evt, el);
                }
            };

            el._cebOnHandlers = events
                .map(([name, target]) => [name, target ? el.querySelector(target) : el])
                .filter(([name, target]) => !!target)
                .map(([name, target]) => {<commit_msg>fix stop propagation and prevent default when delegate<commit_after>import {isFunction, toArray, find, noop} from '../utils.js';
import {Builder} from './Builder.js';

/**
 * The on builder.
 * Its goal is to provide a way to listen events coming from the custom element.
 * @extends {Builder}
 */
export class OnBuilder extends Builder {

    /**
     * @param {!string} events a list of tuple 'event target' separated by comas, the target is optional
     */
    constructor(events) {
        super();
        /**
         * @ignore
         */
        this.data = {events, invoke: noop};
    }

    /**
     * To do something when events occurred.
     * The target arugment is by default the custom element.
     * When the delegate feature is used, target is the matched element.
     * @param {!function(el: HTMLElement, evt: DOMEvent, target: HTMLElement)} fn the event's logic
     * @returns {OnBuilder} the builder
     */
    invoke(fn) {
        if (isFunction(fn)) {
            this.data.invoke = fn;
        }
        return this;
    }

    /**
     * To attach the event on the capture phase instread of on the bubble phase.
     * @returns {OnBuilder} the builder
     */
    capture() {
        this.data.capture = true;
        return this;
    }

    /**
     * To delegate the event.
     * @param {!string} selector the selector
     * @returns {OnBuilder} the builder
     */
    delegate(selector) {
        this.data.selector = selector;
        return this;
    }

    /**
     * To prevent the default behavior.
     * @returns {OnBuilder} the builder
     */
    prevent() {
        this.data.preventDefault = true;
        return this;
    }

    /**
     * To stop the event propagation.
     * @returns {OnBuilder} the builder
     */
    stop() {
        this.data.stopPropagation = true;
        return this;
    }

    /**
     * To prevent the default behavior and to stop the event propagation.
     * @returns {OnBuilder} the builder
     */
    skip() {
        return this.prevent().stop();
    }

    /**
     * @ignore
     */
    build(proto, on) {
        let events = this.data.events.split(',').map(event => event.trim().split(' ')),
            capture = !!this.data.capture,
            invoke = this.data.invoke,
            selector = this.data.selector,
            stopPropagation = this.data.stopPropagation,
            preventDefault = this.data.preventDefault;

        on('before:createdCallback').invoke((el) => {
            el._cebOnHandlers = [];
        });

        on('before:attachedCallback').invoke((el) => {
            let listener = evt => {
                if (selector) {
                    let target = find(
                        toArray(el.querySelectorAll(selector)),
                            el => el === evt.target || el.contains(evt.target)
                    );
                    if (target) {
                        if (stopPropagation) {
                            evt.stopPropagation();
                        }
                        if (preventDefault) {
                            evt.preventDefault();
                        }
                        invoke(el, evt, target);
                    }
                } else {
                    if (stopPropagation) {
                        evt.stopPropagation();
                    }
                    if (preventDefault) {
                        evt.preventDefault();
                    }
                    invoke(el, evt, el);
                }
            };

            el._cebOnHandlers = events
                .map(([name, target]) => [name, target ? el.querySelector(target) : el])
                .filter(([name, target]) => !!target)
                .map(([name, target]) => {
{'fraction_non_alphanumeric': 0.11807296017822333, 'fraction_numerical': 0.0, 'mean_word_length': 1.488049878766886, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5872566', 'n_tokens_mistral': 1910, 'n_tokens_neox': 1883, 'n_words': 523}