title: jQuery.AreYouSure Plugin not working
body: <p>I have spent the last few days trying to properly install the jQuery.AreYouSure? plugin with inconsistent results.
  I decided to use this plugin based on information from this post: <a href="https://stackoverflow.com/questions/7317273/warn-user-before-leaving-web-page-with-unsaved-changes">Warn user before leaving web page with unsaved changes</a>. I've also read through the plugin's documentation on GitHub: <a href="https://github.com/codedance/jquery.AreYouSure" rel="nofollow noreferrer">jQueryAreYouSure</a></p>
  
  <p>Here's what I've done:</p>
  
  <ol>
  <li>I refresh the page. </li>
  <li>I've been copying the code from the custom.js file into the console in chrome.</li>
  <li>I make a change to the form</li>
  <li>I either click on the refresh button or another site link to navigate away without saving.</li>
  </ol>
  
  <p>My result: Sometimes I get the alert message but more times then not, I do not. I also cannot not replicate or understand when I do receive the alert. Sometimes it may come when I first click to leave page and at other times it may appear when I clicked around a few times. </p>
  
  <p>javascripts/application.js:</p>
  
  <pre><code>// This is a manifest file that'll be compiled into application.js, which will include all the files
  // listed below.
  //
  // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
  // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
  //
  // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
  // compiled file.
  //
  // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
  // about supported directives.
  //
  //= require jquery
  //= require jquery_ujs
  //= require bootstrap-sprockets
  //= require turbolinks
  //= require areyousure/areyousure
  //= require_tree .
  </code></pre>
  
  <p>javascripts/areyousure/areyousure.js:</p>
  
  <pre><code>/*!
   * 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 &amp;&amp; !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);
  </code></pre>
  
  <p>I created javascripts/custom.js:</p>
  
  <pre><code>$('form').areYouSure( {'message':'You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?'} );
  </code></pre>