").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ }).complete( callback && function( jqXHR, status ) {
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ });
+ }
+
+ return this;
+};
+
+
+
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
+ jQuery.fn[ type ] = function( fn ) {
+ return this.on( type, fn );
+ };
+});
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+};
+
+
+
+
+
+var docElem = window.document.documentElement;
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+
+jQuery.offset = {
+ setOffset: function( elem, options, i ) {
+ var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+ position = jQuery.css( elem, "position" ),
+ curElem = jQuery( elem ),
+ props = {};
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ curOffset = curElem.offset();
+ curCSSTop = jQuery.css( elem, "top" );
+ curCSSLeft = jQuery.css( elem, "left" );
+ calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+ jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+jQuery.fn.extend({
+ offset: function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ // If we don't have gBCR, just use 0,0 rather than error
+ // BlackBerry 5, iOS 3 (original iPhone)
+ if ( typeof elem.getBoundingClientRect !== strundefined ) {
+ box = elem.getBoundingClientRect();
+ }
+ win = getWindow( doc );
+ return {
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+ },
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ parentOffset = { top: 0, left: 0 },
+ elem = this[ 0 ];
+
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+ // we assume that getBoundingClientRect is available when computed position is fixed
+ offset = elem.getBoundingClientRect();
+ } else {
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || docElem;
+
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || docElem;
+ });
+ }
+});
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ win.document.documentElement[ method ] :
+ elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+});
+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// getComputedStyle returns percent when specified for top/left/bottom/right
+// rather than make the css module depend on the offset module, we just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+ function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+ // if curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ );
+});
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+ // margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ });
+});
+
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+ return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+ define( "jquery", [], function() {
+ return jQuery;
+ });
+}
+
+
+
+
+var
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in
+// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( typeof noGlobal === strundefined ) {
+ window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+
+}));
+(function($, undefined) {
+
+/**
+ * Unobtrusive scripting adapter for jQuery
+ * https://github.com/rails/jquery-ujs
+ *
+ * Requires jQuery 1.8.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], a[data-disable]',
+
+ // Button elements bound by jquery-ujs
+ buttonClickSelector: 'button[data-remote]:not(form button), button[data-confirm]:not(form button)',
+
+ // 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]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])',
+
+ // Form input elements disabled during form submission
+ disableSelector: 'input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled',
+
+ // Form input elements re-enabled after form submission
+ enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]: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], a[data-disable]',
+
+ // Button onClick disable selector with possible reenable after remote submission
+ buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]',
+
+ // 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);
+ },
+
+ // making sure that all forms have actual up-to-date token(cached forms contain old one)
+ refreshCSRFTokens: function(){
+ var csrfToken = $('meta[name=csrf-token]').attr('content');
+ var csrfParam = $('meta[name=csrf-param]').attr('content');
+ $('form input[name="' + csrfParam + '"]').val(csrfToken);
+ },
+
+ // 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);
+ }
+ if (rails.fire(element, 'ajax:beforeSend', [xhr, settings])) {
+ element.trigger('ajax:send', xhr);
+ } else {
+ return false;
+ }
+ },
+ 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; }
+
+ return rails.ajax(options);
+ } else {
+ return false;
+ }
+ },
+
+ // Handles "data-method" on links such as:
+ //
Delete
+ handleMethod: function(link) {
+ var href = rails.href(link),
+ method = link.data('method'),
+ target = link.attr('target'),
+ csrfToken = $('meta[name=csrf-token]').attr('content'),
+ csrfParam = $('meta[name=csrf-param]').attr('content'),
+ form = $('
'),
+ metadataInput = '
';
+
+ if (csrfParam !== undefined && csrfToken !== undefined) {
+ metadataInput += '
';
+ }
+
+ if (target) { form.attr('target', target); }
+
+ form.hide().append(metadataInput).appendTo('body');
+ form.submit();
+ },
+
+ // Helper function that returns form elements that match the specified CSS selector
+ // If form is actually a "form" element this will return associated elements outside the from that have
+ // the html form attribute set
+ formElements: function(form, selector) {
+ return form.is('form') ? $(form[0].elements).filter(selector) : form.find(selector);
+ },
+
+ /* 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) {
+ rails.formElements(form, rails.disableSelector).each(function() {
+ rails.disableFormElement($(this));
+ });
+ },
+
+ disableFormElement: function(element) {
+ var method, replacement;
+
+ method = element.is('button') ? 'html' : 'val';
+ replacement = element.data('disable-with');
+
+ element.data('ujs:enable-with', element[method]());
+ if (replacement !== undefined) {
+ element[method](replacement);
+ }
+
+ 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) {
+ rails.formElements(form, rails.enableSelector).each(function() {
+ rails.enableFormElement($(this));
+ });
+ },
+
+ enableFormElement: function(element) {
+ var 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) {
+ var replacement = element.data('disable-with');
+
+ element.data('ujs:enable-with', element.html()); // store enabled state
+ if (replacement !== undefined) {
+ element.html(replacement);
+ }
+
+ 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); }});
+
+ // This event works the same as the load event, except that it fires every
+ // time the page is loaded.
+ //
+ // See https://github.com/rails/jquery-ujs/issues/357
+ // See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching
+ $(window).on("pageshow.rails", function () {
+ $($.rails.enableSelector).each(function () {
+ var element = $(this);
+
+ if (element.data("ujs:enable-with")) {
+ $.rails.enableFormElement(element);
+ }
+ });
+
+ $($.rails.linkDisableSelector).each(function () {
+ var element = $(this);
+
+ if (element.data("ujs:enable-with")) {
+ $.rails.enableElement(element);
+ }
+ });
+ });
+
+ $document.delegate(rails.linkDisableSelector, 'ajax:complete', function() {
+ rails.enableElement($(this));
+ });
+
+ $document.delegate(rails.buttonDisableSelector, 'ajax:complete', function() {
+ rails.enableFormElement($(this));
+ });
+
+ $document.delegate(rails.linkClickSelector, 'click.rails', function(e) {
+ var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey;
+ if (!rails.allowAction(link)) return rails.stopEverything(e);
+
+ if (!metaClick && link.is(rails.linkDisableSelector)) rails.disableElement(link);
+
+ if (link.data('remote') !== undefined) {
+ if (metaClick && (!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.fail( function() { rails.enableElement(link); } );
+ }
+ return false;
+
+ } else if (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);
+
+ if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button);
+
+ var handleRemote = rails.handleRemote(button);
+ // response from rails.handleRemote() will either be false or a deferred object promise.
+ if (handleRemote === false) {
+ rails.enableFormElement(button);
+ } else {
+ handleRemote.fail( function() { rails.enableFormElement(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,
+ nonBlankFileInputs;
+
+ if (!rails.allowAction(form)) return rails.stopEverything(e);
+
+ // skip other logic when required values are missing or file upload is present
+ if (form.attr('novalidate') == undefined) {
+ blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector);
+ if (blankRequiredInputs && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
+ return rails.stopEverything(e);
+ }
+ }
+
+ if (remote) {
+ nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);
+ 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:send.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(){
+ rails.refreshCSRFTokens();
+ });
+ }
+
+})( jQuery );
+(function() {
+ var CSRFToken, Click, ComponentUrl, EVENTS, Link, ProgressBar, browserIsntBuggy, browserSupportsCustomEvents, browserSupportsPushState, browserSupportsTurbolinks, bypassOnLoadPopstate, cacheCurrentPage, cacheSize, changePage, clone, constrainPageCacheTo, createDocument, crossOriginRedirect, currentState, enableProgressBar, enableTransitionCache, executeScriptTags, extractTitleAndBody, fetch, fetchHistory, fetchReplacement, historyStateIsDefined, initializeTurbolinks, installDocumentReadyPageEventTriggers, installHistoryChangeHandler, installJqueryAjaxSuccessPageUpdateTrigger, loadedAssets, manuallyTriggerHashChangeForFirefox, pageCache, pageChangePrevented, pagesCached, popCookie, processResponse, progressBar, recallScrollPosition, referer, reflectNewUrl, reflectRedirectedUrl, rememberCurrentState, rememberCurrentUrl, rememberReferer, removeNoscriptTags, requestMethodIsSafe, resetScrollPosition, setAutofocusElement, transitionCacheEnabled, transitionCacheFor, triggerEvent, visit, xhr, _ref,
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ __hasProp = {}.hasOwnProperty,
+ __slice = [].slice,
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+
+ pageCache = {};
+
+ cacheSize = 10;
+
+ transitionCacheEnabled = false;
+
+ progressBar = null;
+
+ currentState = null;
+
+ loadedAssets = null;
+
+ referer = null;
+
+ xhr = null;
+
+ EVENTS = {
+ BEFORE_CHANGE: 'page:before-change',
+ FETCH: 'page:fetch',
+ RECEIVE: 'page:receive',
+ CHANGE: 'page:change',
+ UPDATE: 'page:update',
+ LOAD: 'page:load',
+ RESTORE: 'page:restore',
+ BEFORE_UNLOAD: 'page:before-unload',
+ EXPIRE: 'page:expire'
+ };
+
+ fetch = function(url) {
+ var cachedPage;
+ url = new ComponentUrl(url);
+ rememberReferer();
+ cacheCurrentPage();
+ if (progressBar != null) {
+ progressBar.start();
+ }
+ if (transitionCacheEnabled && (cachedPage = transitionCacheFor(url.absolute))) {
+ fetchHistory(cachedPage);
+ return fetchReplacement(url, null, false);
+ } else {
+ return fetchReplacement(url, resetScrollPosition);
+ }
+ };
+
+ transitionCacheFor = function(url) {
+ var cachedPage;
+ cachedPage = pageCache[url];
+ if (cachedPage && !cachedPage.transitionCacheDisabled) {
+ return cachedPage;
+ }
+ };
+
+ enableTransitionCache = function(enable) {
+ if (enable == null) {
+ enable = true;
+ }
+ return transitionCacheEnabled = enable;
+ };
+
+ enableProgressBar = function(enable) {
+ if (enable == null) {
+ enable = true;
+ }
+ if (!browserSupportsTurbolinks) {
+ return;
+ }
+ if (enable) {
+ return progressBar != null ? progressBar : progressBar = new ProgressBar('html');
+ } else {
+ if (progressBar != null) {
+ progressBar.uninstall();
+ }
+ return progressBar = null;
+ }
+ };
+
+ fetchReplacement = function(url, onLoadFunction, showProgressBar) {
+ if (showProgressBar == null) {
+ showProgressBar = true;
+ }
+ triggerEvent(EVENTS.FETCH, {
+ url: url.absolute
+ });
+ if (xhr != null) {
+ xhr.abort();
+ }
+ xhr = new XMLHttpRequest;
+ xhr.open('GET', url.withoutHashForIE10compatibility(), true);
+ xhr.setRequestHeader('Accept', 'text/html, application/xhtml+xml, application/xml');
+ xhr.setRequestHeader('X-XHR-Referer', referer);
+ xhr.onload = function() {
+ var doc;
+ triggerEvent(EVENTS.RECEIVE, {
+ url: url.absolute
+ });
+ if (doc = processResponse()) {
+ reflectNewUrl(url);
+ reflectRedirectedUrl();
+ changePage.apply(null, extractTitleAndBody(doc));
+ manuallyTriggerHashChangeForFirefox();
+ if (typeof onLoadFunction === "function") {
+ onLoadFunction();
+ }
+ return triggerEvent(EVENTS.LOAD);
+ } else {
+ return document.location.href = crossOriginRedirect() || url.absolute;
+ }
+ };
+ if (progressBar && showProgressBar) {
+ xhr.onprogress = (function(_this) {
+ return function(event) {
+ var percent;
+ percent = event.lengthComputable ? event.loaded / event.total * 100 : progressBar.value + (100 - progressBar.value) / 10;
+ return progressBar.advanceTo(percent);
+ };
+ })(this);
+ }
+ xhr.onloadend = function() {
+ return xhr = null;
+ };
+ xhr.onerror = function() {
+ return document.location.href = url.absolute;
+ };
+ return xhr.send();
+ };
+
+ fetchHistory = function(cachedPage) {
+ if (xhr != null) {
+ xhr.abort();
+ }
+ changePage(cachedPage.title, cachedPage.body);
+ recallScrollPosition(cachedPage);
+ return triggerEvent(EVENTS.RESTORE);
+ };
+
+ cacheCurrentPage = function() {
+ var currentStateUrl;
+ currentStateUrl = new ComponentUrl(currentState.url);
+ pageCache[currentStateUrl.absolute] = {
+ url: currentStateUrl.relative,
+ body: document.body,
+ title: document.title,
+ positionY: window.pageYOffset,
+ positionX: window.pageXOffset,
+ cachedAt: new Date().getTime(),
+ transitionCacheDisabled: document.querySelector('[data-no-transition-cache]') != null
+ };
+ return constrainPageCacheTo(cacheSize);
+ };
+
+ pagesCached = function(size) {
+ if (size == null) {
+ size = cacheSize;
+ }
+ if (/^[\d]+$/.test(size)) {
+ return cacheSize = parseInt(size);
+ }
+ };
+
+ constrainPageCacheTo = function(limit) {
+ var cacheTimesRecentFirst, key, pageCacheKeys, _i, _len, _results;
+ pageCacheKeys = Object.keys(pageCache);
+ cacheTimesRecentFirst = pageCacheKeys.map(function(url) {
+ return pageCache[url].cachedAt;
+ }).sort(function(a, b) {
+ return b - a;
+ });
+ _results = [];
+ for (_i = 0, _len = pageCacheKeys.length; _i < _len; _i++) {
+ key = pageCacheKeys[_i];
+ if (!(pageCache[key].cachedAt <= cacheTimesRecentFirst[limit])) {
+ continue;
+ }
+ triggerEvent(EVENTS.EXPIRE, pageCache[key]);
+ _results.push(delete pageCache[key]);
+ }
+ return _results;
+ };
+
+ changePage = function(title, body, csrfToken, runScripts) {
+ triggerEvent(EVENTS.BEFORE_UNLOAD);
+ document.title = title;
+ document.documentElement.replaceChild(body, document.body);
+ if (csrfToken != null) {
+ CSRFToken.update(csrfToken);
+ }
+ setAutofocusElement();
+ if (runScripts) {
+ executeScriptTags();
+ }
+ currentState = window.history.state;
+ if (progressBar != null) {
+ progressBar.done();
+ }
+ triggerEvent(EVENTS.CHANGE);
+ return triggerEvent(EVENTS.UPDATE);
+ };
+
+ executeScriptTags = function() {
+ var attr, copy, nextSibling, parentNode, script, scripts, _i, _j, _len, _len1, _ref, _ref1;
+ scripts = Array.prototype.slice.call(document.body.querySelectorAll('script:not([data-turbolinks-eval="false"])'));
+ for (_i = 0, _len = scripts.length; _i < _len; _i++) {
+ script = scripts[_i];
+ if (!((_ref = script.type) === '' || _ref === 'text/javascript')) {
+ continue;
+ }
+ copy = document.createElement('script');
+ _ref1 = script.attributes;
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ attr = _ref1[_j];
+ copy.setAttribute(attr.name, attr.value);
+ }
+ if (!script.hasAttribute('async')) {
+ copy.async = false;
+ }
+ copy.appendChild(document.createTextNode(script.innerHTML));
+ parentNode = script.parentNode, nextSibling = script.nextSibling;
+ parentNode.removeChild(script);
+ parentNode.insertBefore(copy, nextSibling);
+ }
+ };
+
+ removeNoscriptTags = function(node) {
+ node.innerHTML = node.innerHTML.replace(/