Dirty Forms is a jQuery plugin to help prevent users from losing data when editing forms.
Dirty Forms will alert a user when they attempt to leave a page without submitting a form they have entered data into. It alerts them in a modal popup box, and also falls back to the browser’s default onBeforeUnload handler for events outside the scope of the document such as, but not limited to, page refreshes and browser navigation buttons.
Oh, and it’s pretty easy to use.
$(‘form’).dirtyForms();
Existing solutions were not flexible enough, so Dirty Forms was created to support a wider range of scenarios including support for dynamically added inputs and forms, TinyMCE and CKEditor rich text editor “dirtyness” support, custom widget “dirtyness” support, interoperability with any dialog framework (or the browser’s built-in dialog), a “stash” that can be used in cases where dialogs don’t have stacking support and you want to have a form inside of a dialog, and correct handling of events to refire when the user decides to proceed to an off-page destination.
Features
NO dependencies (except for jQuery of course).
Supports multiple forms.
Works on forms of any size.
Wide browser support.
Advanced state management – tracks the original values of fields so they are “clean” when reset to the original value.
Works with your existing dialog framework for the best user experience (optional).
Falls back to the browser’s dialog (if the browser supports it).
Pluggable helper system that reads and updates the dirty state of custom widgets and common rich text editor frameworks (optional).
Event handler customization (for IFrame support).
Small size (about 2.5 KB gzipped).
Universal Module Definition (UMD) support for AMD, Node/CommonJS, Browserify, etc.
Hosted on jsDelivr CDN for easy combining of modules into a single HTTP request.
Supported Browsers
IE 8+
Google Chrome 1+
Firefox 4+
Safari 5+
Prerequisites
jQuery (>= 1.4.2)
If you are using a Package Manager, these dependencies will be installed automatically, but depending on your environment you may still need to add references to them manually.
Download & Installation
Dirty Forms should be the last jQuery plugin included in the page, as it needs to be the last bound handler in the event stack (except of course for Dirty Forms helpers and dialog modules).
There are several different ways to get the code. Some examples below:
CDN
Dirty Forms is available over jsDelivr CDN and can directly be included on every page.
jsDelivr also supports on-the-fly concatenation of files, so you can reference only 1 URL to get jQuery and jquery.dirtyforms in one request.
Self-Hosted
Download and save one of two available files to include Dirty Forms to your page, either the latest distribution or the latest minified version.
You can also conveniently get all of the latest Dirty Forms files in one Zip Download.
Package Managers
Dirty Forms is even available through NPM, Bower, and NuGet. Just use one of the following commands below to install the helper, including all dependencies.
// NPM
$ npm install jquery.dirtyforms
// Bower
$ bower install jquery.dirtyforms
// NuGet
PM> Install-Package jquery.dirtyforms
SourceMaps
A SourceMap file is also available via CDN or your favorite package manager.
CDN
Package Managers
NPM, Bower, and NuGet will install the SourceMap file into the destination directory.
jquery.dirtyforms.min.js.map
Usage
$(function() { // Enable for all forms. $(‘form’).dirtyForms(); // Enable for just forms of class ‘sodirty’. $(‘form.sodirty’).dirtyForms(); // Customize the title and message. // Note that title is not supported by browser dialogs, so you should // only set it if you are using a custom dialog or dialog module. $(‘form’).dirtyForms({ dialog: { title: ‘Wait!’ }, message: ‘You forgot to save your details. If you leave now, they will be lost forever.’ }); // Enable Debugging (non-minified file only). $(‘form’).dirtyForms({ debug: true }); // Check if anything inside a div with CSS class watch is dirty. if ($(‘div.watch’).dirtyForms(‘isDirty’)) { // There was something dirty inside of the div } // Select all forms that are dirty, and set them clean. // This will make them forget the current dirty state and any changes // after this call will make the form dirty again. $(‘form:dirty’).dirtyForms(‘setClean’); // Rescan to sync the dirty state with any dynamically added forms/fields // or changes to the ignore state. This comes in handy when styling fields // with CSS that are dirty. $(‘form’).dirtyForms(‘rescan’); // Select all forms that are listening for changes. $(‘form:dirtylistening’); // Enable/disable the reset and submit buttons when the state transitions // between dirty and clean. You will need to first set the initial button // state to disabled (either in JavaScript or by setting the attributes in HTML). $(‘form’).find(‘[type=”reset”],[type=”submit”]’).attr(‘disabled’, ‘disabled’); $(‘form’).on(‘dirty.dirtyforms clean.dirtyforms’, function (ev) { var $form = $(ev.target); var $submitResetButtons = $form.find(‘[type=”reset”],[type=”submit”]’); if (ev.type === ‘dirty’) { $submitResetButtons.removeAttr(‘disabled’); } else { $submitResetButtons.attr(‘disabled’, ‘disabled’); } }); // Add a form dynamically and begin tracking it. var $form = $(‘
‘); $(‘body’).append($form); $form.dirtyForms(); });
Setting a Form Dirty Manually
NOTE: This example shows how to set the state of a form dirty. However, it is generally recommended that each of the widgets (whether built by you or a 3rd party) have their own dirty/clean state. Instead of “pushing” the dirty state into Dirty Forms, you should aim to allow Dirty Forms to read the dirty state of each widget using one or more custom helpers. You can then opt to make each widget “undo” its dirty state when the user reverts their edits in the widget, which will provide a better user experience and make it similar to the rest of Dirty Forms state management behavior.
In version 1.x, there was a setDirty method that allowed you to set the form dirty manually. In version 2.x, this method has been removed since this functionality is effectively a duplication of what a custom helper does. It is now recommended that you create a custom helper to set a form dirty manually. You will need to attach a piece of data to the form to track whether it is dirty. In this example, we use a CSS class mydirty for this purpose. Note that this class should not be the same value as $.DirtyForms.dirtyClass because Dirty Forms automatically removes this value when the user undoes their edits (which is probably not the behavior you are after).
$(‘#watched-form’).dirtyForms({
helpers:
[
{
isDirty: function ($node, index) {
if ($node.is(‘form’)) {
return $node.hasClass(‘mydirty’);
}
}
}
]
});
You can then use the jQuery addClass and removeClass methods to get the same behavior as version 1.x.
function setDirty() {
$(‘#watched-form’).addClass(‘mydirty’);
}
function setClean() {
$(‘#watched-form’).removeClass(‘mydirty’);
}
Or, you can improve the behavior of setClean by instead implementing the setClean helper method as needed by your application so it is automatically reset to clean when the dirtyForms(‘setClean’) method is called.
$(‘#watched-form’).dirtyForms({
helpers:
[
{
isDirty: function ($node, index) {
if ($node.is(‘form’)) {
return $node.hasClass(‘mydirty’);
}
},
setClean: function($node, index, excludeIgnored) {
if ($node.is(‘form’)) {
$node.removeClass(‘mydirty’);
}
}
}
]
});
In that case, calling $(‘#watched-form’).dirtyForms(‘setClean’) will set both the fields/forms that are tracked by Dirty Forms and your custom mydirty class to a non-dirty state in one method call instead of having to call your custom setClean method separately.
NOTE: dirtyForms(‘setClean’) is called automatically when a reset button is clicked by the user on a particular form.
Ignoring Things
Set the ignoreSelector option to ignore specific fields, anchors, or buttons.
$(‘form’).dirtyForms({ ignoreSelector: ‘a.ignore-me’ });
Alternatively, add the value of $.DirtyForms.ignoreClass to any elements you wish to ignore, and Dirty Forms will ignore them.
$(‘#ignored-element’).addClass($.DirtyForms.ignoreClass);
If you want to ignore more than one element at a time, you can add the value of $.DirtyForms.ignoreClass (with the default value dirtyignore) to a containing element.
And of course that means if you ignore the topmost element on the page, you will effectively disable Dirty Forms.
$(‘html’).addClass($.DirtyForms.ignoreClass);
You can re-enable elements so Dirty Forms watches them again simply by removing the ignore class.
$(‘html’).removeClass($.DirtyForms.ignoreClass);
Default Anchor Ignoring Behavior
The default behavior ignores anchor tags under the following scenarios. If you want an anchor to be ignored for any other purpose, you should use the ignoreClasss either on the anchor itself or an ancestor container. The default behavior can be changed by overriding the event handling (see Event Handler Customization).
target=”_blank”
If the target is a blank browser window, we assume that the page is not going to reload because (at least in theory) a new browser or tab will open. Note that if the target attribute is changed dynamically, the anchor tag will automatically be un-ignored.
Go to Google
onClick return false;
If the onClick event returns false, the click will be ignored by Dirty Forms.
Go to Google
NOTE: Due to a bug in jQuery < 1.5, Dirty Forms will not ignore anchors in this case, so you will need to use the ignoreClass instead.
.preventDefault() is Called
If the click event handler calls .preventDefault() on its event, Dirty Forms will ignore the click.
Go to Google
$(‘#google-link’).click(function (event) { // Cancel the default browser action event.preventDefault();});
NOTE: Anchor tags with no HREF were ignored in previous versions of Dirty Forms, but now these tags are included by default. We can’t make any assumptions about what an anchor tag does whether or not it has an HREF tag. If you want to ignore them by default, add the ignoreSelector: ‘a:not([href])’.
Options
The following options are available to set during declaration of .dirtyForms() or alternatively via $.DirtyForms.OPTIONNAME = OPTIONVALUE or get via OPTIONVALUE = $.DirtyForms.OPTIONNAME.
$(‘form’).dirtyForms({ message: ‘Doh! You forgot to save.’ }); // OR $.DirtyForms.message = ‘Doh! You forgot to save.’;
Name
Type
Default
Description
message
string
You’ve made changes on this page which aren’t saved. If you leave you will lose these changes.
Sets the message of the dialog (whether JavaScript/CSS dialog or the browser’s built in dialog – note that some browsers do not show this message).
dirtyClass
string
dirty
The class applied to elements and forms when they’re considered dirty. Note you can use this to style the elements to make them stand out if they are dirty (or for debugging).
listeningClass
string
dirtylisten
The class applied to elements that are having their inputs monitored for change.
ignoreClass
string
dirtyignore
The CSS class applied to elements that you wish to be ignored by Dirty Forms. This class can also be applied to container elements (such as