(function($, undefined) {

/**

* Unobtrusive scripting adapter for jQuery
* https://github.com/rails/jquery-ujs
*
* Requires jQuery 1.7.0 or later.
*
* Released under the MIT license
*
*/

 // Cut down on the number of issues from people inadvertently including jquery_ujs twice
 // by detecting and raising an error when it happens.
 if ( $.rails !== undefined ) {
   $.error('jquery-ujs has already been loaded!');
 }

 // Shorthand to make it a little easier to call public rails functions from within rails.js
 var rails;
 var $document = $(document);

 $.rails = rails = {
   // Link elements bound by jquery-ujs
   linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with]',

   // Button elements boud jquery-ujs
   buttonClickSelector: 'button[data-remote]',

   // Select elements bound by jquery-ujs
   inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',

   // Form elements bound by jquery-ujs
   formSubmitSelector: 'form',

   // Form input elements bound by jquery-ujs
   formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type])',

   // Form input elements disabled during form submission
   disableSelector: 'input[data-disable-with], button[data-disable-with], textarea[data-disable-with]',

   // Form input elements re-enabled after form submission
   enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled',

   // Form required input elements
   requiredInputSelector: 'input[name][required]:not([disabled]),textarea[name][required]:not([disabled])',

   // Form file input elements
   fileInputSelector: 'input[type=file]',

   // Link onClick disable selector with possible reenable after remote submission
   linkDisableSelector: 'a[data-disable-with]',

   // Make sure that every Ajax request sends the CSRF token
   CSRFProtection: function(xhr) {
     var token = $('meta[name="csrf-token"]').attr('content');
     if (token) xhr.setRequestHeader('X-CSRF-Token', token);
   },

   // Triggers an event on an element and returns false if the event result is false
   fire: function(obj, name, data) {
     var event = $.Event(name);
     obj.trigger(event, data);
     return event.result !== false;
   },

   // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm
   confirm: function(message) {
     return confirm(message);
   },

   // Default ajax function, may be overridden with custom function in $.rails.ajax
   ajax: function(options) {
     return $.ajax(options);
   },

   // Default way to get an element's href. May be overridden at $.rails.href.
   href: function(element) {
     return element.attr('href');
   },

   // Submits "remote" forms and links with ajax
   handleRemote: function(element) {
     var method, url, data, elCrossDomain, crossDomain, withCredentials, dataType, options;

     if (rails.fire(element, 'ajax:before')) {
       elCrossDomain = element.data('cross-domain');
       crossDomain = elCrossDomain === undefined ? null : elCrossDomain;
       withCredentials = element.data('with-credentials') || null;
       dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType);

       if (element.is('form')) {
         method = element.attr('method');
         url = element.attr('action');
         data = element.serializeArray();
         // memoized value from clicked submit button
         var button = element.data('ujs:submit-button');
         if (button) {
           data.push(button);
           element.data('ujs:submit-button', null);
         }
       } else if (element.is(rails.inputChangeSelector)) {
         method = element.data('method');
         url = element.data('url');
         data = element.serialize();
         if (element.data('params')) data = data + "&" + element.data('params');
       } else if (element.is(rails.buttonClickSelector)) {
         method = element.data('method') || 'get';
         url = element.data('url');
         data = element.serialize();
         if (element.data('params')) data = data + "&" + element.data('params');
       } else {
         method = element.data('method');
         url = rails.href(element);
         data = element.data('params') || null;
       }

       options = {
         type: method || 'GET', data: data, dataType: dataType,
         // stopping the "ajax:beforeSend" event will cancel the ajax request
         beforeSend: function(xhr, settings) {
           if (settings.dataType === undefined) {
             xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
           }
           return rails.fire(element, 'ajax:beforeSend', [xhr, settings]);
         },
         success: function(data, status, xhr) {
           element.trigger('ajax:success', [data, status, xhr]);
         },
         complete: function(xhr, status) {
           element.trigger('ajax:complete', [xhr, status]);
         },
         error: function(xhr, status, error) {
           element.trigger('ajax:error', [xhr, status, error]);
         },
         crossDomain: crossDomain
       };

       // There is no withCredentials for IE6-8 when
       // "Enable native XMLHTTP support" is disabled
       if (withCredentials) {
         options.xhrFields = {
           withCredentials: withCredentials
         };
       }

       // Only pass url to `ajax` options if not blank
       if (url) { options.url = url; }

       var jqxhr = rails.ajax(options);
       element.trigger('ajax:send', jqxhr);
       return jqxhr;
     } else {
       return false;
     }
   },

   // Handles "data-method" on links such as:
   // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
   handleMethod: function(link) {
     var href = rails.href(link),
       method = link.data('method'),
       target = link.attr('target'),
       csrf_token = $('meta[name=csrf-token]').attr('content'),
       csrf_param = $('meta[name=csrf-param]').attr('content'),
       form = $('<form method="post" action="' + href + '"></form>'),
       metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';

     if (csrf_param !== undefined && csrf_token !== undefined) {
       metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
     }

     if (target) { form.attr('target', target); }

     form.hide().append(metadata_input).appendTo('body');
     form.submit();
   },

   /* Disables form elements:
     - Caches element value in 'ujs:enable-with' data store
     - Replaces element text with value of 'data-disable-with' attribute
     - Sets disabled property to true
   */
   disableFormElements: function(form) {
     form.find(rails.disableSelector).each(function() {
       var element = $(this), method = element.is('button') ? 'html' : 'val';
       element.data('ujs:enable-with', element[method]());
       element[method](element.data('disable-with'));
       element.prop('disabled', true);
     });
   },

   /* Re-enables disabled form elements:
     - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
     - Sets disabled property to false
   */
   enableFormElements: function(form) {
     form.find(rails.enableSelector).each(function() {
       var element = $(this), method = element.is('button') ? 'html' : 'val';
       if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with'));
       element.prop('disabled', false);
     });
   },

  /* For 'data-confirm' attribute:
     - Fires `confirm` event
     - Shows the confirmation dialog
     - Fires the `confirm:complete` event

     Returns `true` if no function stops the chain and user chose yes; `false` otherwise.
     Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog.
     Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function
     return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog.
  */
   allowAction: function(element) {
     var message = element.data('confirm'),
         answer = false, callback;
     if (!message) { return true; }

     if (rails.fire(element, 'confirm')) {
       answer = rails.confirm(message);
       callback = rails.fire(element, 'confirm:complete', [answer]);
     }
     return answer && callback;
   },

   // Helper function which checks for blank inputs in a form that match the specified CSS selector
   blankInputs: function(form, specifiedSelector, nonBlank) {
     var inputs = $(), input, valueToCheck,
         selector = specifiedSelector || 'input,textarea',
         allInputs = form.find(selector);

     allInputs.each(function() {
       input = $(this);
       valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : input.val();
       // If nonBlank and valueToCheck are both truthy, or nonBlank and valueToCheck are both falsey
       if (!valueToCheck === !nonBlank) {

         // Don't count unchecked required radio if other radio with same name is checked
         if (input.is('input[type=radio]') && allInputs.filter('input[type=radio]:checked[name="' + input.attr('name') + '"]').length) {
           return true; // Skip to next input
         }

         inputs = inputs.add(input);
       }
     });
     return inputs.length ? inputs : false;
   },

   // Helper function which checks for non-blank inputs in a form that match the specified CSS selector
   nonBlankInputs: function(form, specifiedSelector) {
     return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank
   },

   // Helper function, needed to provide consistent behavior in IE
   stopEverything: function(e) {
     $(e.target).trigger('ujs:everythingStopped');
     e.stopImmediatePropagation();
     return false;
   },

   //  replace element's html with the 'data-disable-with' after storing original html
   //  and prevent clicking on it
   disableElement: function(element) {
     element.data('ujs:enable-with', element.html()); // store enabled state
     element.html(element.data('disable-with')); // set to disabled state
     element.bind('click.railsDisable', function(e) { // prevent further clicking
       return rails.stopEverything(e);
     });
   },

   // restore element to its original state which was disabled by 'disableElement' above
   enableElement: function(element) {
     if (element.data('ujs:enable-with') !== undefined) {
       element.html(element.data('ujs:enable-with')); // set to old enabled state
       element.removeData('ujs:enable-with'); // clean up cache
     }
     element.unbind('click.railsDisable'); // enable element
   }

 };

 if (rails.fire($document, 'rails:attachBindings')) {

   $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }});

   $document.delegate(rails.linkDisableSelector, 'ajax:complete', function() {
       rails.enableElement($(this));
   });

   $document.delegate(rails.linkClickSelector, 'click.rails', function(e) {
     var link = $(this), method = link.data('method'), data = link.data('params');
     if (!rails.allowAction(link)) return rails.stopEverything(e);

     if (link.is(rails.linkDisableSelector)) rails.disableElement(link);

     if (link.data('remote') !== undefined) {
       if ( (e.metaKey || e.ctrlKey) && (!method || method === 'GET') && !data ) { return true; }

       var handleRemote = rails.handleRemote(link);
       // response from rails.handleRemote() will either be false or a deferred object promise.
       if (handleRemote === false) {
         rails.enableElement(link);
       } else {
         handleRemote.error( function() { rails.enableElement(link); } );
       }
       return false;

     } else if (link.data('method')) {
       rails.handleMethod(link);
       return false;
     }
   });

   $document.delegate(rails.buttonClickSelector, 'click.rails', function(e) {
     var button = $(this);
     if (!rails.allowAction(button)) return rails.stopEverything(e);

     rails.handleRemote(button);
     return false;
   });

   $document.delegate(rails.inputChangeSelector, 'change.rails', function(e) {
     var link = $(this);
     if (!rails.allowAction(link)) return rails.stopEverything(e);

     rails.handleRemote(link);
     return false;
   });

   $document.delegate(rails.formSubmitSelector, 'submit.rails', function(e) {
     var form = $(this),
       remote = form.data('remote') !== undefined,
       blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector),
       nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);

     if (!rails.allowAction(form)) return rails.stopEverything(e);

     // skip other logic when required values are missing or file upload is present
     if (blankRequiredInputs && form.attr("novalidate") == undefined && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
       return rails.stopEverything(e);
     }

     if (remote) {
       if (nonBlankFileInputs) {
         // slight timeout so that the submit button gets properly serialized
         // (make it easy for event handler to serialize form without disabled values)
         setTimeout(function(){ rails.disableFormElements(form); }, 13);
         var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);

         // re-enable form elements if event bindings return false (canceling normal form submission)
         if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); }

         return aborted;
       }

       rails.handleRemote(form);
       return false;

     } else {
       // slight timeout so that the submit button gets properly serialized
       setTimeout(function(){ rails.disableFormElements(form); }, 13);
     }
   });

   $document.delegate(rails.formInputClickSelector, 'click.rails', function(event) {
     var button = $(this);

     if (!rails.allowAction(button)) return rails.stopEverything(event);

     // register the pressed submit button
     var name = button.attr('name'),
       data = name ? {name:name, value:button.val()} : null;

     button.closest('form').data('ujs:submit-button', data);
   });

   $document.delegate(rails.formSubmitSelector, 'ajax:beforeSend.rails', function(event) {
     if (this == event.target) rails.disableFormElements($(this));
   });

   $document.delegate(rails.formSubmitSelector, 'ajax:complete.rails', function(event) {
     if (this == event.target) rails.enableFormElements($(this));
   });

   $(function(){
     // making sure that all forms have actual up-to-date token(cached forms contain old one)
     var csrf_token = $('meta[name=csrf-token]').attr('content');
     var csrf_param = $('meta[name=csrf-param]').attr('content');
     $('form input[name="' + csrf_param + '"]').val(csrf_token);
   });
 }

})( jQuery );