bigskysoftware / htmx

</> htmx - high power tools for HTML
https://htmx.org
Other
38.19k stars 1.3k forks source link

evt.preventDefault() doesn't work in an extension #1711

Open infuzu-yidisprei opened 1 year ago

infuzu-yidisprei commented 1 year ago

I have the following extension that I have been working on:

htmx.on('htmx:beforeRequest', function(evt) {
    const el = evt.detail.elt;
    if (el.hasAttribute('hx-classify')) {
        if (el.getAttribute('hx-get') === '/noop-classify') {
            evt.preventDefault();
            console.log("printing one")
        }
    }
})
htmx.logAll()
htmx.defineExtension('classify', {
    onEvent: function(name, evt) {
        if (name === 'htmx:beforeRequest') {
            const el = evt.detail.elt;
            if (el.getAttribute('hx-get') === '/noop-classify') {
                evt.preventDefault();
                console.log("printing two")
            }
        }
        if (name === 'htmx:configRequest') {
            const el = evt.detail.elt;

            // Find the target element
            const hxTarget = el.getAttribute('hx-target');
            let target = hxTarget === 'this' ? el : (htmx.find(hxTarget) || el);

            // Get and process the hx-class-action attribute
            const classActions = el.getAttribute('hx-classify').split(',').map(s => s.trim());
            classActions.forEach(function(classAction) {
                const [action, classNames, revertTime] = classAction.split(':');
                const classList = classNames.split(' ');
                const originalClasses = target.className;

                switch (action) {
                    case 'add':
                        target.classList.add(...classList);
                        break;
                    case 'remove':
                        target.classList.remove(...classList);
                        break;
                    case 'replace':
                        target.className = classNames;
                        break;
                }

                // Revert class changes after revertTime, if provided
                if (revertTime) {
                    const revertMilliseconds = htmx.parseInterval(revertTime); // Convert to milliseconds
                    setTimeout(function() {
                        switch (action) {
                            case 'add':
                                target.classList.remove(...classList);
                                break;
                            case 'remove':
                                target.classList.add(...classList);
                                break;
                            case 'replace':
                                target.className = originalClasses;
                                break;
                        }
                    }, revertMilliseconds);
                }
            });
        }
        else if (name === 'htmx:load') {
            let elementsModified = false;
            document.querySelectorAll('[hx-classify]').forEach(function(el) {
                if (!el.hasAttribute('hx-get') && !el.hasAttribute('hx-post') && !el.hasAttribute('hx-put') && !el.hasAttribute('hx-patch') && !el.hasAttribute('hx-delete')) {
                    el.setAttribute('hx-get', '/noop-classify');
                    elementsModified = true;
                }
            });
            if (elementsModified) {
                htmx.process(document.body);
            }
        }
    }
});

I know there is duplicate code for evt.preventDefault. I put both in so you get the idea. you can comment one out to see that they don't both work. I am aware that both can't exist at the same time in the code because the beforeRequest only triggers one of them. But when you take out the htmx.on code and only leave the extension code in, the console will print "printing two" but the evt.preventDefault() won't do anything. When you comment out that section in the extension and only run the htmx.on code, it does what it's supposed to and stops the request from going out. Any idea why this is happening?

xhaggi commented 1 year ago

There is an open pull request for this issue https://github.com/bigskysoftware/htmx/pull/1456. At the moment you have to use return false instead of evt.preventDefault().

YidiDev commented 1 year ago

thank you so much. returning false does work for now