spec/dummy/tmp/cache/assets/D44/150/sprockets%2Fc8f08fad7d3b25131e9159e47a19b9b3 in api_taster-0.5.1 vs spec/dummy/tmp/cache/assets/D44/150/sprockets%2Fc8f08fad7d3b25131e9159e47a19b9b3 in api_taster-0.6.0

- old
+ new

@@ -1,19 +1,19 @@ -o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1351552062.15172: @value"ö {I" -class:EFI"BundledAsset;FI"logical_path;FI"api_taster/application.js;TI" pathname;FI"\/Users/fredwu/Projects/ruby/api_taster/app/assets/javascripts/api_taster/application.js;FI"content_type;FI"application/javascript;FI" -mtime;FI"2012-10-30T10:00:28+11:00;FI" length;Fi I" digest;F"%6a6335c20e3925172bd0ca310160d43dI" source;FI" /*! - * jQuery JavaScript Library v1.8.2 +o: ActiveSupport::Cache::Entry :@compressedF:@created_atf1354145308.879495:@expires_in0: @value"I±{I" +class:EFI"BundledAsset;FI"logical_path;FI"api_taster/application.js;TI" pathname;FI"\/Users/fredwu/Projects/ruby/api_taster/app/assets/javascripts/api_taster/application.js;TI"content_type;FI"application/javascript;FI" +mtime;FI"2012-11-29T10:26:52+11:00;FI" length;Fia¯I" digest;F"%82980464d97631beac939d1e121f339eI" source;FI"a¯/*! + * jQuery JavaScript Library v1.8.3 * http://jquery.com/ * * Includes Sizzle.js * http://sizzlejs.com/ * * Copyright 2012 jQuery Foundation and other contributors * Released under the MIT license * http://jquery.org/license * - * Date: Thu Sep 20 2012 21:13:05 GMT-0400 (Eastern Daylight Time) + * Date: Tue Nov 13 2012 08:20:33 GMT-0500 (Eastern Standard Time) */ (function( window, undefined ) { var // A central reference to the root jQuery(document) @@ -187,11 +187,11 @@ // Start with an empty selector selector: "", // The current version of jQuery being used - jquery: "1.8.2", + jquery: "1.8.3", // The default length of a jQuery object is 0 length: 0, // The number of elements contained in the matched element set @@ -1000,12 +1000,14 @@ // First, we save the current length var start = list.length; (function add( args ) { jQuery.each( args, function( _, arg ) { var type = jQuery.type( arg ); - if ( type === "function" && ( !options.unique || !self.has( arg ) ) ) { - list.push( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } } else if ( arg && arg.length && type !== "string" ) { // Inspect recursively add( arg ); } }); @@ -1254,28 +1256,27 @@ i, isSupported, clickFn, div = document.createElement("div"); - // Preliminary tests + // Setup div.setAttribute( "className", "t" ); div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; + // Support tests won't run in some limited or non-browser environments all = div.getElementsByTagName("*"); a = div.getElementsByTagName("a")[ 0 ]; - a.style.cssText = "top:1px;float:left;opacity:.5"; - - // Can't get basic test support - if ( !all || !all.length ) { + if ( !all || !a || !all.length ) { return {}; } - // First batch of supports tests + // First batch of tests select = document.createElement("select"); opt = select.appendChild( document.createElement("option") ); input = div.getElementsByTagName("input")[ 0 ]; + a.style.cssText = "top:1px;float:left;opacity:.5"; support = { // IE strips leading whitespace when .innerHTML is used leadingWhitespace: ( div.firstChild.nodeType === 3 ), // Make sure that tbody elements aren't automatically inserted @@ -1313,11 +1314,11 @@ optSelected: opt.selected, // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) getSetAttribute: div.className !== "t", - // Tests for enctype support on a form(#6743) + // Tests for enctype support on a form (#6743) enctype: !!document.createElement("form").enctype, // Makes sure cloning an html5 element does not cause problems // Where outerHTML is undefined, this still works html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>", @@ -2218,30 +2219,29 @@ return !val || val.specified ? elem.value : elem.text; } }, select: { get: function( elem ) { - var value, i, max, option, - index = elem.selectedIndex, - values = [], + var value, option, options = elem.options, - one = elem.type === "select-one"; + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; - // Nothing was selected - if ( index < 0 ) { - return null; - } - // Loop through all the selected options - i = one ? index : 0; - max = one ? index + 1 : options.length; for ( ; i < max; i++ ) { option = options[ i ]; - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { // Get the specific value for the option value = jQuery( option ).val(); // We don't need an array for one selects @@ -2252,15 +2252,10 @@ // Multi-Selects return an array values.push( value ); } } - // Fixes Bug #2551 -- select.val() broken in IE after form.reset() - if ( one && !values.length && options.length ) { - return jQuery( options[ index ] ).val(); - } - return values; }, set: function( elem, value ) { var values = jQuery.makeArray( value ); @@ -3234,11 +3229,11 @@ function( elem, type, handle ) { var name = "on" + type; if ( elem.detachEvent ) { - // #8545, #7054, preventing memory leaks for custom events in IE6-8 – + // #8545, #7054, preventing memory leaks for custom events in IE6-8 // detachEvent needed property on element, by name of that event, to properly expose it to GC if ( typeof elem[ name ] === "undefined" ) { elem[ name ] = null; } @@ -3726,11 +3721,12 @@ // Only keep the most recent entries if ( keys.push( key ) > Expr.cacheLength ) { delete cache[ keys.shift() ]; } - return (cache[ key ] = value); + // Retrieve with (key + " ") to avoid collision with native Object.prototype properties (see Issue #157) + return (cache[ key + " " ] = value); }, cache ); }, classCache = createCache(), tokenCache = createCache(), @@ -4260,17 +4256,17 @@ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; }; }, "CLASS": function( className ) { - var pattern = classCache[ expando ][ className ]; - if ( !pattern ) { - pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") ); - } - return function( elem ) { - return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); - }; + var pattern = classCache[ expando ][ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); + }); }, "ATTR": function( name, operator, check ) { return function( elem, context ) { var result = Sizzle.attr( elem, name ); @@ -4512,38 +4508,38 @@ return rinputs.test( elem.nodeName ); }, "focus": function( elem ) { var doc = elem.ownerDocument; - return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); + return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); }, "active": function( elem ) { return elem === elem.ownerDocument.activeElement; }, // Positional types - "first": createPositionalPseudo(function( matchIndexes, length, argument ) { + "first": createPositionalPseudo(function() { return [ 0 ]; }), - "last": createPositionalPseudo(function( matchIndexes, length, argument ) { + "last": createPositionalPseudo(function( matchIndexes, length ) { return [ length - 1 ]; }), "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { return [ argument < 0 ? argument + length : argument ]; }), - "even": createPositionalPseudo(function( matchIndexes, length, argument ) { + "even": createPositionalPseudo(function( matchIndexes, length ) { for ( var i = 0; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; }), - "odd": createPositionalPseudo(function( matchIndexes, length, argument ) { + "odd": createPositionalPseudo(function( matchIndexes, length ) { for ( var i = 1; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; }), @@ -4660,33 +4656,39 @@ baseHasDuplicate = !hasDuplicate; // Document sorting and removing duplicates Sizzle.uniqueSort = function( results ) { var elem, - i = 1; + duplicates = [], + i = 1, + j = 0; hasDuplicate = baseHasDuplicate; results.sort( sortOrder ); if ( hasDuplicate ) { for ( ; (elem = results[i]); i++ ) { if ( elem === results[ i - 1 ] ) { - results.splice( i--, 1 ); + j = duplicates.push( i ); } } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } } return results; }; Sizzle.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); }; function tokenize( selector, parseOnly ) { - var matched, match, tokens, type, soFar, groups, preFilters, - cached = tokenCache[ expando ][ selector ]; + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ expando ][ selector + " " ]; if ( cached ) { return parseOnly ? 0 : cached.slice( 0 ); } @@ -4697,11 +4699,12 @@ while ( soFar ) { // Comma and first run if ( !matched || (match = rcomma.exec( soFar )) ) { if ( match ) { - soFar = soFar.slice( match[0].length ); + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; } groups.push( tokens = [] ); } matched = false; @@ -4716,12 +4719,11 @@ } // Filters for ( type in Expr.filter ) { if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - // The last two arguments here are (context, xml) for backCompat - (match = preFilters[ type ]( match, document, true ))) ) { + (match = preFilters[ type ]( match ))) ) { tokens.push( matched = new Token( match.shift() ) ); soFar = soFar.slice( matched.length ); matched.type = type; matched.matches = match; @@ -4837,22 +4839,17 @@ } if ( postFinder && !postFinder[ expando ] ) { postFinder = setMatcher( postFinder, postSelector ); } return markFunction(function( seed, results, context, xml ) { - // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones - if ( seed && postFinder ) { - return; - } - - var i, elem, postFilterIn, + var temp, i, elem, preMap = [], postMap = [], preexisting = results.length, // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ), + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), // Prefilter to get matcher input, preserving a map for seed-results synchronization matcherIn = preFilter && ( seed || !selector ) ? condense( elems, preMap, preFilter, context, xml ) : elems, @@ -4873,31 +4870,49 @@ matcher( matcherIn, matcherOut, context, xml ); } // Apply postFilter if ( postFilter ) { - postFilterIn = condense( matcherOut, postMap ); - postFilter( postFilterIn, [], context, xml ); + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); // Un-match failing elements by moving them back to matcherIn - i = postFilterIn.length; + i = temp.length; while ( i-- ) { - if ( (elem = postFilterIn[i]) ) { + if ( (elem = temp[i]) ) { matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); } } } - // Keep seed and results synchronized if ( seed ) { - // Ignore postFinder because it can't coexist with seed - i = preFilter && matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - seed[ preMap[i] ] = !(results[ preMap[i] ] = elem); + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } } + + // Add elements to results, through postFinder if defined } else { matcherOut = condense( matcherOut === results ? matcherOut.splice( preexisting, matcherOut.length ) : matcherOut @@ -4934,11 +4949,10 @@ for ( ; i < len; i++ ) { if ( (matcher = Expr.relative[ tokens[i].type ]) ) { matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; } else { - // The concatenated values are (context, xml) for backCompat matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); // Return special upon seeing a positional matcher if ( matcher[ expando ] ) { // Find the next relative operator (if any) for proper handling @@ -5063,11 +5077,11 @@ compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { var i, setMatchers = [], elementMatchers = [], - cached = compilerCache[ expando ][ selector ]; + cached = compilerCache[ expando ][ selector + " " ]; if ( !cached ) { // Generate a function of recursive functions that can be used to check each element if ( !group ) { group = tokenize( selector ); @@ -5086,15 +5100,15 @@ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); } return cached; }; -function multipleContexts( selector, contexts, results, seed ) { +function multipleContexts( selector, contexts, results ) { var i = 0, len = contexts.length; for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results, seed ); + Sizzle( selector, contexts[i], results ); } return results; } function select( selector, context, results, seed, xml ) { @@ -5168,19 +5182,18 @@ var disconnectedMatch, oldSelect = select, rescape = /'|\\/g, rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, - // qSa(:focus) reports false when true (Chrome 21), + // qSa(:focus) reports false when true (Chrome 21), no need to also add to buggyMatches since matches checks buggyQSA // A support test would require too much code (would include document ready) - rbuggyQSA = [":focus"], + rbuggyQSA = [ ":focus" ], - // matchesSelector(:focus) reports false when true (Chrome 21), // matchesSelector(:active) reports false when true (IE9/Opera 11.5) // A support test would require too much code (would include document ready) // just skip matchesSelector for :active - rbuggyMatches = [ ":active", ":focus" ], + rbuggyMatches = [ ":active" ], matches = docElem.matchesSelector || docElem.mozMatchesSelector || docElem.webkitMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector; @@ -5230,11 +5243,11 @@ select = function( selector, context, results, seed, xml ) { // Only use querySelectorAll when not filtering, // when this is not xml, // and when no QSA bugs apply - if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + if ( !seed && !xml && !rbuggyQSA.test( selector ) ) { var groups, i, old = true, nid = expando, newContext = context, newSelector = context.nodeType === 9 && selector; @@ -5299,11 +5312,11 @@ Sizzle.matchesSelector = function( elem, expr ) { // Make sure that attribute selectors are quoted expr = expr.replace( rattributeQuotes, "='$1']" ); // rbuggyMatches always contains :active, so no need for an existence check - if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { + if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && !rbuggyQSA.test( expr ) ) { try { var ret = matches.call( elem, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || disconnectedMatch || @@ -6534,11 +6547,11 @@ rdisplayswap = /^(none|table(?!-c[ea]).+)/, rmargin = /^margin/, rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ), - elemdisplay = {}, + elemdisplay = { BODY: "block" }, cssShow = { position: "absolute", visibility: "hidden", display: "block" }, cssNormalTransform = { letterSpacing: 0, fontWeight: 400 @@ -6815,11 +6828,13 @@ computed = window.getComputedStyle( elem, null ), style = elem.style; if ( computed ) { - ret = computed[ name ]; + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed.getPropertyValue( name ) || computed[ name ]; + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { ret = jQuery.style( elem, name ); } // A tribute to the "awesome hack by Dean Edwards" @@ -7844,13 +7859,16 @@ // Extract dataTypes list s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace ); // A cross-domain request is in order when we have a protocol:host:port mismatch if ( s.crossDomain == null ) { - parts = rurl.exec( s.url.toLowerCase() ) || false; - s.crossDomain = parts && ( parts.join(":") + ( parts[ 3 ] ? "" : parts[ 1 ] === "http:" ? 80 : 443 ) ) !== - ( ajaxLocParts.join(":") + ( ajaxLocParts[ 3 ] ? "" : ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ); + parts = rurl.exec( s.url.toLowerCase() ); + s.crossDomain = !!( parts && + ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || + ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != + ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) + ); } // Convert data if not already a string if ( s.data && s.processData && typeof s.data !== "string" ) { s.data = jQuery.param( s.data, s.traditional ); @@ -8465,11 +8483,11 @@ // When requesting binary data, IE6-9 will throw an exception // on any attempt to access responseText (#11426) try { responses.text = xhr.responseText; - } catch( _ ) { + } catch( e ) { } // Firefox throws an exception when accessing // statusText for faulty cross-domain requests try { @@ -8618,11 +8636,13 @@ delete tick.elem; }), tick = function() { var currentTime = fxNow || createFxNow(), remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - percent = 1 - ( remaining / animation.duration || 0 ), + // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, index = 0, length = animation.tweens.length; for ( ; index < length ; index++ ) { animation.tweens[ index ].run( percent ); @@ -8770,11 +8790,11 @@ } } }); function defaultPrefilter( elem, props, opts ) { - var index, prop, value, length, dataShow, tween, hooks, oldfire, + var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire, anim = this, style = elem.style, orig = {}, handled = [], hidden = elem.nodeType && isHidden( elem ); @@ -8844,20 +8864,29 @@ // show/hide pass for ( index in props ) { value = props[ index ]; if ( rfxtypes.exec( value ) ) { delete props[ index ]; + toggle = toggle || value === "toggle"; if ( value === ( hidden ? "hide" : "show" ) ) { continue; } handled.push( index ); } } length = handled.length; if ( length ) { dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} ); + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + + // store state if its toggle - enables .stop().toggle() to "reverse" + if ( toggle ) { + dataShow.hidden = !hidden; + } if ( hidden ) { jQuery( elem ).show(); } else { anim.done(function() { jQuery( elem ).hide(); @@ -9150,10 +9179,12 @@ jQuery.fx.tick = function() { var timer, timers = jQuery.timers, i = 0; + fxNow = jQuery.now(); + for ( ; i < timers.length; i++ ) { timer = timers[ i ]; // Checks the timer has not already been removed if ( !timer() && timers[ i ] === timer ) { timers.splice( i--, 1 ); @@ -9161,10 +9192,11 @@ } if ( !timers.length ) { jQuery.fx.stop(); } + fxNow = undefined; }; jQuery.fx.timer = function( timer ) { if ( timer() && jQuery.timers.push( timer ) && !timerId ) { timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); @@ -9868,12 +9900,314 @@ $('form input[name="' + csrf_param + '"]').val(csrf_token); }); } })( jQuery ); +// This [jQuery](http://jquery.com/) plugin implements an `<iframe>` +// [transport](http://api.jquery.com/extending-ajax/#Transports) so that +// `$.ajax()` calls support the uploading of files using standard HTML file +// input fields. This is done by switching the exchange from `XMLHttpRequest` to +// a hidden `iframe` element containing a form that is submitted. + +// The [source for the plugin](http://github.com/cmlenz/jquery-iframe-transport) +// is available on [Github](http://github.com/) and dual licensed under the MIT +// or GPL Version 2 licenses. + +// ## Usage + +// To use this plugin, you simply add a `iframe` option with the value `true` +// to the Ajax settings an `$.ajax()` call, and specify the file fields to +// include in the submssion using the `files` option, which can be a selector, +// jQuery object, or a list of DOM elements containing one or more +// `<input type="file">` elements: + +// $("#myform").submit(function() { +// $.ajax(this.action, { +// files: $(":file", this), +// iframe: true +// }).complete(function(data) { +// console.log(data); +// }); +// }); + +// The plugin will construct a hidden `<iframe>` element containing a copy of +// the form the file field belongs to, will disable any form fields not +// explicitly included, submit that form, and process the response. + +// If you want to include other form fields in the form submission, include them +// in the `data` option, and set the `processData` option to `false`: + +// $("#myform").submit(function() { +// $.ajax(this.action, { +// data: $(":text", this).serializeArray(), +// files: $(":file", this), +// iframe: true, +// processData: false +// }).complete(function(data) { +// console.log(data); +// }); +// }); + +// ### The Server Side + +// If the response is not HTML or XML, you (unfortunately) need to apply some +// trickery on the server side. To send back a JSON payload, send back an HTML +// `<textarea>` element with a `data-type` attribute that contains the MIME +// type, and put the actual payload in the textarea: + +// <textarea data-type="application/json"> +// {"ok": true, "message": "Thanks so much"} +// </textarea> + +// The iframe transport plugin will detect this and attempt to apply the same +// conversions that jQuery applies to regular responses. That means for the +// example above you should get a Javascript object as the `data` parameter of +// the `complete` callback, with the properties `ok: true` and +// `message: "Thanks so much"`. + +// ### Compatibility + +// This plugin has primarily been tested on Safari 5, Firefox 4, and Internet +// Explorer all the way back to version 6. While I haven't found any issues with +// it so far, I'm fairly sure it still doesn't work around all the quirks in all +// different browsers. But the code is still pretty simple overall, so you +// should be able to fix it and contribute a patch :) + +// ## Annotated Source + +(function($, undefined) { + + // Register a prefilter that checks whether the `iframe` option is set, and + // switches to the iframe transport if it is `true`. + $.ajaxPrefilter(function(options, origOptions, jqXHR) { + if (options.iframe) { + return "iframe"; + } + }); + + // Register an iframe transport, independent of requested data type. It will + // only activate when the "files" option has been set to a non-empty list of + // enabled file inputs. + $.ajaxTransport("iframe", function(options, origOptions, jqXHR) { + var form = null, + iframe = null, + origAction = null, + origTarget = null, + origEnctype = null, + addedFields = [], + disabledFields = [], + files = $(options.files).filter(":file:enabled"); + + // This function gets called after a successful submission or an abortion + // and should revert all changes made to the page to enable the + // submission via this transport. + function cleanUp() { + $(addedFields).each(function() { + this.remove(); + }); + $(disabledFields).each(function() { + this.disabled = false; + }); + form.attr("action", origAction || "") + .attr("target", origTarget || "") + .attr("enctype", origEnctype || ""); + iframe.attr("src", "javascript:false;").remove(); + } + + // Remove "iframe" from the data types list so that further processing is + // based on the content type returned by the server, without attempting an + // (unsupported) conversion from "iframe" to the actual type. + options.dataTypes.shift(); + + if (files.length) { + // Determine the form the file fields belong to, and make sure they all + // actually belong to the same form. + files.each(function() { + if (form !== null && this.form !== form) { + jQuery.error("All file fields must belong to the same form"); + } + form = this.form; + }); + form = $(form); + + // Store the original form attributes that we'll be replacing temporarily. + origAction = form.attr("action"); + origTarget = form.attr("target"); + origEnctype = form.attr("enctype"); + + // We need to disable all other inputs in the form so that they don't get + // included in the submitted data unexpectedly. + form.find(":input:not(:submit)").each(function() { + if (!this.disabled && (this.type != "file" || files.index(this) < 0)) { + this.disabled = true; + disabledFields.push(this); + } + }); + + // If there is any additional data specified via the `data` option, + // we add it as hidden fields to the form. This (currently) requires + // the `processData` option to be set to false so that the data doesn't + // get serialized to a string. + if (typeof(options.data) === "string" && options.data.length > 0) { + jQuery.error("data must not be serialized"); + } + $.each(options.data || {}, function(name, value) { + if ($.isPlainObject(value)) { + name = value.name; + value = value.value; + } + addedFields.push($("<input type='hidden'>").attr("name", name) + .attr("value", value).appendTo(form)); + }); + + // Add a hidden `X-Requested-With` field with the value `IFrame` to the + // field, to help server-side code to determine that the upload happened + // through this transport. + addedFields.push($("<input type='hidden' name='X-Requested-With'>") + .attr("value", "IFrame").appendTo(form)); + + // Borrowed straight from the JQuery source + // Provides a way of specifying the accepted data type similar to HTTP_ACCEPTS + accepts = options.dataTypes[ 0 ] && options.accepts[ options.dataTypes[0] ] ? + options.accepts[ options.dataTypes[0] ] + ( options.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) : + options.accepts[ "*" ] + + addedFields.push($("<input type='hidden' name='X-Http-Accept'>") + .attr("value", accepts).appendTo(form)); + + return { + + // The `send` function is called by jQuery when the request should be + // sent. + send: function(headers, completeCallback) { + iframe = $("<iframe src='javascript:false;' name='iframe-" + $.now() + + "' style='display:none'></iframe>"); + + // The first load event gets fired after the iframe has been injected + // into the DOM, and is used to prepare the actual submission. + iframe.bind("load", function() { + + // The second load event gets fired when the response to the form + // submission is received. The implementation detects whether the + // actual payload is embedded in a `<textarea>` element, and + // prepares the required conversions to be made in that case. + iframe.unbind("load").bind("load", function() { + + var doc = this.contentWindow ? this.contentWindow.document : + (this.contentDocument ? this.contentDocument : this.document), + root = doc.documentElement ? doc.documentElement : doc.body, + textarea = root.getElementsByTagName("textarea")[0], + type = textarea ? textarea.getAttribute("data-type") : null; + + var status = textarea ? parseInt(textarea.getAttribute("response-code")) : 200, + statusText = "OK", + responses = { text: type ? textarea.value : root ? root.innerHTML : null }, + headers = "Content-Type: " + (type || "text/html") + + completeCallback(status, statusText, responses, headers); + + setTimeout(cleanUp, 50); + }); + + // Now that the load handler has been set up, reconfigure and + // submit the form. + form.attr("action", options.url) + .attr("target", iframe.attr("name")) + .attr("enctype", "multipart/form-data") + .get(0).submit(); + }); + + // After everything has been set up correctly, the iframe gets + // injected into the DOM so that the submission can be initiated. + iframe.insertAfter(form); + }, + + // The `abort` function is called by jQuery when the request should be + // aborted. + abort: function() { + if (iframe !== null) { + iframe.unbind("load").attr("src", "javascript:false;"); + cleanUp(); + } + } + + }; + } + }); + +})(jQuery); + + + +(function($) { + + var remotipart; + + $.remotipart = remotipart = { + + setup: function(form) { + form + // Allow setup part of $.rails.handleRemote to setup remote settings before canceling default remote handler + // This is required in order to change the remote settings using the form details + .one('ajax:beforeSend.remotipart', function(e, xhr, settings){ + // Delete the beforeSend bindings, since we're about to re-submit via ajaxSubmit with the beforeSubmit + // hook that was just setup and triggered via the default `$.rails.handleRemote` + // delete settings.beforeSend; + delete settings.beforeSend; + + settings.iframe = true; + settings.files = $($.rails.fileInputSelector, form); + settings.data = form.serializeArray(); + settings.processData = false; + + // Modify some settings to integrate JS request with rails helpers and middleware + if (settings.dataType === undefined) { settings.dataType = 'script *'; } + settings.data.push({name: 'remotipart_submitted', value: true}); + + // Allow remotipartSubmit to be cancelled if needed + if ($.rails.fire(form, 'ajax:remotipartSubmit', [xhr, settings])) { + // Second verse, same as the first + $.rails.ajax(settings); + } + + //Run cleanup + remotipart.teardown(form); + + // Cancel the jQuery UJS request + return false; + }) + + // Keep track that we just set this particular form with Remotipart bindings + // Note: The `true` value will get over-written with the `settings.dataType` from the `ajax:beforeSend` handler + .data('remotipartSubmitted', true); + }, + + teardown: function(form) { + form + .unbind('ajax:beforeSend.remotipart') + .removeData('remotipartSubmitted') + } + }; + + $('form').live('ajax:aborted:file', function(){ + var form = $(this); + + remotipart.setup(form); + + // If browser does not support submit bubbling, then this live-binding will be called before direct + // bindings. Therefore, we should directly call any direct bindings before remotely submitting form. + if (!$.support.submitBubbles && $().jquery < '1.7' && $.rails.callFormSubmitBindings(form) === false) return $.rails.stopEverything(e); + + // Manually call jquery-ujs remote call so that it can setup form and settings as usual, + // and trigger the `ajax:beforeSend` callback to which remotipart binds functionality. + $.rails.handleRemote(form); + return false; + }); + +})(jQuery); /* =================================================== - * bootstrap-transition.js v2.1.0 + * bootstrap-transition.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#transitions * =================================================== * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -9891,17 +10225,17 @@ !function ($) { - $(function () { + "use strict"; // jshint ;_; - "use strict"; // jshint ;_; + /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) + * ======================================================= */ - /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) - * ======================================================= */ + $(function () { $.support.transition = (function () { var transitionEnd = (function () { @@ -9930,11 +10264,11 @@ }) }(window.jQuery); /* ========================================================== - * bootstrap-affix.js v2.1.0 + * bootstrap-affix.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#affix * ========================================================== * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -9960,11 +10294,13 @@ /* AFFIX CLASS DEFINITION * ====================== */ var Affix = function (element, options) { this.options = $.extend({}, $.fn.affix.defaults, options) - this.$window = $(window).on('scroll.affix.data-api', $.proxy(this.checkPosition, this)) + this.$window = $(window) + .on('scroll.affix.data-api', $.proxy(this.checkPosition, this)) + .on('click.affix.data-api', $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this)) this.$element = $(element) this.checkPosition() } Affix.prototype.checkPosition = function () { @@ -10035,11 +10371,11 @@ }) }(window.jQuery); /* ========================================================== - * bootstrap-alert.js v2.1.0 + * bootstrap-alert.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#alerts * ========================================================== * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -10120,17 +10456,15 @@ /* ALERT DATA-API * ============== */ - $(function () { - $('body').on('click.alert.data-api', dismiss, Alert.prototype.close) - }) + $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) }(window.jQuery); /* ============================================================ - * bootstrap-button.js v2.1.0 + * bootstrap-button.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#buttons * ============================================================ * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -10179,11 +10513,11 @@ $el.removeClass(d).removeAttr(d) }, 0) } Button.prototype.toggle = function () { - var $parent = this.$element.parent('[data-toggle="buttons-radio"]') + var $parent = this.$element.closest('[data-toggle="buttons-radio"]') $parent && $parent .find('.active') .removeClass('active') @@ -10213,21 +10547,19 @@ /* BUTTON DATA-API * =============== */ - $(function () { - $('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - $btn.button('toggle') - }) + $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') }) }(window.jQuery); /* ========================================================== - * bootstrap-carousel.js v2.1.0 + * bootstrap-carousel.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#carousel * ========================================================== * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -10319,20 +10651,22 @@ , $next = next || $active[type]() , isCycling = this.interval , direction = type == 'next' ? 'left' : 'right' , fallback = type == 'next' ? 'first' : 'last' , that = this - , e = $.Event('slide', { - relatedTarget: $next[0] - }) + , e this.sliding = true isCycling && this.pause() $next = $next.length ? $next : this.$element.find('.item')[fallback]() + e = $.Event('slide', { + relatedTarget: $next[0] + }) + if ($next.hasClass('active')) return if ($.support.transition && this.$element.hasClass('slide')) { this.$element.trigger(e) if (e.isDefaultPrevented()) return @@ -10388,23 +10722,21 @@ /* CAROUSEL DATA-API * ================= */ - $(function () { - $('body').on('click.carousel.data-api', '[data-slide]', function ( e ) { - var $this = $(this), href - , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 - , options = !$target.data('modal') && $.extend({}, $target.data(), $this.data()) - $target.carousel(options) - e.preventDefault() - }) + $(document).on('click.carousel.data-api', '[data-slide]', function (e) { + var $this = $(this), href + , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + , options = $.extend({}, $target.data(), $this.data()) + $target.carousel(options) + e.preventDefault() }) }(window.jQuery); /* ============================================================= - * bootstrap-collapse.js v2.1.0 + * bootstrap-collapse.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#collapse * ============================================================= * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -10545,25 +10877,23 @@ /* COLLAPSIBLE DATA-API * ==================== */ - $(function () { - $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { - var $this = $(this), href - , target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - , option = $(target).data('collapse') ? 'toggle' : $this.data() - $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') - $(target).collapse(option) - }) + $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + , target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + , option = $(target).data('collapse') ? 'toggle' : $this.data() + $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + $(target).collapse(option) }) }(window.jQuery); /* ============================================================ - * bootstrap-dropdown.js v2.1.0 + * bootstrap-dropdown.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#dropdowns * ============================================================ * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -10661,21 +10991,22 @@ } } function clearMenus() { - getParent($(toggle)) - .removeClass('open') + $(toggle).each(function () { + getParent($(this)).removeClass('open') + }) } function getParent($this) { var selector = $this.attr('data-target') , $parent if (!selector) { selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 } $parent = $(selector) $parent.length || ($parent = $this.parent()) @@ -10699,22 +11030,19 @@ /* APPLY TO STANDARD DROPDOWN ELEMENTS * =================================== */ - $(function () { - $('html') - .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus) - $('body') - .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) - .on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle) - .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) - }) + $(document) + .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus) + .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle) + .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) }(window.jQuery); /* ========================================================= - * bootstrap-modal.js v2.1.0 + * bootstrap-modal.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#modals * ========================================================= * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -10761,12 +11089,10 @@ this.$element.trigger(e) if (this.isShown || e.isDefaultPrevented()) return - $('body').addClass('modal-open') - this.isShown = true this.escape() this.backdrop(function () { @@ -10784,17 +11110,16 @@ } that.$element .addClass('in') .attr('aria-hidden', false) - .focus() that.enforceFocus() transition ? - that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) : - that.$element.trigger('shown') + that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) : + that.$element.focus().trigger('shown') }) } , hide: function (e) { @@ -10808,12 +11133,10 @@ if (!this.isShown || e.isDefaultPrevented()) return this.isShown = false - $('body').removeClass('modal-open') - this.escape() $(document).off('focusin.modal') this.$element @@ -10879,13 +11202,15 @@ var doAnimate = $.support.transition && animate this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') .appendTo(document.body) - if (this.options.backdrop != 'static') { - this.$backdrop.click($.proxy(this.hide, this)) - } + this.$backdrop.click( + this.options.backdrop == 'static' ? + $.proxy(this.$element[0].focus, this.$element[0]) + : $.proxy(this.hide, this) + ) if (doAnimate) this.$backdrop[0].offsetWidth // force reflow this.$backdrop.addClass('in') @@ -10931,30 +11256,28 @@ /* MODAL DATA-API * ============== */ - $(function () { - $('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) { - var $this = $(this) - , href = $this.attr('href') - , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7 - , option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) + $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) { + var $this = $(this) + , href = $this.attr('href') + , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7 + , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data()) - e.preventDefault() + e.preventDefault() - $target - .modal(option) - .one('hide', function () { - $this.focus() - }) - }) + $target + .modal(option) + .one('hide', function () { + $this.focus() + }) }) }(window.jQuery); /* ============================================================= - * bootstrap-scrollspy.js v2.1.0 + * bootstrap-scrollspy.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#scrollspy * ============================================================= * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -11102,11 +11425,11 @@ }) }) }(window.jQuery); /* ======================================================== - * bootstrap-tab.js v2.1.0 + * bootstrap-tab.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#tabs * ======================================================== * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -11153,11 +11476,11 @@ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 } if ( $this.parent('li').hasClass('active') ) return - previous = $ul.find('.active a').last()[0] + previous = $ul.find('.active:last a')[0] e = $.Event('show', { relatedTarget: previous }) @@ -11229,20 +11552,18 @@ /* TAB DATA-API * ============ */ - $(function () { - $('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { - e.preventDefault() - $(this).tab('show') - }) + $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { + e.preventDefault() + $(this).tab('show') }) }(window.jQuery); /* =========================================================== - * bootstrap-tooltip.js v2.1.0 + * bootstrap-tooltip.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#tooltips * Inspired by the original jQuery.tipsy by Jason Frame * =========================================================== * Copyright 2012 Twitter, Inc. * @@ -11359,13 +11680,13 @@ this.options.placement inside = /in/.test(placement) $tip - .remove() + .detach() .css({ top: 0, left: 0, display: 'block' }) - .appendTo(inside ? this.$element : document.body) + .insertAfter(this.$element) pos = this.getPosition(inside) actualWidth = $tip[0].offsetWidth actualHeight = $tip[0].offsetHeight @@ -11384,11 +11705,11 @@ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} break } $tip - .css(tp) + .offset(tp) .addClass(placement) .addClass('in') } } @@ -11406,22 +11727,22 @@ $tip.removeClass('in') function removeWithAnimation() { var timeout = setTimeout(function () { - $tip.off($.support.transition.end).remove() + $tip.off($.support.transition.end).detach() }, 500) $tip.one($.support.transition.end, function () { clearTimeout(timeout) - $tip.remove() + $tip.detach() }) } $.support.transition && this.$tip.hasClass('fade') ? removeWithAnimation() : - $tip.remove() + $tip.detach() return this } , fixTitle: function () { @@ -11475,12 +11796,13 @@ , toggleEnabled: function () { this.enabled = !this.enabled } - , toggle: function () { - this[this.tip().hasClass('in') ? 'hide' : 'show']() + , toggle: function (e) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + self[self.tip().hasClass('in') ? 'hide' : 'show']() } , destroy: function () { this.hide().$element.off('.' + this.type).removeData(this.type) } @@ -11509,16 +11831,16 @@ , selector: false , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' , trigger: 'hover' , title: '' , delay: 0 - , html: true + , html: false } }(window.jQuery); /* =========================================================== - * bootstrap-popover.js v2.1.0 + * bootstrap-popover.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#popovers * =========================================================== * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -11618,11 +11940,11 @@ , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>' }) }(window.jQuery); /* ============================================================= - * bootstrap-typeahead.js v2.1.0 + * bootstrap-typeahead.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#typeahead * ============================================================= * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -11794,19 +12116,28 @@ this.$element .on('blur', $.proxy(this.blur, this)) .on('keypress', $.proxy(this.keypress, this)) .on('keyup', $.proxy(this.keyup, this)) - if ($.browser.webkit || $.browser.msie) { + if (this.eventSupported('keydown')) { this.$element.on('keydown', $.proxy(this.keydown, this)) } this.$menu .on('click', $.proxy(this.click, this)) .on('mouseenter', 'li', $.proxy(this.mouseenter, this)) } + , eventSupported: function(eventName) { + var isSupported = eventName in this.$element + if (!isSupported) { + this.$element.setAttribute(eventName, 'return;') + isSupported = typeof this.$element[eventName] === 'function' + } + return isSupported + } + , move: function (e) { if (!this.shown) return switch(e.keyCode) { case 9: // tab @@ -11841,10 +12172,13 @@ , keyup: function (e) { switch(e.keyCode) { case 40: // down arrow case 38: // up arrow + case 16: // shift + case 17: // ctrl + case 18: // alt break case 9: // tab case 13: // enter if (!this.shown) return @@ -11908,17 +12242,15 @@ /* TYPEAHEAD DATA-API * ================== */ - $(function () { - $('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) { - var $this = $(this) - if ($this.data('typeahead')) return - e.preventDefault() - $this.typeahead($this.data()) - }) + $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) { + var $this = $(this) + if ($this.data('typeahead')) return + e.preventDefault() + $this.typeahead($this.data()) }) }(window.jQuery); @@ -11959,1235 +12291,168 @@ ["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b= !k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m, 250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit", PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})(); -/*! - * jQuery Form Plugin - * version: 3.09 (16-APR-2012) - * @requires jQuery v1.3.2 or later - * - * Examples and documentation at: http://malsup.com/jquery/form/ - * Project repository: https://github.com/malsup/form - * Dual licensed under the MIT and GPL licenses: - * http://malsup.github.com/mit-license.txt - * http://malsup.github.com/gpl-license-v2.txt - */ -/*global ActiveXObject alert */ +var ApiTaster = { -;(function($) { -"use strict"; + disableSubmitButton: function() { + $("#submit-api").attr("disabled", true); + }, -/* - Usage Note: - ----------- - Do not use both ajaxSubmit and ajaxForm on the same form. These - functions are mutually exclusive. Use ajaxSubmit if you want - to bind your own submit handler to the form. For example, + enableSubmitButton: function() { + $("#submit-api").attr("disabled", false); + }, - $(document).ready(function() { - $('#myForm').on('submit', function(e) { - e.preventDefault(); // <-- important - $(this).ajaxSubmit({ - target: '#output' - }); - }); - }); + disableUrlParams: function() { + $("fieldset[ref=url-params] input").prop("disabled", true); + }, - Use ajaxForm when you want the plugin to manage all the event binding - for you. For example, + enableUrlParams: function() { + $("fieldset[ref=url-params] input").prop("disabled", false); + }, - $(document).ready(function() { - $('#myForm').ajaxForm({ - target: '#output' - }); - }); + detectContentType: function(response) { + var contentType = response.getResponseHeader("Content-Type"); + var detectedContentType = null - You can also use ajaxForm with delegation (requires jQuery v1.7+), so the - form does not have to exist when you invoke ajaxForm: - - $('#myForm').ajaxForm({ - delegation: true, - target: '#output' - }); - - When using ajaxForm, the ajaxSubmit function will be invoked for you - at the appropriate time. -*/ - -/** - * Feature detection - */ -var feature = {}; -feature.fileapi = $("<input type='file'/>").get(0).files !== undefined; -feature.formdata = window.FormData !== undefined; - -/** - * ajaxSubmit() provides a mechanism for immediately submitting - * an HTML form using AJAX. - */ -$.fn.ajaxSubmit = function(options) { - /*jshint scripturl:true */ - - // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) - if (!this.length) { - log('ajaxSubmit: skipping submit process - no element selected'); - return this; + if (contentType.match(/application\/json/)) { + detectedContentType = 'json'; } - var method, action, url, $form = this; + return detectedContentType; + }, - if (typeof options == 'function') { - options = { success: options }; - } + fillInInfoTab: function($tab, xhr) { + $tab.find('.status td.value').text(xhr.status + " " + xhr.statusText); + $tab.find('.headers td.value').text(xhr.getAllResponseHeaders()); - method = this.attr('method'); - action = this.attr('action'); - url = (typeof action === 'string') ? $.trim(action) : ''; - url = url || window.location.href || ''; - if (url) { - // clean url (don't include hash vaue) - url = (url.match(/^([^#]+)/)||[])[1]; - } + timeTaken = ApiTaster.lastRequest.endTime - ApiTaster.lastRequest.startTime + $tab.find('.time td.value').text(timeTaken + " ms"); + }, - options = $.extend(true, { - url: url, - success: $.ajaxSettings.success, - type: method || 'GET', - iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' - }, options); + getSubmitUrl: function($form) { + var baseUrl = $form.attr('action'); + var matches = baseUrl.match(/\:[^\/]+/g) - // hook for manipulating the form data before it is extracted; - // convenient for use with rich editors like tinyMCE or FCKEditor - var veto = {}; - this.trigger('form-pre-serialize', [this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); - return this; - } + if (matches) { + for(var a = 0; a < matches.length; a++) { + var match = matches[a]; + var str = match.substr(1); - // provide opportunity to alter form data before it is serialized - if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSerialize callback'); - return this; - } + var $input = $form.find( + 'input[name="' + str + '"],input[name="[api_taster_url_params]' + str + '"]' + ); - var traditional = options.traditional; - if ( traditional === undefined ) { - traditional = $.ajaxSettings.traditional; - } - - var elements = []; - var qx, a = this.formToArray(options.semantic, elements); - if (options.data) { - options.extraData = options.data; - qx = $.param(options.data, traditional); - } - - // give pre-submit callback an opportunity to abort the submit - if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSubmit callback'); - return this; - } - - // fire vetoable 'validate' event - this.trigger('form-submit-validate', [a, this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); - return this; - } - - var q = $.param(a, traditional); - if (qx) { - q = ( q ? (q + '&' + qx) : qx ); - } - if (options.type.toUpperCase() == 'GET') { - options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; - options.data = null; // data is null for 'get' - } - else { - options.data = q; // data is the query string for 'post' - } - - var callbacks = []; - if (options.resetForm) { - callbacks.push(function() { $form.resetForm(); }); - } - if (options.clearForm) { - callbacks.push(function() { $form.clearForm(options.includeHidden); }); - } - - // perform a load on the target only if dataType is not provided - if (!options.dataType && options.target) { - var oldSuccess = options.success || function(){}; - callbacks.push(function(data) { - var fn = options.replaceTarget ? 'replaceWith' : 'html'; - $(options.target)[fn](data).each(oldSuccess, arguments); - }); - } - else if (options.success) { - callbacks.push(options.success); - } - - options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg - var context = options.context || options; // jQuery 1.4+ supports scope context - for (var i=0, max=callbacks.length; i < max; i++) { - callbacks[i].apply(context, [data, status, xhr || $form, $form]); + if ($input.length > 0) { + baseUrl = baseUrl.replace(match, $input.val()); } - }; - - // are there files to upload? - var fileInputs = $('input:file:enabled[value]', this); // [value] (issue #113) - var hasFileInputs = fileInputs.length > 0; - var mp = 'multipart/form-data'; - var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); - - var fileAPI = feature.fileapi && feature.formdata; - log("fileAPI :" + fileAPI); - var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI; - - // options.iframe allows user to force iframe mode - // 06-NOV-09: now defaulting to iframe mode if file input is detected - if (options.iframe !== false && (options.iframe || shouldUseFrame)) { - // hack to fix Safari hang (thanks to Tim Molendijk for this) - // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d - if (options.closeKeepAlive) { - $.get(options.closeKeepAlive, function() { - fileUploadIframe(a); - }); - } - else { - fileUploadIframe(a); - } + } } - else if ((hasFileInputs || multipart) && fileAPI) { - fileUploadXhr(a); - } - else { - $.ajax(options); - } - // clear element array - for (var k=0; k < elements.length; k++) - elements[k] = null; + return baseUrl; + } - // fire 'notify' event - this.trigger('form-submit-notify', [this, options]); - return this; - - // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz) - function fileUploadXhr(a) { - var formdata = new FormData(); - - for (var i=0; i < a.length; i++) { - formdata.append(a[i].name, a[i].value); - } - - if (options.extraData) { - for (var p in options.extraData) - if (options.extraData.hasOwnProperty(p)) - formdata.append(p, options.extraData[p]); - } - - options.data = null; - - var s = $.extend(true, {}, $.ajaxSettings, options, { - contentType: false, - processData: false, - cache: false, - type: 'POST' - }); - - if (options.uploadProgress) { - // workaround because jqXHR does not expose upload property - s.xhr = function() { - var xhr = jQuery.ajaxSettings.xhr(); - if (xhr.upload) { - xhr.upload.onprogress = function(event) { - var percent = 0; - var position = event.loaded || event.position; /*event.position is deprecated*/ - var total = event.total; - if (event.lengthComputable) { - percent = Math.ceil(position / total * 100); - } - options.uploadProgress(event, position, total, percent); - }; - } - return xhr; - }; - } - - s.data = null; - var beforeSend = s.beforeSend; - s.beforeSend = function(xhr, o) { - o.data = formdata; - if(beforeSend) - beforeSend.call(o, xhr, options); - }; - $.ajax(s); - } - - // private function for handling file uploads (hat tip to YAHOO!) - function fileUploadIframe(a) { - var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle; - var useProp = !!$.fn.prop; - - if ($(':input[name=submit],:input[id=submit]', form).length) { - // if there is an input with a name or id of 'submit' then we won't be - // able to invoke the submit fn on the form (at least not x-browser) - alert('Error: Form elements must not have name or id of "submit".'); - return; - } - - if (a) { - // ensure that every serialized input is still enabled - for (i=0; i < elements.length; i++) { - el = $(elements[i]); - if ( useProp ) - el.prop('disabled', false); - else - el.removeAttr('disabled'); - } - } - - s = $.extend(true, {}, $.ajaxSettings, options); - s.context = s.context || s; - id = 'jqFormIO' + (new Date().getTime()); - if (s.iframeTarget) { - $io = $(s.iframeTarget); - n = $io.attr('name'); - if (!n) - $io.attr('name', id); - else - id = n; - } - else { - $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />'); - $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); - } - io = $io[0]; - - - xhr = { // mock object - aborted: 0, - responseText: null, - responseXML: null, - status: 0, - statusText: 'n/a', - getAllResponseHeaders: function() {}, - getResponseHeader: function() {}, - setRequestHeader: function() {}, - abort: function(status) { - var e = (status === 'timeout' ? 'timeout' : 'aborted'); - log('aborting upload... ' + e); - this.aborted = 1; - $io.attr('src', s.iframeSrc); // abort op in progress - xhr.error = e; - if (s.error) - s.error.call(s.context, xhr, e, status); - if (g) - $.event.trigger("ajaxError", [xhr, s, e]); - if (s.complete) - s.complete.call(s.context, xhr, e); - } - }; - - g = s.global; - // trigger ajax global events so that activity/block indicators work like normal - if (g && 0 === $.active++) { - $.event.trigger("ajaxStart"); - } - if (g) { - $.event.trigger("ajaxSend", [xhr, s]); - } - - if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) { - if (s.global) { - $.active--; - } - return; - } - if (xhr.aborted) { - return; - } - - // add submitting element to data if we know it - sub = form.clk; - if (sub) { - n = sub.name; - if (n && !sub.disabled) { - s.extraData = s.extraData || {}; - s.extraData[n] = sub.value; - if (sub.type == "image") { - s.extraData[n+'.x'] = form.clk_x; - s.extraData[n+'.y'] = form.clk_y; - } - } - } - - var CLIENT_TIMEOUT_ABORT = 1; - var SERVER_ABORT = 2; - - function getDoc(frame) { - var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document; - return doc; - } - - // Rails CSRF hack (thanks to Yvan Barthelemy) - var csrf_token = $('meta[name=csrf-token]').attr('content'); - var csrf_param = $('meta[name=csrf-param]').attr('content'); - if (csrf_param && csrf_token) { - s.extraData = s.extraData || {}; - s.extraData[csrf_param] = csrf_token; - } - - // take a breath so that pending repaints get some cpu time before the upload starts - function doSubmit() { - // make sure form attrs are set - var t = $form.attr('target'), a = $form.attr('action'); - - // update form attrs in IE friendly way - form.setAttribute('target',id); - if (!method) { - form.setAttribute('method', 'POST'); - } - if (a != s.url) { - form.setAttribute('action', s.url); - } - - // ie borks in some cases when setting encoding - if (! s.skipEncodingOverride && (!method || /post/i.test(method))) { - $form.attr({ - encoding: 'multipart/form-data', - enctype: 'multipart/form-data' - }); - } - - // support timout - if (s.timeout) { - timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout); - } - - // look for server aborts - function checkState() { - try { - var state = getDoc(io).readyState; - log('state = ' + state); - if (state && state.toLowerCase() == 'uninitialized') - setTimeout(checkState,50); - } - catch(e) { - log('Server abort: ' , e, ' (', e.name, ')'); - cb(SERVER_ABORT); - if (timeoutHandle) - clearTimeout(timeoutHandle); - timeoutHandle = undefined; - } - } - - // add "extra" data to form if provided in options - var extraInputs = []; - try { - if (s.extraData) { - for (var n in s.extraData) { - if (s.extraData.hasOwnProperty(n)) { - extraInputs.push( - $('<input type="hidden" name="'+n+'">').attr('value',s.extraData[n]) - .appendTo(form)[0]); - } - } - } - - if (!s.iframeTarget) { - // add iframe to doc and submit the form - $io.appendTo('body'); - if (io.attachEvent) - io.attachEvent('onload', cb); - else - io.addEventListener('load', cb, false); - } - setTimeout(checkState,15); - form.submit(); - } - finally { - // reset attrs and remove "extra" input elements - form.setAttribute('action',a); - if(t) { - form.setAttribute('target', t); - } else { - $form.removeAttr('target'); - } - $(extraInputs).remove(); - } - } - - if (s.forceSync) { - doSubmit(); - } - else { - setTimeout(doSubmit, 10); // this lets dom updates render - } - - var data, doc, domCheckCount = 50, callbackProcessed; - - function cb(e) { - if (xhr.aborted || callbackProcessed) { - return; - } - try { - doc = getDoc(io); - } - catch(ex) { - log('cannot access response document: ', ex); - e = SERVER_ABORT; - } - if (e === CLIENT_TIMEOUT_ABORT && xhr) { - xhr.abort('timeout'); - return; - } - else if (e == SERVER_ABORT && xhr) { - xhr.abort('server abort'); - return; - } - - if (!doc || doc.location.href == s.iframeSrc) { - // response not received yet - if (!timedOut) - return; - } - if (io.detachEvent) - io.detachEvent('onload', cb); - else - io.removeEventListener('load', cb, false); - - var status = 'success', errMsg; - try { - if (timedOut) { - throw 'timeout'; - } - - var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc); - log('isXml='+isXml); - if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) { - if (--domCheckCount) { - // in some browsers (Opera) the iframe DOM is not always traversable when - // the onload callback fires, so we loop a bit to accommodate - log('requeing onLoad callback, DOM not available'); - setTimeout(cb, 250); - return; - } - // let this fall through because server response could be an empty document - //log('Could not access iframe DOM after mutiple tries.'); - //throw 'DOMException: not available'; - } - - //log('response detected'); - var docRoot = doc.body ? doc.body : doc.documentElement; - xhr.responseText = docRoot ? docRoot.innerHTML : null; - xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; - if (isXml) - s.dataType = 'xml'; - xhr.getResponseHeader = function(header){ - var headers = {'content-type': s.dataType}; - return headers[header]; - }; - // support for XHR 'status' & 'statusText' emulation : - if (docRoot) { - xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status; - xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText; - } - - var dt = (s.dataType || '').toLowerCase(); - var scr = /(json|script|text)/.test(dt); - if (scr || s.textarea) { - // see if user embedded response in textarea - var ta = doc.getElementsByTagName('textarea')[0]; - if (ta) { - xhr.responseText = ta.value; - // support for XHR 'status' & 'statusText' emulation : - xhr.status = Number( ta.getAttribute('status') ) || xhr.status; - xhr.statusText = ta.getAttribute('statusText') || xhr.statusText; - } - else if (scr) { - // account for browsers injecting pre around json response - var pre = doc.getElementsByTagName('pre')[0]; - var b = doc.getElementsByTagName('body')[0]; - if (pre) { - xhr.responseText = pre.textContent ? pre.textContent : pre.innerText; - } - else if (b) { - xhr.responseText = b.textContent ? b.textContent : b.innerText; - } - } - } - else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) { - xhr.responseXML = toXml(xhr.responseText); - } - - try { - data = httpData(xhr, dt, s); - } - catch (e) { - status = 'parsererror'; - xhr.error = errMsg = (e || status); - } - } - catch (e) { - log('error caught: ',e); - status = 'error'; - xhr.error = errMsg = (e || status); - } - - if (xhr.aborted) { - log('upload aborted'); - status = null; - } - - if (xhr.status) { // we've set xhr.status - status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error'; - } - - // ordering of these callbacks/triggers is odd, but that's how $.ajax does it - if (status === 'success') { - if (s.success) - s.success.call(s.context, data, 'success', xhr); - if (g) - $.event.trigger("ajaxSuccess", [xhr, s]); - } - else if (status) { - if (errMsg === undefined) - errMsg = xhr.statusText; - if (s.error) - s.error.call(s.context, xhr, status, errMsg); - if (g) - $.event.trigger("ajaxError", [xhr, s, errMsg]); - } - - if (g) - $.event.trigger("ajaxComplete", [xhr, s]); - - if (g && ! --$.active) { - $.event.trigger("ajaxStop"); - } - - if (s.complete) - s.complete.call(s.context, xhr, status); - - callbackProcessed = true; - if (s.timeout) - clearTimeout(timeoutHandle); - - // clean up - setTimeout(function() { - if (!s.iframeTarget) - $io.remove(); - xhr.responseXML = null; - }, 100); - } - - var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+) - if (window.ActiveXObject) { - doc = new ActiveXObject('Microsoft.XMLDOM'); - doc.async = 'false'; - doc.loadXML(s); - } - else { - doc = (new DOMParser()).parseFromString(s, 'text/xml'); - } - return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null; - }; - var parseJSON = $.parseJSON || function(s) { - /*jslint evil:true */ - return window['eval']('(' + s + ')'); - }; - - var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4 - - var ct = xhr.getResponseHeader('content-type') || '', - xml = type === 'xml' || !type && ct.indexOf('xml') >= 0, - data = xml ? xhr.responseXML : xhr.responseText; - - if (xml && data.documentElement.nodeName === 'parsererror') { - if ($.error) - $.error('parsererror'); - } - if (s && s.dataFilter) { - data = s.dataFilter(data, type); - } - if (typeof data === 'string') { - if (type === 'json' || !type && ct.indexOf('json') >= 0) { - data = parseJSON(data); - } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) { - $.globalEval(data); - } - } - return data; - }; - } }; -/** - * ajaxForm() provides a mechanism for fully automating form submission. - * - * The advantages of using this method instead of ajaxSubmit() are: - * - * 1: This method will include coordinates for <input type="image" /> elements (if the element - * is used to submit the form). - * 2. This method will include the submit element's name/value data (for the element that was - * used to submit the form). - * 3. This method binds the submit() method to the form for you. - * - * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely - * passes the options argument along after properly binding events for submit elements and - * the form itself. - */ -$.fn.ajaxForm = function(options) { - options = options || {}; - options.delegation = options.delegation && $.isFunction($.fn.on); +$.fn.extend({ - // in jQuery 1.3+ we can fix mistakes with the ready state - if (!options.delegation && this.length === 0) { - var o = { s: this.selector, c: this.context }; - if (!$.isReady && o.s) { - log('DOM not ready, queuing ajaxForm'); - $(function() { - $(o.s,o.c).ajaxForm(options); - }); - return this; - } - // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready() - log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)')); - return this; - } + enableNavTabsFor: function(contentElement) { + var $container = $(this); - if ( options.delegation ) { - $(document) - .off('submit.form-plugin', this.selector, doAjaxSubmit) - .off('click.form-plugin', this.selector, captureSubmittingElement) - .on('submit.form-plugin', this.selector, options, doAjaxSubmit) - .on('click.form-plugin', this.selector, options, captureSubmittingElement); - return this; - } + $container.find("ul.nav-tabs a").click(function() { + $link = $(this); + $li = $link.parent(); - return this.ajaxFormUnbind() - .bind('submit.form-plugin', options, doAjaxSubmit) - .bind('click.form-plugin', options, captureSubmittingElement); -}; + $li.addClass("active").siblings().removeClass("active"); -// private event handlers -function doAjaxSubmit(e) { - /*jshint validthis:true */ - var options = e.data; - if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed - e.preventDefault(); - $(this).ajaxSubmit(options); - } -} + $container.find(contentElement).hide(); + $container.find(contentElement + "[ref=" + $link.attr("id") + "]").show(); + return false; + }); + }, -function captureSubmittingElement(e) { - /*jshint validthis:true */ - var target = e.target; - var $el = $(target); - if (!($el.is(":submit,input:image"))) { - // is this a child element of the submit el? (ex: a span within a button) - var t = $el.closest(':submit'); - if (t.length === 0) { - return; - } - target = t[0]; - } - var form = this; - form.clk = target; - if (target.type == 'image') { - if (e.offsetX !== undefined) { - form.clk_x = e.offsetX; - form.clk_y = e.offsetY; - } else if (typeof $.fn.offset == 'function') { - var offset = $el.offset(); - form.clk_x = e.pageX - offset.left; - form.clk_y = e.pageY - offset.top; - } else { - form.clk_x = e.pageX - target.offsetLeft; - form.clk_y = e.pageY - target.offsetTop; - } - } - // clear form vars - setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100); -} + showNavTab: function(name) { + $response = $(this); + $response.find("ul.nav-tabs li").removeClass("active"); + $response.find("ul.nav-tabs li a#response-" + name).parent().show().addClass("active"); + $response.find("pre").hide(); -// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm -$.fn.ajaxFormUnbind = function() { - return this.unbind('submit.form-plugin click.form-plugin'); -}; + return $response.find("pre[ref=response-" + name + "]").show(); + }, -/** - * formToArray() gathers form element data into an array of objects that can - * be passed to any of the following ajax functions: $.get, $.post, or load. - * Each object in the array has both a 'name' and 'value' property. An example of - * an array for a simple login form might be: - * - * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] - * - * It is this array that is passed to pre-submit callback functions provided to the - * ajaxSubmit() and ajaxForm() methods. - */ -$.fn.formToArray = function(semantic, elements) { - var a = []; - if (this.length === 0) { - return a; - } + displayOnlySelectedParamsFieldset: function() { + $("fieldset", this).hide(); + $("fieldset[ref=" + $("ul.nav-tabs li.active a").attr("id") + "]", this).show(); + } - var form = this[0]; - var els = semantic ? form.getElementsByTagName('*') : form.elements; - if (!els) { - return a; - } +}); - var i,j,n,v,el,max,jmax; - for(i=0, max=els.length; i < max; i++) { - el = els[i]; - n = el.name; - if (!n) { - continue; - } +jQuery(function($) { + $("#list-api-div a").click(function(e) { + e.preventDefault(); - if (semantic && form.clk && el.type == "image") { - // handle image inputs on the fly when semantic == true - if(!el.disabled && form.clk == el) { - a.push({name: n, value: $(el).val(), type: el.type }); - a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); - } - continue; - } + $(this).parent().siblings().removeClass("active"); + $(this).parent().addClass("active"); - v = $.fieldValue(el, true); - if (v && v.constructor == Array) { - if (elements) - elements.push(el); - for(j=0, jmax=v.length; j < jmax; j++) { - a.push({name: n, value: v[j]}); - } - } - else if (feature.fileapi && el.type == 'file' && !el.disabled) { - if (elements) - elements.push(el); - var files = el.files; - if (files.length) { - for (j=0; j < files.length; j++) { - a.push({name: n, value: files[j], type: el.type}); - } - } - else { - // #180 - a.push({ name: n, value: '', type: el.type }); - } - } - else if (v !== null && typeof v != 'undefined') { - if (elements) - elements.push(el); - a.push({name: n, value: v, type: el.type, required: el.required}); - } - } + $("#show-api-div .div-container").load(this.href, function() { + prettyPrint(); - if (!semantic && form.clk) { - // input type=='image' are not found in elements array! handle it here - var $input = $(form.clk), input = $input[0]; - n = input.name; - if (n && !input.disabled && input.type == 'image') { - a.push({name: n, value: $input.val()}); - a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); - } - } - return a; -}; + $("#show-api-div form").enableNavTabsFor("fieldset"); + $("#show-api-div form").displayOnlySelectedParamsFieldset(); -/** - * Serializes form data into a 'submittable' string. This method will return a string - * in the format: name1=value1&amp;name2=value2 - */ -$.fn.formSerialize = function(semantic) { - //hand off to jQuery.param for proper encoding - return $.param(this.formToArray(semantic)); -}; - -/** - * Serializes all field elements in the jQuery object into a query string. - * This method will return a string in the format: name1=value1&amp;name2=value2 - */ -$.fn.fieldSerialize = function(successful) { - var a = []; - this.each(function() { - var n = this.name; - if (!n) { - return; - } - var v = $.fieldValue(this, successful); - if (v && v.constructor == Array) { - for (var i=0,max=v.length; i < max; i++) { - a.push({name: n, value: v[i]}); - } - } - else if (v !== null && typeof v != 'undefined') { - a.push({name: this.name, value: v}); - } + $("#show-api-div form").submit(onSubmit); + $("#show-api-response-div").enableNavTabsFor("pre"); }); - //hand off to jQuery.param for proper encoding - return $.param(a); -}; + }); -/** - * Returns the value(s) of the element in the matched set. For example, consider the following form: - * - * <form><fieldset> - * <input name="A" type="text" /> - * <input name="A" type="text" /> - * <input name="B" type="checkbox" value="B1" /> - * <input name="B" type="checkbox" value="B2"/> - * <input name="C" type="radio" value="C1" /> - * <input name="C" type="radio" value="C2" /> - * </fieldset></form> - * - * var v = $(':text').fieldValue(); - * // if no values are entered into the text inputs - * v == ['',''] - * // if values entered into the text inputs are 'foo' and 'bar' - * v == ['foo','bar'] - * - * var v = $(':checkbox').fieldValue(); - * // if neither checkbox is checked - * v === undefined - * // if both checkboxes are checked - * v == ['B1', 'B2'] - * - * var v = $(':radio').fieldValue(); - * // if neither radio is checked - * v === undefined - * // if first radio is checked - * v == ['C1'] - * - * The successful argument controls whether or not the field element must be 'successful' - * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls). - * The default value of the successful argument is true. If this value is false the value(s) - * for each element is returned. - * - * Note: This method *always* returns an array. If no valid value can be determined the - * array will be empty, otherwise it will contain one or more values. - */ -$.fn.fieldValue = function(successful) { - for (var val=[], i=0, max=this.length; i < max; i++) { - var el = this[i]; - var v = $.fieldValue(el, successful); - if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) { - continue; - } - if (v.constructor == Array) - $.merge(val, v); - else - val.push(v); - } - return val; -}; + function onSubmit(e) { + $form = $(e.target); + ApiTaster.disableSubmitButton(); + ApiTaster.disableUrlParams(); -/** - * Returns the value of the field element. - */ -$.fieldValue = function(el, successful) { - var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); - if (successful === undefined) { - successful = true; - } + window.ajax = $.ajax({ + url: ApiTaster.getSubmitUrl($form), + type: $form.attr('method'), + data: $form.serialize(), + dataType: 'xml' + }).complete(onComplete); - if (successful && (!n || el.disabled || t == 'reset' || t == 'button' || - (t == 'checkbox' || t == 'radio') && !el.checked || - (t == 'submit' || t == 'image') && el.form && el.form.clk != el || - tag == 'select' && el.selectedIndex == -1)) { - return null; - } + ApiTaster.lastRequest = {}; + ApiTaster.lastRequest.startTime = Date.now(); - if (tag == 'select') { - var index = el.selectedIndex; - if (index < 0) { - return null; - } - var a = [], ops = el.options; - var one = (t == 'select-one'); - var max = (one ? index+1 : ops.length); - for(var i=(one ? index : 0); i < max; i++) { - var op = ops[i]; - if (op.selected) { - var v = op.value; - if (!v) { // extra pain for IE... - v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value; - } - if (one) { - return v; - } - a.push(v); - } - } - return a; - } - return $(el).val(); -}; + return false; + } -/** - * Clears the form data. Takes the following actions on the form's input fields: - * - input text fields will have their 'value' property set to the empty string - * - select elements will have their 'selectedIndex' property set to -1 - * - checkbox and radio inputs will have their 'checked' property set to false - * - inputs of type submit, button, reset, and hidden will *not* be effected - * - button elements will *not* be effected - */ -$.fn.clearForm = function(includeHidden) { - return this.each(function() { - $('input,select,textarea', this).clearFields(includeHidden); - }); -}; + function onComplete(xhr, status) { + ApiTaster.lastRequest.endTime = Date.now(); + ApiTaster.enableSubmitButton(); + ApiTaster.enableUrlParams(); -/** - * Clears the selected form elements. - */ -$.fn.clearFields = $.fn.clearInputs = function(includeHidden) { - var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list - return this.each(function() { - var t = this.type, tag = this.tagName.toLowerCase(); - if (re.test(t) || tag == 'textarea') { - this.value = ''; - } - else if (t == 'checkbox' || t == 'radio') { - this.checked = false; - } - else if (tag == 'select') { - this.selectedIndex = -1; - } - else if (includeHidden) { - // includeHidden can be the valud true, or it can be a selector string - // indicating a special test; for example: - // $('#myForm').clearForm('.special:hidden') - // the above would clean hidden inputs that have the class of 'special' - if ( (includeHidden === true && /hidden/.test(t)) || - (typeof includeHidden == 'string' && $(this).is(includeHidden)) ) - this.value = ''; - } - }); -}; - -/** - * Resets the form data. Causes all form elements to be reset to their original value. - */ -$.fn.resetForm = function() { - return this.each(function() { - // guard against an input with the name of 'reset' - // note that IE reports the reset function as an 'object' - if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) { - this.reset(); - } - }); -}; - -/** - * Enables or disables any matching elements. - */ -$.fn.enable = function(b) { - if (b === undefined) { - b = true; + if ($("#show-api-response-div:visible").length == 0) { + $("#show-api-response-div").slideDown(100); } - return this.each(function() { - this.disabled = !b; - }); -}; -/** - * Checks/unchecks any matching checkboxes or radio buttons and - * selects/deselects and matching option elements. - */ -$.fn.selected = function(select) { - if (select === undefined) { - select = true; - } - return this.each(function() { - var t = this.type; - if (t == 'checkbox' || t == 'radio') { - this.checked = select; - } - else if (this.tagName.toLowerCase() == 'option') { - var $sel = $(this).parent('select'); - if (select && $sel[0] && $sel[0].type == 'select-one') { - // deselect all other options - $sel.find('option').selected(false); - } - this.selected = select; - } - }); -}; + ApiTaster.fillInInfoTab( + $("#show-api-response-div").showNavTab("info"), + xhr + ); -// expose debug var -$.fn.ajaxSubmit.debug = false; - -// helper fn for console logging -function log() { - if (!$.fn.ajaxSubmit.debug) - return; - var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,''); - if (window.console && window.console.log) { - window.console.log(msg); + switch (ApiTaster.detectContentType(xhr)) { + case "json": + $("#show-api-response-div").showNavTab("json").text( + JSON.stringify(JSON.parse(xhr.responseText), null, 2) + ); + break; } - else if (window.opera && window.opera.postError) { - window.opera.postError(msg); - } -} -})(jQuery); -var ApiTaster = { + $("#show-api-response-div pre[ref=response-raw]").text(xhr.responseText); - formAction: '', - - disableSubmitButton: function() { - $("#submit-api").attr("disabled", true); - }, - - enableSubmitButton: function() { - $("#submit-api").attr("disabled", false); - }, - - disableUrlParams: function() { - $("fieldset[ref=url-params] input").prop("disabled", true); - }, - - enableUrlParams: function() { - $("fieldset[ref=url-params] input").prop("disabled", false); - }, - - storeFormActionFor: function(form) { - ApiTaster.formAction = form.attr("action") - }, - - restoreFormActionFor: function(form) { - $(form).attr("action", ApiTaster.formAction); - }, - - detectContentType: function(response) { - var contentType = response.getResponseHeader("Content-Type"); - var detectedContentType = null - - if (contentType.match(/application\/json/)) { - detectedContentType = 'json'; - } - - return detectedContentType; - } - -}; - -$.fn.extend({ - - replaceUrlParams: function(params) { - var form = this; - - ApiTaster.storeFormActionFor(form); - - var formAction = form.attr("action"); - - $.each(params, function(i, param) { - var matches = param["name"].match(/\[api_taster_url_params\](.*)/) - if (matches) { - var paramKey = matches[1]; - var paramValue = param["value"]; - var regex = new RegExp(":" + paramKey); - - formAction = formAction.replace(regex, paramValue); - } - }); - - form.attr("action", formAction); - }, - - enableNavTabsFor: function(contentElement) { - var container = this; - - $("ul.nav-tabs a", container).click(function(e) { - e.preventDefault(); - - $(this).parent().siblings().removeClass("active"); - $(this).parent().addClass("active"); - - $(contentElement, container).hide(); - $(contentElement + "[ref=" + $(this).attr("id") + "]", container).show(); - }); - }, - - showNavTab: function(name) { - $("ul.nav-tabs li", this).removeClass("active"); - $("ul.nav-tabs li a#response-" + name, this).parent().show().addClass("active"); - - $("pre", this).hide(); - - return $("pre[ref=response-" + name + "]", this).show(); - }, - - displayOnlySelectedParamsFieldset: function() { - $("fieldset", this).hide(); - $("fieldset[ref=" + $("ul.nav-tabs li.active a").attr("id") + "]", this).show(); - } - + prettyPrint(); + } }); - -jQuery(function($) { - $("#list-api-div a").click(function(e) { - e.preventDefault(); - - $(this).parent().siblings().removeClass("active"); - $(this).parent().addClass("active"); - - $("#show-api-div .div-container").load(this.href, function() { - prettyPrint(); - - $("#show-api-div form").enableNavTabsFor("fieldset"); - $("#show-api-div form").displayOnlySelectedParamsFieldset(); - }); - }); - - $("#show-api-div").on("click", "#submit-api", function() { - $(this).parents("form").submit(function() { - ApiTaster.disableSubmitButton(); - - $(this).unbind("submit").ajaxSubmit({ - beforeSubmit: function(arr, $form, options) { - $form.replaceUrlParams(arr); - ApiTaster.disableUrlParams(); - return false; - } - }); - }); - - $("form").bind("ajax:complete", function(e, xhr, status) { - ApiTaster.enableSubmitButton(); - ApiTaster.enableUrlParams(); - ApiTaster.restoreFormActionFor(this); - - if ($("#show-api-response-div:visible").length == 0) { - $("#show-api-response-div").slideDown(100); - } - - switch (ApiTaster.detectContentType(xhr)) { - case "json": - $("#show-api-response-div").showNavTab("json").text( - JSON.stringify(JSON.parse(xhr.responseText), null, 2) - ); - break; - } - - $("#show-api-response-div pre[ref=response-raw]").text(xhr.responseText); - - prettyPrint(); - }); - - $("#show-api-response-div").enableNavTabsFor("pre"); - }); -}); - // 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 vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. @@ -13200,7 +12465,8 @@ // + ; -;TI"required_assets_digest;F"%6047f327eeb973d7ab25edc109e93480I" _version;F"%9f3b95dd7ea3030dc35985c0a8020862 +;FI"required_assets_digest;F"%cd6a9f0ed6f455a72880fb5771a64d09I" _version;F"%9f3b95dd7ea3030dc35985c0a8020862 \ No newline at end of file