You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
7.5 KiB
JavaScript
289 lines
7.5 KiB
JavaScript
/*
|
|
* jQuery JSONP Core Plugin 2.3.1 (2012-05-16)
|
|
*
|
|
* https://github.com/jaubourg/jquery-jsonp
|
|
*
|
|
* Copyright (c) 2012 Julian Aubourg
|
|
*
|
|
* This document is licensed as free software under the terms of the
|
|
* MIT License: http://www.opensource.org/licenses/mit-license.php
|
|
*/
|
|
( function( $ ) {
|
|
|
|
// ###################### UTILITIES ##
|
|
|
|
// Noop
|
|
function noop() {
|
|
}
|
|
|
|
// Generic callback
|
|
function genericCallback( data ) {
|
|
lastValue = [ data ];
|
|
}
|
|
|
|
// Call if defined
|
|
function callIfDefined( method , object , parameters , returnFlag ) {
|
|
try {
|
|
returnFlag = method && method.apply( object.context || object , parameters );
|
|
} catch( _ ) {
|
|
returnFlag = !1;
|
|
}
|
|
return returnFlag;
|
|
}
|
|
|
|
// Give joining character given url
|
|
function qMarkOrAmp( url ) {
|
|
return /\?/ .test( url ) ? "&" : "?";
|
|
}
|
|
|
|
var // String constants (for better minification)
|
|
STR_ASYNC = "async",
|
|
STR_CHARSET = "charset",
|
|
STR_EMPTY = "",
|
|
STR_ERROR = "error",
|
|
STR_INSERT_BEFORE = "insertBefore",
|
|
STR_JQUERY_JSONP = "_jqjsp",
|
|
STR_ON = "on",
|
|
STR_ON_CLICK = STR_ON + "click",
|
|
STR_ON_ERROR = STR_ON + STR_ERROR,
|
|
STR_ON_LOAD = STR_ON + "load",
|
|
STR_ON_READY_STATE_CHANGE = STR_ON + "readystatechange",
|
|
STR_READY_STATE = "readyState",
|
|
STR_REMOVE_CHILD = "removeChild",
|
|
STR_SCRIPT_TAG = "<script>",
|
|
STR_SUCCESS = "success",
|
|
STR_TIMEOUT = "timeout",
|
|
|
|
// Window
|
|
win = window,
|
|
// Deferred
|
|
Deferred = $.Deferred,
|
|
// Head element
|
|
head = $( "head" )[ 0 ] || document.documentElement,
|
|
// Page cache
|
|
pageCache = {},
|
|
// Counter
|
|
count = 0,
|
|
// Last returned value
|
|
lastValue,
|
|
|
|
// ###################### DEFAULT OPTIONS ##
|
|
xOptionsDefaults = {
|
|
//beforeSend: undefined,
|
|
//cache: false,
|
|
callback: STR_JQUERY_JSONP,
|
|
//callbackParameter: undefined,
|
|
//charset: undefined,
|
|
//complete: undefined,
|
|
//context: undefined,
|
|
//data: "",
|
|
//dataFilter: undefined,
|
|
//error: undefined,
|
|
//pageCache: false,
|
|
//success: undefined,
|
|
//timeout: 0,
|
|
//traditional: false,
|
|
url: location.href
|
|
},
|
|
|
|
// opera demands sniffing :/
|
|
opera = win.opera;
|
|
|
|
// ###################### MAIN FUNCTION ##
|
|
function jsonp( xOptions ) {
|
|
|
|
// Build data with default
|
|
xOptions = $.extend( {} , xOptionsDefaults , xOptions );
|
|
|
|
// References to xOptions members (for better minification)
|
|
var successCallback = xOptions.success,
|
|
errorCallback = xOptions.error,
|
|
completeCallback = xOptions.complete,
|
|
dataFilter = xOptions.dataFilter,
|
|
callbackParameter = xOptions.callbackParameter,
|
|
successCallbackName = xOptions.callback,
|
|
cacheFlag = xOptions.cache,
|
|
pageCacheFlag = xOptions.pageCache,
|
|
charset = xOptions.charset,
|
|
url = xOptions.url,
|
|
data = xOptions.data,
|
|
timeout = xOptions.timeout,
|
|
pageCached,
|
|
|
|
// Abort/done flag
|
|
done = 0,
|
|
|
|
// Life-cycle functions
|
|
cleanUp = noop,
|
|
|
|
// Support vars
|
|
supportOnload,
|
|
supportOnreadystatechange,
|
|
|
|
// Request execution vars
|
|
firstChild,
|
|
script,
|
|
scriptAfter,
|
|
timeoutTimer;
|
|
|
|
// If we have Deferreds:
|
|
// - substitute callbacks
|
|
// - promote xOptions to a promise
|
|
Deferred && Deferred(function( defer ) {
|
|
defer.done( successCallback ).fail( errorCallback );
|
|
successCallback = defer.resolve;
|
|
errorCallback = defer.reject;
|
|
}).promise( xOptions );
|
|
|
|
// Create the abort method
|
|
xOptions.abort = function() {
|
|
!( done++ ) && cleanUp();
|
|
};
|
|
|
|
// Call beforeSend if provided (early abort if false returned)
|
|
if ( callIfDefined( xOptions.beforeSend, xOptions , [ xOptions ] ) === !1 || done ) {
|
|
return xOptions;
|
|
}
|
|
|
|
// Control entries
|
|
url = url || STR_EMPTY;
|
|
data = data ? ( (typeof data) == "string" ? data : $.param( data , xOptions.traditional ) ) : STR_EMPTY;
|
|
|
|
// Build final url
|
|
url += data ? ( qMarkOrAmp( url ) + data ) : STR_EMPTY;
|
|
|
|
// Add callback parameter if provided as option
|
|
callbackParameter && ( url += qMarkOrAmp( url ) + encodeURIComponent( callbackParameter ) + "=?" );
|
|
|
|
// Add anticache parameter if needed
|
|
!cacheFlag && !pageCacheFlag && ( url += qMarkOrAmp( url ) + "_" + ( new Date() ).getTime() + "=" );
|
|
|
|
// Replace last ? by callback parameter
|
|
url = url.replace( /=\?(&|$)/ , "=" + successCallbackName + "$1" );
|
|
|
|
// Success notifier
|
|
function notifySuccess( json ) {
|
|
|
|
if ( !( done++ ) ) {
|
|
|
|
cleanUp();
|
|
// Pagecache if needed
|
|
pageCacheFlag && ( pageCache [ url ] = { s: [ json ] } );
|
|
// Apply the data filter if provided
|
|
dataFilter && ( json = dataFilter.apply( xOptions , [ json ] ) );
|
|
// Call success then complete
|
|
callIfDefined( successCallback , xOptions , [ json , STR_SUCCESS ] );
|
|
callIfDefined( completeCallback , xOptions , [ xOptions , STR_SUCCESS ] );
|
|
|
|
}
|
|
}
|
|
|
|
// Error notifier
|
|
function notifyError( type ) {
|
|
|
|
if ( !( done++ ) ) {
|
|
|
|
// Clean up
|
|
cleanUp();
|
|
// If pure error (not timeout), cache if needed
|
|
pageCacheFlag && type != STR_TIMEOUT && ( pageCache[ url ] = type );
|
|
// Call error then complete
|
|
callIfDefined( errorCallback , xOptions , [ xOptions , type ] );
|
|
callIfDefined( completeCallback , xOptions , [ xOptions , type ] );
|
|
|
|
}
|
|
}
|
|
|
|
// Check page cache
|
|
if ( pageCacheFlag && ( pageCached = pageCache[ url ] ) ) {
|
|
|
|
pageCached.s ? notifySuccess( pageCached.s[ 0 ] ) : notifyError( pageCached );
|
|
|
|
} else {
|
|
|
|
// Install the generic callback
|
|
// (BEWARE: global namespace pollution ahoy)
|
|
win[ successCallbackName ] = genericCallback;
|
|
|
|
// Create the script tag
|
|
script = $( STR_SCRIPT_TAG )[ 0 ];
|
|
script.id = STR_JQUERY_JSONP + count++;
|
|
|
|
// Set charset if provided
|
|
if ( charset ) {
|
|
script[ STR_CHARSET ] = charset;
|
|
}
|
|
|
|
opera && opera.version() < 11.60 ?
|
|
// onerror is not supported: do not set as async and assume in-order execution.
|
|
// Add a trailing script to emulate the event
|
|
( ( scriptAfter = $( STR_SCRIPT_TAG )[ 0 ] ).text = "document.getElementById('" + script.id + "')." + STR_ON_ERROR + "()" )
|
|
:
|
|
// onerror is supported: set the script as async to avoid requests blocking each others
|
|
( script[ STR_ASYNC ] = STR_ASYNC )
|
|
|
|
;
|
|
|
|
// Internet Explorer: event/htmlFor trick
|
|
if ( STR_ON_READY_STATE_CHANGE in script ) {
|
|
|
|
script.htmlFor = script.id;
|
|
script.event = STR_ON_CLICK;
|
|
}
|
|
|
|
// Attached event handlers
|
|
script[ STR_ON_LOAD ] = script[ STR_ON_ERROR ] = script[ STR_ON_READY_STATE_CHANGE ] = function ( result ) {
|
|
|
|
// Test readyState if it exists
|
|
if ( !script[ STR_READY_STATE ] || !/i/.test( script[ STR_READY_STATE ] ) ) {
|
|
|
|
try {
|
|
|
|
script[ STR_ON_CLICK ] && script[ STR_ON_CLICK ]();
|
|
|
|
} catch( _ ) {}
|
|
|
|
result = lastValue;
|
|
lastValue = 0;
|
|
result ? notifySuccess( result[ 0 ] ) : notifyError( STR_ERROR );
|
|
|
|
}
|
|
};
|
|
|
|
// Set source
|
|
script.src = url;
|
|
|
|
// Re-declare cleanUp function
|
|
cleanUp = function( i ) {
|
|
timeoutTimer && clearTimeout( timeoutTimer );
|
|
script[ STR_ON_READY_STATE_CHANGE ] = script[ STR_ON_LOAD ] = script[ STR_ON_ERROR ] = null;
|
|
head[ STR_REMOVE_CHILD ]( script );
|
|
scriptAfter && head[ STR_REMOVE_CHILD ]( scriptAfter );
|
|
};
|
|
|
|
// Append main script
|
|
head[ STR_INSERT_BEFORE ]( script , ( firstChild = head.firstChild ) );
|
|
|
|
// Append trailing script if needed
|
|
scriptAfter && head[ STR_INSERT_BEFORE ]( scriptAfter , firstChild );
|
|
|
|
// If a timeout is needed, install it
|
|
timeoutTimer = timeout > 0 && setTimeout( function() {
|
|
notifyError( STR_TIMEOUT );
|
|
} , timeout );
|
|
|
|
}
|
|
|
|
return xOptions;
|
|
}
|
|
|
|
// ###################### SETUP FUNCTION ##
|
|
jsonp.setup = function( xOptions ) {
|
|
$.extend( xOptionsDefaults , xOptions );
|
|
};
|
|
|
|
// ###################### INSTALL in jQuery ##
|
|
$.jsonp = jsonp;
|
|
|
|
} )( jQuery );
|