Browser back button restores empty fields

后端 未结 6 1294
小鲜肉
小鲜肉 2020-12-05 09:02

I have a web page x.php (in a password protected area of my web site) which has a form and a button which uses the POST method to send the form dat

相关标签:
6条回答
  • 2020-12-05 09:36

    IE will retain form contents on a back button click automatically, as long as:

    • you haven't broken cacheing with a no-cache pragma or similar
    • the form fields in question weren't dynamically created by script

    You seem to have the cacheing in hand, so I'm guessing the latter may apply. (As mkoeller says, Firefox avoids this problem if the page is in the last few back clicks by keeping the page itself alive for longer than it's on the screen. However this is optional, and Firefox will revert to the same behaviour as IE and other browsers once you've browsed a few pages ahead and it has expired the old one.)

    If you're creating your own form fields from script onload, then the browser has no way of knowing that the new input control is ‘the same’ as the old instance, so it can't fill it in with the previously-submitted value. In this case if you want it to play well with the back button you have to start storing data on the client.

    Then you have to use some sort of state-keying so that each set of data is tied to exactly one instance of the page, otherwise going through multiple instances of the same form or having two browsers tabs open on the form at once will severely confuse your script.

    And then you are starting to collect a lot of data if they're big forms, and if the client-side storage mechanism you're using is cookies you can start to lose data, as well as sending a load of unnecessary state nonsense with every HTTP request. Other client-side storage mechanisms are available but they're browser-specific.

    In short: doing dynamically-generated forms nicely is a huge pain and it's probably best avoided if you can. Having a hidden form on the page that a script makes visible, thus allowing browsers to do their field-remembering-magic instead of giving you the task, is typically much easier.

    0 讨论(0)
  • 2020-12-05 09:40

    Firefox does this kind of caching. As I understand your question, you want IE7 to behave the way Firefox does. I think that's not possible.

    Firefox and IE7 differ on the way they interpret the back button.

    Firefox will display the DOM tree of the previous page as it was last displayed before the page was left. That is, all the form data will still be contained in the form's input field. But you won't see an onload event upon hitting the back button.

    IE7 will render the page again based upon the response it receives from the server. Thus the form is emtpy (unless there were default values sent by the server originally), but you'll see an onload event.

    0 讨论(0)
  • 2020-12-05 09:40

    I poked around and this is quite a hard problem. Its also a major pain in the ass for Dynamically modified content. You visit the page, javascript augments it with your instruction, you go to the next page, and come back, and javascript has forgotten. And there's no way to simply update the page server-side, because the page comes out of cache.

    So I devised a back-button-cache-breaker.

    Its evil and bad-for-the-web, but it makes it able for pages to behave how people expect them to behave instead of magically warping all over the place.

    <script type="text/javascript">//<!-- <![CDATA[
    (function(){
        if( document.location.hash === "" )
        {
            document.location.hash="_";
        }
        else
        {
          var l = document.location;
          var myurl = ( l.protocol + "//" + l.hostname + l.pathname + l.search); 
          document.location = myurl;
        }
    })();
    //]]> --></script>
    

    This will do a bit of magic in that it detects whether or not the page you are /currently/ viewing was loaded from cache or not.

    if you're there the first time, it will detect "no hash" , and add "#_" to the page url. if you're there for the >1st time ( ie: not a direct link to the page ), the page already has the #_ on it, so it removes it and in the process of removing it, triggers a page reload.

    0 讨论(0)
  • 2020-12-05 09:46

    While trying to further narrow down the problem, I've found the cause of my problem. I was using URLs which were being rewritten by Apache (i.e. I always accessed my page as http://foo.com/page which is mapped by Apache to http://foo.com/page.htm). Using the real URLs solved the problem and made IE7 happy, as long as I specify the proper HTTP header (Cache-Control, Expires, etc.).

    Here is what I do in the PHP code to output headers which seem to make all browsers happy with the cache:

    function emitConditionalGet($timestamp)
    {
        // See also http://www.mnot.net/cache_docs/
        // and code sample http://simonwillison.net/2003/Apr/23/conditionalGet/
    
        $gmdate_exp    = gmdate('D, d M Y H:i:s', time() + 1) . ' GMT';
        $last_modified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
        $etag          = '"'.md5($last_modified).'"';
    
        // If the client provided any of the if-modified-since or if-none-match
        // infos, take them into account:
    
        $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
                           ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false;
        $if_none_match     = isset($_SERVER['HTTP_IF_NONE_MATCH'])
                           ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])     : false;
    
        if (!$if_modified_since && !$if_none_match)
        {
            return;  // the client does not cache anything
        }
    
        if ($if_none_match && $if_none_match != $etag)
        {
            return;  // ETag mismatch: the page changed!
        }
        if ($if_modified_since && $if_modified_since != $last_modified)
        {
            return;  // if-modified-since mismatch: the page changed!
        }
    
        // Nothing changed since last time client visited this page.
    
        header("HTTP/1.0 304 Not Modified");
        header("Last-Modified: $last_modified");
        header("ETag: $etag");
        header("Cache-Control: private, max-age=1, must-revalidate");
        header("Expires: $gmdate_exp");
        header("Pragma: private, cache");
        header("Content-Type: text/html; charset=utf-8");
        exit;
    }
    
    function emitDefaultHeaders($timestamp)
    {
        $gmdate_exp    = gmdate('D, d M Y H:i:s', time() + 1) . ' GMT';
        $last_modified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
        $etag          = '"'.md5($last_modified).'"';
    
        header("Last-Modified: $last_modified");
        header("ETag: $etag");
        header("Cache-Control: private, max-age=1, must-revalidate");
        header("Expires: $gmdate_exp");
        header("Pragma: private, cache");
        header("Content-Type: text/html; charset=utf-8");
    }
    
    function getTimestamp()
    {
        // Find out when this page's contents last changed; in a static system,
        // this would be the file time of the backing HTML/PHP page. Add your
        // own logic here:
        return filemtime($SCRIPT_FILENAME);
    }
    
    // ...
    
    $timestamp = getTimestamp();
    emitConditionalGet($timestamp);
    emitDefaultHeaders($timestamp); //previously, this variable was mistyped as "$timestaml"
    
    0 讨论(0)
  • 2020-12-05 09:47

    This is an old post, and much has changed since. None the less, I had this very problem with one of my forms (but with Chrome acting up.) It would clear all the info if going back. I found the workaround by total coincidence and needed to share it here, just because it was so odd. Probably it is not the very best place to post this, but here we go.

    This is what I had (a stripped down version and not working.)

    <table>
        <form>
        <tr>
            <td><input type="number" value="0"></td>
        </tr>
        </form>
    </table>
    

    And this fixed it (now working.) Moving the <form> tag outside of the <table> and the <tr> tag.

    <form>
    <table>
        <tr>
            <td><input type="number" value="0"></td>
        </tr>
    </table>
    </form>
    
    0 讨论(0)
  • 2020-12-05 09:51

    You could use autocomplete="off" in your fields. This way the values won't be cached by the browser so the values won't be filled in the form when the user clicks the back button.

    0 讨论(0)
提交回复
热议问题