UNPKG

jquery.are-you-sure

Version:

A light-weight jQuery "dirty forms" Plugin - it monitors HTML forms and alerts users to unsaved changes if they attempt to close the browser or navigate away from the page. (Are you sure?)

193 lines (167 loc) 5.75 kB
/*! * jQuery Plugin: Are-You-Sure (Dirty Form Detection) * https://github.com/codedance/jquery.AreYouSure/ * * Copyright (c) 2012-2014, Chris Dance and PaperCut Software http://www.papercut.com/ * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Author: chris.dance@papercut.com * Version: 1.9.0 * Date: 13th August 2014 */ (function($) { $.fn.areYouSure = function(options) { var settings = $.extend( { 'message' : 'You have unsaved changes!', 'dirtyClass' : 'dirty', 'change' : null, 'silent' : false, 'addRemoveFieldsMarksDirty' : false, 'fieldEvents' : 'change keyup propertychange input', 'fieldSelector': ":input:not(input[type=submit]):not(input[type=button])" }, options); var getValue = function($field) { if ($field.hasClass('ays-ignore') || $field.hasClass('aysIgnore') || $field.attr('data-ays-ignore') || $field.attr('name') === undefined) { return null; } if ($field.is(':disabled')) { return 'ays-disabled'; } var val; var type = $field.attr('type'); if ($field.is('select')) { type = 'select'; } switch (type) { case 'checkbox': case 'radio': val = $field.is(':checked'); break; case 'select': val = ''; $field.find('option').each(function(o) { var $option = $(this); if ($option.is(':selected')) { val += $option.val(); } }); break; default: val = $field.val(); } return val; }; var storeOrigValue = function($field) { $field.data('ays-orig', getValue($field)); }; var checkForm = function(evt) { var isFieldDirty = function($field) { var origValue = $field.data('ays-orig'); if (undefined === origValue) { return false; } return (getValue($field) != origValue); }; var $form = ($(this).is('form')) ? $(this) : $(this).parents('form'); // Test on the target first as it's the most likely to be dirty if (isFieldDirty($(evt.target))) { setDirtyStatus($form, true); return; } $fields = $form.find(settings.fieldSelector); if (settings.addRemoveFieldsMarksDirty) { // Check if field count has changed var origCount = $form.data("ays-orig-field-count"); if (origCount != $fields.length) { setDirtyStatus($form, true); return; } } // Brute force - check each field var isDirty = false; $fields.each(function() { $field = $(this); if (isFieldDirty($field)) { isDirty = true; return false; // break } }); setDirtyStatus($form, isDirty); }; var initForm = function($form) { var fields = $form.find(settings.fieldSelector); $(fields).each(function() { storeOrigValue($(this)); }); $(fields).unbind(settings.fieldEvents, checkForm); $(fields).bind(settings.fieldEvents, checkForm); $form.data("ays-orig-field-count", $(fields).length); setDirtyStatus($form, false); }; var setDirtyStatus = function($form, isDirty) { var changed = isDirty != $form.hasClass(settings.dirtyClass); $form.toggleClass(settings.dirtyClass, isDirty); // Fire change event if required if (changed) { if (settings.change) settings.change.call($form, $form); if (isDirty) $form.trigger('dirty.areYouSure', [$form]); if (!isDirty) $form.trigger('clean.areYouSure', [$form]); $form.trigger('change.areYouSure', [$form]); } }; var rescan = function() { var $form = $(this); var fields = $form.find(settings.fieldSelector); $(fields).each(function() { var $field = $(this); if (!$field.data('ays-orig')) { storeOrigValue($field); $field.bind(settings.fieldEvents, checkForm); } }); // Check for changes while we're here $form.trigger('checkform.areYouSure'); }; var reinitialize = function() { initForm($(this)); } if (!settings.silent && !window.aysUnloadSet) { window.aysUnloadSet = true; $(window).bind('beforeunload', function() { $dirtyForms = $("form").filter('.' + settings.dirtyClass); if ($dirtyForms.length == 0) { return; } // Prevent multiple prompts - seen on Chrome and IE if (navigator.userAgent.toLowerCase().match(/msie|chrome/)) { if (window.aysHasPrompted) { return; } window.aysHasPrompted = true; window.setTimeout(function() {window.aysHasPrompted = false;}, 900); } return settings.message; }); } return this.each(function(elem) { if (!$(this).is('form')) { return; } var $form = $(this); $form.submit(function() { $form.removeClass(settings.dirtyClass); }); $form.bind('reset', function() { setDirtyStatus($form, false); }); // Add a custom events $form.bind('rescan.areYouSure', rescan); $form.bind('reinitialize.areYouSure', reinitialize); $form.bind('checkform.areYouSure', checkForm); initForm($form); }); }; })(jQuery);