jquery.are-you-sure.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*!
  2. * jQuery Plugin: Are-You-Sure (Dirty Form Detection)
  3. * https://github.com/codedance/jquery.AreYouSure/
  4. *
  5. * Copyright (c) 2012-2014, Chris Dance and PaperCut Software http://www.papercut.com/
  6. * Dual licensed under the MIT or GPL Version 2 licenses.
  7. * http://jquery.org/license
  8. *
  9. * Author: chris.dance@papercut.com
  10. * Version: 1.9.0
  11. * Date: 13th August 2014
  12. */
  13. (function($) {
  14. $.fn.areYouSure = function(options) {
  15. var settings = $.extend(
  16. {
  17. 'message' : 'You have unsaved changes!',
  18. 'dirtyClass' : 'dirty',
  19. 'change' : null,
  20. 'silent' : false,
  21. 'addRemoveFieldsMarksDirty' : false,
  22. 'fieldEvents' : 'change keyup propertychange input',
  23. 'fieldSelector': ":input:not(input[type=submit]):not(input[type=button])"
  24. }, options);
  25. var getValue = function($field) {
  26. if ($field.hasClass('ays-ignore')
  27. || $field.hasClass('aysIgnore')
  28. || $field.attr('data-ays-ignore')
  29. || $field.attr('name') === undefined) {
  30. return null;
  31. }
  32. if ($field.is(':disabled')) {
  33. return 'ays-disabled';
  34. }
  35. var val;
  36. var type = $field.attr('type');
  37. if ($field.is('select')) {
  38. type = 'select';
  39. }
  40. switch (type) {
  41. case 'checkbox':
  42. case 'radio':
  43. val = $field.is(':checked');
  44. break;
  45. case 'select':
  46. val = '';
  47. $field.find('option').each(function(o) {
  48. var $option = $(this);
  49. if ($option.is(':selected')) {
  50. val += $option.val();
  51. }
  52. });
  53. break;
  54. default:
  55. val = $field.val();
  56. }
  57. return val;
  58. };
  59. var storeOrigValue = function($field) {
  60. $field.data('ays-orig', getValue($field));
  61. };
  62. var checkForm = function(evt) {
  63. var isFieldDirty = function($field) {
  64. var origValue = $field.data('ays-orig');
  65. if (undefined === origValue) {
  66. return false;
  67. }
  68. return (getValue($field) != origValue);
  69. };
  70. var $form = ($(this).is('form'))
  71. ? $(this)
  72. : $(this).parents('form');
  73. // Test on the target first as it's the most likely to be dirty
  74. if (isFieldDirty($(evt.target))) {
  75. setDirtyStatus($form, true);
  76. return;
  77. }
  78. $fields = $form.find(settings.fieldSelector);
  79. if (settings.addRemoveFieldsMarksDirty) {
  80. // Check if field count has changed
  81. var origCount = $form.data("ays-orig-field-count");
  82. if (origCount != $fields.length) {
  83. setDirtyStatus($form, true);
  84. return;
  85. }
  86. }
  87. // Brute force - check each field
  88. var isDirty = false;
  89. $fields.each(function() {
  90. $field = $(this);
  91. if (isFieldDirty($field)) {
  92. isDirty = true;
  93. return false; // break
  94. }
  95. });
  96. setDirtyStatus($form, isDirty);
  97. };
  98. var initForm = function($form) {
  99. var fields = $form.find(settings.fieldSelector);
  100. $(fields).each(function() { storeOrigValue($(this)); });
  101. $(fields).unbind(settings.fieldEvents, checkForm);
  102. $(fields).bind(settings.fieldEvents, checkForm);
  103. $form.data("ays-orig-field-count", $(fields).length);
  104. setDirtyStatus($form, false);
  105. };
  106. var setDirtyStatus = function($form, isDirty) {
  107. var changed = isDirty != $form.hasClass(settings.dirtyClass);
  108. $form.toggleClass(settings.dirtyClass, isDirty);
  109. // Fire change event if required
  110. if (changed) {
  111. if (settings.change) settings.change.call($form, $form);
  112. if (isDirty) $form.trigger('dirty.areYouSure', [$form]);
  113. if (!isDirty) $form.trigger('clean.areYouSure', [$form]);
  114. $form.trigger('change.areYouSure', [$form]);
  115. }
  116. };
  117. var rescan = function() {
  118. var $form = $(this);
  119. var fields = $form.find(settings.fieldSelector);
  120. $(fields).each(function() {
  121. var $field = $(this);
  122. if (!$field.data('ays-orig')) {
  123. storeOrigValue($field);
  124. $field.bind(settings.fieldEvents, checkForm);
  125. }
  126. });
  127. // Check for changes while we're here
  128. $form.trigger('checkform.areYouSure');
  129. };
  130. var reinitialize = function() {
  131. initForm($(this));
  132. }
  133. if (!settings.silent && !window.aysUnloadSet) {
  134. window.aysUnloadSet = true;
  135. $(window).bind('beforeunload', function() {
  136. $dirtyForms = $("form").filter('.' + settings.dirtyClass);
  137. if ($dirtyForms.length == 0) {
  138. return;
  139. }
  140. // Prevent multiple prompts - seen on Chrome and IE
  141. if (navigator.userAgent.toLowerCase().match(/msie|chrome/)) {
  142. if (window.aysHasPrompted) {
  143. return;
  144. }
  145. window.aysHasPrompted = true;
  146. window.setTimeout(function() {window.aysHasPrompted = false;}, 900);
  147. }
  148. return settings.message;
  149. });
  150. }
  151. return this.each(function(elem) {
  152. if (!$(this).is('form')) {
  153. return;
  154. }
  155. var $form = $(this);
  156. $form.submit(function() {
  157. $form.removeClass(settings.dirtyClass);
  158. });
  159. $form.bind('reset', function() { setDirtyStatus($form, false); });
  160. // Add a custom events
  161. $form.bind('rescan.areYouSure', rescan);
  162. $form.bind('reinitialize.areYouSure', reinitialize);
  163. $form.bind('checkform.areYouSure', checkForm);
  164. initForm($form);
  165. });
  166. };
  167. })(jQuery);