8

I'm having problems making style alterations to the DOM after I submit a form in Safari. Does anyone have any idea if its even possible? Is this expected browser behavior from Safari?

I have set up a very simple example so you can see the issue in action: http://jamesmichaelking.com/stackoverflow/safari/index.html

The example consists of a html form posting to itself, with a jquery form submit event which looks for the input button and changes the background to red.

The example works fine in Firefox and Chrome

I've included the html, js and css from the example:

HTML

<form action="index.html" method="post">
    <input type="submit" value="Submit me!">
</form>

CSS

body {
    font-family: sans-serif;
    color: #fff;        
    text-align: center;
}

input {
    border: none;
    padding: 20px;
    font-size: 20px;
    background: #036;
    color: #fff;
}

JQUERY

$(function() {

            $('form').on('submit', function() {
                $(this).find('input').css('background', '#c00');
            });

        });

Strangely, I have created a JSFiddle of the same code and it works fine: http://jsfiddle.net/jamesking/q8WcV/

I'm testing using Safari 7 on a mac

Any help much appreciated

James King
  • 1,897
  • 11
  • 16
  • 2
    It does work. The problem is that the altering of the Style will be removed by the page reload. You can append a `event.preventDefault();` to stop the button from submiting. But the form wont be submitted then either. You will have to submit your form via ajax or you append a get paramter like `?submited=true` and if you find this in the request you set the button style. – Nico O Feb 26 '14 at 14:00
  • 3
    Looks like just Safari doesn't redraw UI in time, due to redirection. You can test it using a timeout like here: http://jsfiddle.net/q8WcV/3/ – A. Wolff Feb 26 '14 at 14:03
  • 1
    Nico O - I appreciate the style will be reset when the page reloads, but I do expect the button to flash red before the form submission completes - it doesn't do that in Safari but all other browsers it does – James King Feb 26 '14 at 14:42
  • My problem was similar except I'm submitting form myself. Right before submitting I was adding class to one element to notify user that submit is in process. Only Safari on Mac was ignoring this new class while submitting. So I added dummy animation after adding class and it works: $(".logo").addClass("rotate").animate({ left: "+=0" }, 100 ); – Vladimir Kojic Mar 28 '14 at 01:25
  • I'm having exactly the same problem with Safari: no changes, including disabling the submit button, are taken into account. It must be a timing issue, since when my machine was heavily loaded during a back-up it sometimes worked. I tried A. Wolff's solution, but it won't work since the form submit after the timeout is disabled with the preventDefault. I also tried Vladimir's solution and it helps in 30% of the cases (just resubmitting the same form will do the DOM changes sometimes). If I insert an alert before returning it will always work (but needless to say, that is not a solution). – Christer Fernstrom Feb 08 '15 at 22:52
  • Same on all iOS devices. Any solution at the moment? – user1561346 Oct 24 '15 at 11:57

2 Answers2

3

Looks like A. Wolff's solution doesn't work for me on Safari 8.0.6

I also tried other things like restoring the default submit event handler (How to unbind a listener that is calling event.preventDefault() (using jQuery)?), but it didn't work.

After a lot of testing, I came up with a solution. It might not be the cleanest one, but it's working.

var form = $("form");
form.on("submit", function (e) {

    // Do your thing

    e.preventDefault();

    setTimeout(function(){
        form.off("submit");
        form.find("input[type=submit], button[type=submit]").eq(0).click();
    }, 500);
});
Community
  • 1
  • 1
paul.ago
  • 3,904
  • 1
  • 22
  • 15
2

I have found that the solution is to not use the form submit event but instead the click event of the submit button. If you, as I do, also want to disable the submit button to prevent double submits, you have to submit the form programmatically otherwise the disabling of the submit button will prevent the form from being submitted. You also need to introduce a short delay before submitting. I have found that 500 msecs works, and this is barely noticeably to the user. This is the code I use

jQuery.fn.preventDoubleSubmission = function() {
  $form = $(this);
  var submit_btn = $form.find(":submit");
  wait_msg = "One moment please"
  submit_btn.on("click", function(e) {
    var $subm = $(this);
    var the_form = $subm.closest('form');
    $subm.attr("disabled", true);
    $subm.val(wait_msg+" ...");
    setTimeout(function() {
      the_form.submit();
    }, (100));
  });
  // Keep chainability
  return this;
};

To apply this behavior to a form you need to do

$("#myform").preventDoubleSubmission;
  • Your solution has 2 problems: 1) It doesn't work if you submit the form hitting return inside a text field (in that case only the submit event of the form will be triggered) 2) You need to add the brackets to call the method, like: $("#myform").preventDoubleSubmission(); otherwise it will not work at all. – paul.ago May 20 '15 at 13:13