Problem/Motivation

I had two views on the page with two ajax exposed filter forms. Due to a bug in views, i spent a lot of time debugging JS. I found a couple of things about auto-submit :

  • the change event was bubbling and triggering a click at each step. The submit button was triggered a lot of times
  • textfield handling wasn't working at all
  • would it be working timeoutID would probably get in the way
  • there was a typo in addClass() that defeated the purpose of adding the class

Proposed resolution

  • I cleaned up the selectors (based on #875020) it's actually readable now
  • thanks to that, change is not bubbling anymore and textfield handling is back
  • each textfield has his own timeoutID

Remaining tasks

I understand why but i'm not too happy with the way textfields are handled. You really can't be slow while typing. I'd feel better if we used change event on this too or having a config option somewhere to choose.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

nod_’s picture

More on the textfield handling. I think polling for changes of the textfield value is a better way than using keyup. And this way we can trigger a change event and have only one function take care of submit. Should take care of mouse copy/paste too.

Should i open another issue or just a patch on top of this one ?

nod_’s picture

Status: Active » Needs review
nod_’s picture

Status: Needs review » Needs work

Sorry about that it was a half-hearted attempt, i'm rewriting my patch. It'll be there in a couple of hours.

nod_’s picture

Status: Needs work » Needs review
FileSize
3.99 KB
3.14 KB

The first patch is the bare minimum to fix the issues. No behavior change exept the timeout for keyup that was bumped to 500ms, not much difference but avoid most premature submit when you type slowly, at least for me. The big size is only because of the indenting for the switch.

The second patch is a complete rewrite, cleaning up selectors, fixing behaviors on textfields by adding a clearTimeout on keydown and wait for bubbling change event for ctools-auto-submit-full-form.

for both radios and checkboxes are now supported.

merlinofchaos’s picture

Title: auto-submit.js is broken and ugly » Clean up and improve auto-submit.js

Just FYI, while I'm not at all against a patch to clean up the code, every time I see this title I am demotivated to actually look at it, because it's insulting and inaccurate.

nod_’s picture

I'm sorry merlinofchaos. I wrote that after losing a lot of time over the issue, it's nothing personal and certainly not a judgment of the rest of the module which I appreciate. It was just an unlucky patch that got through a couple of months ago.

If you need any follow up/testing on this, I'll do my best to make up for my initial rudeness.

merlinofchaos’s picture

I'm generally in favor of the cleanup you've got. My one comment:

+    // e.keyCode: key
+    // 16: shift
+    // 17: ctrl
+    // 18: alt
+    // 20: caps lock
+    // 33: page up
+    // 34: page down
+    // 35: end
+    // 36: home
+    // 37: left arrow
+    // 38: up arrow
+    // 39: right arrow
+    // 40: down arrow
+    //  9: tab
+    // 13: enter
+    // 27: esc
+    var discardKeyCode = [16, 17,18, 20, 33, 34, 35, 36, 37, 38, 39, 40, 9, 13, 27];

I'd rather have these combined so that it looks more like:

var discardKeyCode = [
  16, // shift
  // ... etc
  27 // esc
];

Just because the way it's commented isn't as intuitive what's going on I think.

nod_’s picture

agreed it makes more sense. The new patch uses .once() instead of .not() and .addClass() too.

Thanks for taking the time to review.

yannickoo’s picture

I attached a patch here #1400802: Fix for auto-submit.js. Can we merge it with this one here? I added support for all input types and select lists.

nod_’s picture

Ok checked both patches and mine already takes care of select and other input types. There is a .filter('form, select, input:not(:text, :submit)') and $('.ctools-auto-submit-full-form input:text, input:text.ctools-auto-submit').

Can you please confirm yannickoo ?

nod_’s picture

FYI the patch at #1400802: Fix for auto-submit.js has a bug, it binds the change event on text input which would cause issues with the special handling of text input in the second half of the file, I ran into this working on my patch too. No harm but I'm pointing it out for yannickoo, do some more testing for your next patch ;)

yannickoo’s picture

Then we could just exclude textfields with $('... :not(input[type=text])')?

nod_’s picture

yeah look up the patch, it's in there.

yannickoo’s picture

Ah cool, why we are wating? Let's commit!

nod_’s picture

Because merlinofchaos has his own schedule about how he does stuff. The way to help get this committed is to test it well and set RTBC if you don't find any issue. It'll inform him that he can use his time to review/commit the patch.

I can't mark it RTBC because i'm the one who wrote the patch, so it's all in your hands yannickoo :)

merlinofchaos’s picture

I've just been waiting on the two of you to come to consensus. If you can test it and verify it all works as expected then I will commit it and probably right away.

yannickoo’s picture

We should also support file inputs! And also the HTML5 inputs. We could just get them with $('input') - why you didn't do that nod_?

nod_’s picture

Status: Needs review » Reviewed & tested by the community

I did, test the patch before asking that kind of question.

I'll make this simple by marking it RTBC #8 works and we're already on comment #18, let's close this already.

mdupont’s picture

Here is a D6 version of the patch in #8. The only difference is that .once() doesn't exist in D6 so I used the old way of -processed classes.

levialliance’s picture

If I'm not mistaken, the attach() function should take a context argument as per http://drupal.org/node/756722#behaviors

Edit: Fixed the .add() in response to soulston's comment below

(diff is against the patched file)

diff --git a/js/auto-submit.js b/js/auto-submit.js
index 169878a..bc5a58e 100644
--- a/js/auto-submit.js
+++ b/js/auto-submit.js
@@ -27,7 +27,7 @@
  */

 Drupal.behaviors.CToolsAutoSubmit = {
-  attach: function() {
+  attach: function(context) {
     // 'this' references the form element
     function triggerSubmit (e) {
       if (!$(this).hasClass('ctools-ajaxing')) {
@@ -36,8 +36,8 @@ Drupal.behaviors.CToolsAutoSubmit = {
     }

     // the change event bubbles so we only need to bind it to the outer form
-    $('form.ctools-auto-submit-full-form')
-      .add('.ctools-auto-submit')
+    $('form.ctools-auto-submit-full-form', context)
+      .add('.ctools-auto-submit', context)
       .filter('form, select, input:not(:text, :submit)')
       .once('ctools-auto-submit')
       .change(function (e) {
@@ -66,7 +66,7 @@ Drupal.behaviors.CToolsAutoSubmit = {
       27  // esc
     ];
     // Don't wait for change event on textfields
-    $('.ctools-auto-submit-full-form input:text, input:text.ctools-auto-submit')
+    $('.ctools-auto-submit-full-form input:text, input:text.ctools-auto-submit', context)
       .once('ctools-auto-submit', function () {
         // each textinput element has his own timeout
         var timeoutID = 0;

I don't know whether this should be here or in a new issue (given that this patch hasn't actually been committed yet), but the following allows ctools auto submit to work with date_popup: (again, diff is against the patched file)

--- auto-submit.js
+++ auto-submit.js
@@ -81,6 +81,15 @@
               timeoutID = setTimeout($.proxy(triggerSubmit, this.form), 500);
             }
           });
+
+        // date popup autosubmit
+        if (Drupal.settings.datePopup) {
+          $(this)
+            .filter(function() {
+              return Drupal.settings.datePopup[this.id] !== undefined;
+            })
+            .change($.proxy(triggerSubmit, this.form));
+        }
       });
   }
 }
soulston’s picture

Shouldn't this:

.add('.ctools-auto-submit')

be

.add('ctools-auto-submit')

i.e. no dot when adding the class in lines 35 and 42:


Drupal.behaviors.CToolsAutoSubmit = {
  attach: function() {
    var timeoutID = 0;

    // Bind to any select widgets that will be auto submitted.
    $('select.ctools-auto-submit:not(.ctools-auto-submit-processed),.ctools-auto-submit-full-form *[type!=input]:not(.ctools-auto-submit-processed)')
      .addClass('.ctools-auto-submit-processed')
      .change(function() {
        $(this.form).find('.ctools-auto-submit-click').click();
      });

    // Bind to any textfield widgets that will be auto submitted.
    $('input[type=text].ctools-auto-submit:not(.ctools-auto-submit-processed),.ctools-auto-submit-full-form input[type=text]:not(.ctools-auto-submit-processed)')
      .addClass('.ctools-auto-submit-processed')
      .keyup(function(e) {
        var form = this.form;
        switch (e.keyCode) {
          case 16: // shift

soulston’s picture

FileSize
1 KB

Here's a patch against 7.x-1.x

levialliance’s picture

Shouldn't this:

.add('.ctools-auto-submit')

be

.add('ctools-auto-submit')

i.e. no dot when adding the class in lines 35 and 42:

This comment is a bit confusing: you refer to add() (which should have a dot) but your patch below only modifies addClass() calls (which shouldn't have a dot) [and were already changed in all of nod_'s patches].

Although now that you've pointed it out, the .add() in nod_'s last patch should respect the context argument.

soulston’s picture

Ah - yeah I see now, sorry but I patched against dev and didn't add in the patches in this issue :(

rlmumford’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
3.89 KB

Here's a complete version of nod_'s patch with the context arguments in place. Didn't solve my problem with the media browser though, but I think thats a special case:

rlmumford’s picture

MY bad, this does fix the media browser problem (I was using an out of date version of views)

gmclelland’s picture

I haven't tested the newer patches, but @nod_ patch in #8 seems to fix the issue with the Media module's "Views Media Library" view randomly redirecting the inside of the modal to the homepage when a search is performed.

Here is the issue #1319528: Media browser view library exposed form submit problem

merlinofchaos’s picture

Status: Needs review » Fixed

Committed and pushed.

dawehner’s picture

I'm wondering whether this patch might be a possible candidate to backport to 6.x.

EugenMayer’s picture

Version: 7.x-1.x-dev » 6.x-1.x-dev
Status: Fixed » Needs review

i would so much love to help / see this happening for D6. Currently, the auto-submit implementation is basically unusable with textfields. I really love the functionality. What are the tasks for the backport?

klonos’s picture

The issue summary doesn't mention any API changes, so I'm not sure if this would be possible or not, but since you are mentioning backports, you might be interested in this #1505456: Add a "Backports" or "Drupal update" module to Drupal 7 core so that UI changes from Drupal 8 can be backported

merlinofchaos’s picture

Status: Needs review » Patch (to be ported)

By all means yes, please backport it.

However, 'needs review' isn't appropriate until it's actually backported. :)

EugenMayer’s picture

Sorry, wasnt aware of which status is going to fit best - but obviously you are right :). Perfectly fine with path to be ported

Setting this on my todo-list

temkin’s picture

Hi guys,

First of all, thank you for the work you've already done to fix that issue. Much appreciated.

I just wanted to let you know that I still see it happening for Drupal 7. An easy way how you can reproduce it is just start typing something while previous AJAX request is still in progress.

I've spent some time looking at this issue and it looks like when AJAX request goes out the field that initiated it doesn't have "ctools-ajaxing" class on it. There is a logic that relies on that class that prevents another AJAX requests to go out until there is one in progress.

So in order to fix the issue I've done a small change:

function triggerSubmit (e) {
  var $this = $(this);
  if (!$this.hasClass('ctools-ajaxing')) {
    $this.addClass('ctools-ajaxing').find('.ctools-auto-submit-click').click();
  }
}

Basically I'm just adding the missing class.

It did the trick for me and hopefully will help others to get rid of that issue.

- Artem

jenlampton’s picture

Title: Clean up and improve auto-submit.js » Not all views exposed forms auto-submit correctly (was: Clean up and improve auto-submit.js0
Status: Patch (to be ported) » Needs review
FileSize
1002 bytes

Well, this is a bug-fix that makes the auto-submit work by cleaning up the class name with the extra dot in it. It doesn't contain all the other fixes from @nod_'s 7.x version, but it's a start.

Ronino’s picture

The original poster stated that the change event was bubbling and triggering multiple submits. This also happens for me on D7: change the text in a textfield, wait, the form is submitted, click outside the textfield, the form is submitted again.

I saw in the D6 patches on this page that there is no change event handler for textfields, removed it from my D7 version and all my issues are solved! Here is a D7 patch.

Status: Needs review » Needs work

The last submitted patch, ctools-rm-bubbling-change-event-1324238-36.patch, failed testing.

  • merlinofchaos committed 91e224e on 8.x-2.x
    Issue #1324238 by nod_, soulston, rlmumford and others: Rewrite auto-...
annya’s picture

Issue summary: View changes

Code in #34 works great for Drupal 7! But I'm not sure that we should add it in auto-submit function, because autosubmit isn't always work with ajax. Often it's just a common submit without ajax. So maybe functionality that ajaxify forms(for example views) should add this class when form is submitted.

  • merlinofchaos committed 91e224e on 8.x-3.x
    Issue #1324238 by nod_, soulston, rlmumford and others: Rewrite auto-...