").append( jQuery.parseHTML( responseText ) ).find( selector ) :
// Otherwise use the full result
responseText );
}).complete( callback && function( jqXHR, status ) {
self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
});
}
return this;
};
// Attach a bunch of functions for handling common AJAX events
jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
jQuery.fn[ type ] = function( fn ){
return this.on( type, fn );
};
});
jQuery.each( [ "get", "post" ], function( i, method ) {
jQuery[ method ] = function( url, data, callback, type ) {
// shift arguments if data argument was omitted
if ( jQuery.isFunction( data ) ) {
type = type || callback;
callback = data;
data = undefined;
}
return jQuery.ajax({
url: url,
type: method,
dataType: type,
data: data,
success: callback
});
};
});
jQuery.extend({
// Counter for holding the number of active queries
active: 0,
// Last-Modified header cache for next request
lastModified: {},
etag: {},
ajaxSettings: {
url: ajaxLocation,
type: "GET",
isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
global: true,
processData: true,
async: true,
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
/*
timeout: 0,
data: null,
dataType: null,
username: null,
password: null,
cache: null,
throws: false,
traditional: false,
headers: {},
*/
accepts: {
"*": allTypes,
text: "text/plain",
html: "text/html",
xml: "application/xml, text/xml",
json: "application/json, text/javascript"
},
contents: {
xml: /xml/,
html: /html/,
json: /json/
},
responseFields: {
xml: "responseXML",
text: "responseText"
},
// Data converters
// Keys separate source (or catchall "*") and destination types with a single space
converters: {
// Convert anything to text
"* text": window.String,
// Text to html (true = no transformation)
"text html": true,
// Evaluate text as a json expression
"text json": jQuery.parseJSON,
// Parse text as xml
"text xml": jQuery.parseXML
},
// For options that shouldn't be deep extended:
// you can add your own custom options here if
// and when you create one that shouldn't be
// deep extended (see ajaxExtend)
flatOptions: {
url: true,
context: true
}
},
// Creates a full fledged settings object into target
// with both ajaxSettings and settings fields.
// If target is omitted, writes into ajaxSettings.
ajaxSetup: function( target, settings ) {
return settings ?
// Building a settings object
ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
// Extending ajaxSettings
ajaxExtend( jQuery.ajaxSettings, target );
},
ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
ajaxTransport: addToPrefiltersOrTransports( transports ),
// Main method
ajax: function( url, options ) {
// If url is an object, simulate pre-1.5 signature
if ( typeof url === "object" ) {
options = url;
url = undefined;
}
// Force options to be an object
options = options || {};
var // Cross-domain detection vars
parts,
// Loop variable
i,
// URL without anti-cache param
cacheURL,
// Response headers as string
responseHeadersString,
// timeout handle
timeoutTimer,
// To know if global events are to be dispatched
fireGlobals,
transport,
// Response headers
responseHeaders,
// Create the final options object
s = jQuery.ajaxSetup( {}, options ),
// Callbacks context
callbackContext = s.context || s,
// Context for global events is callbackContext if it is a DOM node or jQuery collection
globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
jQuery( callbackContext ) :
jQuery.event,
// Deferreds
deferred = jQuery.Deferred(),
completeDeferred = jQuery.Callbacks("once memory"),
// Status-dependent callbacks
statusCode = s.statusCode || {},
// Headers (they are sent all at once)
requestHeaders = {},
requestHeadersNames = {},
// The jqXHR state
state = 0,
// Default abort message
strAbort = "canceled",
// Fake xhr
jqXHR = {
readyState: 0,
// Builds headers hashtable if needed
getResponseHeader: function( key ) {
var match;
if ( state === 2 ) {
if ( !responseHeaders ) {
responseHeaders = {};
while ( (match = rheaders.exec( responseHeadersString )) ) {
responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
}
}
match = responseHeaders[ key.toLowerCase() ];
}
return match == null ? null : match;
},
// Raw string
getAllResponseHeaders: function() {
return state === 2 ? responseHeadersString : null;
},
// Caches the header
setRequestHeader: function( name, value ) {
var lname = name.toLowerCase();
if ( !state ) {
name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
requestHeaders[ name ] = value;
}
return this;
},
// Overrides response content-type header
overrideMimeType: function( type ) {
if ( !state ) {
s.mimeType = type;
}
return this;
},
// Status-dependent callbacks
statusCode: function( map ) {
var code;
if ( map ) {
if ( state < 2 ) {
for ( code in map ) {
// Lazy-add the new callback in a way that preserves old ones
statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
}
} else {
// Execute the appropriate callbacks
jqXHR.always( map[ jqXHR.status ] );
}
}
return this;
},
// Cancel the request
abort: function( statusText ) {
var finalText = statusText || strAbort;
if ( transport ) {
transport.abort( finalText );
}
done( 0, finalText );
return this;
}
};
// Attach deferreds
deferred.promise( jqXHR ).complete = completeDeferred.add;
jqXHR.success = jqXHR.done;
jqXHR.error = jqXHR.fail;
// Remove hash character (#7531: and string promotion)
// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
// Handle falsy url in the settings object (#10093: consistency with old signature)
// We also use the url parameter if available
s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
// Alias method option to type as per ticket #12004
s.type = options.method || options.type || s.method || s.type;
// Extract dataTypes list
s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
// 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() );
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 );
}
// Apply prefilters
inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
// If request was aborted inside a prefilter, stop there
if ( state === 2 ) {
return jqXHR;
}
// We can fire global events as of now if asked to
fireGlobals = s.global;
// Watch for a new set of requests
if ( fireGlobals && jQuery.active++ === 0 ) {
jQuery.event.trigger("ajaxStart");
}
// Uppercase the type
s.type = s.type.toUpperCase();
// Determine if request has content
s.hasContent = !rnoContent.test( s.type );
// Save the URL in case we're toying with the If-Modified-Since
// and/or If-None-Match header later on
cacheURL = s.url;
// More options handling for requests with no content
if ( !s.hasContent ) {
// If data is available, append data to url
if ( s.data ) {
cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
// #9682: remove data so that it's not used in an eventual retry
delete s.data;
}
// Add anti-cache in url if needed
if ( s.cache === false ) {
s.url = rts.test( cacheURL ) ?
// If there is already a '_' parameter, set its value
cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
// Otherwise add one to the end
cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
}
}
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( s.ifModified ) {
if ( jQuery.lastModified[ cacheURL ] ) {
jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
}
if ( jQuery.etag[ cacheURL ] ) {
jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
}
}
// Set the correct header, if data is being sent
if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
jqXHR.setRequestHeader( "Content-Type", s.contentType );
}
// Set the Accepts header for the server, depending on the dataType
jqXHR.setRequestHeader(
"Accept",
s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
s.accepts[ "*" ]
);
// Check for headers option
for ( i in s.headers ) {
jqXHR.setRequestHeader( i, s.headers[ i ] );
}
// Allow custom headers/mimetypes and early abort
if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
// Abort if not done already and return
return jqXHR.abort();
}
// aborting is no longer a cancellation
strAbort = "abort";
// Install callbacks on deferreds
for ( i in { success: 1, error: 1, complete: 1 } ) {
jqXHR[ i ]( s[ i ] );
}
// Get transport
transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
// If no transport, we auto-abort
if ( !transport ) {
done( -1, "No Transport" );
} else {
jqXHR.readyState = 1;
// Send global event
if ( fireGlobals ) {
globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
}
// Timeout
if ( s.async && s.timeout > 0 ) {
timeoutTimer = setTimeout(function() {
jqXHR.abort("timeout");
}, s.timeout );
}
try {
state = 1;
transport.send( requestHeaders, done );
} catch ( e ) {
// Propagate exception as error if not done
if ( state < 2 ) {
done( -1, e );
// Simply rethrow otherwise
} else {
throw e;
}
}
}
// Callback for when everything is done
function done( status, nativeStatusText, responses, headers ) {
var isSuccess, success, error, response, modified,
statusText = nativeStatusText;
// Called once
if ( state === 2 ) {
return;
}
// State is "done" now
state = 2;
// Clear timeout if it exists
if ( timeoutTimer ) {
clearTimeout( timeoutTimer );
}
// Dereference transport for early garbage collection
// (no matter how long the jqXHR object will be used)
transport = undefined;
// Cache response headers
responseHeadersString = headers || "";
// Set readyState
jqXHR.readyState = status > 0 ? 4 : 0;
// Get response data
if ( responses ) {
response = ajaxHandleResponses( s, jqXHR, responses );
}
// If successful, handle type chaining
if ( status >= 200 && status < 300 || status === 304 ) {
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( s.ifModified ) {
modified = jqXHR.getResponseHeader("Last-Modified");
if ( modified ) {
jQuery.lastModified[ cacheURL ] = modified;
}
modified = jqXHR.getResponseHeader("etag");
if ( modified ) {
jQuery.etag[ cacheURL ] = modified;
}
}
// if no content
if ( status === 204 ) {
isSuccess = true;
statusText = "nocontent";
// if not modified
} else if ( status === 304 ) {
isSuccess = true;
statusText = "notmodified";
// If we have data, let's convert it
} else {
isSuccess = ajaxConvert( s, response );
statusText = isSuccess.state;
success = isSuccess.data;
error = isSuccess.error;
isSuccess = !error;
}
} else {
// We extract error from statusText
// then normalize statusText and status for non-aborts
error = statusText;
if ( status || !statusText ) {
statusText = "error";
if ( status < 0 ) {
status = 0;
}
}
}
// Set data for the fake xhr object
jqXHR.status = status;
jqXHR.statusText = ( nativeStatusText || statusText ) + "";
// Success/Error
if ( isSuccess ) {
deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
} else {
deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
}
// Status-dependent callbacks
jqXHR.statusCode( statusCode );
statusCode = undefined;
if ( fireGlobals ) {
globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
[ jqXHR, s, isSuccess ? success : error ] );
}
// Complete
completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
if ( fireGlobals ) {
globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
// Handle the global AJAX counter
if ( !( --jQuery.active ) ) {
jQuery.event.trigger("ajaxStop");
}
}
}
return jqXHR;
},
getScript: function( url, callback ) {
return jQuery.get( url, undefined, callback, "script" );
},
getJSON: function( url, data, callback ) {
return jQuery.get( url, data, callback, "json" );
}
});
/* Handles responses to an ajax request:
* - sets all responseXXX fields accordingly
* - finds the right dataType (mediates between content-type and expected dataType)
* - returns the corresponding response
*/
function ajaxHandleResponses( s, jqXHR, responses ) {
var firstDataType, ct, finalDataType, type,
contents = s.contents,
dataTypes = s.dataTypes,
responseFields = s.responseFields;
// Fill responseXXX fields
for ( type in responseFields ) {
if ( type in responses ) {
jqXHR[ responseFields[type] ] = responses[ type ];
}
}
// Remove auto dataType and get content-type in the process
while( dataTypes[ 0 ] === "*" ) {
dataTypes.shift();
if ( ct === undefined ) {
ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
}
}
// Check if we're dealing with a known content-type
if ( ct ) {
for ( type in contents ) {
if ( contents[ type ] && contents[ type ].test( ct ) ) {
dataTypes.unshift( type );
break;
}
}
}
// Check to see if we have a response for the expected dataType
if ( dataTypes[ 0 ] in responses ) {
finalDataType = dataTypes[ 0 ];
} else {
// Try convertible dataTypes
for ( type in responses ) {
if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
finalDataType = type;
break;
}
if ( !firstDataType ) {
firstDataType = type;
}
}
// Or just use first one
finalDataType = finalDataType || firstDataType;
}
// If we found a dataType
// We add the dataType to the list if needed
// and return the corresponding response
if ( finalDataType ) {
if ( finalDataType !== dataTypes[ 0 ] ) {
dataTypes.unshift( finalDataType );
}
return responses[ finalDataType ];
}
}
// Chain conversions given the request and the original response
function ajaxConvert( s, response ) {
var conv2, current, conv, tmp,
converters = {},
i = 0,
// Work with a copy of dataTypes in case we need to modify it for conversion
dataTypes = s.dataTypes.slice(),
prev = dataTypes[ 0 ];
// Apply the dataFilter if provided
if ( s.dataFilter ) {
response = s.dataFilter( response, s.dataType );
}
// Create converters map with lowercased keys
if ( dataTypes[ 1 ] ) {
for ( conv in s.converters ) {
converters[ conv.toLowerCase() ] = s.converters[ conv ];
}
}
// Convert to each sequential dataType, tolerating list modification
for ( ; (current = dataTypes[++i]); ) {
// There's only work to do if current dataType is non-auto
if ( current !== "*" ) {
// Convert response if prev dataType is non-auto and differs from current
if ( prev !== "*" && prev !== current ) {
// Seek a direct converter
conv = converters[ prev + " " + current ] || converters[ "* " + current ];
// If none found, seek a pair
if ( !conv ) {
for ( conv2 in converters ) {
// If conv2 outputs current
tmp = conv2.split(" ");
if ( tmp[ 1 ] === current ) {
// If prev can be converted to accepted input
conv = converters[ prev + " " + tmp[ 0 ] ] ||
converters[ "* " + tmp[ 0 ] ];
if ( conv ) {
// Condense equivalence converters
if ( conv === true ) {
conv = converters[ conv2 ];
// Otherwise, insert the intermediate dataType
} else if ( converters[ conv2 ] !== true ) {
current = tmp[ 0 ];
dataTypes.splice( i--, 0, current );
}
break;
}
}
}
}
// Apply converter (if not an equivalence)
if ( conv !== true ) {
// Unless errors are allowed to bubble, catch and return them
if ( conv && s["throws"] ) {
response = conv( response );
} else {
try {
response = conv( response );
} catch ( e ) {
return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
}
}
}
}
// Update prev for next iteration
prev = current;
}
}
return { state: "success", data: response };
}
// Install script dataType
jQuery.ajaxSetup({
accepts: {
script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
},
contents: {
script: /(?:java|ecma)script/
},
converters: {
"text script": function( text ) {
jQuery.globalEval( text );
return text;
}
}
});
// Handle cache's special case and global
jQuery.ajaxPrefilter( "script", function( s ) {
if ( s.cache === undefined ) {
s.cache = false;
}
if ( s.crossDomain ) {
s.type = "GET";
s.global = false;
}
});
// Bind script tag hack transport
jQuery.ajaxTransport( "script", function(s) {
// This transport only deals with cross domain requests
if ( s.crossDomain ) {
var script,
head = document.head || jQuery("head")[0] || document.documentElement;
return {
send: function( _, callback ) {
script = document.createElement("script");
script.async = true;
if ( s.scriptCharset ) {
script.charset = s.scriptCharset;
}
script.src = s.url;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function( _, isAbort ) {
if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
// Remove the script
if ( script.parentNode ) {
script.parentNode.removeChild( script );
}
// Dereference the script
script = null;
// Callback if not abort
if ( !isAbort ) {
callback( 200, "success" );
}
}
};
// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
// Use native DOM manipulation to avoid our domManip AJAX trickery
head.insertBefore( script, head.firstChild );
},
abort: function() {
if ( script ) {
script.onload( undefined, true );
}
}
};
}
});
var oldCallbacks = [],
rjsonp = /(=)\?(?=&|$)|\?\?/;
// Default jsonp settings
jQuery.ajaxSetup({
jsonp: "callback",
jsonpCallback: function() {
var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
this[ callback ] = true;
return callback;
}
});
// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
var callbackName, overwritten, responseContainer,
jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
"url" :
typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
);
// Handle iff the expected data type is "jsonp" or we have a parameter to set
if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
// Get callback name, remembering preexisting value associated with it
callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
s.jsonpCallback() :
s.jsonpCallback;
// Insert callback into url or form data
if ( jsonProp ) {
s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
} else if ( s.jsonp !== false ) {
s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
}
// Use data converter to retrieve json after script execution
s.converters["script json"] = function() {
if ( !responseContainer ) {
jQuery.error( callbackName + " was not called" );
}
return responseContainer[ 0 ];
};
// force json dataType
s.dataTypes[ 0 ] = "json";
// Install callback
overwritten = window[ callbackName ];
window[ callbackName ] = function() {
responseContainer = arguments;
};
// Clean-up function (fires after converters)
jqXHR.always(function() {
// Restore preexisting value
window[ callbackName ] = overwritten;
// Save back as free
if ( s[ callbackName ] ) {
// make sure that re-using the options doesn't screw things around
s.jsonpCallback = originalSettings.jsonpCallback;
// save the callback name for future use
oldCallbacks.push( callbackName );
}
// Call if it was a function and we have a response
if ( responseContainer && jQuery.isFunction( overwritten ) ) {
overwritten( responseContainer[ 0 ] );
}
responseContainer = overwritten = undefined;
});
// Delegate to script
return "script";
}
});
var xhrCallbacks, xhrSupported,
xhrId = 0,
// #5280: Internet Explorer will keep connections alive if we don't abort on unload
xhrOnUnloadAbort = window.ActiveXObject && function() {
// Abort all pending requests
var key;
for ( key in xhrCallbacks ) {
xhrCallbacks[ key ]( undefined, true );
}
};
// Functions to create xhrs
function createStandardXHR() {
try {
return new window.XMLHttpRequest();
} catch( e ) {}
}
function createActiveXHR() {
try {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} catch( e ) {}
}
// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
/* Microsoft failed to properly
* implement the XMLHttpRequest in IE7 (can't request local files),
* so we use the ActiveXObject when it is available
* Additionally XMLHttpRequest can be disabled in IE7/IE8 so
* we need a fallback.
*/
function() {
return !this.isLocal && createStandardXHR() || createActiveXHR();
} :
// For all other browsers, use the standard XMLHttpRequest object
createStandardXHR;
// Determine support properties
xhrSupported = jQuery.ajaxSettings.xhr();
jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
xhrSupported = jQuery.support.ajax = !!xhrSupported;
// Create transport if the browser can provide an xhr
if ( xhrSupported ) {
jQuery.ajaxTransport(function( s ) {
// Cross domain only allowed if supported through XMLHttpRequest
if ( !s.crossDomain || jQuery.support.cors ) {
var callback;
return {
send: function( headers, complete ) {
// Get a new xhr
var handle, i,
xhr = s.xhr();
// Open the socket
// Passing null username, generates a login popup on Opera (#2865)
if ( s.username ) {
xhr.open( s.type, s.url, s.async, s.username, s.password );
} else {
xhr.open( s.type, s.url, s.async );
}
// Apply custom fields if provided
if ( s.xhrFields ) {
for ( i in s.xhrFields ) {
xhr[ i ] = s.xhrFields[ i ];
}
}
// Override mime type if needed
if ( s.mimeType && xhr.overrideMimeType ) {
xhr.overrideMimeType( s.mimeType );
}
// X-Requested-With header
// For cross-domain requests, seeing as conditions for a preflight are
// akin to a jigsaw puzzle, we simply never set it to be sure.
// (it can always be set on a per-request basis or even using ajaxSetup)
// For same-domain requests, won't change header if already provided.
if ( !s.crossDomain && !headers["X-Requested-With"] ) {
headers["X-Requested-With"] = "XMLHttpRequest";
}
// Need an extra try/catch for cross domain requests in Firefox 3
try {
for ( i in headers ) {
xhr.setRequestHeader( i, headers[ i ] );
}
} catch( err ) {}
// Do send the request
// This may raise an exception which is actually
// handled in jQuery.ajax (so no try/catch here)
xhr.send( ( s.hasContent && s.data ) || null );
// Listener
callback = function( _, isAbort ) {
var status, responseHeaders, statusText, responses;
// Firefox throws exceptions when accessing properties
// of an xhr when a network error occurred
// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
try {
// Was never called and is aborted or complete
if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
// Only called once
callback = undefined;
// Do not keep as active anymore
if ( handle ) {
xhr.onreadystatechange = jQuery.noop;
if ( xhrOnUnloadAbort ) {
delete xhrCallbacks[ handle ];
}
}
// If it's an abort
if ( isAbort ) {
// Abort it manually if needed
if ( xhr.readyState !== 4 ) {
xhr.abort();
}
} else {
responses = {};
status = xhr.status;
responseHeaders = xhr.getAllResponseHeaders();
// When requesting binary data, IE6-9 will throw an exception
// on any attempt to access responseText (#11426)
if ( typeof xhr.responseText === "string" ) {
responses.text = xhr.responseText;
}
// Firefox throws an exception when accessing
// statusText for faulty cross-domain requests
try {
statusText = xhr.statusText;
} catch( e ) {
// We normalize with Webkit giving an empty statusText
statusText = "";
}
// Filter status for non standard behaviors
// If the request is local and we have data: assume a success
// (success with no data won't get notified, that's the best we
// can do given current implementations)
if ( !status && s.isLocal && !s.crossDomain ) {
status = responses.text ? 200 : 404;
// IE - #1450: sometimes returns 1223 when it should be 204
} else if ( status === 1223 ) {
status = 204;
}
}
}
} catch( firefoxAccessException ) {
if ( !isAbort ) {
complete( -1, firefoxAccessException );
}
}
// Call complete if needed
if ( responses ) {
complete( status, statusText, responses, responseHeaders );
}
};
if ( !s.async ) {
// if we're in sync mode we fire the callback
callback();
} else if ( xhr.readyState === 4 ) {
// (IE6 & IE7) if it's in cache and has been
// retrieved directly we need to fire the callback
setTimeout( callback );
} else {
handle = ++xhrId;
if ( xhrOnUnloadAbort ) {
// Create the active xhrs callbacks list if needed
// and attach the unload handler
if ( !xhrCallbacks ) {
xhrCallbacks = {};
jQuery( window ).unload( xhrOnUnloadAbort );
}
// Add to list of active xhrs callbacks
xhrCallbacks[ handle ] = callback;
}
xhr.onreadystatechange = callback;
}
},
abort: function() {
if ( callback ) {
callback( undefined, true );
}
}
};
}
});
}
var fxNow, timerId,
rfxtypes = /^(?:toggle|show|hide)$/,
rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
rrun = /queueHooks$/,
animationPrefilters = [ defaultPrefilter ],
tweeners = {
"*": [function( prop, value ) {
var end, unit,
tween = this.createTween( prop, value ),
parts = rfxnum.exec( value ),
target = tween.cur(),
start = +target || 0,
scale = 1,
maxIterations = 20;
if ( parts ) {
end = +parts[2];
unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
// We need to compute starting value
if ( unit !== "px" && start ) {
// Iteratively approximate from a nonzero starting point
// Prefer the current property, because this process will be trivial if it uses the same units
// Fallback to end or a simple constant
start = jQuery.css( tween.elem, prop, true ) || end || 1;
do {
// If previous iteration zeroed out, double until we get *something*
// Use a string for doubling factor so we don't accidentally see scale as unchanged below
scale = scale || ".5";
// Adjust and apply
start = start / scale;
jQuery.style( tween.elem, prop, start + unit );
// Update scale, tolerating zero or NaN from tween.cur()
// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
}
tween.unit = unit;
tween.start = start;
// If a +=/-= token was provided, we're doing a relative animation
tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
}
return tween;
}]
};
// Animations created synchronously will run synchronously
function createFxNow() {
setTimeout(function() {
fxNow = undefined;
});
return ( fxNow = jQuery.now() );
}
function createTweens( animation, props ) {
jQuery.each( props, function( prop, value ) {
var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
index = 0,
length = collection.length;
for ( ; index < length; index++ ) {
if ( collection[ index ].call( animation, prop, value ) ) {
// we're done with this property
return;
}
}
});
}
function Animation( elem, properties, options ) {
var result,
stopped,
index = 0,
length = animationPrefilters.length,
deferred = jQuery.Deferred().always( function() {
// don't match elem in the :animated selector
delete tick.elem;
}),
tick = function() {
if ( stopped ) {
return false;
}
var currentTime = fxNow || createFxNow(),
remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
// 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 );
}
deferred.notifyWith( elem, [ animation, percent, remaining ]);
if ( percent < 1 && length ) {
return remaining;
} else {
deferred.resolveWith( elem, [ animation ] );
return false;
}
},
animation = deferred.promise({
elem: elem,
props: jQuery.extend( {}, properties ),
opts: jQuery.extend( true, { specialEasing: {} }, options ),
originalProperties: properties,
originalOptions: options,
startTime: fxNow || createFxNow(),
duration: options.duration,
tweens: [],
createTween: function( prop, end ) {
var tween = jQuery.Tween( elem, animation.opts, prop, end,
animation.opts.specialEasing[ prop ] || animation.opts.easing );
animation.tweens.push( tween );
return tween;
},
stop: function( gotoEnd ) {
var index = 0,
// if we are going to the end, we want to run all the tweens
// otherwise we skip this part
length = gotoEnd ? animation.tweens.length : 0;
if ( stopped ) {
return this;
}
stopped = true;
for ( ; index < length ; index++ ) {
animation.tweens[ index ].run( 1 );
}
// resolve when we played the last frame
// otherwise, reject
if ( gotoEnd ) {
deferred.resolveWith( elem, [ animation, gotoEnd ] );
} else {
deferred.rejectWith( elem, [ animation, gotoEnd ] );
}
return this;
}
}),
props = animation.props;
propFilter( props, animation.opts.specialEasing );
for ( ; index < length ; index++ ) {
result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
if ( result ) {
return result;
}
}
createTweens( animation, props );
if ( jQuery.isFunction( animation.opts.start ) ) {
animation.opts.start.call( elem, animation );
}
jQuery.fx.timer(
jQuery.extend( tick, {
elem: elem,
anim: animation,
queue: animation.opts.queue
})
);
// attach callbacks from options
return animation.progress( animation.opts.progress )
.done( animation.opts.done, animation.opts.complete )
.fail( animation.opts.fail )
.always( animation.opts.always );
}
function propFilter( props, specialEasing ) {
var value, name, index, easing, hooks;
// camelCase, specialEasing and expand cssHook pass
for ( index in props ) {
name = jQuery.camelCase( index );
easing = specialEasing[ name ];
value = props[ index ];
if ( jQuery.isArray( value ) ) {
easing = value[ 1 ];
value = props[ index ] = value[ 0 ];
}
if ( index !== name ) {
props[ name ] = value;
delete props[ index ];
}
hooks = jQuery.cssHooks[ name ];
if ( hooks && "expand" in hooks ) {
value = hooks.expand( value );
delete props[ name ];
// not quite $.extend, this wont overwrite keys already present.
// also - reusing 'index' from above because we have the correct "name"
for ( index in value ) {
if ( !( index in props ) ) {
props[ index ] = value[ index ];
specialEasing[ index ] = easing;
}
}
} else {
specialEasing[ name ] = easing;
}
}
}
jQuery.Animation = jQuery.extend( Animation, {
tweener: function( props, callback ) {
if ( jQuery.isFunction( props ) ) {
callback = props;
props = [ "*" ];
} else {
props = props.split(" ");
}
var prop,
index = 0,
length = props.length;
for ( ; index < length ; index++ ) {
prop = props[ index ];
tweeners[ prop ] = tweeners[ prop ] || [];
tweeners[ prop ].unshift( callback );
}
},
prefilter: function( callback, prepend ) {
if ( prepend ) {
animationPrefilters.unshift( callback );
} else {
animationPrefilters.push( callback );
}
}
});
function defaultPrefilter( elem, props, opts ) {
/*jshint validthis:true */
var prop, index, length,
value, dataShow, toggle,
tween, hooks, oldfire,
anim = this,
style = elem.style,
orig = {},
handled = [],
hidden = elem.nodeType && isHidden( elem );
// handle queue: false promises
if ( !opts.queue ) {
hooks = jQuery._queueHooks( elem, "fx" );
if ( hooks.unqueued == null ) {
hooks.unqueued = 0;
oldfire = hooks.empty.fire;
hooks.empty.fire = function() {
if ( !hooks.unqueued ) {
oldfire();
}
};
}
hooks.unqueued++;
anim.always(function() {
// doing this makes sure that the complete handler will be called
// before this completes
anim.always(function() {
hooks.unqueued--;
if ( !jQuery.queue( elem, "fx" ).length ) {
hooks.empty.fire();
}
});
});
}
// height/width overflow pass
if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
// Make sure that nothing sneaks out
// Record all 3 overflow attributes because IE does not
// change the overflow attribute when overflowX and
// overflowY are set to the same value
opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
// Set display property to inline-block for height/width
// animations on inline elements that are having width/height animated
if ( jQuery.css( elem, "display" ) === "inline" &&
jQuery.css( elem, "float" ) === "none" ) {
// inline-level elements accept inline-block;
// block-level elements need to be inline with layout
if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
style.display = "inline-block";
} else {
style.zoom = 1;
}
}
}
if ( opts.overflow ) {
style.overflow = "hidden";
if ( !jQuery.support.shrinkWrapBlocks ) {
anim.always(function() {
style.overflow = opts.overflow[ 0 ];
style.overflowX = opts.overflow[ 1 ];
style.overflowY = opts.overflow[ 2 ];
});
}
}
// 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();
});
}
anim.done(function() {
var prop;
jQuery._removeData( elem, "fxshow" );
for ( prop in orig ) {
jQuery.style( elem, prop, orig[ prop ] );
}
});
for ( index = 0 ; index < length ; index++ ) {
prop = handled[ index ];
tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
if ( !( prop in dataShow ) ) {
dataShow[ prop ] = tween.start;
if ( hidden ) {
tween.end = tween.start;
tween.start = prop === "width" || prop === "height" ? 1 : 0;
}
}
}
}
}
function Tween( elem, options, prop, end, easing ) {
return new Tween.prototype.init( elem, options, prop, end, easing );
}
jQuery.Tween = Tween;
Tween.prototype = {
constructor: Tween,
init: function( elem, options, prop, end, easing, unit ) {
this.elem = elem;
this.prop = prop;
this.easing = easing || "swing";
this.options = options;
this.start = this.now = this.cur();
this.end = end;
this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
},
cur: function() {
var hooks = Tween.propHooks[ this.prop ];
return hooks && hooks.get ?
hooks.get( this ) :
Tween.propHooks._default.get( this );
},
run: function( percent ) {
var eased,
hooks = Tween.propHooks[ this.prop ];
if ( this.options.duration ) {
this.pos = eased = jQuery.easing[ this.easing ](
percent, this.options.duration * percent, 0, 1, this.options.duration
);
} else {
this.pos = eased = percent;
}
this.now = ( this.end - this.start ) * eased + this.start;
if ( this.options.step ) {
this.options.step.call( this.elem, this.now, this );
}
if ( hooks && hooks.set ) {
hooks.set( this );
} else {
Tween.propHooks._default.set( this );
}
return this;
}
};
Tween.prototype.init.prototype = Tween.prototype;
Tween.propHooks = {
_default: {
get: function( tween ) {
var result;
if ( tween.elem[ tween.prop ] != null &&
(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
return tween.elem[ tween.prop ];
}
// passing an empty string as a 3rd parameter to .css will automatically
// attempt a parseFloat and fallback to a string if the parse fails
// so, simple values such as "10px" are parsed to Float.
// complex values such as "rotate(1rad)" are returned as is.
result = jQuery.css( tween.elem, tween.prop, "" );
// Empty strings, null, undefined and "auto" are converted to 0.
return !result || result === "auto" ? 0 : result;
},
set: function( tween ) {
// use step hook for back compat - use cssHook if its there - use .style if its
// available and use plain properties where available
if ( jQuery.fx.step[ tween.prop ] ) {
jQuery.fx.step[ tween.prop ]( tween );
} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
} else {
tween.elem[ tween.prop ] = tween.now;
}
}
}
};
// Remove in 2.0 - this supports IE8's panic based approach
// to setting things on disconnected nodes
Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
set: function( tween ) {
if ( tween.elem.nodeType && tween.elem.parentNode ) {
tween.elem[ tween.prop ] = tween.now;
}
}
};
jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
var cssFn = jQuery.fn[ name ];
jQuery.fn[ name ] = function( speed, easing, callback ) {
return speed == null || typeof speed === "boolean" ?
cssFn.apply( this, arguments ) :
this.animate( genFx( name, true ), speed, easing, callback );
};
});
jQuery.fn.extend({
fadeTo: function( speed, to, easing, callback ) {
// show any hidden elements after setting opacity to 0
return this.filter( isHidden ).css( "opacity", 0 ).show()
// animate to the value specified
.end().animate({ opacity: to }, speed, easing, callback );
},
animate: function( prop, speed, easing, callback ) {
var empty = jQuery.isEmptyObject( prop ),
optall = jQuery.speed( speed, easing, callback ),
doAnimation = function() {
// Operate on a copy of prop so per-property easing won't be lost
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
doAnimation.finish = function() {
anim.stop( true );
};
// Empty animations, or finishing resolves immediately
if ( empty || jQuery._data( this, "finish" ) ) {
anim.stop( true );
}
};
doAnimation.finish = doAnimation;
return empty || optall.queue === false ?
this.each( doAnimation ) :
this.queue( optall.queue, doAnimation );
},
stop: function( type, clearQueue, gotoEnd ) {
var stopQueue = function( hooks ) {
var stop = hooks.stop;
delete hooks.stop;
stop( gotoEnd );
};
if ( typeof type !== "string" ) {
gotoEnd = clearQueue;
clearQueue = type;
type = undefined;
}
if ( clearQueue && type !== false ) {
this.queue( type || "fx", [] );
}
return this.each(function() {
var dequeue = true,
index = type != null && type + "queueHooks",
timers = jQuery.timers,
data = jQuery._data( this );
if ( index ) {
if ( data[ index ] && data[ index ].stop ) {
stopQueue( data[ index ] );
}
} else {
for ( index in data ) {
if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
stopQueue( data[ index ] );
}
}
}
for ( index = timers.length; index--; ) {
if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
timers[ index ].anim.stop( gotoEnd );
dequeue = false;
timers.splice( index, 1 );
}
}
// start the next in the queue if the last step wasn't forced
// timers currently will call their complete callbacks, which will dequeue
// but only if they were gotoEnd
if ( dequeue || !gotoEnd ) {
jQuery.dequeue( this, type );
}
});
},
finish: function( type ) {
if ( type !== false ) {
type = type || "fx";
}
return this.each(function() {
var index,
data = jQuery._data( this ),
queue = data[ type + "queue" ],
hooks = data[ type + "queueHooks" ],
timers = jQuery.timers,
length = queue ? queue.length : 0;
// enable finishing flag on private data
data.finish = true;
// empty the queue first
jQuery.queue( this, type, [] );
if ( hooks && hooks.cur && hooks.cur.finish ) {
hooks.cur.finish.call( this );
}
// look for any active animations, and finish them
for ( index = timers.length; index--; ) {
if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
timers[ index ].anim.stop( true );
timers.splice( index, 1 );
}
}
// look for any animations in the old queue and finish them
for ( index = 0; index < length; index++ ) {
if ( queue[ index ] && queue[ index ].finish ) {
queue[ index ].finish.call( this );
}
}
// turn off finishing flag
delete data.finish;
});
}
});
// Generate parameters to create a standard animation
function genFx( type, includeWidth ) {
var which,
attrs = { height: type },
i = 0;
// if we include width, step value is 1 to do all cssExpand values,
// if we don't include width, step value is 2 to skip over Left and Right
includeWidth = includeWidth? 1 : 0;
for( ; i < 4 ; i += 2 - includeWidth ) {
which = cssExpand[ i ];
attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
}
if ( includeWidth ) {
attrs.opacity = attrs.width = type;
}
return attrs;
}
// Generate shortcuts for custom animations
jQuery.each({
slideDown: genFx("show"),
slideUp: genFx("hide"),
slideToggle: genFx("toggle"),
fadeIn: { opacity: "show" },
fadeOut: { opacity: "hide" },
fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
jQuery.fn[ name ] = function( speed, easing, callback ) {
return this.animate( props, speed, easing, callback );
};
});
jQuery.speed = function( speed, easing, fn ) {
var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
complete: fn || !fn && easing ||
jQuery.isFunction( speed ) && speed,
duration: speed,
easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
};
opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
// normalize opt.queue - true/undefined/null -> "fx"
if ( opt.queue == null || opt.queue === true ) {
opt.queue = "fx";
}
// Queueing
opt.old = opt.complete;
opt.complete = function() {
if ( jQuery.isFunction( opt.old ) ) {
opt.old.call( this );
}
if ( opt.queue ) {
jQuery.dequeue( this, opt.queue );
}
};
return opt;
};
jQuery.easing = {
linear: function( p ) {
return p;
},
swing: function( p ) {
return 0.5 - Math.cos( p*Math.PI ) / 2;
}
};
jQuery.timers = [];
jQuery.fx = Tween.prototype.init;
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 );
}
}
if ( !timers.length ) {
jQuery.fx.stop();
}
fxNow = undefined;
};
jQuery.fx.timer = function( timer ) {
if ( timer() && jQuery.timers.push( timer ) ) {
jQuery.fx.start();
}
};
jQuery.fx.interval = 13;
jQuery.fx.start = function() {
if ( !timerId ) {
timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
}
};
jQuery.fx.stop = function() {
clearInterval( timerId );
timerId = null;
};
jQuery.fx.speeds = {
slow: 600,
fast: 200,
// Default speed
_default: 400
};
// Back Compat <1.8 extension point
jQuery.fx.step = {};
if ( jQuery.expr && jQuery.expr.filters ) {
jQuery.expr.filters.animated = function( elem ) {
return jQuery.grep(jQuery.timers, function( fn ) {
return elem === fn.elem;
}).length;
};
}
jQuery.fn.offset = function( options ) {
if ( arguments.length ) {
return options === undefined ?
this :
this.each(function( i ) {
jQuery.offset.setOffset( this, options, i );
});
}
var docElem, win,
box = { top: 0, left: 0 },
elem = this[ 0 ],
doc = elem && elem.ownerDocument;
if ( !doc ) {
return;
}
docElem = doc.documentElement;
// Make sure it's not a disconnected DOM node
if ( !jQuery.contains( docElem, elem ) ) {
return box;
}
// If we don't have gBCR, just use 0,0 rather than error
// BlackBerry 5, iOS 3 (original iPhone)
if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
box = elem.getBoundingClientRect();
}
win = getWindow( doc );
return {
top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
};
};
jQuery.offset = {
setOffset: function( elem, options, i ) {
var position = jQuery.css( elem, "position" );
// set position first, in-case top/left are set even on static elem
if ( position === "static" ) {
elem.style.position = "relative";
}
var curElem = jQuery( elem ),
curOffset = curElem.offset(),
curCSSTop = jQuery.css( elem, "top" ),
curCSSLeft = jQuery.css( elem, "left" ),
calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
props = {}, curPosition = {}, curTop, curLeft;
// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
if ( calculatePosition ) {
curPosition = curElem.position();
curTop = curPosition.top;
curLeft = curPosition.left;
} else {
curTop = parseFloat( curCSSTop ) || 0;
curLeft = parseFloat( curCSSLeft ) || 0;
}
if ( jQuery.isFunction( options ) ) {
options = options.call( elem, i, curOffset );
}
if ( options.top != null ) {
props.top = ( options.top - curOffset.top ) + curTop;
}
if ( options.left != null ) {
props.left = ( options.left - curOffset.left ) + curLeft;
}
if ( "using" in options ) {
options.using.call( elem, props );
} else {
curElem.css( props );
}
}
};
jQuery.fn.extend({
position: function() {
if ( !this[ 0 ] ) {
return;
}
var offsetParent, offset,
parentOffset = { top: 0, left: 0 },
elem = this[ 0 ];
// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
if ( jQuery.css( elem, "position" ) === "fixed" ) {
// we assume that getBoundingClientRect is available when computed position is fixed
offset = elem.getBoundingClientRect();
} else {
// Get *real* offsetParent
offsetParent = this.offsetParent();
// Get correct offsets
offset = this.offset();
if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
parentOffset = offsetParent.offset();
}
// Add offsetParent borders
parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
}
// Subtract parent offsets and element margins
// note: when an element has margin: auto the offsetLeft and marginLeft
// are the same in Safari causing offset.left to incorrectly be 0
return {
top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
};
},
offsetParent: function() {
return this.map(function() {
var offsetParent = this.offsetParent || document.documentElement;
while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
offsetParent = offsetParent.offsetParent;
}
return offsetParent || document.documentElement;
});
}
});
// Create scrollLeft and scrollTop methods
jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
var top = /Y/.test( prop );
jQuery.fn[ method ] = function( val ) {
return jQuery.access( this, function( elem, method, val ) {
var win = getWindow( elem );
if ( val === undefined ) {
return win ? (prop in win) ? win[ prop ] :
win.document.documentElement[ method ] :
elem[ method ];
}
if ( win ) {
win.scrollTo(
!top ? val : jQuery( win ).scrollLeft(),
top ? val : jQuery( win ).scrollTop()
);
} else {
elem[ method ] = val;
}
}, method, val, arguments.length, null );
};
});
function getWindow( elem ) {
return jQuery.isWindow( elem ) ?
elem :
elem.nodeType === 9 ?
elem.defaultView || elem.parentWindow :
false;
}
// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
// margin is only for outerHeight, outerWidth
jQuery.fn[ funcName ] = function( margin, value ) {
var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
return jQuery.access( this, function( elem, type, value ) {
var doc;
if ( jQuery.isWindow( elem ) ) {
// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
// isn't a whole lot we can do. See pull request at this URL for discussion:
// https://github.com/jquery/jquery/pull/764
return elem.document.documentElement[ "client" + name ];
}
// Get document width or height
if ( elem.nodeType === 9 ) {
doc = elem.documentElement;
// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
return Math.max(
elem.body[ "scroll" + name ], doc[ "scroll" + name ],
elem.body[ "offset" + name ], doc[ "offset" + name ],
doc[ "client" + name ]
);
}
return value === undefined ?
// Get width or height on the element, requesting but not forcing parseFloat
jQuery.css( elem, type, extra ) :
// Set width or height on the element
jQuery.style( elem, type, value, extra );
}, type, chainable ? margin : undefined, chainable, null );
};
});
});
// Limit scope pollution from any deprecated API
// (function() {
// })();
// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;
// Expose jQuery as an AMD module, but only for AMD loaders that
// understand the issues with loading multiple versions of jQuery
// in a page that all might call define(). The loader will indicate
// they have special allowances for multiple jQuery versions by
// specifying define.amd.jQuery = true. Register as a named module,
// since jQuery can be concatenated with other files that may use define,
// but not use a proper concatenation script that understands anonymous
// AMD modules. A named AMD is safest and most robust way to register.
// Lowercase jquery is used because AMD module names are derived from
// file names, and jQuery is normally delivered in a lowercase file name.
// Do this after creating the global so that if an AMD module wants to call
// noConflict to hide this version of jQuery, it will work.
if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
define( "jquery", [], function () { return jQuery; } );
}
})( window );
================================================
FILE: public/assets/dashboard/js/contabs.js
================================================
$(function () {
function t(t) {
var e = 0;
return $(t).each(function () {
e += $(this).outerWidth(!0)
}), e
}
function e(e) {
var a = t($(e).prevAll()), i = t($(e).nextAll()), n = t($(".content-tabs").children().not(".J_menuTabs")), s = $(".content-tabs").outerWidth(!0) - n, r = 0;
if ($(".page-tabs-content").outerWidth() < s)r = 0; else if (i <= s - $(e).outerWidth(!0) - $(e).next().outerWidth(!0)) {
if (s - $(e).next().outerWidth(!0) > i) {
r = a;
for (var o = e; r - $(o).outerWidth() > $(".page-tabs-content").outerWidth() - s;)r -= $(o).prev().outerWidth(), o = $(o).prev()
}
} else a > s - $(e).outerWidth(!0) - $(e).prev().outerWidth(!0) && (r = a - $(e).prev().outerWidth(!0));
$(".page-tabs-content").animate({marginLeft: 0 - r + "px"}, "fast")
}
function a() {
var e = Math.abs(parseInt($(".page-tabs-content").css("margin-left"))), a = t($(".content-tabs").children().not(".J_menuTabs")), i = $(".content-tabs").outerWidth(!0) - a, n = 0;
if ($(".page-tabs-content").width() < i)return !1;
for (var s = $(".J_menuTab:first"), r = 0; r + $(s).outerWidth(!0) <= e;)r += $(s).outerWidth(!0), s = $(s).next();
if (r = 0, t($(s).prevAll()) > i) {
for (; r + $(s).outerWidth(!0) < i && s.length > 0;)r += $(s).outerWidth(!0), s = $(s).prev();
n = t($(s).prevAll())
}
$(".page-tabs-content").animate({marginLeft: 0 - n + "px"}, "fast")
}
function i() {
var e = Math.abs(parseInt($(".page-tabs-content").css("margin-left"))), a = t($(".content-tabs").children().not(".J_menuTabs")), i = $(".content-tabs").outerWidth(!0) - a, n = 0;
if ($(".page-tabs-content").width() < i)return !1;
for (var s = $(".J_menuTab:first"), r = 0; r + $(s).outerWidth(!0) <= e;)r += $(s).outerWidth(!0), s = $(s).next();
for (r = 0; r + $(s).outerWidth(!0) < i && s.length > 0;)r += $(s).outerWidth(!0), s = $(s).next();
n = t($(s).prevAll()), n > 0 && $(".page-tabs-content").animate({marginLeft: 0 - n + "px"}, "fast")
}
function n() {
var t = $(this).attr("href"), a = $(this).data("index"), i = $.trim($(this).text()), n = !0;
if (void 0 == t || 0 == $.trim(t).length)return !1;
if ($(".J_menuTab").each(function () {
return $(this).data("id") == t ? ($(this).hasClass("active") || ($(this).addClass("active").siblings(".J_menuTab").removeClass("active"), e(this), $(".J_mainContent .J_iframe").each(function () {
return $(this).data("id") == t ? ($(this).show().siblings(".J_iframe").hide(), !1) : void 0
})), n = !1, !1) : void 0
}), n) {
var s = '';
$(".J_menuTab").removeClass("active");
var r = '
';
$(".J_mainContent").find("iframe.J_iframe").hide().parents(".J_mainContent").append(r);
var o = layer.load();
$(".J_mainContent iframe:visible").load(function () {
layer.close(o)
}), $(".J_menuTabs .page-tabs-content").append(s), e($(".J_menuTab.active"))
}
return !1
}
function s() {
var t = $(this).parents(".J_menuTab").data("id"), a = $(this).parents(".J_menuTab").width();
if ($(this).parents(".J_menuTab").hasClass("active")) {
if ($(this).parents(".J_menuTab").next(".J_menuTab").size()) {
var i = $(this).parents(".J_menuTab").next(".J_menuTab:eq(0)").data("id");
$(this).parents(".J_menuTab").next(".J_menuTab:eq(0)").addClass("active"), $(".J_mainContent .J_iframe").each(function () {
return $(this).data("id") == i ? ($(this).show().siblings(".J_iframe").hide(), !1) : void 0
});
var n = parseInt($(".page-tabs-content").css("margin-left"));
0 > n && $(".page-tabs-content").animate({marginLeft: n + a + "px"}, "fast"), $(this).parents(".J_menuTab").remove(), $(".J_mainContent .J_iframe").each(function () {
return $(this).data("id") == t ? ($(this).remove(), !1) : void 0
})
}
if ($(this).parents(".J_menuTab").prev(".J_menuTab").size()) {
var i = $(this).parents(".J_menuTab").prev(".J_menuTab:last").data("id");
$(this).parents(".J_menuTab").prev(".J_menuTab:last").addClass("active"), $(".J_mainContent .J_iframe").each(function () {
return $(this).data("id") == i ? ($(this).show().siblings(".J_iframe").hide(), !1) : void 0
}), $(this).parents(".J_menuTab").remove(), $(".J_mainContent .J_iframe").each(function () {
return $(this).data("id") == t ? ($(this).remove(), !1) : void 0
})
}
} else $(this).parents(".J_menuTab").remove(), $(".J_mainContent .J_iframe").each(function () {
return $(this).data("id") == t ? ($(this).remove(), !1) : void 0
}), e($(".J_menuTab.active"));
return !1
}
function r() {
$(".page-tabs-content").children("[data-id]").not(":first").not(".active").each(function () {
$('.J_iframe[data-id="' + $(this).data("id") + '"]').remove(), $(this).remove()
}), $(".page-tabs-content").css("margin-left", "0")
}
function o() {
e($(".J_menuTab.active"))
}
function d() {
if (!$(this).hasClass("active")) {
var t = $(this).data("id");
$(".J_mainContent .J_iframe").each(function () {
return $(this).data("id") == t ? ($(this).show().siblings(".J_iframe").hide(), !1) : void 0
}), $(this).addClass("active").siblings(".J_menuTab").removeClass("active"), e(this)
}
}
function c() {
var t = $('.J_iframe[data-id="' + $(this).data("id") + '"]'), e = t.attr("src"), a = layer.load();
t.attr("src", e).load(function () {
layer.close(a)
})
}
$(".J_menuItem").each(function (t) {
$(this).attr("data-index") || $(this).attr("data-index", t)
}), $(".J_menuItem").on("click", n), $(".J_menuTabs").on("click", ".J_menuTab i", s), $(".J_tabCloseOther").on("click", r), $(".J_tabShowActive").on("click", o), $(".J_menuTabs").on("click", ".J_menuTab", d), $(".J_menuTabs").on("dblclick", ".J_menuTab", c), $(".J_tabLeft").on("click", a), $(".J_tabRight").on("click", i), $(".J_tabCloseAll").on("click", function () {
$(".page-tabs-content").children("[data-id]").not(":first").each(function () {
$('.J_iframe[data-id="' + $(this).data("id") + '"]').remove(), $(this).remove()
}), $(".page-tabs-content").children("[data-id]:first").each(function () {
$('.J_iframe[data-id="' + $(this).data("id") + '"]').show(), $(this).addClass("active")
}), $(".page-tabs-content").css("margin-left", "0")
});
/**
* 常用工具-点击刷新页面
* */
$('.J_tabFresh').on("click", function(){
$(".J_mainContent .J_iframe").each(function(){
if($(this).css('display') == 'inline'){
layer.msg('刷新成功', {icon: 1,time:2000}, function() {
});
$(this)[0].contentWindow.location.reload();
};
})
})
});
================================================
FILE: public/assets/dashboard/js/contabs1.js
================================================
$(function() {
function f(l) {
var k = 0;
$(l).each(function() {
k += $(this).outerWidth(true)
});
return k
}
function g(n) {
var o = f($(n).prevAll()),
q = f($(n).nextAll());
var l = f($(".content-tabs").children().not(".J_menuTabs"));
var k = $(".content-tabs").outerWidth(true) - l;
var p = 0;
if ($(".page-tabs-content").outerWidth() < k) {
p = 0
} else {
if (q <= (k - $(n).outerWidth(true) - $(n).next().outerWidth(true))) {
if ((k - $(n).next().outerWidth(true)) > q) {
p = o;
var m = n;
while ((p - $(m).outerWidth()) > ($(".page-tabs-content").outerWidth() - k)) {
p -= $(m).prev().outerWidth();
m = $(m).prev()
}
}
} else {
if (o > (k - $(n).outerWidth(true) - $(n).prev().outerWidth(true))) {
p = o - $(n).prev().outerWidth(true)
}
}
}
$(".page-tabs-content").animate({
marginLeft: 0 - p + "px"
},
"fast")
}
function a() {
var o = Math.abs(parseInt($(".page-tabs-content").css("margin-left")));
var l = f($(".content-tabs").children().not(".J_menuTabs"));
var k = $(".content-tabs").outerWidth(true) - l;
var p = 0;
if ($(".page-tabs-content").width() < k) {
return false
} else {
var m = $(".J_menuTab:first");
var n = 0;
while ((n + $(m).outerWidth(true)) <= o) {
n += $(m).outerWidth(true);
m = $(m).next()
}
n = 0;
if (f($(m).prevAll()) > k) {
while ((n + $(m).outerWidth(true)) < (k) && m.length > 0) {
n += $(m).outerWidth(true);
m = $(m).prev()
}
p = f($(m).prevAll())
}
}
$(".page-tabs-content").animate({
marginLeft: 0 - p + "px"
},
"fast")
}
function b() {
var o = Math.abs(parseInt($(".page-tabs-content").css("margin-left")));
var l = f($(".content-tabs").children().not(".J_menuTabs"));
var k = $(".content-tabs").outerWidth(true) - l;
var p = 0;
if ($(".page-tabs-content").width() < k) {
return false
} else {
var m = $(".J_menuTab:first");
var n = 0;
while ((n + $(m).outerWidth(true)) <= o) {
n += $(m).outerWidth(true);
m = $(m).next()
}
n = 0;
while ((n + $(m).outerWidth(true)) < (k) && m.length > 0) {
n += $(m).outerWidth(true);
m = $(m).next()
}
p = f($(m).prevAll());
if (p > 0) {
$(".page-tabs-content").animate({
marginLeft: 0 - p + "px"
},
"fast")
}
}
}
$(".J_menuItem").each(function(k) {
if (!$(this).attr("data-index")) {
$(this).attr("data-index", k)
}
});
function c() {
var o = $(this).attr("href"),
m = $(this).data("index"),
l = $.trim($(this).text()),
k = true;
if (o == undefined || $.trim(o).length == 0) {
return false
}
$(".J_menuTab").each(function() {
if ($(this).data("id") == o) {
if (!$(this).hasClass("active")) {
$(this).addClass("active").siblings(".J_menuTab").removeClass("active");
g(this);
$(".J_mainContent .J_iframe").each(function() {
if ($(this).data("id") == o) {
$(this).show().siblings(".J_iframe").hide();
return false
}
})
}
k = false;
return false
}
});
if (k) {
var p = '';
$(".J_menuTab").removeClass("active");
var n = '
';
$(".J_mainContent").find("iframe.J_iframe").hide().parents(".J_mainContent").append(n);
$(".J_menuTabs .page-tabs-content").append(p);
g($(".J_menuTab.active"))
}
if(!k){
$(".J_mainContent .J_iframe").each(function(){
if($(this).css('display') == 'inline'){
$(this).attr('src', $(this).attr('src'));
};
})
}
return false
}
$(".J_menuItem").on("click", c);
function h() {
var m = $(this).parents(".J_menuTab").data("id");
var l = $(this).parents(".J_menuTab").width();
if ($(this).parents(".J_menuTab").hasClass("active")) {
if ($(this).parents(".J_menuTab").next(".J_menuTab").size()) {
var k = $(this).parents(".J_menuTab").next(".J_menuTab:eq(0)").data("id");
$(this).parents(".J_menuTab").next(".J_menuTab:eq(0)").addClass("active");
$(".J_mainContent .J_iframe").each(function() {
if ($(this).data("id") == k) {
$(this).show().siblings(".J_iframe").hide();
return false
}
});
var n = parseInt($(".page-tabs-content").css("margin-left"));
if (n < 0) {
$(".page-tabs-content").animate({
marginLeft: (n + l) + "px"
},
"fast")
}
$(this).parents(".J_menuTab").remove();
$(".J_mainContent .J_iframe").each(function() {
if ($(this).data("id") == m) {
$(this).remove();
return false
}
})
}
if ($(this).parents(".J_menuTab").prev(".J_menuTab").size()) {
var k = $(this).parents(".J_menuTab").prev(".J_menuTab:last").data("id");
$(this).parents(".J_menuTab").prev(".J_menuTab:last").addClass("active");
$(".J_mainContent .J_iframe").each(function() {
if ($(this).data("id") == k) {
$(this).show().siblings(".J_iframe").hide();
return false
}
});
$(this).parents(".J_menuTab").remove();
$(".J_mainContent .J_iframe").each(function() {
if ($(this).data("id") == m) {
$(this).remove();
return false
}
})
}
} else {
$(this).parents(".J_menuTab").remove();
$(".J_mainContent .J_iframe").each(function() {
if ($(this).data("id") == m) {
$(this).remove();
return false
}
});
g($(".J_menuTab.active"))
}
return false
}
$(".J_menuTabs").on("click", ".J_menuTab i", h);
function i() {
$(".page-tabs-content").children("[data-id]").not(":first").not(".active").each(function() {
$('.J_iframe[data-id="' + $(this).data("id") + '"]').remove();
$(this).remove()
});
$(".page-tabs-content").css("margin-left", "0")
}
$(".J_tabCloseOther").on("click", i);
function j() {
g($(".J_menuTab.active"))
}
$(".J_tabShowActive").on("click", j);
function e() {
if (!$(this).hasClass("active")) {
var k = $(this).data("id");
$(".J_mainContent .J_iframe").each(function() {
if ($(this).data("id") == k) {
$(this).show().siblings(".J_iframe").hide();
return false
}
});
$(this).addClass("active").siblings(".J_menuTab").removeClass("active");
g(this)
}
}
$(".J_menuTabs").on("click", ".J_menuTab", e);
function d() {
var l = $('.J_iframe[data-id="' + $(this).data("id") + '"]');
var k = l.attr("src")
}
$(".J_menuTabs").on("dblclick", ".J_menuTab", d);
$(".J_tabLeft").on("click", a);
$(".J_tabRight").on("click", b);
$(".J_tabCloseAll").on("click",
function() {
$(".page-tabs-content").children("[data-id]").not(":first").each(function() {
$('.J_iframe[data-id="' + $(this).data("id") + '"]').remove();
$(this).remove()
});
$(".page-tabs-content").children("[data-id]:first").each(function() {
$('.J_iframe[data-id="' + $(this).data("id") + '"]').show();
$(this).addClass("active")
});
$(".page-tabs-content").css("margin-left", "0")
});
$('.J_tabGo').on("click", function(){
$(".J_mainContent .J_iframe").each(function(){
if($(this).css('display') == 'inline'){
$(this)[0].contentWindow.history.forward();
};
})
});
$('.J_tabBack').on("click", function(){
$(".J_mainContent .J_iframe").each(function(){
if($(this).css('display') == 'inline'){
$(this)[0].contentWindow.history.back();
};
})
});
/**
* 常用工具-点击刷新页面
* */
$('.J_tabFresh').on("click", function(){
$(".J_mainContent .J_iframe").each(function(){
if($(this).css('display') == 'inline'){
layer.msg('刷新成功', {icon: 1,time:2000}, function() {
});
$(this)[0].contentWindow.location.reload();
};
})
})
});
================================================
FILE: public/assets/dashboard/js/fileinput.js
================================================
/*!
* @copyright Copyright © Kartik Visweswaran, Krajee.com, 2014 - 2015
* @version 4.1.9
*
* File input styled for Bootstrap 3.0 that utilizes HTML5 File Input's advanced
* features including the FileReader API.
*
* The plugin drastically enhances the HTML file input to preview multiple files on the client before
* upload. In addition it provides the ability to preview content of images, text, videos, audio, html,
* flash and other objects. It also offers the ability to upload and delete files using AJAX, and add
* files in batches (i.e. preview, append, or remove before upload).
*
* Author: Kartik Visweswaran
* Copyright: 2015, Kartik Visweswaran, Krajee.com
* For more JQuery plugins visit http://plugins.krajee.com
* For more Yii related demos visit http://demos.krajee.com
*/
(function ($) {
"use strict";
String.prototype.repl = function (from, to) {
return this.split(from).join(to);
};
var isIE = function (ver) {
var div = document.createElement("div"), status;
div.innerHTML = "";
status = (div.getElementsByTagName("i").length === 1);
document.body.appendChild(div);
div.parentNode.removeChild(div);
return status;
},
previewCache = {
data: {},
init: function (obj) {
var content = obj.initialPreview, id = obj.id;
if (content.length > 0 && !isArray(content)) {
content = content.split(obj.initialPreviewDelimiter);
}
previewCache.data[id] = {
content: content,
config: obj.initialPreviewConfig,
tags: obj.initialPreviewThumbTags,
delimiter: obj.initialPreviewDelimiter,
template: obj.previewGenericTemplate,
msg: function (n) {
return obj.getMsgSelected(n);
},
initId: obj.previewInitId,
footer: obj.getLayoutTemplate('footer'),
isDelete: obj.initialPreviewShowDelete,
caption: obj.initialCaption,
actions: function (showUpload, showDelete, disabled, url, key) {
return obj.renderFileActions(showUpload, showDelete, disabled, url, key);
}
};
},
fetch: function (id) {
return previewCache.data[id].content.filter(function (n) {
return n !== null;
});
},
count: function (id, all) {
return !!previewCache.data[id] && !!previewCache.data[id].content ?
(all ? previewCache.data[id].content.length : previewCache.fetch(id).length) : 0;
},
get: function (id, i, isDisabled) {
var ind = 'init_' + i, data = previewCache.data[id],
previewId = data.initId + '-' + ind, out;
isDisabled = isDisabled === undefined ? true : isDisabled;
if (data.content[i] === null) {
return '';
}
out = data.template
.repl('{previewId}', previewId)
.repl('{frameClass}', ' file-preview-initial')
.repl('{fileindex}', ind)
.repl('{content}', data.content[i])
.repl('{footer}', previewCache.footer(id, i, isDisabled));
if (data.tags.length && data.tags[i]) {
out = replaceTags(out, data.tags[i]);
}
return out;
},
add: function (id, content, config, tags, append) {
var data = $.extend(true, {}, previewCache.data[id]), index;
if (!isArray(content)) {
content = content.split(data.delimiter);
}
if (append) {
index = data.content.push(content) - 1;
data.config[index] = config;
data.tags[index] = tags;
} else {
index = content.length;
data.content = content;
data.config = config;
data.tags = tags;
}
previewCache.data[id] = data;
return index;
},
set: function (id, content, config, tags, append) {
var data = $.extend(true, {}, previewCache.data[id]), i;
if (!isArray(content)) {
content = content.split(data.delimiter);
}
if (append) {
for (i = 0; i < content.length; i++) {
data.content.push(content[i]);
}
for (i = 0; i < config.length; i++) {
data.config.push(config[i]);
}
for (i = 0; i < tags.length; i++) {
data.tags.push(tags[i]);
}
} else {
data.content = content;
data.config = config;
data.tags = tags;
}
previewCache.data[id] = data;
},
unset: function (id, index) {
var chk = previewCache.count(id);
if (!chk) {
return;
}
if (chk === 1) {
previewCache.data[id].content = [];
previewCache.data[id].config = [];
return;
}
previewCache.data[id].content[index] = null;
previewCache.data[id].config[index] = null;
},
out: function (id) {
var html = '', data = previewCache.data[id], caption, len = previewCache.count(id, true);
if (len === 0) {
return {content: '', caption: ''};
}
for (var i = 0; i < len; i++) {
html += previewCache.get(id, i);
}
caption = data.msg(previewCache.count(id));
return {content: html, caption: caption};
},
footer: function (id, i, isDisabled) {
var data = previewCache.data[id];
isDisabled = isDisabled === undefined ? true : isDisabled;
if (data.config.length === 0 || isEmpty(data.config[i])) {
return '';
}
var config = data.config[i],
caption = isSet('caption', config) ? config.caption : '',
width = isSet('width', config) ? config.width : 'auto',
url = isSet('url', config) ? config.url : false,
key = isSet('key', config) ? config.key : null,
disabled = (url === false) && isDisabled,
actions = data.isDelete ? data.actions(false, true, disabled, url, key) : '',
footer = data.footer.repl('{actions}', actions);
return footer
.repl('{caption}', caption)
.repl('{width}', width)
.repl('{indicator}', '')
.repl('{indicatorTitle}', '');
}
},
getNum = function (num, def) {
def = def || 0;
if (typeof num === "number") {
return num;
}
if (typeof num === "string") {
num = parseFloat(num);
}
return isNaN(num) ? def : num;
},
hasFileAPISupport = function () {
return window.File && window.FileReader;
},
hasDragDropSupport = function () {
var $div = document.createElement('div');
return !isIE(9) && ($div.draggable !== undefined || ($div.ondragstart !== undefined && $div.ondrop !== undefined));
},
hasFileUploadSupport = function () {
return hasFileAPISupport && window.FormData;
},
addCss = function ($el, css) {
$el.removeClass(css).addClass(css);
},
STYLE_SETTING = 'style="width:{width};height:{height};"',
OBJECT_PARAMS = '
\n' +
'
\n' +
'
\n' +
'
\n' +
'
\n' +
'
\n',
DEFAULT_PREVIEW = '
\n' +
' {previewFileIcon}\n' +
'
',
defaultFileActionSettings = {
removeIcon: '
',
removeClass: 'btn btn-xs btn-default',
removeTitle: 'Remove file',
uploadIcon: '
',
uploadClass: 'btn btn-xs btn-default',
uploadTitle: 'Upload file',
indicatorNew: '
',
indicatorSuccess: '
',
indicatorError: '
',
indicatorLoading: '
',
indicatorNewTitle: 'Not uploaded yet',
indicatorSuccessTitle: 'Uploaded',
indicatorErrorTitle: 'Upload Error',
indicatorLoadingTitle: 'Uploading ...'
},
tMain1 = '{preview}\n' +
'
\n' +
'
',
tMain2 = '{preview}\n
\n{remove}\n{cancel}\n{upload}\n{browse}\n',
tPreview = '
\n' +
'
×
\n' +
'
\n' +
'
\n' +
'
\n' +
'
' +
'
\n' +
'
\n' +
'
\n' +
'
',
tIcon = '
',
tCaption = '
',
tModal = '
\n' +
'
\n' +
'
\n' +
' \n' +
'
\n' +
' \n' +
'
\n' +
'
\n' +
'
\n' +
'
',
tProgress = '
\n' +
'
\n' +
' {percent}%\n' +
'
\n' +
'
',
tFooter = '',
tActions = '
\n' +
' \n' +
'
{indicator}
\n' +
'
\n' +
'
',
tActionDelete = '
\n',
tActionUpload = '',
tGeneric = '
\n' +
' {content}\n' +
' {footer}\n' +
'
\n',
tHtml = '
\n' +
' \n' +
' {footer}\n' +
'
',
tImage = '
\n' +
'

\n' +
' {footer}\n' +
'
\n',
tText = '
\n' +
'
\n' +
' {data}\n' +
'
\n' +
' {footer}\n' +
'
',
tVideo = '
\n' +
' \n' +
' {footer}\n' +
'
\n',
tAudio = '
\n' +
'
\n' +
' {footer}\n' +
'
',
tFlash = '
\n' +
' \n' +
' {footer}\n' +
'
\n',
tObject = '
\n' +
'
\n' +
' {footer}\n' +
'
',
tOther = '
\n' +
' ' + DEFAULT_PREVIEW + '\n' +
' {footer}\n' +
'
',
defaultLayoutTemplates = {
main1: tMain1,
main2: tMain2,
preview: tPreview,
icon: tIcon,
caption: tCaption,
modal: tModal,
progress: tProgress,
footer: tFooter,
actions: tActions,
actionDelete: tActionDelete,
actionUpload: tActionUpload
},
defaultPreviewTemplates = {
generic: tGeneric,
html: tHtml,
image: tImage,
text: tText,
video: tVideo,
audio: tAudio,
flash: tFlash,
object: tObject,
other: tOther
},
defaultPreviewTypes = ['image', 'html', 'text', 'video', 'audio', 'flash', 'object'],
defaultPreviewSettings = {
image: {width: "auto", height: "120px"},
html: {width: "213px", height: "160px"},
text: {width: "160px", height: "160px"},
video: {width: "213px", height: "160px"},
audio: {width: "213px", height: "80px"},
flash: {width: "213px", height: "160px"},
object: {width: "160px", height: "160px"},
other: {width: "160px", height: "160px"}
},
defaultFileTypeSettings = {
image: function (vType, vName) {
return (vType !== undefined) ? vType.match('image.*') : vName.match(/\.(gif|png|jpe?g)$/i);
},
html: function (vType, vName) {
return (vType !== undefined) ? vType === 'text/html' : vName.match(/\.(htm|html)$/i);
},
text: function (vType, vName) {
return (vType !== undefined && vType.match('text.*')) || vName.match(/\.(txt|md|csv|nfo|php|ini)$/i);
},
video: function (vType, vName) {
return (vType !== undefined && vType.match(/\.video\/(ogg|mp4|webm)$/i)) || vName.match(/\.(og?|mp4|webm)$/i);
},
audio: function (vType, vName) {
return (vType !== undefined && vType.match(/\.audio\/(ogg|mp3|wav)$/i)) || vName.match(/\.(ogg|mp3|wav)$/i);
},
flash: function (vType, vName) {
return (vType !== undefined && vType === 'application/x-shockwave-flash') || vName.match(/\.(swf)$/i);
},
object: function () {
return true;
},
other: function () {
return true;
}
},
isEmpty = function (value, trim) {
return value === null || value === undefined || value.length === 0 || (trim && $.trim(value) === '');
},
isArray = function (a) {
return Array.isArray(a) || Object.prototype.toString.call(a) === '[object Array]';
},
isSet = function (needle, haystack) {
return (typeof haystack === 'object' && needle in haystack);
},
getElement = function (options, param, value) {
return (isEmpty(options) || isEmpty(options[param])) ? value : $(options[param]);
},
uniqId = function () {
return Math.round(new Date().getTime() + (Math.random() * 100));
},
htmlEncode = function (str) {
return String(str).repl('&', '&')
.repl('"', '"')
.repl("'", ''')
.repl('<', '<')
.repl('>', '>');
},
replaceTags = function (str, tags) {
var out = str;
tags = tags || {};
$.each(tags, function (key, value) {
if (typeof value === "function") {
value = value();
}
out = out.repl(key, value);
});
return out;
},
objUrl = window.URL || window.webkitURL,
FileInput = function (element, options) {
var self = this;
self.$element = $(element);
if (!self.validate()) {
return;
}
if (hasFileAPISupport() || isIE(9)) {
self.init(options);
self.listen();
} else {
self.$element.removeClass('file-loading');
}
};
FileInput.prototype = {
constructor: FileInput,
validate: function() {
var self = this, $exception;
if (self.$element.attr('type') === 'file') {
return true;
}
$exception = '
' +
'
Invalid Input Type
' +
'You must set an input type = file for bootstrap-fileinput plugin to initialize.' +
'';
self.$element.after($exception);
return false;
},
init: function (options) {
var self = this, $el = self.$element, t;
$.each(options, function (key, value) {
self[key] = (key === 'maxFileCount' || key === 'maxFileSize') ? getNum(value) : value;
});
self.fileInputCleared = false;
self.fileBatchCompleted = true;
if (isEmpty(self.allowedPreviewTypes)) {
self.allowedPreviewTypes = defaultPreviewTypes;
}
self.uploadFileAttr = !isEmpty($el.attr('name')) ? $el.attr('name') : 'file_data';
self.reader = null;
self.formdata = {};
self.isIE9 = isIE(9);
self.isIE10 = isIE(10);
self.filestack = [];
self.ajaxRequests = [];
self.isError = false;
self.ajaxAborted = false;
self.dropZoneEnabled = hasDragDropSupport() && self.dropZoneEnabled;
self.isDisabled = self.$element.attr('disabled') || self.$element.attr('readonly');
self.isUploadable = hasFileUploadSupport && !isEmpty(self.uploadUrl);
self.slug = typeof options.slugCallback === "function" ? options.slugCallback : self.slugDefault;
self.mainTemplate = self.showCaption ? self.getLayoutTemplate('main1') : self.getLayoutTemplate('main2');
self.captionTemplate = self.getLayoutTemplate('caption');
self.previewGenericTemplate = self.getPreviewTemplate('generic');
if (isEmpty(self.$element.attr('id'))) {
self.$element.attr('id', uniqId());
}
if (self.$container === undefined) {
self.$container = self.createContainer();
} else {
self.refreshContainer();
}
self.$progress = self.$container.find('.kv-upload-progress');
self.$btnUpload = self.$container.find('.kv-fileinput-upload');
self.$captionContainer = getElement(options, 'elCaptionContainer', self.$container.find('.file-caption'));
self.$caption = getElement(options, 'elCaptionText', self.$container.find('.file-caption-name'));
self.$previewContainer = getElement(options, 'elPreviewContainer', self.$container.find('.file-preview'));
self.$preview = getElement(options, 'elPreviewImage', self.$container.find('.file-preview-thumbnails'));
self.$previewStatus = getElement(options, 'elPreviewStatus', self.$container.find('.file-preview-status'));
self.$errorContainer = getElement(options, 'elErrorContainer',
self.$previewContainer.find('.kv-fileinput-error'));
if (!isEmpty(self.msgErrorClass)) {
addCss(self.$errorContainer, self.msgErrorClass);
}
self.$errorContainer.hide();
self.fileActionSettings = $.extend(defaultFileActionSettings, options.fileActionSettings);
self.previewInitId = "preview-" + uniqId();
self.id = self.$element.attr('id');
previewCache.init(self);
self.initPreview(true);
self.initPreviewDeletes();
self.options = options;
self.setFileDropZoneTitle();
self.uploadCount = 0;
self.uploadPercent = 0;
self.$element.removeClass('file-loading');
t = self.getLayoutTemplate('progress');
self.progressTemplate = t.replace('{class}', self.progressClass);
self.progressCompleteTemplate = t.replace('{class}', self.progressCompleteClass);
self.setEllipsis();
},
parseError: function (jqXHR, errorThrown, fileName) {
var self = this, errMsg = $.trim(errorThrown + ''),
dot = errMsg.slice(-1) === '.' ? '' : '.',
text = $(jqXHR.responseText).text();
if (self.showAjaxErrorDetails) {
text = $.trim(text.replace(/\n\s*\n/g, '\n'));
text = text.length > 0 ? '
' + text + '
' : '';
errMsg += dot + text;
} else {
errMsg += dot;
}
return fileName ? '
' + fileName + ': ' + jqXHR : errMsg;
},
raise: function (event, params) {
var self = this, e = $.Event(event), out = false;
if (params !== undefined) {
self.$element.trigger(e, params);
} else {
self.$element.trigger(e);
}
if (e.result) {
out = true;
}
if (!out) {
return;
}
switch (event) {
// ignore these events
case 'filebatchuploadcomplete':
case 'filebatchuploadsuccess':
case 'fileuploaded':
case 'fileclear':
case 'filecleared':
case 'filereset':
case 'fileerror':
case 'filefoldererror':
case 'fileuploaderror':
case 'filebatchuploaderror':
case 'filedeleteerror':
case 'filecustomerror':
break;
// can trigger filecustomerror to abort upload
default:
self.ajaxAborted = out;
break;
}
},
getLayoutTemplate: function (t) {
var self = this,
template = isSet(t, self.layoutTemplates) ? self.layoutTemplates[t] : defaultLayoutTemplates[t];
if (isEmpty(self.customLayoutTags)) {
return template;
}
return replaceTags(template, self.customLayoutTags);
},
getPreviewTemplate: function (t) {
var self = this,
template = isSet(t, self.previewTemplates) ? self.previewTemplates[t] : defaultPreviewTemplates[t];
template = template.repl('{previewFileIcon}', self.previewFileIcon);
if (isEmpty(self.customPreviewTags)) {
return template;
}
return replaceTags(template, self.customPreviewTags);
},
getOutData: function (jqXHR, responseData, filesData) {
var self = this;
jqXHR = jqXHR || {};
responseData = responseData || {};
filesData = filesData || self.filestack.slice(0) || {};
return {
form: self.formdata,
files: filesData,
extra: self.getExtraData(),
response: responseData,
reader: self.reader,
jqXHR: jqXHR
};
},
setEllipsis: function () {
var self = this, $capCont = self.$captionContainer, $cap = self.$caption,
$div = $cap.clone().css('height', 'auto').hide();
$capCont.parent().before($div);
$capCont.removeClass('kv-has-ellipsis');
if ($div.outerWidth() > $cap.outerWidth()) {
$capCont.addClass('kv-has-ellipsis');
}
$div.remove();
},
listen: function () {
var self = this, $el = self.$element, $cap = self.$captionContainer, $btnFile = self.$btnFile,
$form = $el.closest('form');
$el.on('change', $.proxy(self.change, self));
$(window).on('resize', function () {
self.setEllipsis();
});
$btnFile.off('click').on('click', function () {
self.raise('filebrowse');
if (self.isError && !self.isUploadable) {
self.clear();
}
$cap.focus();
});
$form.off('reset').on('reset', $.proxy(self.reset, self));
self.$container.off('click')
.on('click', '.fileinput-remove:not([disabled])', $.proxy(self.clear, self))
.on('click', '.fileinput-cancel', $.proxy(self.cancel, self));
if (self.isUploadable && self.dropZoneEnabled && self.showPreview) {
self.initDragDrop();
}
if (!self.isUploadable) {
$form.on('submit', $.proxy(self.submitForm, self));
}
self.$container.find('.kv-fileinput-upload').off('click').on('click', function (e) {
if (!self.isUploadable) {
return;
}
e.preventDefault();
if (!$(this).hasClass('disabled') && isEmpty($(this).attr('disabled'))) {
self.upload();
}
});
},
submitForm: function () {
var self = this, $el = self.$element, files = $el.get(0).files;
if (files && files.length < self.minFileCount && self.minFileCount > 0) {
self.noFilesError({});
return false;
}
return !self.abort({});
},
abort: function (params) {
var self = this, data;
if (self.ajaxAborted && typeof self.ajaxAborted === "object" && self.ajaxAborted.message !== undefined) {
if (self.ajaxAborted.data !== undefined) {
data = self.getOutData({}, self.ajaxAborted.data);
} else {
data = self.getOutData();
}
data = $.extend(data, params);
self.showUploadError(self.ajaxAborted.message, data, 'filecustomerror');
return true;
}
return false;
},
noFilesError: function (params) {
var self = this, label = self.minFileCount > 1 ? self.filePlural : self.fileSingle,
msg = self.msgFilesTooLess.repl('{n}', self.minFileCount).repl('{files}', label),
$error = self.$errorContainer;
$error.html(msg);
self.isError = true;
self.updateFileDetails(0);
$error.fadeIn(800);
self.raise('fileerror', [params]);
self.clearFileInput();
addCss(self.$container, 'has-error');
},
setProgress: function (p) {
var self = this, pct = Math.min(p, 100),
template = pct < 100 ? self.progressTemplate : self.progressCompleteTemplate;
self.$progress.html(template.repl('{percent}', pct));
},
upload: function () {
var self = this, totLen = self.getFileStack().length, params = {},
i, outData, len, hasExtraData = !$.isEmptyObject(self.getExtraData());
if (totLen < self.minFileCount && self.minFileCount > 0) {
self.noFilesError(params);
return;
}
if (!self.isUploadable || self.isDisabled || (totLen === 0 && !hasExtraData)) {
return;
}
self.resetUpload();
self.$progress.removeClass('hide');
self.uploadCount = 0;
self.uploadPercent = 0;
self.lock();
self.setProgress(0);
if (totLen === 0 && hasExtraData) {
self.uploadExtraOnly();
return;
}
len = self.filestack.length;
self.hasInitData = false;
if (self.uploadAsync && self.showPreview) {
outData = self.getOutData();
self.raise('filebatchpreupload', [outData]);
self.fileBatchCompleted = false;
self.uploadCache = {content: [], config: [], tags: [], append: true};
for (i = 0; i < len; i += 1) {
if (self.filestack[i] !== undefined) {
self.uploadSingle(i, self.filestack, true);
}
}
return;
}
self.uploadBatch();
},
lock: function () {
var self = this;
self.resetErrors();
self.disable();
if (self.showRemove) {
addCss(self.$container.find('.fileinput-remove'), 'hide');
}
if (self.showCancel) {
self.$container.find('.fileinput-cancel').removeClass('hide');
}
self.raise('filelock', [self.filestack, self.getExtraData()]);
},
unlock: function (reset) {
var self = this;
if (reset === undefined) {
reset = true;
}
self.enable();
if (self.showCancel) {
addCss(self.$container.find('.fileinput-cancel'), 'hide');
}
if (self.showRemove) {
self.$container.find('.fileinput-remove').removeClass('hide');
}
if (reset) {
self.resetFileStack();
}
self.raise('fileunlock', [self.filestack, self.getExtraData()]);
},
resetFileStack: function () {
var self = this, i = 0, newstack = [];
self.getThumbs().each(function () {
var $thumb = $(this), ind = $thumb.attr('data-fileindex'),
file = self.filestack[ind];
if (ind === -1) {
return;
}
if (file !== undefined) {
newstack[i] = file;
$thumb.attr({
'id': self.previewInitId + '-' + i,
'data-fileindex': i
});
i += 1;
} else {
$thumb.attr({
'id': 'uploaded-' + uniqId(),
'data-fileindex': '-1'
});
}
});
self.filestack = newstack;
},
refresh: function (options) {
var self = this, $el = self.$element, $zone,
params = (arguments.length) ? $.extend(self.options, options) : self.options;
$el.off();
self.init(params);
$zone = self.$container.find('.file-drop-zone');
$zone.off('dragenter dragover drop');
$(document).off('dragenter dragover drop');
self.listen();
self.setFileDropZoneTitle();
},
initDragDrop: function () {
var self = this, $zone = self.$container.find('.file-drop-zone');
$zone.off('dragenter dragover drop');
$(document).off('dragenter dragover drop');
$zone.on('dragenter dragover', function (e) {
e.stopPropagation();
e.preventDefault();
if (self.isDisabled) {
return;
}
addCss($(this), 'highlighted');
});
$zone.on('dragleave', function (e) {
e.stopPropagation();
e.preventDefault();
if (self.isDisabled) {
return;
}
$(this).removeClass('highlighted');
});
$zone.on('drop', function (e) {
e.preventDefault();
if (self.isDisabled) {
return;
}
self.change(e, 'dragdrop');
$(this).removeClass('highlighted');
});
$(document).on('dragenter dragover drop', function (e) {
e.stopPropagation();
e.preventDefault();
});
},
setFileDropZoneTitle: function () {
var self = this, $zone = self.$container.find('.file-drop-zone');
$zone.find('.' + self.dropZoneTitleClass).remove();
if (!self.isUploadable || !self.showPreview || $zone.length === 0 || self.getFileStack().length > 0 || !self.dropZoneEnabled) {
return;
}
if ($zone.find('.file-preview-frame').length === 0) {
$zone.prepend('
' + self.dropZoneTitle + '
');
}
self.$container.removeClass('file-input-new');
addCss(self.$container, 'file-input-ajax-new');
},
initFileActions: function () {
var self = this;
self.$preview.find('.kv-file-remove').each(function () {
var $el = $(this), $frame = $el.closest('.file-preview-frame'),
ind = $frame.attr('data-fileindex'), n, cap;
$el.off('click').on('click', function () {
$frame.fadeOut('slow', function () {
self.filestack[ind] = undefined;
self.clearObjects($frame);
$frame.remove();
var filestack = self.getFileStack(), len = filestack.length,
chk = previewCache.count(self.id);
self.clearFileInput();
if (len === 0 && chk === 0) {
self.reset();
} else {
n = chk + len;
cap = n > 1 ? self.getMsgSelected(n) : filestack[0].name;
self.setCaption(cap);
}
});
});
});
self.$preview.find('.kv-file-upload').each(function () {
var $el = $(this);
$el.off('click').on('click', function () {
var $frame = $el.closest('.file-preview-frame'),
ind = $frame.attr('data-fileindex');
self.uploadSingle(ind, self.filestack, false);
});
});
},
getMsgSelected: function (n) {
var self = this, strFiles = n === 1 ? self.fileSingle : self.filePlural;
return self.msgSelected.repl('{n}', n).repl('{files}', strFiles);
},
renderFileFooter: function (caption, width) {
var self = this, config = self.fileActionSettings, footer, out,
template = self.getLayoutTemplate('footer');
if (self.isUploadable) {
footer = template.repl('{actions}', self.renderFileActions(true, true, false, false, false));
out = footer.repl('{caption}', caption)
.repl('{width}', width)
.repl('{indicator}', config.indicatorNew)
.repl('{indicatorTitle}', config.indicatorNewTitle);
} else {
out = template.repl('{actions}', '')
.repl('{caption}', caption)
.repl('{width}', width)
.repl('{indicator}', '')
.repl('{indicatorTitle}', '');
}
out = replaceTags(out, self.previewThumbTags);
return out;
},
renderFileActions: function (showUpload, showDelete, disabled, url, key) {
if (!showUpload && !showDelete) {
return '';
}
var self = this,
vUrl = url === false ? '' : ' data-url="' + url + '"',
vKey = key === false ? '' : ' data-key="' + key + '"',
btnDelete = self.getLayoutTemplate('actionDelete'),
btnUpload = '',
template = self.getLayoutTemplate('actions'),
otherButtons = self.otherActionButtons.repl('{dataKey}', vKey),
config = self.fileActionSettings,
removeClass = disabled ? config.removeClass + ' disabled' : config.removeClass;
btnDelete = btnDelete
.repl('{removeClass}', removeClass)
.repl('{removeIcon}', config.removeIcon)
.repl('{removeTitle}', config.removeTitle)
.repl('{dataUrl}', vUrl)
.repl('{dataKey}', vKey);
if (showUpload) {
btnUpload = self.getLayoutTemplate('actionUpload')
.repl('{uploadClass}', config.uploadClass)
.repl('{uploadIcon}', config.uploadIcon)
.repl('{uploadTitle}', config.uploadTitle);
}
return template
.repl('{delete}', btnDelete)
.repl('{upload}', btnUpload)
.repl('{other}', otherButtons);
},
initPreview: function (isInit) {
var self = this, cap = self.initialCaption || '', out;
if (!previewCache.count(self.id)) {
self.$preview.html('');
if (isInit) {
self.setCaption(cap);
} else {
self.initCaption();
}
return;
}
out = previewCache.out(self.id);
cap = isInit && self.initialCaption ? self.initialCaption : out.caption;
self.$preview.html(out.content);
self.setCaption(cap);
if (!isEmpty(out.content)) {
self.$container.removeClass('file-input-new');
}
},
initPreviewDeletes: function () {
var self = this, deleteExtraData = self.deleteExtraData || {},
resetProgress = function () {
if (self.$preview.find('.kv-file-remove').length === 0) {
self.reset();
self.initialCaption = '';
}
};
self.$preview.find('.kv-file-remove').each(function () {
var $el = $(this), vUrl = $el.data('url') || self.deleteUrl, vKey = $el.data('key');
if (isEmpty(vUrl) || vKey === undefined) {
return;
}
var $frame = $el.closest('.file-preview-frame'), cache = previewCache.data[self.id],
settings, params, index = $frame.data('fileindex'), config, extraData;
index = parseInt(index.replace('init_', ''));
config = isEmpty(cache.config) && isEmpty(cache.config[index]) ? null : cache.config[index];
extraData = isEmpty(config) || isEmpty(config.extra) ? deleteExtraData : config.extra;
if (typeof extraData === "function") {
extraData = extraData();
}
params = {id: $el.attr('id'), key: vKey, extra: extraData};
settings = $.extend({
url: vUrl,
type: 'DELETE',
dataType: 'json',
data: $.extend({key: vKey}, extraData),
beforeSend: function (jqXHR) {
self.ajaxAborted = false;
self.raise('filepredelete', [vKey, jqXHR, extraData]);
if (self.ajaxAborted) {
jqXHR.abort();
} else {
addCss($frame, 'file-uploading');
addCss($el, 'disabled');
}
},
success: function (data, textStatus, jqXHR) {
var n, cap;
if (data === undefined || data.error === undefined) {
previewCache.unset(self.id, index);
n = previewCache.count(self.id);
cap = n > 0 ? self.getMsgSelected(n) : '';
self.raise('filedeleted', [vKey, jqXHR, extraData]);
self.setCaption(cap);
} else {
params.jqXHR = jqXHR;
params.response = data;
self.showError(data.error, params, 'filedeleteerror');
$frame.removeClass('file-uploading');
$el.removeClass('disabled');
resetProgress();
return;
}
$frame.removeClass('file-uploading').addClass('file-deleted');
$frame.fadeOut('slow', function () {
self.clearObjects($frame);
$frame.remove();
resetProgress();
if (!n && self.getFileStack().length === 0) {
self.setCaption('');
self.reset();
}
});
},
error: function (jqXHR, textStatus, errorThrown) {
var errMsg = self.parseError(jqXHR, errorThrown);
params.jqXHR = jqXHR;
params.response = {};
self.showError(errMsg, params, 'filedeleteerror');
$frame.removeClass('file-uploading');
resetProgress();
}
}, self.ajaxDeleteSettings);
$el.off('click').on('click', function () {
$.ajax(settings);
});
});
},
clearObjects: function ($el) {
$el.find('video audio').each(function () {
this.pause();
$(this).remove();
});
$el.find('img object div').each(function () {
$(this).remove();
});
},
clearFileInput: function () {
var self = this, $el = self.$element, $srcFrm, $tmpFrm, $tmpEl;
if (isEmpty($el.val())) {
return;
}
// Fix for IE ver < 11, that does not clear file inputs
// Requires a sequence of steps to prevent IE crashing but
// still allow clearing of the file input.
if (self.isIE9 || self.isIE10) {
$srcFrm = $el.closest('form');
$tmpFrm = $(document.createElement('form'));
$tmpEl = $(document.createElement('div'));
$el.before($tmpEl);
if ($srcFrm.length) {
$srcFrm.after($tmpFrm);
} else {
$tmpEl.after($tmpFrm);
}
$tmpFrm.append($el).trigger('reset');
$tmpEl.before($el).remove();
$tmpFrm.remove();
} else { // normal input clear behavior for other sane browsers
$el.val('');
}
self.fileInputCleared = true;
},
resetUpload: function () {
var self = this;
self.uploadCache = {content: [], config: [], tags: [], append: true};
self.uploadCount = 0;
self.uploadPercent = 0;
self.$btnUpload.removeAttr('disabled');
self.setProgress(0);
addCss(self.$progress, 'hide');
self.resetErrors(false);
self.ajaxAborted = false;
self.ajaxRequests = [];
},
cancel: function () {
var self = this, xhr = self.ajaxRequests, len = xhr.length, i;
if (len > 0) {
for (i = 0; i < len; i += 1) {
xhr[i].abort();
}
}
self.getThumbs().each(function () {
var $thumb = $(this), ind = $thumb.attr('data-fileindex');
$thumb.removeClass('file-uploading');
if (self.filestack[ind] !== undefined) {
$thumb.find('.kv-file-upload').removeClass('disabled').removeAttr('disabled');
$thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled');
}
self.unlock();
});
},
clear: function () {
var self = this, cap;
self.$btnUpload.removeAttr('disabled');
self.resetUpload();
self.filestack = [];
self.clearFileInput();
self.resetErrors(true);
self.raise('fileclear');
if (!self.overwriteInitial && previewCache.count(self.id)) {
self.showFileIcon();
self.resetPreview();
self.setEllipsis();
self.initPreviewDeletes();
self.$container.removeClass('file-input-new');
} else {
self.getThumbs().each(function () {
self.clearObjects($(this));
});
self.$preview.html('');
cap = (!self.overwriteInitial && self.initialCaption.length > 0) ? self.initialCaption : '';
self.setCaption(cap);
self.setEllipsis();
self.$caption.attr('title', '');
addCss(self.$container, 'file-input-new');
}
if (self.$container.find('.file-preview-frame').length === 0) {
if (!self.initCaption()) {
self.$captionContainer.find('.kv-caption-icon').hide();
}
self.setEllipsis();
}
self.hideFileIcon();
self.raise('filecleared');
self.$captionContainer.focus();
self.setFileDropZoneTitle();
},
resetPreview: function () {
var self = this, out;
if (previewCache.count(self.id)) {
out = previewCache.out(self.id);
self.$preview.html(out.content);
self.setCaption(out.caption);
} else {
self.$preview.html('');
self.initCaption();
}
},
reset: function () {
var self = this;
self.clear();
self.resetPreview();
self.setEllipsis();
self.$container.find('.fileinput-filename').text('');
self.raise('filereset');
if (self.initialPreview.length > 0) {
self.$container.removeClass('file-input-new');
}
self.setFileDropZoneTitle();
self.filestack = [];
self.formdata = {};
},
disable: function () {
var self = this;
self.isDisabled = true;
self.raise('filedisabled');
self.$element.attr('disabled', 'disabled');
self.$container.find(".kv-fileinput-caption").addClass("file-caption-disabled");
self.$container.find(".btn-file, .fileinput-remove, .kv-fileinput-upload").attr("disabled", true);
self.initDragDrop();
},
enable: function () {
var self = this;
self.isDisabled = false;
self.raise('fileenabled');
self.$element.removeAttr('disabled');
self.$container.find(".kv-fileinput-caption").removeClass("file-caption-disabled");
self.$container.find(".btn-file, .fileinput-remove, .kv-fileinput-upload").removeAttr("disabled");
self.initDragDrop();
},
getThumbs: function (css) {
css = css || '';
return this.$preview.find('.file-preview-frame:not(.file-preview-initial)' + css);
},
getExtraData: function () {
var self = this, data = self.uploadExtraData;
if (typeof self.uploadExtraData === "function") {
data = self.uploadExtraData();
}
return data;
},
uploadExtra: function () {
var self = this, data = self.getExtraData();
if (data.length === 0) {
return;
}
$.each(data, function (key, value) {
self.formdata.append(key, value);
});
},
initXhr: function (xhrobj, factor) {
var self = this;
if (xhrobj.upload) {
xhrobj.upload.addEventListener('progress', function (event) {
var pct = 0, position = event.loaded || event.position, total = event.total;
if (event.lengthComputable) {
pct = Math.ceil(position / total * factor);
}
self.uploadPercent = Math.max(pct, self.uploadPercent);
self.setProgress(self.uploadPercent);
}, false);
}
return xhrobj;
},
ajaxSubmit: function (fnBefore, fnSuccess, fnComplete, fnError) {
var self = this, settings;
self.uploadExtra();
settings = $.extend({
xhr: function () {
var xhrobj = $.ajaxSettings.xhr();
return self.initXhr(xhrobj, 98);
},
url: self.uploadUrl,
type: 'POST',
dataType: 'json',
data: self.formdata,
cache: false,
processData: false,
contentType: false,
beforeSend: fnBefore,
success: fnSuccess,
complete: fnComplete,
error: fnError
}, self.ajaxSettings);
self.ajaxRequests.push($.ajax(settings));
},
initUploadSuccess: function (out, $thumb, allFiles) {
var self = this, append, data, index, $newThumb, content, config, tags;
if (typeof out !== 'object' || $.isEmptyObject(out)) {
return;
}
if (out.initialPreview !== undefined && out.initialPreview.length > 0) {
self.hasInitData = true;
content = out.initialPreview || [];
config = out.initialPreviewConfig || [];
tags = out.initialPreviewThumbTags || [];
append = out.append === undefined || out.append ? true : false;
self.overwriteInitial = false;
if ($thumb !== undefined && !allFiles) {
index = previewCache.add(self.id, content, config[0], tags[0], append);
data = previewCache.get(self.id, index, false);
$newThumb = $(data).hide();
$thumb.after($newThumb).fadeOut('slow', function () {
$newThumb.fadeIn('slow').css('display:inline-block');
self.initPreviewDeletes();
self.clearFileInput();
});
} else {
if (allFiles) {
self.uploadCache.content.push(content[0]);
self.uploadCache.config.push(config[0]);
self.uploadCache.tags.push(tags[0]);
self.uploadCache.append = append;
} else {
previewCache.set(self.id, content, config, tags, append);
self.initPreview();
self.initPreviewDeletes();
}
}
}
},
uploadSingle: function (i, files, allFiles) {
var self = this, total = self.getFileStack().length, formdata = new FormData(), outData,
previewId = self.previewInitId + "-" + i, $thumb = $('#' + previewId + ':not(.file-preview-initial)'),
pct, chkComplete, $btnUpload = $thumb.find('.kv-file-upload'), $btnDelete = $thumb.find('.kv-file-remove'),
$indicator = $thumb.find('.file-upload-indicator'), config = self.fileActionSettings,
hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
setIndicator, updateProgress, resetActions, fnBefore, fnSuccess, fnComplete, fnError,
params = {id: previewId, index: i};
self.formdata = formdata;
if (total === 0 || !hasPostData || $btnUpload.hasClass('disabled') || self.abort(params)) {
return;
}
chkComplete = function () {
var $thumbs = self.getThumbs('.file-uploading');
if ($thumbs.length > 0 || self.fileBatchCompleted) {
return;
}
self.fileBatchCompleted = true;
setTimeout(function () {
previewCache.set(self.id, self.uploadCache.content, self.uploadCache.config, self.uploadCache.tags,
self.uploadCache.append);
if (self.hasInitData) {
self.initPreview();
self.initPreviewDeletes();
}
self.setProgress(100);
self.unlock();
self.clearFileInput();
self.raise('filebatchuploadcomplete', [self.filestack, self.getExtraData()]);
}, 100);
};
setIndicator = function (icon, msg) {
$indicator.html(config[icon]);
$indicator.attr('title', config[msg]);
};
updateProgress = function () {
if (!allFiles || total === 0 || self.uploadPercent >= 100) {
return;
}
self.uploadCount += 1;
pct = 80 + Math.ceil(self.uploadCount * 20 / total);
self.uploadPercent = Math.max(pct, self.uploadPercent);
self.setProgress(self.uploadPercent);
self.initPreviewDeletes();
};
resetActions = function () {
$btnUpload.removeAttr('disabled');
$btnDelete.removeAttr('disabled');
$thumb.removeClass('file-uploading');
};
fnBefore = function (jqXHR) {
outData = self.getOutData(jqXHR);
setIndicator('indicatorLoading', 'indicatorLoadingTitle');
addCss($thumb, 'file-uploading');
$btnUpload.attr('disabled', true);
$btnDelete.attr('disabled', true);
if (!allFiles) {
self.lock();
}
self.raise('filepreupload', [outData, previewId, i]);
params = $.extend(params, outData);
if (self.abort(params)) {
jqXHR.abort();
self.setProgress(100);
}
};
fnSuccess = function (data, textStatus, jqXHR) {
outData = self.getOutData(jqXHR, data);
params = $.extend(params, outData);
setTimeout(function () {
if (data.error === undefined) {
setIndicator('indicatorSuccess', 'indicatorSuccessTitle');
$btnUpload.hide();
$btnDelete.hide();
self.filestack[i] = undefined;
self.raise('fileuploaded', [outData, previewId, i]);
self.initUploadSuccess(data, $thumb, allFiles);
if (!allFiles) {
self.resetFileStack();
}
} else {
setIndicator('indicatorError', 'indicatorErrorTitle');
self.showUploadError(data.error, params);
}
}, 100);
};
fnComplete = function () {
setTimeout(function () {
updateProgress();
resetActions();
if (!allFiles) {
self.unlock(false);
} else {
chkComplete();
}
}, 100);
};
fnError = function (jqXHR, textStatus, errorThrown) {
var errMsg = self.parseError(jqXHR, errorThrown, (allFiles ? files[i].name : null));
setIndicator('indicatorError', 'indicatorErrorTitle');
params = $.extend(params, self.getOutData(jqXHR));
self.showUploadError(errMsg, params);
};
formdata.append(self.uploadFileAttr, files[i]);
formdata.append('file_id', i);
self.ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
},
uploadBatch: function () {
var self = this, files = self.filestack, total = files.length, config,
hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
setIndicator, setAllUploaded, enableActions, fnBefore, fnSuccess, fnComplete, fnError,
params = {};
self.formdata = new FormData();
if (total === 0 || !hasPostData || self.abort(params)) {
return;
}
config = self.fileActionSettings;
setIndicator = function (i, icon, msg) {
var $indicator = $('#' + self.previewInitId + "-" + i).find('.file-upload-indicator');
$indicator.html(config[icon]);
$indicator.attr('title', config[msg]);
};
enableActions = function (i) {
var $thumb = $('#' + self.previewInitId + "-" + i + ':not(.file-preview-initial)'),
$btnUpload = $thumb.find('.kv-file-upload'),
$btnDelete = $thumb.find('.kv-file-delete');
$thumb.removeClass('file-uploading');
$btnUpload.removeAttr('disabled');
$btnDelete.removeAttr('disabled');
};
setAllUploaded = function () {
$.each(files, function (key) {
self.filestack[key] = undefined;
});
self.clearFileInput();
};
fnBefore = function (jqXHR) {
self.lock();
var outData = self.getOutData(jqXHR);
if (self.showPreview) {
self.getThumbs().each(function () {
var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'), $btnDelete = $thumb.find('.kv-file-remove');
addCss($thumb, 'file-uploading');
$btnUpload.attr('disabled', true);
$btnDelete.attr('disabled', true);
});
}
self.raise('filebatchpreupload', [outData]);
if (self.abort(outData)) {
jqXHR.abort();
}
};
fnSuccess = function (data, textStatus, jqXHR) {
var outData = self.getOutData(jqXHR, data), $thumbs = self.getThumbs(),
keys = isEmpty(data.errorkeys) ? [] : data.errorkeys;
if (data.error === undefined || isEmpty(data.error)) {
self.raise('filebatchuploadsuccess', [outData]);
setAllUploaded();
if (self.showPreview) {
$thumbs.find('.kv-file-upload').hide();
$thumbs.find('.kv-file-remove').hide();
$thumbs.each(function () {
var $thumb = $(this), key = $thumb.attr('data-fileindex');
setIndicator(key, 'indicatorSuccess', 'indicatorSuccessTitle');
enableActions(key);
});
self.initUploadSuccess(data);
} else {
self.reset();
}
} else {
if (self.showPreview) {
$thumbs.each(function () {
var $thumb = $(this), key = parseInt($thumb.attr('data-fileindex'), 10);
enableActions(key);
if (keys.length === 0) {
setIndicator(key, 'indicatorError', 'indicatorErrorTitle');
return;
}
if ($.inArray(key, keys) !== -1) {
setIndicator(key, 'indicatorError', 'indicatorErrorTitle');
} else {
$thumb.find('.kv-file-upload').hide();
$thumb.find('.kv-file-remove').hide();
setIndicator(key, 'indicatorSuccess', 'indicatorSuccessTitle');
self.filestack[key] = undefined;
}
});
self.initUploadSuccess(data);
}
self.showUploadError(data.error, outData, 'filebatchuploaderror');
}
};
fnComplete = function () {
self.setProgress(100);
self.unlock();
self.raise('filebatchuploadcomplete', [self.filestack, self.getExtraData()]);
self.clearFileInput();
};
fnError = function (jqXHR, textStatus, errorThrown) {
var outData = self.getOutData(jqXHR), errMsg = self.parseError(jqXHR, errorThrown);
self.showUploadError(errMsg, outData, 'filebatchuploaderror');
self.uploadFileCount = total - 1;
if (!self.showPreview) {
return;
}
self.getThumbs().each(function () {
var $thumb = $(this), key = $thumb.attr('data-fileindex');
$thumb.removeClass('file-uploading');
if (self.filestack[key] !== undefined) {
setIndicator(key, 'indicatorError', 'indicatorErrorTitle');
}
});
self.getThumbs().removeClass('file-uploading');
self.getThumbs(' .kv-file-upload').removeAttr('disabled');
self.getThumbs(' .kv-file-delete').removeAttr('disabled');
};
$.each(files, function (key, data) {
if (!isEmpty(files[key])) {
self.formdata.append(self.uploadFileAttr, data);
}
});
self.ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
},
uploadExtraOnly: function () {
var self = this, params = {}, fnBefore, fnSuccess, fnComplete, fnError;
self.formdata = new FormData();
if (self.abort(params)) {
return;
}
fnBefore = function (jqXHR) {
self.lock();
var outData = self.getOutData(jqXHR);
self.raise('filebatchpreupload', [outData]);
self.setProgress(50);
params.data = outData;
params.xhr = jqXHR;
if (self.abort(params)) {
jqXHR.abort();
self.setProgress(100);
}
};
fnSuccess = function (data, textStatus, jqXHR) {
var outData = self.getOutData(jqXHR, data);
if (data.error === undefined || isEmpty(data.error)) {
self.raise('filebatchuploadsuccess', [outData]);
self.clearFileInput();
self.initUploadSuccess(data);
} else {
self.showUploadError(data.error, outData, 'filebatchuploaderror');
}
};
fnComplete = function () {
self.setProgress(100);
self.unlock();
self.raise('filebatchuploadcomplete', [self.filestack, self.getExtraData()]);
self.clearFileInput();
};
fnError = function (jqXHR, textStatus, errorThrown) {
var outData = self.getOutData(jqXHR), errMsg = self.parseError(jqXHR, errorThrown);
params.data = outData;
self.showUploadError(errMsg, outData, 'filebatchuploaderror');
};
self.ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
},
hideFileIcon: function () {
if (this.overwriteInitial) {
this.$captionContainer.find('.kv-caption-icon').hide();
}
},
showFileIcon: function () {
this.$captionContainer.find('.kv-caption-icon').show();
},
resetErrors: function (fade) {
var self = this, $error = self.$errorContainer;
self.isError = false;
self.$container.removeClass('has-error');
$error.html('');
if (fade) {
$error.fadeOut('slow');
} else {
$error.hide();
}
},
showFolderError: function (folders) {
var self = this, $error = self.$errorContainer;
if (!folders) {
return;
}
$error.html(self.msgFoldersNotAllowed.repl('{n}', folders));
$error.fadeIn(800);
addCss(self.$container, 'has-error');
self.raise('filefoldererror', [folders]);
},
showUploadError: function (msg, params, event) {
var self = this, $error = self.$errorContainer, ev = event || 'fileuploaderror';
if ($error.find('ul').length === 0) {
$error.html('
');
} else {
$error.find('ul').append('
' + msg + '');
}
$error.fadeIn(800);
self.raise(ev, [params]);
addCss(self.$container, 'has-error');
return true;
},
showError: function (msg, params, event) {
var self = this, $error = self.$errorContainer, ev = event || 'fileerror';
params = params || {};
params.reader = self.reader;
$error.html(msg);
$error.fadeIn(800);
self.raise(ev, [params]);
if (!self.isUploadable) {
self.clearFileInput();
}
addCss(self.$container, 'has-error');
self.$btnUpload.attr('disabled', true);
return true;
},
errorHandler: function (evt, caption) {
var self = this, err = evt.target.error;
switch (err.code) {
case err.NOT_FOUND_ERR:
self.showError(self.msgFileNotFound.repl('{name}', caption));
break;
case err.SECURITY_ERR:
self.showError(self.msgFileSecured.repl('{name}', caption));
break;
case err.NOT_READABLE_ERR:
self.showError(self.msgFileNotReadable.repl('{name}', caption));
break;
case err.ABORT_ERR:
self.showError(self.msgFilePreviewAborted.repl('{name}', caption));
break;
default:
self.showError(self.msgFilePreviewError.repl('{name}', caption));
}
},
parseFileType: function (file) {
var self = this, isValid, vType, cat, i;
for (i = 0; i < defaultPreviewTypes.length; i += 1) {
cat = defaultPreviewTypes[i];
isValid = isSet(cat, self.fileTypeSettings) ? self.fileTypeSettings[cat] : defaultFileTypeSettings[cat];
vType = isValid(file.type, file.name) ? cat : '';
if (!isEmpty(vType)) {
return vType;
}
}
return 'other';
},
previewDefault: function (file, previewId, isDisabled) {
if (!this.showPreview) {
return;
}
var self = this, data = objUrl.createObjectURL(file), $obj = $('#' + previewId),
config = self.previewSettings.other,
footer = self.renderFileFooter(file.name, config.width),
previewOtherTemplate = self.getPreviewTemplate('other'),
ind = previewId.slice(previewId.lastIndexOf('-') + 1),
frameClass = '';
if (isDisabled === true) {
frameClass = ' btn disabled';
footer += '
';
}
self.$preview.append("\n" + previewOtherTemplate
.repl('{previewId}', previewId)
.repl('{frameClass}', frameClass)
.repl('{fileindex}', ind)
.repl('{caption}', self.slug(file.name))
.repl('{width}', config.width)
.repl('{height}', config.height)
.repl('{type}', file.type)
.repl('{data}', data)
.repl('{footer}', footer));
$obj.on('load', function () {
objUrl.revokeObjectURL($obj.attr('data'));
});
},
previewFile: function (file, theFile, previewId, data) {
if (!this.showPreview) {
return;
}
var self = this, cat = self.parseFileType(file), caption = self.slug(file.name), content, strText,
types = self.allowedPreviewTypes, mimes = self.allowedPreviewMimeTypes,
tmplt = self.getPreviewTemplate(cat),
config = isSet(cat, self.previewSettings) ? self.previewSettings[cat] : defaultPreviewSettings[cat],
wrapLen = parseInt(self.wrapTextLength, 10), wrapInd = self.wrapIndicator,
chkTypes = types.indexOf(cat) >= 0, id, height,
chkMimes = isEmpty(mimes) || (!isEmpty(mimes) && mimes.indexOf(file.type) !== -1),
footer = self.renderFileFooter(caption, config.width), modal = '',
ind = previewId.slice(previewId.lastIndexOf('-') + 1);
if (chkTypes && chkMimes) {
if (cat === 'text') {
strText = htmlEncode(theFile.target.result);
objUrl.revokeObjectURL(data);
if (strText.length > wrapLen) {
id = 'text-' + uniqId();
height = window.innerHeight * 0.75;
modal = self.getLayoutTemplate('modal').repl('{id}', id)
.repl('{title}', caption)
.repl('{height}', height)
.repl('{body}', strText);
wrapInd = wrapInd
.repl('{title}', caption)
.repl('{dialog}', "$('#" + id + "').modal('show')");
strText = strText.substring(0, (wrapLen - 1)) + wrapInd;
}
content = tmplt.repl('{previewId}', previewId).repl('{caption}', caption)
.repl('{frameClass}', '')
.repl('{type}', file.type).repl('{width}', config.width)
.repl('{height}', config.height).repl('{data}', strText)
.repl('{footer}', footer).repl('{fileindex}', ind) + modal;
} else {
content = tmplt.repl('{previewId}', previewId).repl('{caption}', caption)
.repl('{frameClass}', '')
.repl('{type}', file.type).repl('{data}', data)
.repl('{width}', config.width).repl('{height}', config.height)
.repl('{footer}', footer).repl('{fileindex}', ind);
}
self.$preview.append("\n" + content);
self.autoSizeImage(previewId);
} else {
self.previewDefault(file, previewId);
}
},
slugDefault: function (text) {
return isEmpty(text) ? '' : text.split(/(\\|\/)/g).pop().replace(/[^\w\u00C0-\u017F\-.\\\/ ]+/g, '');
},
getFileStack: function () {
var self = this;
return self.filestack.filter(function (n) {
return n !== undefined;
});
},
readFiles: function (files) {
this.reader = new FileReader();
var self = this, $el = self.$element, $preview = self.$preview, reader = self.reader,
$container = self.$previewContainer, $status = self.$previewStatus, msgLoading = self.msgLoading,
msgProgress = self.msgProgress, previewInitId = self.previewInitId, numFiles = files.length,
settings = self.fileTypeSettings, ctr = self.filestack.length,
throwError = function (msg, file, previewId, index) {
var p1 = $.extend(self.getOutData({}, {}, files), {id: previewId, index: index}),
p2 = {id: previewId, index: index, file: file, files: files};
self.previewDefault(file, previewId, true);
return self.isUploadable ? self.showUploadError(msg, p1) : self.showError(msg, p2);
};
function readFile(i) {
if (isEmpty($el.attr('multiple'))) {
numFiles = 1;
}
if (i >= numFiles) {
if (self.isUploadable && self.filestack.length > 0) {
self.raise('filebatchselected', [self.getFileStack()]);
} else {
self.raise('filebatchselected', [files]);
}
$container.removeClass('loading');
$status.html('');
return;
}
var node = ctr + i, previewId = previewInitId + "-" + node, isText, file = files[i],
caption = self.slug(file.name), fileSize = (file.size || 0) / 1000, checkFile, fileExtExpr = '',
previewData = objUrl.createObjectURL(file), fileCount = 0, j, msg, typ, chk,
fileTypes = self.allowedFileTypes, strTypes = isEmpty(fileTypes) ? '' : fileTypes.join(', '),
fileExt = self.allowedFileExtensions, strExt = isEmpty(fileExt) ? '' : fileExt.join(', ');
if (!isEmpty(fileExt)) {
fileExtExpr = new RegExp('\\.(' + fileExt.join('|') + ')$', 'i');
}
fileSize = fileSize.toFixed(2);
if (self.maxFileSize > 0 && fileSize > self.maxFileSize) {
msg = self.msgSizeTooLarge.repl('{name}', caption)
.repl('{size}', fileSize)
.repl('{maxSize}', self.maxFileSize);
self.isError = throwError(msg, file, previewId, i);
return;
}
if (!isEmpty(fileTypes) && isArray(fileTypes)) {
for (j = 0; j < fileTypes.length; j += 1) {
typ = fileTypes[j];
checkFile = settings[typ];
chk = (checkFile !== undefined && checkFile(file.type, caption));
fileCount += isEmpty(chk) ? 0 : chk.length;
}
if (fileCount === 0) {
msg = self.msgInvalidFileType.repl('{name}', caption).repl('{types}', strTypes);
self.isError = throwError(msg, file, previewId, i);
return;
}
}
if (fileCount === 0 && !isEmpty(fileExt) && isArray(fileExt) && !isEmpty(fileExtExpr)) {
chk = caption.match(fileExtExpr);
fileCount += isEmpty(chk) ? 0 : chk.length;
if (fileCount === 0) {
msg = self.msgInvalidFileExtension.repl('{name}', caption).repl('{extensions}',
strExt);
self.isError = throwError(msg, file, previewId, i);
return;
}
}
if (!self.showPreview) {
self.filestack.push(file);
setTimeout(readFile(i + 1), 100);
self.raise('fileloaded', [file, previewId, i, reader]);
return;
}
if ($preview.length > 0 && FileReader !== undefined) {
$status.html(msgLoading.repl('{index}', i + 1).repl('{files}', numFiles));
$container.addClass('loading');
reader.onerror = function (evt) {
self.errorHandler(evt, caption);
};
reader.onload = function (theFile) {
self.previewFile(file, theFile, previewId, previewData);
self.initFileActions();
};
reader.onloadend = function () {
msg = msgProgress
.repl('{index}', i + 1).repl('{files}', numFiles)
.repl('{percent}', 50).repl('{name}', caption);
setTimeout(function () {
$status.html(msg);
objUrl.revokeObjectURL(previewData);
}, 100);
setTimeout(function () {
readFile(i + 1);
self.updateFileDetails(numFiles);
}, 100);
self.raise('fileloaded', [file, previewId, i, reader]);
};
reader.onprogress = function (data) {
if (data.lengthComputable) {
var fact = (data.loaded / data.total) * 100, progress = Math.ceil(fact);
msg = msgProgress.repl('{index}', i + 1).repl('{files}', numFiles)
.repl('{percent}', progress).repl('{name}', caption);
setTimeout(function () {
$status.html(msg);
}, 100);
}
};
isText = isSet('text', settings) ? settings.text : defaultFileTypeSettings.text;
if (isText(file.type, caption)) {
reader.readAsText(file, self.textEncoding);
} else {
reader.readAsArrayBuffer(file);
}
} else {
self.previewDefault(file, previewId);
setTimeout(function () {
readFile(i + 1);
self.updateFileDetails(numFiles);
}, 100);
self.raise('fileloaded', [file, previewId, i, reader]);
}
self.filestack.push(file);
}
readFile(0);
self.updateFileDetails(numFiles, false);
},
updateFileDetails: function (numFiles) {
var self = this, $el = self.$element, fileStack = self.getFileStack(),
name = $el.val() || (fileStack.length && fileStack[0].name) || '', label = self.slug(name),
n = self.isUploadable ? fileStack.length : numFiles,
nFiles = previewCache.count(self.id) + n,
log = n > 1 ? self.getMsgSelected(nFiles) : label;
if (self.isError) {
self.$previewContainer.removeClass('loading');
self.$previewStatus.html('');
self.$captionContainer.find('.kv-caption-icon').hide();
} else {
self.showFileIcon();
}
self.setCaption(log, self.isError);
self.$container.removeClass('file-input-new file-input-ajax-new');
if (arguments.length === 1) {
self.raise('fileselect', [numFiles, label]);
}
if (previewCache.count(self.id)) {
self.initPreviewDeletes();
}
},
change: function (e) {
var self = this, $el = self.$element;
if (!self.isUploadable && isEmpty($el.val()) && self.fileInputCleared) { // IE 11 fix
self.fileInputCleared = false;
return;
}
self.fileInputCleared = false;
var tfiles, msg, total, $preview = self.$preview, isDragDrop = arguments.length > 1,
files = isDragDrop ? e.originalEvent.dataTransfer.files : $el.get(0).files,
isSingleUpload = isEmpty($el.attr('multiple')), i = 0, f, m, folders = 0,
ctr = self.filestack.length, isAjaxUpload = self.isUploadable,
throwError = function (mesg, file, previewId, index) {
var p1 = $.extend(self.getOutData({}, {}, files), {id: previewId, index: index}),
p2 = {id: previewId, index: index, file: file, files: files};
return self.isUploadable ? self.showUploadError(mesg, p1) : self.showError(mesg, p2);
};
self.reader = null;
self.resetUpload();
self.hideFileIcon();
if (self.isUploadable) {
self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove();
}
if (isDragDrop) {
tfiles = [];
while (files[i]) {
f = files[i];
if (!f.type && f.size % 4096 === 0) {
folders++;
} else {
tfiles.push(f);
}
i++;
}
} else {
if (e.target.files === undefined) {
tfiles = e.target && e.target.value ? [
{name: e.target.value.replace(/^.+\\/, '')}
] : [];
} else {
tfiles = e.target.files;
}
}
if (isEmpty(tfiles) || tfiles.length === 0) {
if (!isAjaxUpload) {
self.clear();
}
self.showFolderError(folders);
self.raise('fileselectnone');
return;
}
self.resetErrors();
if (!isAjaxUpload || (isSingleUpload && ctr > 0)) {
if (!self.overwriteInitial && previewCache.count(self.id)) {
var out = previewCache.out(self.id);
$preview.html(out.content);
self.setCaption(out.caption);
self.initPreviewDeletes();
} else {
$preview.html('');
}
if (isSingleUpload && ctr > 0) {
self.filestack = [];
}
}
total = self.isUploadable ? self.getFileStack().length + tfiles.length : tfiles.length;
if (self.maxFileCount > 0 && total > self.maxFileCount) {
msg = self.msgFilesTooMany.repl('{m}', self.maxFileCount).repl('{n}', total);
self.isError = throwError(msg, null, null, null);
self.$captionContainer.find('.kv-caption-icon').hide();
self.$caption.html(self.msgValidationError);
self.setEllipsis();
self.$container.removeClass('file-input-new file-input-ajax-new');
return;
}
if (!self.isIE9) {
self.readFiles(tfiles);
} else {
self.updateFileDetails(1);
}
self.showFolderError(folders);
},
autoSizeImage: function (previewId) {
var self = this, $preview = self.$preview,
$thumb = $preview.find("#" + previewId),
$img = $thumb.find('img'), w1, w2, $cap;
if (!$img.length) {
return;
}
$img.on('load', function () {
w1 = $thumb.width();
w2 = $preview.width();
if (w1 > w2) {
$img.css('width', '100%');
$thumb.css('width', '97%');
}
$cap = $img.closest('.file-preview-frame').find('.file-caption-name');
if ($cap.length) {
$cap.width($img.width());
$cap.attr('title', $cap.text());
}
self.raise('fileimageloaded', previewId);
});
},
initCaption: function () {
var self = this, cap = self.initialCaption || '';
if (self.overwriteInitial || isEmpty(cap)) {
self.$caption.html('');
return false;
}
self.setCaption(cap);
return true;
},
setCaption: function (content, isError) {
var self = this, err = isError || false, title, out;
if (err) {
title = $('
' + self.msgValidationError + '
').text();
out = '
' +
self.msgValidationErrorIcon + title + '';
} else {
if (isEmpty(content) || self.$caption.length === 0) {
return;
}
title = $('
' + content + '
').text();
out = self.getLayoutTemplate('icon') + title;
}
self.$caption.html(out);
self.$caption.attr('title', title);
self.$captionContainer.find('.file-caption-ellipsis').attr('title', title);
self.setEllipsis();
},
initBrowse: function ($container) {
var self = this;
self.$btnFile = $container.find('.btn-file');
self.$btnFile.append(self.$element);
},
createContainer: function () {
var self = this,
$container = $(document.createElement("span"))
.attr({"class": 'file-input file-input-new'})
.html(self.renderMain());
self.$element.before($container);
self.initBrowse($container);
return $container;
},
refreshContainer: function () {
var self = this, $container = self.$container;
$container.before(self.$element);
$container.html(self.renderMain());
self.initBrowse($container);
},
renderMain: function () {
var self = this, dropCss = (self.isUploadable && self.dropZoneEnabled) ? ' file-drop-zone' : '',
preview = self.showPreview ? self.getLayoutTemplate('preview').repl('{class}', self.previewClass)
.repl('{dropClass}', dropCss) : '',
css = self.isDisabled ? self.captionClass + ' file-caption-disabled' : self.captionClass,
caption = self.captionTemplate.repl('{class}', css + ' kv-fileinput-caption');
return self.mainTemplate.repl('{class}', self.mainClass)
.repl('{preview}', preview)
.repl('{caption}', caption)
.repl('{upload}', self.renderUpload())
.repl('{remove}', self.renderRemove())
.repl('{cancel}', self.renderCancel())
.repl('{browse}', self.renderBrowse());
},
renderBrowse: function () {
var self = this, css = self.browseClass + ' btn-file', status = '';
if (self.isDisabled) {
status = ' disabled ';
}
return '
' + self.browseIcon + self.browseLabel + '
';
},
renderRemove: function () {
var self = this, css = self.removeClass + ' fileinput-remove fileinput-remove-button', status = '';
if (!self.showRemove) {
return '';
}
if (self.isDisabled) {
status = ' disabled ';
}
return '';
},
renderCancel: function () {
var self = this, css = self.cancelClass + ' fileinput-cancel fileinput-cancel-button';
if (!self.showCancel) {
return '';
}
return '
';
},
renderUpload: function () {
var self = this, css = self.uploadClass + ' kv-fileinput-upload fileinput-upload-button', content = '', status = '';
if (!self.showUpload) {
return '';
}
if (self.isDisabled) {
status = ' disabled ';
}
if (!self.isUploadable || self.isDisabled) {
content = '';
} else {
content = '';
}
return content;
}
};
//FileInput plugin definition
$.fn.fileinput = function (option) {
if (!hasFileAPISupport() && !isIE(9)) {
return;
}
var args = Array.apply(null, arguments);
args.shift();
return this.each(function () {
var $this = $(this),
data = $this.data('fileinput'),
options = typeof option === 'object' && option;
if (!data) {
data = new FileInput(this, $.extend({}, $.fn.fileinput.defaults, options, $(this).data()));
$this.data('fileinput', data);
}
if (typeof option === 'string') {
data[option].apply(data, args);
}
});
};
$.fn.fileinput.defaults = {
showCaption: true,
showPreview: true,
showRemove: true,
showUpload: true,
showCancel: true,
mainClass: '',
previewClass: '',
captionClass: '',
mainTemplate: null,
initialCaption: '',
initialPreview: [],
initialPreviewDelimiter: '*$$*',
initialPreviewConfig: [],
initialPreviewThumbTags: [],
previewThumbTags: {},
initialPreviewShowDelete: true,
deleteUrl: '',
deleteExtraData: {},
overwriteInitial: true,
layoutTemplates: defaultLayoutTemplates,
previewTemplates: defaultPreviewTemplates,
allowedPreviewTypes: defaultPreviewTypes,
allowedPreviewMimeTypes: null,
allowedFileTypes: null,
allowedFileExtensions: null,
customLayoutTags: {},
customPreviewTags: {},
previewSettings: defaultPreviewSettings,
fileTypeSettings: defaultFileTypeSettings,
previewFileIcon: '
',
browseIcon: '
',
browseClass: 'btn btn-primary',
removeIcon: '
',
removeClass: 'btn btn-default',
cancelIcon: '
',
cancelClass: 'btn btn-default',
uploadIcon: '
',
uploadClass: 'btn btn-default',
uploadUrl: null,
uploadAsync: true,
uploadExtraData: {},
maxFileSize: 0,
minFileCount: 0,
maxFileCount: 0,
msgValidationErrorClass: 'text-danger',
msgValidationErrorIcon: '
',
msgErrorClass: 'file-error-message',
progressClass: "progress-bar progress-bar-success progress-bar-striped active",
progressCompleteClass: "progress-bar progress-bar-success",
previewFileType: 'image',
wrapTextLength: 250,
wrapIndicator: '
[…]',
elCaptionContainer: null,
elCaptionText: null,
elPreviewContainer: null,
elPreviewImage: null,
elPreviewStatus: null,
elErrorContainer: null,
slugCallback: null,
dropZoneEnabled: true,
dropZoneTitleClass: 'file-drop-zone-title',
fileActionSettings: {},
otherActionButtons: '',
textEncoding: 'UTF-8',
ajaxSettings: {},
ajaxDeleteSettings: {},
showAjaxErrorDetails: true
};
$.fn.fileinput.locales = {};
$.fn.fileinput.locales.en = {
fileSingle: 'file',
filePlural: 'files',
browseLabel: 'Browse …',
removeLabel: 'Remove',
removeTitle: 'Clear selected files',
cancelLabel: 'Cancel',
cancelTitle: 'Abort ongoing upload',
uploadLabel: 'Upload',
uploadTitle: 'Upload selected files',
msgSizeTooLarge: 'File "{name}" (
{size} KB) exceeds maximum allowed upload size of
{maxSize} KB. Please retry your upload!',
msgFilesTooLess: 'You must select at least
{n} {files} to upload. Please retry your upload!',
msgFilesTooMany: 'Number of files selected for upload
({n}) exceeds maximum allowed limit of
{m}. Please retry your upload!',
msgFileNotFound: 'File "{name}" not found!',
msgFileSecured: 'Security restrictions prevent reading the file "{name}".',
msgFileNotReadable: 'File "{name}" is not readable.',
msgFilePreviewAborted: 'File preview aborted for "{name}".',
msgFilePreviewError: 'An error occurred while reading the file "{name}".',
msgInvalidFileType: 'Invalid type for file "{name}". Only "{types}" files are supported.',
msgInvalidFileExtension: 'Invalid extension for file "{name}". Only "{extensions}" files are supported.',
msgValidationError: 'File Upload Error',
msgLoading: 'Loading file {index} of {files} …',
msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
msgSelected: '{n} {files} selected',
msgFoldersNotAllowed: 'Drag & drop files only! {n} folder(s) dropped were skipped.',
dropZoneTitle: 'Drag & drop files here …'
};
$.extend($.fn.fileinput.defaults, $.fn.fileinput.locales.en);
$.fn.fileinput.Constructor = FileInput;
/**
* Convert automatically file inputs with class 'file'
* into a bootstrap fileinput control.
*/
$(document).ready(function () {
var $input = $('input.file[type=file]'), count = $input.attr('type') ? $input.length : 0;
if (count > 0) {
$input.fileinput();
}
});
})(window.jQuery);
================================================
FILE: public/assets/dashboard/js/fileinput_locale_zh.js
================================================
/*!
* FileInput Chinese Translations
*
* This file must be loaded after 'fileinput.js'. Patterns in braces '{}', or
* any HTML markup tags in the messages must not be converted or translated.
*
* @see http://github.com/kartik-v/bootstrap-fileinput
* @author kangqf
*
* NOTE: this file must be saved in UTF-8 encoding.
*/
(function ($) {
"use strict";
$.fn.fileinput.locales.zh = {
fileSingle: '文件',
filePlural: '多个文件',
browseLabel: '选择 …',
removeLabel: '移除全部',
removeTitle: '清除选中文件',
cancelLabel: '取消',
cancelTitle: '取消进行中的上传',
uploadLabel: '上传',
uploadTitle: '上传选中文件',
msgSizeTooLarge: '文件 "{name}" ({size} KB) 超过了允许大小 {maxSize} KB. 请重新上传!',
msgFilesTooLess: '你必须选择最少 {n} {files} 来上传. 请重新上传!',
msgFilesTooMany: '选择的上传文件个数 ({n}) 超出最大文件的限制个数 {m}. 请重新上传!',
msgFileNotFound: '文件 "{name}" 未找到!',
msgFileSecured: '安全限制,为了防止读取文件 "{name}".',
msgFileNotReadable: '文件 "{name}" 不可读.',
msgFilePreviewAborted: '取消 "{name}" 的预览.',
msgFilePreviewError: '读取 "{name}" 时出现了一个错误.',
msgInvalidFileType: '不正确的类型 "{name}". 只支持 "{types}" 类型的文件.',
msgInvalidFileExtension: '不正确的文件扩展名 "{name}". 只支持 "{extensions}" 的文件扩展名.',
msgValidationError: '文件上传错误',
msgLoading: '加载第 {index} 文件 共 {files} …',
msgProgress: '加载第 {index} 文件 共 {files} - {name} - {percent}% 完成.',
msgSelected: '{n} {files} 选中',
msgFoldersNotAllowed: '只支持拖拽文件! 跳过 {n} 拖拽的文件夹.',
dropZoneTitle: '拖拽文件到这里 …',
slugCallback: function(text) {
return text ? text.split(/(\\|\/)/g).pop().replace(/[^\w\u4e00-\u9fa5\-.\\\/ ]+/g, '') : '';
}
};
$.extend($.fn.fileinput.defaults, $.fn.fileinput.locales.zh);
})(window.jQuery);
================================================
FILE: public/assets/dashboard/js/global.js
================================================
/**
* Created by PhpKiller.
* User: Across The Pacific
* Date: 2016/12/29
* Time: 15:33
* 鸿杰 张
*/
//公共js文件
/**
* ajax提交表单检测
*@param var status 检测条件
*@param var value 检测字段值
*@param var value 提示消息
* */
var isEmpty = function (status, value, msg) {
if (status === $.trim(value)) {//trim 去除空格
layer.msg(msg, {icon: 5, time: 1000, shade: [0.8, '#393D49']}, function (index) {
layer.close(index);
});
return false;
}
};
/**
* jquery 正则检测
*@param var reg 正则匹配条件
*@param var value 检测字段值
*@param var value 提示消息
* */
var prexRule = function (reg, value, msg) {
if (!reg.test(value)) {
layer.msg(msg, {icon: 5, time: 1000, shade: [0.8, '#393D49']}, function (index) {
layer.close(index);
});
return false;
}
};
/**
* 修改指定表的某一字段值
*@param var table 表名
*@param var column 字段名
*@param var value 字段值
*@param var msg 提示消息
* */
function updateSort(obj) {
var id = $(obj).attr("data-id");
var table = $(obj).attr("data-table");
var column = $(obj).attr("data-column");
var value = $(obj).val();
var msg = $(obj).attr('data-msg');
$.ajax({
url:"/dashboard/commonStatus?id="+id+'&table='+table+'&column='+column+'&value='+value,
success: function (data) {
if (data.status == 1) {
layer.msg(msg, {icon: 1, time: 1000, shade: [0.8, '#393D49']}, function (index) {
layer.close(index);
});
} else {
layer.msg(data.msg, {icon: 5, time: 1000, shade: [0.8, '#393D49']}, function (index) {
window.location.reload();
});
}
}
});
};
/**
* 点击刷新列表页
* */
var refresh = function () {
layer.msg('更新成功', {icon: 1, time: 1000, shade: [0.8, '#393D49']}, function () {
location.href = location.href;
});
}
/**
* jquery全选
*@param var obj this对象
* */
var checkAll = function (obj) {
$('input[name *= \'ids\']').prop('checked', obj.checked)
};
/**
* jquery获取选中的id
*@param var obj this对象
*@param var id 要删除的主键
*@param var attr('data-url') 要调用的url
* */
var getIds = function (obj) {
var a = [];
$("input[name *= ids]").each(function (i, o) {
if ($(o).is(":checked")) {
a.push($(o).val());
}
});
var url = $(obj).attr('data-url')
delBtn('', a, url)
}
/**
* jquery删除数据
*@param var obj this对象
*@param var a 批量删除的主键
*@param var urla 要调用的url
*@param var attr('data-id') 要删除的id(单条)
*@param var attr('data-name') 要删除name(单条)
*@param var attr('data-url') 要调用的url(单条)
* */
var delBtn = function (obj, a, urla) {
if (a) {
var id = a
var name = '所选择的'
var url = urla
} else {
var id = $(obj).attr('data-id')
var name = $(obj).attr('data-name')
var url = $(obj).attr('data-url')
}
if (isEmpty('', id, '请选择要删除的数据') == false) {
return false;
}
layer.confirm('确定要删除' + '' + name + '' + '吗?', {icon: 3}, function () {
$.ajax({
type: 'POST',
url: url,
data: {
ids: id
},
dataType: "json",
beforeSend: function () {
layer.closeAll();
},
success: function (data) {
layer.closeAll();
if (data.status == 1) {
layer.msg(data.msg, {icon: 1, time: 1000, shade: [0.8, '#393D49']}, function () {
location.href = location.href;
});
} else {
layer.msg(data.msg, {icon: 5, time: 1000, shade: [0.8, '#393D49']}, function (index) {
layer.close(index);
});
}
},
});
});
};
/*数据库优化|修复
*@param var obj this对象
*@param var msg 没有选中时提示消息
*@param var tab tab是单张表,没有值则为批量操作
*@param var url 要调用的url
* */
var jqOptimize = function (obj, msg, tab) {
if (tab) {
var a = tab;
} else {
var a = [];
$("input[name *= ids]").each(function (i, o) {
if ($(o).is(":checked")) {
a.push($(o).val());
}
});
}
if (a.length == 0) {
layer.msg('请选择要' + msg + '的数据表', {icon: 5, time: 2000}, function (index) {
layer.close(index);
return;
});
} else {
$(obj).addClass('disabled');
$(obj).html(msg + '中...');
$.ajax({
type: 'post',
url: $(obj).attr('data-url'),
dataType: 'json',
data: {tables: a},
success: function (data) {
if (data.code == 1) {
layer.msg(data.msg, {icon: 1, time: 2000, shade: [0.8, '#393D49']}, function (index) {
location.href = location.href;
});
} else {
layer.msg(data.msg, {icon: 5, time: 2000, shade: [0.8, '#393D49']}, function (index) {
location.href = location.href;
});
}
},
error: function () {
layer.msg(data.msg, {icon: 5, time: 2000, shade: [0.8, '#393D49']}, function (index) {
return false;
});
}
});
}
};
/*ajax分页
*@param var form 表单id
*@param var url 要调用的url
* */
var ajaxList = function (form, url) {
$.ajax({
type: 'POST',
url: url,
data: $('#' + form).serialize(),//导航搜索
success: function (data) {
$('#ajax_return').html('');
$('#ajax_return').append(data);
$(".spiner-example").css('display', 'none');
},
});
};
/*jquery文件上传[注意:需要引入jquery.easyui.min.js]
*@param url 文件上传控制器url
*@param path 要上传到哪个目录下
*@param input_name input框的name
* */
$(document).ready(function () {//打开页面执行
html = "';
$('body').append(html);
});
$(document).delegate('[uploader]', 'click', function () {//找到属性,点击时执行
var s = $(this);
var url = s.attr('data-url');
var path = s.attr('data-path');
var input_name = s.attr('uploader');
var f = $("[up=file]");
f.click();
f.change(function () {
if (!input_name) {
return false;
}
$("#upload").form('submit', {
type: 'post',
url: url,
onSubmit: function (param) {
param.path = path;
},
success: function (res) {
var obj = eval('(' + res + ')');
if (obj.status == 1) {
$("#" + input_name).val(obj.msg);
$("#" + input_name + "_img").attr('src', obj.msg);
} else {
layer.msg(obj.msg, {icon: 5, time: 1000, shade: [0.8, '#393D49']}, function (index) {
layer.close(index);
});
}
input_name = false;
},
});
});
});
/**
* 时间插件
*@param $pagesize 每一页的总数
*@param min 最小时间
*@param tody 是否显示今天
*/
$(document).delegate('[time_plugin]', 'click', function () {//找到属性,点击时执行
var s = $(this);
var min = s.attr('data-min');
var namea = s.attr('data-min');
//var now = show();
var now = '2017-03-01';
var tody = true;
if (min != 'input') {
now = $("input[name ='" + namea + "']").val()
tody = false;
}
laydate({
istime: true, format: 'YYYY-MM-DD hh:mm:ss',
istoday: true, //是否显示今天
festival: true, //是否显示节日
min: now, //最小日期
issure: true, //是否显示确认
max: '2099-12-31 23:59:59', //最大日期
fixed: false, //是否固定在可视区域
zIndex: 99999999, //css z-index
choose: function (dates) { //选择好日期的回调
}
});
});
/**
* 获取当前日期
*/
function show() {
var d = new Date();//定义一个date对象d
var month = d.getMonth() + 1;//从d中获取月份
var day = d.getDate();//日
var time = d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds();//组装时间参数
var timea = d.getFullYear() + '-' + (month < 10 ? '0' : '') + month + '-' + (day < 10 ? '0' : '') + day + " " + time;
return timea;//2017-03-17 15:42:15
}
/**获取活动剩余天数 小时 分钟
//倒计时js代码精确到时分秒,使用方法:注意 var EndTime= new Date('2013/05/1 10:00:00');
//截止时间 这一句,特别是 '2013/05/1 10:00:00' 这个js日期格式一定要注意,否则在IE6、7下工作计算不正确哦。
//js代码如下:
**/
function GetRTime(end_time) {
console.log(end_time);
// var EndTime= new Date('2016/05/1 10:00:00'); //截止时间 前端路上 http://www.51xuediannao.com/qd63/
var EndTime = new Date(end_time); //截止时间 前端路上 http://www.51xuediannao.com/qd63/
var NowTime = new Date();
var t = EndTime.getTime() - NowTime.getTime();
var d = Math.floor(t / 1000 / 60 / 60 / 24);
var h = Math.floor(t / 1000 / 60 / 60 % 24);
var m = Math.floor(t / 1000 / 60 % 60);
var s = Math.floor(t / 1000 % 60);
if (s >= 0) {
if (d == 0) {
return h + '小时' + m + '分' + s + '秒';
}
if (h == 0) {
return m + '分' + s + '秒';
}
return d + '天' + h + '小时' + m + '分' + s + '秒';
}
}
/**
* 异步显示隐藏
*@param id 表id
*@param table 表名
*@param column 字段名
*@param value 要改成什么值
*@param todo 为1表示要开启check,0表示要关闭close
*@param cv 当前的值
*@param cur 当前的msg
*@param msg 要改成什么值
*/
var changeStatus = function (obj) {
var todo = $(obj).attr('data-todo');
var cv = $(obj).attr('data-cv');
var cur = $(obj).attr('data-cur');
var msg = $(obj).attr('data-msg');
var value = $(obj).attr('data-value');
var id = $(obj).attr('data-id');
var table = $(obj).attr('data-table');
var column = $(obj).attr('data-column');
$.ajax({
url:"/dashboard/commonStatus?id="+id+'&table='+table+'&column='+column+'&value='+value,
success: function (data) {
if(data.status == 0) {
layer.msg(data.msg, {icon: 5, time: 1000, shade: [0.8, '#393D49']}, function (index) {
layer.close(index);
});
} else {
layer.msg(data.msg, {icon: 1, time: 1000, shade: [0.8, '#393D49']}, function (index) {
layer.close(index);
});
}
if (todo > 0) {
$(obj).removeClass('fa-close').addClass('fa-check');
$(obj).attr('data-todo', 0);
} else {
$(obj).removeClass('fa-check').addClass('fa-close');
$(obj).attr('data-todo', 1);
}
$(obj).html(msg);
$(obj).attr('data-value', cv);
$(obj).attr('data-cv', value);
$(obj).attr('data-msg', cur);
$(obj).attr('data-cur', msg);
}
});
};
/**
* 获取多级联动的商品分类
*@param id 当前选中的id
*@param next 要填充的id
*@param select_id 当前选中的id
*/
var getNextCate = function (id, next, select_id) {
var url = "/admin/Goods/ajaxGetNext/pid/" + id;
$.ajax({
type: "GET",
url: url,
error: function (request) {
layer.msg('服务器繁忙, 请联系管理员!', {icon: 5, time: 1000, shade: [0.8, '#393D49']}, function (index) {
layer.close(index);
});
return;
},
success: function (v) {
v = "" + v;
$('#' + next).empty().html(v);
(select_id > 0) && $('#' + next).val(select_id);//默认选中
}
});
}
/**
* 序列化表单ajax异步提交
*@param url 控制器url
*@param formId 表单id
*/
function ajaxFormBtn(url, formId, layerClose) {
$.ajax({
type: 'post',
url: url,
data: $("#" + formId).serialize(),
success: function (data) {
if (data.status == 1) {
layer.msg(data.msg, {icon: 1, time: 1000, shade: [0.8, '#393D49']}, function () {
if (layerClose) {
parent.layer.closeAll();
}
window.location = data.url;
});
} else {
layer.msg(data.msg, {icon: 5, time: 1000, shade: [0.8, '#393D49']});
return false;
}
},
error: function (data) {
if (data.status == 422) {
var responseJSON = data.responseJSON;
let content = '';
for (var k in responseJSON) {
let value = responseJSON[k];
content += '' + value[0] + '
';
}
layer.msg(content, {icon: 5, time: 2000, shade: [0.8, '#393D49']});
} else if (data.status == 403) {
layer.msg('你没有权限这么做', {icon: 5, time: 2000, shade: [0.8, '#393D49']});
} else {
layer.msg('网络错误,请稍后复试', {icon: 5, time: 2000, shade: [0.8, '#393D49']});
}
return false;
}
});
}
/**
* 读取 cookie
*@param c_name cookie名字
*/
function getCookie(c_name) {
if (document.cookie.length > 0) {
c_start = document.cookie.indexOf(c_name + "=")
if (c_start != -1) {
c_start = c_start + c_name.length + 1
c_end = document.cookie.indexOf(";", c_start)
if (c_end == -1) c_end = document.cookie.length
return unescape(document.cookie.substring(c_start, c_end))
}
}
return 0;
}
/**
* 设置 cookie
*@param name cookie名字
*@param value cookie值
*@param time cookie有效期
*/
function setCookies(name, value, time) {
var cookieString = name + "=" + escape(value) + ";";
if (time != 0) {
var Times = new Date();
Times.setTime(Times.getTime() + time);
cookieString += "expires=" + Times.toGMTString() + ";"
}
document.cookie = cookieString;
}
/**
* 点击收藏商品
*@param goods_id 商品id
*/
function collectGoods(goods_id) {
$.ajax({
type: "POST",
url: "/mobile/Goods/collectGoods",
data: {goods_id: goods_id},
dataType: 'json',
success: function (data) {
layer.open({content: data.msg, time: 1});
return false;
},
error: function () {
layer.open({content: '网络错误,请稍后再试', time: 1});
return false;
}
});
}
/**
* 根据省份id获取省份下面的城市列表
*/
function getCity(obj) {
var pid = $(obj).val();//当前选中的省id
$("#district").empty().html('');
$('#twon').empty().css('display', 'none');
$.ajax({
type: "POST",
url: "/home/Api/getRegion/level/2/pid/" + pid,
success: function (data) {
var res = '' + data;
$("#city").empty().html(res);
},
error: function () {
layer.open({content: '网络错误,请稍后再试', time: 1});
return false;
}
});
};
/**
* 根据城市id获取下面的地区列表
*/
function getArea(obj) {
var pid = $(obj).val();//当前选中的省id
$('#twon').empty().css('display', 'none');
$.ajax({
type: "POST",
url: "/home/Api/getRegion/level/3/pid/" + pid,
success: function (data) {
var res = '' + data;
$("#district").empty().html(res);
},
error: function () {
layer.open({content: '网络错误,请稍后再试', time: 1});
return false;
}
});
};
/**
* 根据地区id获取下面的乡镇列表
*/
function getTown(obj) {
var pid = $(obj).val();//当前选中的省id
$.ajax({
type: "POST",
url: "/home/Api/getTwon/pid/" + pid,
success: function (data) {
if (parseInt(data) == 0) {
$('#twon').empty().css('display', 'none');
} else {
$('#twon').css('display', 'block');
$('#twon').empty().html(data);
}
},
error: function () {
layer.open({content: '网络错误,请稍后再试', time: 1});
return false;
}
});
};
// // 保存按钮 enter
// document.onkeydown = function (event) {
// var e = event || window.event || arguments.callee.caller.arguments[0];
// if (e && e.keyCode == 13) { // enter 键
// $('.saveBtn').click();
// }
// };
================================================
FILE: public/assets/dashboard/js/jquery.form.js
================================================
/*!
* jQuery Form Plugin
* version: 3.51.0-2014.06.20
* Requires jQuery v1.5 or later
* Copyright (c) 2014 M. Alsup
* Examples and documentation at: http://malsup.com/jquery/form/
* Project repository: https://github.com/malsup/form
* Dual licensed under the MIT and GPL licenses.
* https://github.com/malsup/form#copyright-and-license
*/
/*global ActiveXObject */
// AMD support
(function (factory) {
"use strict";
if (typeof define === 'function' && define.amd) {
// using AMD; register as anon module
define(['jquery'], factory);
} else {
// no AMD; invoke directly
factory( (typeof(jQuery) != 'undefined') ? jQuery : window.Zepto );
}
}
(function($) {
"use strict";
/*
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,
$(document).ready(function() {
$('#myForm').on('submit', function(e) {
e.preventDefault(); // <-- important
$(this).ajaxSubmit({
target: '#output'
});
});
});
Use ajaxForm when you want the plugin to manage all the event binding
for you. For example,
$(document).ready(function() {
$('#myForm').ajaxForm({
target: '#output'
});
});
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 = $("").get(0).files !== undefined;
feature.formdata = window.FormData !== undefined;
var hasProp = !!$.fn.prop;
// attr2 uses prop when it can but checks the return type for
// an expected string. this accounts for the case where a form
// contains inputs with names like "action" or "method"; in those
// cases "prop" returns the element
$.fn.attr2 = function() {
if ( ! hasProp ) {
return this.attr.apply(this, arguments);
}
var val = this.prop.apply(this, arguments);
if ( ( val && val.jquery ) || typeof val === 'string' ) {
return val;
}
return this.attr.apply(this, arguments);
};
/**
* 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;
}
var method, action, url, $form = this;
if (typeof options == 'function') {
options = { success: options };
}
else if ( options === undefined ) {
options = {};
}
method = options.type || this.attr2('method');
action = options.url || this.attr2('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];
}
options = $.extend(true, {
url: url,
success: $.ajaxSettings.success,
type: method || $.ajaxSettings.type,
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
}, options);
// 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;
}
// 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 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 || this ; // 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 (options.error) {
var oldError = options.error;
options.error = function(xhr, status, error) {
var context = options.context || this;
oldError.apply(context, [xhr, status, error, $form]);
};
}
if (options.complete) {
var oldComplete = options.complete;
options.complete = function(xhr, status) {
var context = options.context || this;
oldComplete.apply(context, [xhr, status, $form]);
};
}
// are there files to upload?
// [value] (issue #113), also see comment:
// https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
var fileInputs = $('input[type=file]:enabled', this).filter(function() { return $(this).val() !== ''; });
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;
var jqxhr;
// 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() {
jqxhr = fileUploadIframe(a);
});
}
else {
jqxhr = fileUploadIframe(a);
}
}
else if ((hasFileInputs || multipart) && fileAPI) {
jqxhr = fileUploadXhr(a);
}
else {
jqxhr = $.ajax(options);
}
$form.removeData('jqxhr').data('jqxhr', jqxhr);
// clear element array
for (var k=0; k < elements.length; k++) {
elements[k] = null;
}
// fire 'notify' event
this.trigger('form-submit-notify', [this, options]);
return this;
// utility fn for deep serialization
function deepSerialize(extraData){
var serialized = $.param(extraData, options.traditional).split('&');
var len = serialized.length;
var result = [];
var i, part;
for (i=0; i < len; i++) {
// #252; undo param space replacement
serialized[i] = serialized[i].replace(/\+/g,' ');
part = serialized[i].split('=');
// #278; use array instead of object storage, favoring array serializations
result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
}
return result;
}
// 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) {
var serializedData = deepSerialize(options.extraData);
for (i=0; i < serializedData.length; i++) {
if (serializedData[i]) {
formdata.append(serializedData[i][0], serializedData[i][1]);
}
}
}
options.data = null;
var s = $.extend(true, {}, $.ajaxSettings, options, {
contentType: false,
processData: false,
cache: false,
type: method || 'POST'
});
if (options.uploadProgress) {
// workaround because jqXHR does not expose upload property
s.xhr = function() {
var xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', 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);
}, false);
}
return xhr;
};
}
s.data = null;
var beforeSend = s.beforeSend;
s.beforeSend = function(xhr, o) {
//Send FormData() provided by user
if (options.formData) {
o.data = options.formData;
}
else {
o.data = formdata;
}
if(beforeSend) {
beforeSend.call(this, xhr, o);
}
};
return $.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 deferred = $.Deferred();
// #341
deferred.abort = function(status) {
xhr.abort(status);
};
if (a) {
// ensure that every serialized input is still enabled
for (i=0; i < elements.length; i++) {
el = $(elements[i]);
if ( hasProp ) {
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.attr2('name');
if (!n) {
$io.attr2('name', id);
}
else {
id = n;
}
}
else {
$io = $('');
$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;
try { // #214, #257
if (io.contentWindow.document.execCommand) {
io.contentWindow.document.execCommand('Stop');
}
}
catch(ignore) {}
$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--;
}
deferred.reject();
return deferred;
}
if (xhr.aborted) {
deferred.reject();
return deferred;
}
// 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) {
/* it looks like contentWindow or contentDocument do not
* carry the protocol property in ie8, when running under ssl
* frame.document is the only valid response document, since
* the protocol is know but not on the other two objects. strange?
* "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
*/
var doc = null;
// IE8 cascading access check
try {
if (frame.contentWindow) {
doc = frame.contentWindow.document;
}
} catch(err) {
// IE8 access denied under ssl & missing protocol
log('cannot get iframe.contentWindow document: ' + err);
}
if (doc) { // successful getting content
return doc;
}
try { // simply checking may throw in ie8 under ssl or mismatched protocol
doc = frame.contentDocument ? frame.contentDocument : frame.document;
} catch(err) {
// last attempt
log('cannot get iframe.contentDocument: ' + err);
doc = 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.attr2('target'),
a = $form.attr2('action'),
mp = 'multipart/form-data',
et = $form.attr('enctype') || $form.attr('encoding') || mp;
// update form attrs in IE friendly way
form.setAttribute('target',id);
if (!method || /post/i.test(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)) {
// if using the $.param format that allows for multiple values with the same name
if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
extraInputs.push(
$('').val(s.extraData[n].value)
.appendTo(form)[0]);
} else {
extraInputs.push(
$('').val(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);
try {
form.submit();
} catch(err) {
// just in case form has element with name/id of 'submit'
var submitFn = document.createElement('form').submit;
submitFn.apply(form);
}
}
finally {
// reset attrs and remove "extra" input elements
form.setAttribute('action',a);
form.setAttribute('enctype', et); // #380
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;
}
doc = getDoc(io);
if(!doc) {
log('cannot access response document');
e = SERVER_ABORT;
}
if (e === CLIENT_TIMEOUT_ABORT && xhr) {
xhr.abort('timeout');
deferred.reject(xhr, 'timeout');
return;
}
else if (e == SERVER_ABORT && xhr) {
xhr.abort('server abort');
deferred.reject(xhr, 'error', '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.toLowerCase()];
};
// 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 (err) {
status = 'parsererror';
xhr.error = errMsg = (err || status);
}
}
catch (err) {
log('error caught: ',err);
status = 'error';
xhr.error = errMsg = (err || 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);
}
deferred.resolve(xhr.responseText, '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);
}
deferred.reject(xhr, 'error', 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();
}
else { //adding else to clean up existing iframe response.
$io.attr('src', s.iframeSrc);
}
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;
};
return deferred;
}
};
/**
* 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 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);
// 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;
}
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;
}
return this.ajaxFormUnbind()
.bind('submit.form-plugin', options, doAjaxSubmit)
.bind('click.form-plugin', options, captureSubmittingElement);
};
// 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();
$(e.target).ajaxSubmit(options); // #365
}
}
function captureSubmittingElement(e) {
/*jshint validthis:true */
var target = e.target;
var $el = $(target);
if (!($el.is("[type=submit],[type=image]"))) {
// is this a child element of the submit el? (ex: a span within a button)
var t = $el.closest('[type=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);
}
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
return this.unbind('submit.form-plugin click.form-plugin');
};
/**
* 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;
}
var form = this[0];
var formId = this.attr('id');
var els = semantic ? form.getElementsByTagName('*') : form.elements;
var els2;
if (els && !/MSIE [678]/.test(navigator.userAgent)) { // #390
els = $(els).get(); // convert to standard array
}
// #386; account for inputs outside the form which use the 'form' attribute
if ( formId ) {
els2 = $(':input[form="' + formId + '"]').get(); // hat tip @thet
if ( els2.length ) {
els = (els || []).concat(els2);
}
}
if (!els || !els.length) {
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 || el.disabled) {
continue;
}
if (semantic && form.clk && el.type == "image") {
// handle image inputs on the fly when semantic == true
if(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;
}
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') {
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});
}
}
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;
};
/**
* Serializes form data into a 'submittable' string. This method will return a string
* in the format: name1=value1&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&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});
}
});
//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:
*
*
*
* var v = $('input[type=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 = $('input[type=checkbox]').fieldValue();
* // if neither checkbox is checked
* v === undefined
* // if both checkboxes are checked
* v == ['B1', 'B2']
*
* var v = $('input[type=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;
};
/**
* 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;
}
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;
}
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();
};
/**
* 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);
});
};
/**
* 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 (t == "file") {
if (/MSIE/.test(navigator.userAgent)) {
$(this).replaceWith($(this).clone(true));
} else {
$(this).val('');
}
}
else if (includeHidden) {
// includeHidden can be the value 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;
}
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;
}
});
};
// 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);
}
else if (window.opera && window.opera.postError) {
window.opera.postError(msg);
}
}
}));
================================================
FILE: public/assets/dashboard/js/layer/extend/layer.ext.js
================================================
/*! layer弹层组件拓展类 */
================================================
FILE: public/assets/dashboard/js/layer/layer.js
================================================
/*! layer-v2.4 弹层组件 License LGPL http://layer.layui.com/ By 贤心 */
;!function(a,b){"use strict";var c,d,e={getPath:function(){var a=document.scripts,b=a[a.length-1],c=b.src;if(!b.getAttribute("merge"))return c.substring(0,c.lastIndexOf("/")+1)}(),enter:function(a){13===a.keyCode&&a.preventDefault()},config:{},end:{},btn:["确定","取消"],type:["dialog","page","iframe","loading","tips"]},f={v:"2.4",ie6:!!a.ActiveXObject&&!a.XMLHttpRequest,index:0,path:e.getPath,config:function(a,b){var d=0;return a=a||{},f.cache=e.config=c.extend(e.config,a),f.path=e.config.path||f.path,"string"==typeof a.extend&&(a.extend=[a.extend]),f.use("skin/layer.css",a.extend&&a.extend.length>0?function g(){var c=a.extend;f.use(c[c[d]?d:d-1],d'+(i?f.title[0]:f.title)+" ":"";return f.zIndex=g,b([f.shade?'