Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensuring $.fn.submit is aligned with jQuery #363

Open
vovayatsyuk opened this issue Feb 22, 2021 · 11 comments
Open

Ensuring $.fn.submit is aligned with jQuery #363

vovayatsyuk opened this issue Feb 22, 2021 · 11 comments
Labels

Comments

@vovayatsyuk
Copy link
Contributor

vovayatsyuk commented Feb 22, 2021

I'm trying to submit a form and trigger the submit event as well.

$(document).on('submit', function (event) {
    alert('submit');
});
form.trigger('submit') // event is raised, but form is not submitted
form.submit() // form is submitted, but event is not raised

To accomplish this task I tried to do the following:

$.fn.submit = function () {
    this.each(function () {
        $(this).trigger('submit');
        this.submit();
    });
};

It works as expected until I decided to use turbo. When the turbo is included on the site
and my custom fn.submit is used, the form gets submitted twice. Looks like turbo handles triggered events and submits a form on its own.

The interesting part in this thing that when using jquery's $form.submit() an event is raised and the form is submitted as well but only once. With or without turbo.

So, what magic trick does jquery do to submit the form once only? Or is it some fix in turbo code? And is there any other way to trigger an event and submit a form?

@fabiospampinato
Copy link
Owner

It would be good to have a codepen that reproduces the problem with cash but works with jquery, so that I can spend more time fixing the issue than reproducing it.

@vovayatsyuk
Copy link
Contributor Author

vovayatsyuk commented Feb 22, 2021

https://codepen.io/vovayatsyuk/pen/dyOVzPE?editors=1011 - I don't know how to easily see the double submit. I've opened the network panel in the Chrome dev toolbar and watched for all post requests.

I've added two event listeners for the submit event:

$c(document).on('submit', function (event) {
  // only native events are watched (jquery was not catched here)
});
$j(document).on('submit', function (event) {
  // all events are watched (cash and jquery events where catched)
});

Looks like the key is that jquery doesn't raise the native 'submit' event, so my question is not valid anymore :).

@vovayatsyuk
Copy link
Contributor Author

Here is how jquery do the trick:

$j(document).on('submit', function (event) {}); // listens to native js 'submit' events
$form.submit(); // doesn't trigger native event.

The way the first callback gets called is that jquery has a collection of all event handlers created on the page and run all of them (filtered) manually in a loop when you call $form.submit();: https://github.com/jquery/jquery/blob/025da4dd343e6734f3d3c1b4785b1548498115d8/src/event.js#L314-L344

@vovayatsyuk
Copy link
Contributor Author

Since jquery is not firing the native event, the turbo doesn't submit this form via ajax.

I can do the same with cash and data-turbo=false on a form.

Here is the code I will use:

$.fn.submit = function () {
    this.each(function () {
        $(this).data('turbo', false).trigger('submit');
        this.submit();
    });
};

$('form').submit(); // will trigger event, submit form and turbo will not do anything.

@vovayatsyuk
Copy link
Contributor Author

Not sure if anybody needs this, but I ended up with the following code.

It submits the form with turbo via ajax if possible:

$.fn.submit = function () {
    this.each(function () {
        var event = document.createEvent('Event');

        event.initEvent('submit', true, true);

        $(this).trigger(event);

        if (!event.defaultPrevented) {
            this.submit();
        }
    });
};

@fabiospampinato
Copy link
Owner

Reopening as it would seem that jQuery behaves differently than Cash in this scenario, which I would consider a bug.

@vovayatsyuk
Copy link
Contributor Author

I don’t think it’s a bug. jQuery uses custom events while cash uses native events (turbo listens to them). This is the reason of different results.

@fabiospampinato
Copy link
Owner

Yes but I think this kind of implementation detail shouldn't surface in your use case 🤔 Like I think probably turbo shouldn't be able to tell the difference.

@vovayatsyuk
Copy link
Contributor Author

My codepen is messed up a bit, but try to make the console panel a little bigger and you'll see that when pressing "Submit form with cash" button an event is raised and it's caught by cash, jquery, and native listeners:

Screenshot 2021-04-01 at 22 52 45

But, when pressing "Submit form with jquery" output is different. No one catches an event except jQuery:

Screenshot 2021-04-01 at 22 54 11

So, maybe jquery isn't really firing an event? Maybe jQuery triggers an event listener without firing an event?

@fabiospampinato
Copy link
Owner

Maybe, that'd be risky though I think, I don't know I'll have to look more closely into that once I'll find the time.

@fabiospampinato fabiospampinato changed the title A way to trigger native event with the native method? (Double submit issue when turbolinks is used) Ensuring $.fn.submit is aligned with jQuery Apr 2, 2021
@fabiospampinato fabiospampinato changed the title Ensuring $.fn.submit is aligned with jQuery Ensuring $.fn.submit is aligned with jQuery Apr 2, 2021
@niksy
Copy link

niksy commented Apr 22, 2021

This maybe seems like a large hack, but simulating click event on dynamically created submit button inside form should work: https://gist.github.com/mems/97a733d9c787dcf99cff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants