<?xml version='1.0' encoding='utf-8' ?>
<rss version='2.0' xmlns:dc='http://purl.org/dc/elements/1.1/'>
  <channel>
    <title>Wolfmans Howlings: How to protect a form from accidentally losing data</title>
    <link>http://blog.wolfman.com/articles/2006/11/14/how-to-protect-a-form-from-accidentally-losing-data</link>
    <description>A programmers Blog about Ruby, Rails and a few other issue</description>
    <language>en-us</language>
    <ttl>40</ttl>
    <item>
      <title>How to protect a form from accidentally losing data</title>
      <description>
        &lt;p&gt;Here is a good one, your users are complaining that they have spent 5
        minutes filling in a web form, then lose it all by clicking on a link
        away from the form, and back arrow doesn't restore the fields that
        were entered. (At least on IE).&lt;/p&gt;
        
        &lt;p&gt;I saw an interesting design in the Rails Recipes book for saving form
        data at regular intervals, but I didn't like the overhead of that one.&lt;/p&gt;
        
        &lt;p&gt;So I found a snippet of javascript that detects when you are about to
        switch away from a page, I coupled that with a simple observer that
        sets a dirty flag when any field is modified in anyway, and you get
        something that pops up a dialog asking if they really want to leave
        this page and lose their input data, they get the option to not go to
        the new page and submit the form instead.&lt;/p&gt;
        
        &lt;p&gt;This is not as clean as I'd like, so anyone with ideas of making it
        cleaner please let me know.&lt;/p&gt;
        
        &lt;p&gt;This would go in app/helpers/application.rb...&lt;/p&gt;
        
        &lt;pre&gt;  &lt;span class=&quot;comment&quot;&gt;# if the given form has changed at all then pop-up a dialog if they&lt;/span&gt;
          &lt;span class=&quot;comment&quot;&gt;# try to move away from the form before saving&lt;/span&gt;
          &lt;span class=&quot;comment&quot;&gt;# You have to add :html =&amp;gt; {:id =&amp;gt; 'new_mission_form'} to the form&lt;/span&gt;
          &lt;span class=&quot;comment&quot;&gt;# and  :onclick =&amp;gt; &amp;quot;dirty_page= false;&amp;quot; to the submit button&lt;/span&gt;
          &lt;span class=&quot;keyword&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;method&quot;&gt;catch_page_change_if_changed&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;punct&quot;&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;END&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;
              &amp;lt;script language=&amp;quot;javascript&amp;quot;&amp;gt;
                  &amp;lt;!--
                    dirty_page = &lt;span class=&quot;expr&quot;&gt;#{obj.nil? || obj.errors.empty? ? &amp;quot;false&amp;quot; : &amp;quot;true&amp;quot;}&lt;/span&gt;;
                    new Form.EventObserver(&lt;span class=&quot;expr&quot;&gt;#{form}&lt;/span&gt;, function(element, value) {dirty_page= true; });
                    window.onbeforeunload = function (evt) {
                      if (dirty_page) {
                        var message = 'Leaving this page will lose all entered values';
                        if (typeof evt == 'undefined') {
                          evt = window.event;
                        }
                        if (evt) {
                          evt.returnValue = message;
                        }
                        return message;
                      }
                    }
                 //--&amp;gt;
              &amp;lt;/script&amp;gt;
        &lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;    END&lt;/span&gt;
          &lt;span class=&quot;keyword&quot;&gt;end&lt;/span&gt;
        &lt;/pre&gt;
        
        &lt;p&gt;In the view you give the form an id, and you also need to add an
        :onclick to the submit button so it allows you to submit the form
        without popping up the dialog... &lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;&amp;lt;% form_for :obj, @obj,  :html =&amp;gt; {:id =&amp;gt; 'new_form'}, :url =&amp;gt; { :action =&amp;gt; 'create' } do |f| %&amp;gt;
        ...
        &amp;lt;%= submit_tag &quot;Submit&quot;, :onclick =&amp;gt; &quot;dirty_page= false;&quot; %&amp;gt;
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;then call this somewhere in that view...&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;catch_page_change_if_changed('new_form', @obj)
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;Basically I just set a javascript variable called dirty_page to false,
        and have the observer set it to true if anything changes. The optional
        object being passed in to the helper is used to detect if we are back
        on the form due to input errors, in which case we set the dirty_flag
        to true, so we don't lose the fields that were not in error.&lt;/p&gt;
        
        &lt;p&gt;Oh this only works if javascript is enabled (of course!)&lt;/p&gt;
        
        &lt;p&gt;&lt;a href=&quot;http://technorati.com/tag/rails+form&quot; rel=&quot;tag&quot;&gt;&lt;/a&gt;
        &lt;a href=&quot;http://technorati.com/tag/rails+save+form&quot; rel=&quot;tag&quot;&gt;&lt;/a&gt;&lt;/p&gt;
      </description>
      <author>Jim Morris</author>
      <pubDate>Tue, 14 Nov 2006 22:47:44 -0800</pubDate>
      <link>http://blog.wolfman.com/articles/2006/11/14/how-to-protect-a-form-from-accidentally-losing-data</link>
      <guid isPermaLink='false'>urn:uuid:f5917acc-0fbe-4e30-904c-e57c396c155b</guid>
    </item>
    <item>
      <title>"How to protect a form from accidentally losing data" by Jason</title>
      <description>
        This is great, but it DOES NOT WORK AS POSTED!!!
        
        You need to encapsulate new Form.EventObserver within an onload observer, AND they way you are refering to the form #{form} needs to be in quotes or the form is never found.
        
        Like this
        
        def catch_page_change_if_changed(form, obj= nil)
            &lt;&lt;-END
              &lt;script language=&quot;javascript&quot;&gt;
                  &lt;!--
                    dirty_page = #{obj.nil? || obj.errors.empty? ? &quot;false&quot; : &quot;true&quot;};
                    new Event.observe(window, 'load', function() {
                      new Form.EventObserver($(&quot;#{form}&quot;), function(element, value) {dirty_page= true; });
                    });  
                    window.onbeforeunload = function (evt) {
                      if (dirty_page) {
                        var message = 'Form values have not been submitted, leaving without submitting will loose all inputs.';
                        if (typeof evt == 'undefined') {
                          evt = window.event;
                        }
                        if (evt) {
                          evt.returnValue = message;
                        }
                        return message;
                      }
                    }
                 //--&gt;
              &lt;/script&gt;
            END
          end
      </description>
      <pubDate>Mon, 10 Dec 2007 17:10:37 -0800</pubDate>
      <link>http://blog.wolfman.com/posts/16#comment-56</link>
      <guid isPermaLink='false'>urn:uuid:ac9e1263-6656-4cb9-9d54-15662835cfd7</guid>
    </item>
    <item>
      <title>"How to protect a form from accidentally losing data" by Jason</title>
      <description>
        its scrubbing my inputs, it needs  this change in the application helper:&lt;BR&gt;&lt;BR&gt;
        
         new Event.observe(window, 'load', function() {&lt;BR&gt;
         &amp;nbsp;&amp;nbsp;  new Form.EventObserver($(&quot;#{form}&quot;), function(element, value) {dirty_page= true; });&lt;BR&gt;
        });
      </description>
      <pubDate>Mon, 10 Dec 2007 17:17:07 -0800</pubDate>
      <link>http://blog.wolfman.com/posts/16#comment-57</link>
      <guid isPermaLink='false'>urn:uuid:0abee444-5f4d-4b7b-b83d-cf9d5d40e277</guid>
    </item>
  </channel>
</rss>
