Hack 33. Confirm Before Closing Modified Pages

 < Day Day Up > 

Don't lose your changes in web forms when you accidentally close your browser window.

It's becoming more and more common for complex tasks to be performed on the Web. Of course, there is web-based email, and weblogging and wikis are also popular. Message boards are a great way to form a community, and there are many more online applications that are used every day by many people. One of the drawbacks, though, in not using a normal desktop program is losing that prompt, "Are you sure you wish to exit? You have unsaved work."

With Greasemonkey, we can restore this functionality and save the hassle caused by closing a window and losing your unsubmitted form data.

4.6.1. The Code

This script uses the power of the onbeforeunload event to catch the browser just before it moves off the page. When the page loads, the script finds all <textarea> elements and records the initial value of each one. Then, we register an onbeforeunload event handler to call our function that checks the current value of each <textarea>. If the current value differs from the previously recorded value, we display a dialog box to give the user the chance to save his work.

To make sure we don't interfere when the user actually submits the form, the script attaches an onsubmit event handler to all forms. This handler sets an internal flag to record that the user submitted the form and that we should not bother checking for unsubmitted data, since the user just submitted it!

Save the following user script as protect-textarea.user.js:

 // ==UserScript== // @name   Protect Textarea // @namespace   http://www.arantius.com/ // @description   Confirm before closing a web page with modified textareas // @include   * // @exclude   http*://*mail.google.com/* // ==/UserScript== // based on code by Anthony Lieuallen // and included here with his gracious permission // http://www.arantius.com/article/arantius/protect+textarea/ //indicator to skip handler because the unload is caused by form submission var _pt_skip=false; var real_submit = null; //find all textarea elements and record their original value var els=document.evaluate('//textarea', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for (var el=null, i=0; el=els.snapshotItem(i); i++) { var real_el = el.wrappedJSObject || el; real_el._pt_orig_value=el.value; } //if i>0 we found textareas, so do the rest if (i == 0) { return; } //this function handles the case where we are submitting the form, //in this case, we do not want to bother the user about losing data var handleSubmit = function() { _pt_skip=true; return real_submit(); } //this function will handle the event when the page is unloaded and //check to see if any textareas have been modified var handleUnload = function() { if (_pt_skip) { return; } var els=document.getElementsByTagName('textarea'); for (var el=null, i=0; el=els[i]; i++) { var real_el = el.wrappedJSObject || el; if (real_el._pt_orig_value!=el.value) { return 'You have modified a textarea, and have not ' + 'submitted the form.'; } } } // trap form submit to set flag real_submit = HTMLFormElement.prototype.submit; HTMLFormElement.prototype.submit = handleSubmit; window.addEventListener('submit', handleSubmit, true); // trap unload to check for unmodified textareas unsafeWindow.onbeforeunload = handleUnload; 

4.6.2. Running the Hack

After installing the user script (Tools Install This User Script), go to http://www.iupui.edu/~webtrain/tutorials/forms_sample.html. At the bottom of the form is a large box for entering additional comments. Enter some text, and then try to close the browser window. You will see a confirmation dialog, as shown in Figure 4-5.

Figure 4-5. Unsaved changes dialog


If you press Cancel, you'll stay right where you are and can submit the form. If you press OK, the browser window will close.

4.6.3. Hacking the Hack

This hack can easily be extended to monitor all form fields, not just <textarea> elements. Instead of using document.getElementsByTagName to find only <textarea> elements, we can use an XPath expression to look for <input> elements, too.

 var els=document.evaluate('//textarea|//input', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for (var el=null, i=0; el=els.snapshotItem(i); i++) { … } 

This will cause the script to protect all form fields containing text boxes, checkboxes, and radio buttons. It will not handle drop-down select boxes, though, because they function differently. It's more complicated than just adding //select to the XPath expression and examining the selectedIndex attribute of the <select> element, because some <select> boxes have multiple selections.

Anthony Lieuallen

     < Day Day Up > 


    Greasemonkey Hacks
    Greasemonkey Hacks: Tips & Tools for Remixing the Web with Firefox
    ISBN: 0596101651
    EAN: 2147483647
    Year: 2005
    Pages: 168
    Authors: Mark Pilgrim

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net