Merge branch 'master' of git://github.com/jquery/jquery into bug_2773

This commit is contained in:
timmywil 2011-02-26 18:53:25 -05:00
commit 9e5ec378e3
70 changed files with 1736 additions and 15275 deletions

View file

@ -9,6 +9,7 @@ DIST_DIR = ${PREFIX}/dist
JS_ENGINE ?= `which node nodejs` JS_ENGINE ?= `which node nodejs`
COMPILER = ${JS_ENGINE} ${BUILD_DIR}/uglify.js --unsafe COMPILER = ${JS_ENGINE} ${BUILD_DIR}/uglify.js --unsafe
POST_COMPILER = ${JS_ENGINE} ${BUILD_DIR}/post-compile.js
BASE_FILES = ${SRC_DIR}/core.js\ BASE_FILES = ${SRC_DIR}/core.js\
${SRC_DIR}/support.js\ ${SRC_DIR}/support.js\
@ -43,7 +44,7 @@ VER = sed "s/@VERSION/${JQ_VER}/"
DATE=$(shell git log -1 --pretty=format:%ad) DATE=$(shell git log -1 --pretty=format:%ad)
all: init jquery min lint all: jquery min lint
@@echo "jQuery build complete." @@echo "jQuery build complete."
${DIST_DIR}: ${DIST_DIR}:
@ -68,12 +69,16 @@ define clone_or_pull
endef endef
init: ${QUNIT_DIR}:
$(call clone_or_pull, ${QUNIT_DIR}, git://github.com/jquery/qunit.git) $(call clone_or_pull, ${QUNIT_DIR}, git://github.com/jquery/qunit.git)
${SIZZLE_DIR}:
$(call clone_or_pull, ${SIZZLE_DIR}, git://github.com/jeresig/sizzle.git) $(call clone_or_pull, ${SIZZLE_DIR}, git://github.com/jeresig/sizzle.git)
jquery: ${JQ} init: ${QUNIT_DIR} ${SIZZLE_DIR}
jq: ${JQ}
jquery: init ${JQ}
jq: init ${JQ}
${JQ}: ${MODULES} | ${DIST_DIR} ${JQ}: ${MODULES} | ${DIST_DIR}
@@echo "Building" ${JQ} @@echo "Building" ${JQ}
@ -88,18 +93,26 @@ ${SRC_DIR}/selector.js: ${SIZZLE_DIR}/sizzle.js
@@echo "Building selector code from Sizzle" @@echo "Building selector code from Sizzle"
@@sed '/EXPOSE/r src/sizzle-jquery.js' ${SIZZLE_DIR}/sizzle.js | grep -v window.Sizzle > ${SRC_DIR}/selector.js @@sed '/EXPOSE/r src/sizzle-jquery.js' ${SIZZLE_DIR}/sizzle.js | grep -v window.Sizzle > ${SRC_DIR}/selector.js
lint: ${JQ} lint: jquery
@@echo "Checking jQuery against JSLint..." @@if test ! -z ${JS_ENGINE}; then \
@@${JS_ENGINE} build/jslint-check.js echo "Checking jQuery against JSLint..."; \
${JS_ENGINE} build/jslint-check.js; \
else \
echo "You must have NodeJS installed in order to test jQuery against JSLint."; \
fi
min: ${JQ_MIN} min: ${JQ_MIN}
${JQ_MIN}: ${JQ} ${JQ_MIN}: jquery
@@echo "Building" ${JQ_MIN} @@if test ! -z ${JS_ENGINE}; then \
@@${COMPILER} ${JQ} > ${JQ_MIN}.tmp echo "Minifying jQuery" ${JQ_MIN}; \
@@echo ";" >> ${JQ_MIN}.tmp ${COMPILER} ${JQ} > ${JQ_MIN}.tmp; \
@@sed 's/\*\/(/*\/ʩ(/' ${JQ_MIN}.tmp | tr "ʩ" "\n" > ${JQ_MIN} ${POST_COMPILER} ${JQ_MIN}.tmp > ${JQ_MIN}; \
@@rm -rf ${JQ_MIN}.tmp rm -f ${JQ_MIN}.tmp; \
else \
echo "You must have NodeJS installed in order to minify jQuery."; \
fi
clean: clean:
@@echo "Removing Distribution directory:" ${DIST_DIR} @@echo "Removing Distribution directory:" ${DIST_DIR}

7
build/post-compile.js Normal file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env node
var print = require("sys").print,
src = require("fs").readFileSync(process.argv[2], "utf8");
// Previously done in sed but reimplemented here due to portability issues
print(src.replace(/^(\s*\*\/)(.+)/m, "$1\n$2;"));

View file

@ -524,11 +524,9 @@ jQuery.extend({
if ( data && rnotwhite.test(data) ) { if ( data && rnotwhite.test(data) ) {
// Inspired by code by Andrea Giammarchi // Inspired by code by Andrea Giammarchi
// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
var head = document.getElementsByTagName("head")[0] || document.documentElement, var head = document.head || document.getElementsByTagName("head")[0] || document.documentElement,
script = document.createElement("script"); script = document.createElement("script");
script.type = "text/javascript";
if ( jQuery.support.scriptEval ) { if ( jQuery.support.scriptEval ) {
script.appendChild( document.createTextNode( data ) ); script.appendChild( document.createTextNode( data ) );
} else { } else {
@ -5060,7 +5058,7 @@ jQuery.extend({
// If we're requesting a remote document // If we're requesting a remote document
// and trying to load JSON or Script with a GET // and trying to load JSON or Script with a GET
if ( s.dataType === "script" && type === "GET" && remote ) { if ( s.dataType === "script" && type === "GET" && remote ) {
var head = document.getElementsByTagName("head")[0] || document.documentElement; var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
var script = document.createElement("script"); var script = document.createElement("script");
script.src = s.url; script.src = s.url;
if ( s.scriptCharset ) { if ( s.scriptCharset ) {

View file

@ -4,18 +4,22 @@ var r20 = /%20/g,
rbracket = /\[\]$/, rbracket = /\[\]$/,
rCRLF = /\r?\n/g, rCRLF = /\r?\n/g,
rhash = /#.*$/, rhash = /#.*$/,
rheaders = /^(.*?):\s*(.*?)\r?$/mg, // IE leaves an \r character at EOL rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
// #7653, #8125, #8152: local protocol detection
rlocalProtocol = /(?:^file|^widget|\-extension):$/,
rnoContent = /^(?:GET|HEAD)$/, rnoContent = /^(?:GET|HEAD)$/,
rprotocol = /^\/\//,
rquery = /\?/, rquery = /\?/,
rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
rselectTextarea = /^(?:select|textarea)/i, rselectTextarea = /^(?:select|textarea)/i,
rspacesAjax = /\s+/, rspacesAjax = /\s+/,
rts = /([?&])_=[^&]*/, rts = /([?&])_=[^&]*/,
rurl = /^(\w+:)?\/\/([^\/?#:]+)(?::(\d+))?/, rucHeaders = /(^|\-)([a-z])/g,
rucHeadersFunc = function( _, $1, $2 ) {
// Slice function return $1 + $2.toUpperCase();
sliceFunc = Array.prototype.slice, },
rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?|\/[^\/])/,
// Keep a copy of the old load method // Keep a copy of the old load method
_load = jQuery.fn.load, _load = jQuery.fn.load,
@ -36,7 +40,28 @@ var r20 = /%20/g,
* 2) the catchall symbol "*" can be used * 2) the catchall symbol "*" can be used
* 3) selection will start with transport dataType and THEN go to "*" if needed * 3) selection will start with transport dataType and THEN go to "*" if needed
*/ */
transports = {}; transports = {},
// Document location
ajaxLocation,
// Document location segments
ajaxLocParts;
// #8138, IE may throw an exception when accessing
// a field from document.location if document.domain has been set
try {
ajaxLocation = document.location.href;
} catch( e ) {
// Use the href attribute of an A element
// since IE will modify it given document.location
ajaxLocation = document.createElement( "a" );
ajaxLocation.href = "";
ajaxLocation = ajaxLocation.href;
}
// Segment location into parts
ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() );
// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) { function addToPrefiltersOrTransports( structure ) {
@ -50,7 +75,7 @@ function addToPrefiltersOrTransports( structure ) {
} }
if ( jQuery.isFunction( func ) ) { if ( jQuery.isFunction( func ) ) {
var dataTypes = dataTypeExpression.split( rspacesAjax ), var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
i = 0, i = 0,
length = dataTypes.length, length = dataTypes.length,
dataType, dataType,
@ -64,7 +89,7 @@ function addToPrefiltersOrTransports( structure ) {
// any existing element // any existing element
placeBefore = /^\+/.test( dataType ); placeBefore = /^\+/.test( dataType );
if ( placeBefore ) { if ( placeBefore ) {
dataType = dataType.substr( 1 ); dataType = dataType.substr( 1 ) || "*";
} }
list = structure[ dataType ] = structure[ dataType ] || []; list = structure[ dataType ] = structure[ dataType ] || [];
// then we add to the structure accordingly // then we add to the structure accordingly
@ -75,7 +100,7 @@ function addToPrefiltersOrTransports( structure ) {
} }
//Base inspection function for prefilters and transports //Base inspection function for prefilters and transports
function inspectPrefiltersOrTransports( structure, options, originalOptions, function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
dataType /* internal */, inspected /* internal */ ) { dataType /* internal */, inspected /* internal */ ) {
dataType = dataType || options.dataTypes[ 0 ]; dataType = dataType || options.dataTypes[ 0 ];
@ -90,16 +115,16 @@ function inspectPrefiltersOrTransports( structure, options, originalOptions,
selection; selection;
for(; i < length && ( executeOnly || !selection ); i++ ) { for(; i < length && ( executeOnly || !selection ); i++ ) {
selection = list[ i ]( options, originalOptions ); selection = list[ i ]( options, originalOptions, jqXHR );
// If we got redirected to another dataType // If we got redirected to another dataType
// we try there if not done already // we try there if executing only and not done already
if ( typeof selection === "string" ) { if ( typeof selection === "string" ) {
if ( inspected[ selection ] ) { if ( !executeOnly || inspected[ selection ] ) {
selection = undefined; selection = undefined;
} else { } else {
options.dataTypes.unshift( selection ); options.dataTypes.unshift( selection );
selection = inspectPrefiltersOrTransports( selection = inspectPrefiltersOrTransports(
structure, options, originalOptions, selection, inspected ); structure, options, originalOptions, jqXHR, selection, inspected );
} }
} }
} }
@ -107,7 +132,7 @@ function inspectPrefiltersOrTransports( structure, options, originalOptions,
// we try the catchall dataType if not done already // we try the catchall dataType if not done already
if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) { if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
selection = inspectPrefiltersOrTransports( selection = inspectPrefiltersOrTransports(
structure, options, originalOptions, "*", inspected ); structure, options, originalOptions, jqXHR, "*", inspected );
} }
// unnecessary when only executing (prefilters) // unnecessary when only executing (prefilters)
// but it'll be ignored by the caller in that case // but it'll be ignored by the caller in that case
@ -139,7 +164,7 @@ jQuery.fn.extend({
if ( jQuery.isFunction( params ) ) { if ( jQuery.isFunction( params ) ) {
// We assume that it's the callback // We assume that it's the callback
callback = params; callback = params;
params = null; params = undefined;
// Otherwise, build a param string // Otherwise, build a param string
} else if ( typeof params === "object" ) { } else if ( typeof params === "object" ) {
@ -157,14 +182,14 @@ jQuery.fn.extend({
dataType: "html", dataType: "html",
data: params, data: params,
// Complete callback (responseText is used internally) // Complete callback (responseText is used internally)
complete: function( jXHR, status, responseText ) { complete: function( jqXHR, status, responseText ) {
// Store the response as specified by the jXHR object // Store the response as specified by the jqXHR object
responseText = jXHR.responseText; responseText = jqXHR.responseText;
// If successful, inject the HTML into all the matched elements // If successful, inject the HTML into all the matched elements
if ( jXHR.isResolved() ) { if ( jqXHR.isResolved() ) {
// #4825: Get the actual response in case // #4825: Get the actual response in case
// a dataFilter is present in ajaxSettings // a dataFilter is present in ajaxSettings
jXHR.done(function( r ) { jqXHR.done(function( r ) {
responseText = r; responseText = r;
}); });
// See if a selector was specified // See if a selector was specified
@ -183,7 +208,7 @@ jQuery.fn.extend({
} }
if ( callback ) { if ( callback ) {
self.each( callback, [ responseText, status, jXHR ] ); self.each( callback, [ responseText, status, jqXHR ] );
} }
} }
}); });
@ -231,7 +256,7 @@ jQuery.each( [ "get", "post" ], function( i, method ) {
if ( jQuery.isFunction( data ) ) { if ( jQuery.isFunction( data ) ) {
type = type || callback; type = type || callback;
callback = data; callback = data;
data = null; data = undefined;
} }
return jQuery.ajax({ return jQuery.ajax({
@ -247,22 +272,39 @@ jQuery.each( [ "get", "post" ], function( i, method ) {
jQuery.extend({ jQuery.extend({
getScript: function( url, callback ) { getScript: function( url, callback ) {
return jQuery.get( url, null, callback, "script" ); return jQuery.get( url, undefined, callback, "script" );
}, },
getJSON: function( url, data, callback ) { getJSON: function( url, data, callback ) {
return jQuery.get( url, data, callback, "json" ); return jQuery.get( url, data, callback, "json" );
}, },
ajaxSetup: function( settings ) { // Creates a full fledged settings object into target
jQuery.extend( true, jQuery.ajaxSettings, settings ); // with both ajaxSettings and settings fields.
if ( settings.context ) { // If target is omitted, writes into ajaxSettings.
jQuery.ajaxSettings.context = settings.context; ajaxSetup: function ( target, settings ) {
if ( !settings ) {
// Only one parameter, we extend ajaxSettings
settings = target;
target = jQuery.extend( true, jQuery.ajaxSettings, settings );
} else {
// target was provided, we extend into it
jQuery.extend( true, target, jQuery.ajaxSettings, settings );
} }
// Flatten fields we don't want deep extended
for( var field in { context: 1, url: 1 } ) {
if ( field in settings ) {
target[ field ] = settings[ field ];
} else if( field in jQuery.ajaxSettings ) {
target[ field ] = jQuery.ajaxSettings[ field ];
}
}
return target;
}, },
ajaxSettings: { ajaxSettings: {
url: location.href, url: ajaxLocation,
isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
global: true, global: true,
type: "GET", type: "GET",
contentType: "application/x-www-form-urlencoded", contentType: "application/x-www-form-urlencoded",
@ -324,9 +366,8 @@ jQuery.extend({
// Main method // Main method
ajax: function( url, options ) { ajax: function( url, options ) {
// If options is not an object, // If url is an object, simulate pre-1.5 signature
// we simulate pre-1.5 signature if ( typeof url === "object" ) {
if ( typeof options !== "object" ) {
options = url; options = url;
url = undefined; url = undefined;
} }
@ -335,19 +376,22 @@ jQuery.extend({
options = options || {}; options = options || {};
var // Create the final options object var // Create the final options object
s = jQuery.extend( true, {}, jQuery.ajaxSettings, options ), s = jQuery.ajaxSetup( {}, options ),
// Callbacks contexts // Callbacks context
// We force the original context if it exists callbackContext = s.context || s,
// or take it from jQuery.ajaxSettings otherwise // Context for global events
// (plain objects used as context get extended) // It's the callbackContext if one was provided in the options
callbackContext = // and if it's a DOM node or a jQuery collection
( s.context = ( "context" in options ? options : jQuery.ajaxSettings ).context ) || s, globalEventContext = callbackContext !== s &&
globalEventContext = callbackContext === s ? jQuery.event : jQuery( callbackContext ), ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
jQuery( callbackContext ) : jQuery.event,
// Deferreds // Deferreds
deferred = jQuery.Deferred(), deferred = jQuery.Deferred(),
completeDeferred = jQuery._Deferred(), completeDeferred = jQuery._Deferred(),
// Status-dependent callbacks // Status-dependent callbacks
statusCode = s.statusCode || {}, statusCode = s.statusCode || {},
// ifModified key
ifModifiedKey,
// Headers (they are sent all at once) // Headers (they are sent all at once)
requestHeaders = {}, requestHeaders = {},
// Response headers // Response headers
@ -358,22 +402,22 @@ jQuery.extend({
// timeout handle // timeout handle
timeoutTimer, timeoutTimer,
// Cross-domain detection vars // Cross-domain detection vars
loc = document.location,
protocol = loc.protocol || "http:",
parts, parts,
// The jXHR state // The jqXHR state
state = 0, state = 0,
// To know if global events are to be dispatched
fireGlobals,
// Loop variable // Loop variable
i, i,
// Fake xhr // Fake xhr
jXHR = { jqXHR = {
readyState: 0, readyState: 0,
// Caches the header // Caches the header
setRequestHeader: function( name, value ) { setRequestHeader: function( name, value ) {
if ( state === 0 ) { if ( !state ) {
requestHeaders[ name.toLowerCase() ] = value; requestHeaders[ name.toLowerCase().replace( rucHeaders, rucHeadersFunc ) ] = value;
} }
return this; return this;
}, },
@ -395,13 +439,22 @@ jQuery.extend({
} }
match = responseHeaders[ key.toLowerCase() ]; match = responseHeaders[ key.toLowerCase() ];
} }
return match || null; return match === undefined ? null : match;
},
// Overrides response content-type header
overrideMimeType: function( type ) {
if ( !state ) {
s.mimeType = type;
}
return this;
}, },
// Cancel the request // Cancel the request
abort: function( statusText ) { abort: function( statusText ) {
statusText = statusText || "abort";
if ( transport ) { if ( transport ) {
transport.abort( statusText || "abort" ); transport.abort( statusText );
} }
done( 0, statusText ); done( 0, statusText );
return this; return this;
@ -411,7 +464,7 @@ jQuery.extend({
// Callback for when everything is done // Callback for when everything is done
// It is defined here because jslint complains if it is declared // It is defined here because jslint complains if it is declared
// at the end of the function (which would be more logical and readable) // at the end of the function (which would be more logical and readable)
function done( status, statusText, responses, headers) { function done( status, statusText, responses, headers ) {
// Called once // Called once
if ( state === 2 ) { if ( state === 2 ) {
@ -427,19 +480,19 @@ jQuery.extend({
} }
// Dereference transport for early garbage collection // Dereference transport for early garbage collection
// (no matter how long the jXHR object will be used) // (no matter how long the jqXHR object will be used)
transport = undefined; transport = undefined;
// Cache response headers // Cache response headers
responseHeadersString = headers || ""; responseHeadersString = headers || "";
// Set readyState // Set readyState
jXHR.readyState = status ? 4 : 0; jqXHR.readyState = status ? 4 : 0;
var isSuccess, var isSuccess,
success, success,
error = ( statusText = statusText || "error" ), error,
response = responses ? ajaxHandleResponses( s, jXHR, responses ) : undefined, response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
lastModified, lastModified,
etag; etag;
@ -449,11 +502,11 @@ jQuery.extend({
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( s.ifModified ) { if ( s.ifModified ) {
if ( ( lastModified = jXHR.getResponseHeader( "Last-Modified" ) ) ) { if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
jQuery.lastModified[ s.url ] = lastModified; jQuery.lastModified[ ifModifiedKey ] = lastModified;
} }
if ( ( etag = jXHR.getResponseHeader( "Etag" ) ) ) { if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
jQuery.etag[ s.url ] = etag; jQuery.etag[ ifModifiedKey ] = etag;
} }
} }
@ -473,36 +526,46 @@ jQuery.extend({
} catch(e) { } catch(e) {
// We have a parsererror // We have a parsererror
statusText = "parsererror"; statusText = "parsererror";
error = "" + e; error = e;
}
}
} else {
// We extract error from statusText
// then normalize statusText and status for non-aborts
error = statusText;
if( !statusText || status ) {
statusText = "error";
if ( status < 0 ) {
status = 0;
} }
} }
} }
// Set data for the fake xhr object // Set data for the fake xhr object
jXHR.status = status; jqXHR.status = status;
jXHR.statusText = statusText; jqXHR.statusText = statusText;
// Success/Error // Success/Error
if ( isSuccess ) { if ( isSuccess ) {
deferred.resolveWith( callbackContext, [ success, statusText, jXHR ] ); deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
} else { } else {
deferred.rejectWith( callbackContext, [ jXHR, statusText, error ] ); deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
} }
// Status-dependent callbacks // Status-dependent callbacks
jXHR.statusCode( statusCode ); jqXHR.statusCode( statusCode );
statusCode = undefined; statusCode = undefined;
if ( s.global ) { if ( fireGlobals ) {
globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
[ jXHR, s, isSuccess ? success : error ] ); [ jqXHR, s, isSuccess ? success : error ] );
} }
// Complete // Complete
completeDeferred.resolveWith( callbackContext, [ jXHR, statusText ] ); completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );
if ( s.global ) { if ( fireGlobals ) {
globalEventContext.trigger( "ajaxComplete", [ jXHR, s] ); globalEventContext.trigger( "ajaxComplete", [ jqXHR, s] );
// Handle the global AJAX counter // Handle the global AJAX counter
if ( !( --jQuery.active ) ) { if ( !( --jQuery.active ) ) {
jQuery.event.trigger( "ajaxStop" ); jQuery.event.trigger( "ajaxStop" );
@ -511,13 +574,13 @@ jQuery.extend({
} }
// Attach deferreds // Attach deferreds
deferred.promise( jXHR ); deferred.promise( jqXHR );
jXHR.success = jXHR.done; jqXHR.success = jqXHR.done;
jXHR.error = jXHR.fail; jqXHR.error = jqXHR.fail;
jXHR.complete = completeDeferred.done; jqXHR.complete = completeDeferred.done;
// Status-dependent callbacks // Status-dependent callbacks
jXHR.statusCode = function( map ) { jqXHR.statusCode = function( map ) {
if ( map ) { if ( map ) {
var tmp; var tmp;
if ( state < 2 ) { if ( state < 2 ) {
@ -525,16 +588,17 @@ jQuery.extend({
statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
} }
} else { } else {
tmp = map[ jXHR.status ]; tmp = map[ jqXHR.status ];
jXHR.then( tmp, tmp ); jqXHR.then( tmp, tmp );
} }
} }
return this; return this;
}; };
// Remove hash character (#7531: and string promotion) // Remove hash character (#7531: and string promotion)
// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
// We also use the url parameter if available // We also use the url parameter if available
s.url = ( "" + ( url || s.url ) ).replace( rhash, "" ); s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
// Extract dataTypes list // Extract dataTypes list
s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
@ -542,12 +606,10 @@ jQuery.extend({
// Determine if a cross-domain request is in order // Determine if a cross-domain request is in order
if ( !s.crossDomain ) { if ( !s.crossDomain ) {
parts = rurl.exec( s.url.toLowerCase() ); parts = rurl.exec( s.url.toLowerCase() );
s.crossDomain = !!( s.crossDomain = !!( parts &&
parts && ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
( parts[ 1 ] && parts[ 1 ] != protocol || ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
parts[ 2 ] != loc.hostname || ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
( parts[ 3 ] || ( ( parts[ 1 ] || protocol ) === "http:" ? 80 : 443 ) ) !=
( loc.port || ( protocol === "http:" ? 80 : 443 ) ) )
); );
} }
@ -557,7 +619,15 @@ jQuery.extend({
} }
// Apply prefilters // Apply prefilters
inspectPrefiltersOrTransports( prefilters, s, options ); inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
// If request was aborted inside a prefiler, stop there
if ( state === 2 ) {
return false;
}
// We can fire global events as of now if asked to
fireGlobals = s.global;
// Uppercase the type // Uppercase the type
s.type = s.type.toUpperCase(); s.type = s.type.toUpperCase();
@ -566,7 +636,7 @@ jQuery.extend({
s.hasContent = !rnoContent.test( s.type ); s.hasContent = !rnoContent.test( s.type );
// Watch for a new set of requests // Watch for a new set of requests
if ( s.global && jQuery.active++ === 0 ) { if ( fireGlobals && jQuery.active++ === 0 ) {
jQuery.event.trigger( "ajaxStart" ); jQuery.event.trigger( "ajaxStart" );
} }
@ -578,6 +648,9 @@ jQuery.extend({
s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
} }
// Get ifModifiedKey before adding the anti-cache parameter
ifModifiedKey = s.url;
// Add anti-cache in url if needed // Add anti-cache in url if needed
if ( s.cache === false ) { if ( s.cache === false ) {
@ -592,78 +665,77 @@ jQuery.extend({
// Set the correct header, if data is being sent // Set the correct header, if data is being sent
if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
requestHeaders[ "content-type" ] = s.contentType; requestHeaders[ "Content-Type" ] = s.contentType;
} }
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( s.ifModified ) { if ( s.ifModified ) {
if ( jQuery.lastModified[ s.url ] ) { ifModifiedKey = ifModifiedKey || s.url;
requestHeaders[ "if-modified-since" ] = jQuery.lastModified[ s.url ]; if ( jQuery.lastModified[ ifModifiedKey ] ) {
requestHeaders[ "If-Modified-Since" ] = jQuery.lastModified[ ifModifiedKey ];
} }
if ( jQuery.etag[ s.url ] ) { if ( jQuery.etag[ ifModifiedKey ] ) {
requestHeaders[ "if-none-match" ] = jQuery.etag[ s.url ]; requestHeaders[ "If-None-Match" ] = jQuery.etag[ ifModifiedKey ];
} }
} }
// Set the Accepts header for the server, depending on the dataType // Set the Accepts header for the server, depending on the dataType
requestHeaders.accept = s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? requestHeaders.Accept = s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) : s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
s.accepts[ "*" ]; s.accepts[ "*" ];
// Check for headers option // Check for headers option
for ( i in s.headers ) { for ( i in s.headers ) {
requestHeaders[ i.toLowerCase() ] = s.headers[ i ]; jqXHR.setRequestHeader( i, s.headers[ i ] );
} }
// Allow custom headers/mimetypes and early abort // Allow custom headers/mimetypes and early abort
if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jXHR, s ) === false || state === 2 ) ) { if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
// Abort if not done already // Abort if not done already
done( 0, "abort" ); jqXHR.abort();
// Return false return false;
jXHR = false;
}
// 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 { } else {
jqXHR.readyState = 1;
// Install callbacks on deferreds // Send global event
for ( i in { success: 1, error: 1, complete: 1 } ) { if ( fireGlobals ) {
jXHR[ i ]( s[ i ] ); globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
}
// Timeout
if ( s.async && s.timeout > 0 ) {
timeoutTimer = setTimeout( function(){
jqXHR.abort( "timeout" );
}, s.timeout );
} }
// Get transport try {
transport = inspectPrefiltersOrTransports( transports, s, options ); state = 1;
transport.send( requestHeaders, done );
// If no transport, we auto-abort } catch (e) {
if ( !transport ) { // Propagate exception as error if not done
done( 0, "notransport" ); if ( status < 2 ) {
} else { done( -1, e );
// Set state as sending // Simply rethrow otherwise
state = jXHR.readyState = 1; } else {
// Send global event jQuery.error( e );
if ( s.global ) {
globalEventContext.trigger( "ajaxSend", [ jXHR, s ] );
}
// Timeout
if ( s.async && s.timeout > 0 ) {
timeoutTimer = setTimeout( function(){
jXHR.abort( "timeout" );
}, s.timeout );
}
try {
transport.send( requestHeaders, done );
} catch (e) {
// Propagate exception as error if not done
if ( status === 1 ) {
done( 0, "error", "" + e );
jXHR = false;
// Simply rethrow otherwise
} else {
jQuery.error( e );
}
} }
} }
} }
return jXHR;
return jqXHR;
}, },
// Serialize an array of form elements or a set of // Serialize an array of form elements or a set of
@ -682,7 +754,7 @@ jQuery.extend({
} }
// If an array was passed in, assume that it is an array of form elements. // If an array was passed in, assume that it is an array of form elements.
if ( jQuery.isArray( a ) || a.jquery ) { if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
// Serialize the form elements // Serialize the form elements
jQuery.each( a, function() { jQuery.each( a, function() {
add( this.name, this.value ); add( this.name, this.value );
@ -729,9 +801,9 @@ function buildParams( prefix, obj, traditional, add ) {
// Serialize object item. // Serialize object item.
} else { } else {
jQuery.each( obj, function( k, v ) { for ( var name in obj ) {
buildParams( prefix + "[" + k + "]", v, traditional, add ); buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
}); }
} }
} else { } else {
@ -758,7 +830,7 @@ jQuery.extend({
* - finds the right dataType (mediates between content-type and expected dataType) * - finds the right dataType (mediates between content-type and expected dataType)
* - returns the corresponding response * - returns the corresponding response
*/ */
function ajaxHandleResponses( s, jXHR, responses ) { function ajaxHandleResponses( s, jqXHR, responses ) {
var contents = s.contents, var contents = s.contents,
dataTypes = s.dataTypes, dataTypes = s.dataTypes,
@ -771,7 +843,7 @@ function ajaxHandleResponses( s, jXHR, responses ) {
// Fill responseXXX fields // Fill responseXXX fields
for( type in responseFields ) { for( type in responseFields ) {
if ( type in responses ) { if ( type in responses ) {
jXHR[ responseFields[type] ] = responses[ type ]; jqXHR[ responseFields[type] ] = responses[ type ];
} }
} }
@ -779,7 +851,7 @@ function ajaxHandleResponses( s, jXHR, responses ) {
while( dataTypes[ 0 ] === "*" ) { while( dataTypes[ 0 ] === "*" ) {
dataTypes.shift(); dataTypes.shift();
if ( ct === undefined ) { if ( ct === undefined ) {
ct = jXHR.getResponseHeader( "content-type" ); ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
} }
} }
@ -831,8 +903,9 @@ function ajaxConvert( s, response ) {
} }
var dataTypes = s.dataTypes, var dataTypes = s.dataTypes,
converters = s.converters, converters = {},
i, i,
key,
length = dataTypes.length, length = dataTypes.length,
tmp, tmp,
// Current and previous dataTypes // Current and previous dataTypes
@ -842,13 +915,23 @@ function ajaxConvert( s, response ) {
conversion, conversion,
// Conversion function // Conversion function
conv, conv,
// Conversion functions (when text is used in-between) // Conversion functions (transitive conversion)
conv1, conv1,
conv2; conv2;
// For each dataType in the chain // For each dataType in the chain
for( i = 1; i < length; i++ ) { for( i = 1; i < length; i++ ) {
// Create converters map
// with lowercased keys
if ( i === 1 ) {
for( key in s.converters ) {
if( typeof key === "string" ) {
converters[ key.toLowerCase() ] = s.converters[ key ];
}
}
}
// Get the dataTypes // Get the dataTypes
prev = current; prev = current;
current = dataTypes[ i ]; current = dataTypes[ i ];

View file

@ -1,20 +1,20 @@
(function( jQuery ) { (function( jQuery ) {
var jsc = jQuery.now(), var jsc = jQuery.now(),
jsre = /(\=)(?:\?|%3F)(&|$)|()(?:\?\?|%3F%3F)()/i; jsre = /(\=)\?(&|$)|\?\?/i;
// Default jsonp settings // Default jsonp settings
jQuery.ajaxSetup({ jQuery.ajaxSetup({
jsonp: "callback", jsonp: "callback",
jsonpCallback: function() { jsonpCallback: function() {
return "jsonp" + jsc++; return jQuery.expando + "_" + ( jsc++ );
} }
}); });
// Detect, normalize options and install callbacks for jsonp requests // Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, dataIsString /* internal */ ) { jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
dataIsString = ( typeof s.data === "string" ); var dataIsString = ( typeof s.data === "string" );
if ( s.dataTypes[ 0 ] === "jsonp" || if ( s.dataTypes[ 0 ] === "jsonp" ||
originalSettings.jsonpCallback || originalSettings.jsonpCallback ||
@ -28,7 +28,15 @@ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, dataIsString
previous = window[ jsonpCallback ], previous = window[ jsonpCallback ],
url = s.url, url = s.url,
data = s.data, data = s.data,
replace = "$1" + jsonpCallback + "$2"; replace = "$1" + jsonpCallback + "$2",
cleanUp = function() {
// Set callback back to previous value
window[ jsonpCallback ] = previous;
// Call if it was a function and we have a response
if ( responseContainer && jQuery.isFunction( previous ) ) {
window[ jsonpCallback ]( responseContainer[ 0 ] );
}
};
if ( s.jsonp !== false ) { if ( s.jsonp !== false ) {
url = url.replace( jsre, replace ); url = url.replace( jsre, replace );
@ -46,32 +54,17 @@ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, dataIsString
s.url = url; s.url = url;
s.data = data; s.data = data;
// Install callback
window[ jsonpCallback ] = function( response ) { window[ jsonpCallback ] = function( response ) {
responseContainer = [ response ]; responseContainer = [ response ];
}; };
s.complete = [ function() { // Install cleanUp function
jqXHR.then( cleanUp, cleanUp );
// Set callback back to previous value
window[ jsonpCallback ] = previous;
// Call if it was a function and we have a response
if ( previous) {
if ( responseContainer && jQuery.isFunction( previous ) ) {
window[ jsonpCallback ] ( responseContainer[ 0 ] );
}
} else {
// else, more memory leak avoidance
try{
delete window[ jsonpCallback ];
} catch( e ) {}
}
}, s.complete ];
// Use data converter to retrieve json after script execution // Use data converter to retrieve json after script execution
s.converters["script json"] = function() { s.converters["script json"] = function() {
if ( ! responseContainer ) { if ( !responseContainer ) {
jQuery.error( jsonpCallback + " was not called" ); jQuery.error( jsonpCallback + " was not called" );
} }
return responseContainer[ 0 ]; return responseContainer[ 0 ];

View file

@ -3,13 +3,16 @@
// Install script dataType // Install script dataType
jQuery.ajaxSetup({ jQuery.ajaxSetup({
accepts: { accepts: {
script: "text/javascript, application/javascript" script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
}, },
contents: { contents: {
script: /javascript/ script: /javascript|ecmascript/
}, },
converters: { converters: {
"text script": jQuery.globalEval "text script": function( text ) {
jQuery.globalEval( text );
return text;
}
} }
}); });
@ -31,7 +34,7 @@ jQuery.ajaxTransport( "script", function(s) {
if ( s.crossDomain ) { if ( s.crossDomain ) {
var script, var script,
head = document.getElementsByTagName( "head" )[ 0 ] || document.documentElement; head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
return { return {

View file

@ -1,17 +1,35 @@
(function( jQuery ) { (function( jQuery ) {
var // Next active xhr id var // #5280: next active xhr id and list of active xhrs' callbacks
xhrId = jQuery.now(), xhrId = jQuery.now(),
xhrCallbacks,
// active xhrs
xhrs = {},
// #5280: see below
xhrUnloadAbortInstalled,
// XHR used to determine supports properties // XHR used to determine supports properties
testXHR; testXHR;
// #5280: Internet Explorer will keep connections alive if we don't abort on unload
function xhrOnUnloadAbort() {
jQuery( window ).unload(function() {
// Abort all pending requests
for ( var key in xhrCallbacks ) {
xhrCallbacks[ key ]( 0, 1 );
}
});
}
// 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 // Create the request object
// (This is still attached to ajaxSettings for backward compatibility) // (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ? jQuery.ajaxSettings.xhr = window.ActiveXObject ?
@ -22,27 +40,13 @@ jQuery.ajaxSettings.xhr = window.ActiveXObject ?
* we need a fallback. * we need a fallback.
*/ */
function() { function() {
if ( window.location.protocol !== "file:" ) { return !this.isLocal && createStandardXHR() || createActiveXHR();
try {
return new window.XMLHttpRequest();
} catch( xhrError ) {}
}
try {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} catch( activeError ) {}
} : } :
// For all other browsers, use the standard XMLHttpRequest object // For all other browsers, use the standard XMLHttpRequest object
function() { createStandardXHR;
return new window.XMLHttpRequest();
};
// Test if we can create an xhr object // Test if we can create an xhr object
try { testXHR = jQuery.ajaxSettings.xhr();
testXHR = jQuery.ajaxSettings.xhr();
} catch( xhrCreationException ) {}
//Does this browser support XHR requests?
jQuery.support.ajax = !!testXHR; jQuery.support.ajax = !!testXHR;
// Does this browser support crossDomain XHR requests // Does this browser support crossDomain XHR requests
@ -63,26 +67,10 @@ if ( jQuery.support.ajax ) {
return { return {
send: function( headers, complete ) { send: function( headers, complete ) {
// #5280: we need to abort on unload or IE will keep connections alive
if ( !xhrUnloadAbortInstalled ) {
xhrUnloadAbortInstalled = 1;
jQuery(window).bind( "unload", function() {
// Abort all pending requests
jQuery.each( xhrs, function( _, xhr ) {
if ( xhr.onreadystatechange ) {
xhr.onreadystatechange( 1 );
}
} );
} );
}
// Get a new xhr // Get a new xhr
var xhr = s.xhr(), var xhr = s.xhr(),
handle; handle,
i;
// Open the socket // Open the socket
// Passing null username, generates a login popup on Opera (#2865) // Passing null username, generates a login popup on Opera (#2865)
@ -92,100 +80,113 @@ if ( jQuery.support.ajax ) {
xhr.open( s.type, s.url, s.async ); 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 );
}
// Requested-With header // Requested-With header
// Not set for crossDomain requests with no content // Not set for crossDomain requests with no content
// (see why at http://trac.dojotoolkit.org/ticket/9486) // (see why at http://trac.dojotoolkit.org/ticket/9486)
// Won't change header if already provided // Won't change header if already provided
if ( !( s.crossDomain && !s.hasContent ) && !headers["x-requested-with"] ) { if ( !( s.crossDomain && !s.hasContent ) && !headers["X-Requested-With"] ) {
headers[ "x-requested-with" ] = "XMLHttpRequest"; headers[ "X-Requested-With" ] = "XMLHttpRequest";
} }
// Need an extra try/catch for cross domain requests in Firefox 3 // Need an extra try/catch for cross domain requests in Firefox 3
try { try {
jQuery.each( headers, function( key, value ) { for ( i in headers ) {
xhr.setRequestHeader( key, value ); xhr.setRequestHeader( i, headers[ i ] );
} ); }
} catch( _ ) {} } catch( _ ) {}
// Do send the request // Do send the request
try { // This may raise an exception which is actually
xhr.send( ( s.hasContent && s.data ) || null ); // handled in jQuery.ajax (so no try/catch here)
} catch( e ) { xhr.send( ( s.hasContent && s.data ) || null );
complete( 0, "error", "" + e );
return;
}
// Listener // Listener
callback = function( _, isAbort ) { callback = function( _, isAbort ) {
// Was never called and is aborted or complete var status,
if ( callback && ( isAbort || xhr.readyState === 4 ) ) { statusText,
responseHeaders,
responses,
xml;
// Only called once // Firefox throws exceptions when accessing properties
callback = 0; // of an xhr when a network error occured
// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
try {
// Do not keep as active anymore // Was never called and is aborted or complete
if ( handle ) { if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
xhr.onreadystatechange = jQuery.noop;
delete xhrs[ handle ];
}
// If it's an abort // Only called once
if ( isAbort ) { callback = undefined;
// Abort it manually if needed
if ( xhr.readyState !== 4 ) { // Do not keep as active anymore
xhr.abort(); if ( handle ) {
xhr.onreadystatechange = jQuery.noop;
delete xhrCallbacks[ handle ];
} }
} else {
// Get info // If it's an abort
var status = xhr.status, if ( isAbort ) {
statusText, // Abort it manually if needed
responseHeaders = xhr.getAllResponseHeaders(), if ( xhr.readyState !== 4 ) {
responses = {}, xhr.abort();
}
} else {
status = xhr.status;
responseHeaders = xhr.getAllResponseHeaders();
responses = {};
xml = xhr.responseXML; xml = xhr.responseXML;
// Construct response list // Construct response list
if ( xml && xml.documentElement /* #4958 */ ) { if ( xml && xml.documentElement /* #4958 */ ) {
responses.xml = xml; responses.xml = xml;
}
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;
}
} }
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 behaviours
status =
// Opera returns 0 when it should be 304
// Webkit returns 0 for failing cross-domain no matter the real status
status === 0 ?
(
// Webkit, Firefox: filter out faulty cross-domain requests
!s.crossDomain || statusText ?
(
// Opera: filter out real aborts #6060
responseHeaders ?
304 :
0
) :
// We assume 302 but could be anything cross-domain related
302
) :
(
// IE sometimes returns 1223 when it should be 204 (see #1450)
status == 1223 ?
204 :
status
);
// Call complete
complete( status, statusText, responses, responseHeaders );
} }
} catch( firefoxAccessException ) {
if ( !isAbort ) {
complete( -1, firefoxAccessException );
}
}
// Call complete if needed
if ( responses ) {
complete( status, statusText, responses, responseHeaders );
} }
}; };
@ -195,10 +196,15 @@ if ( jQuery.support.ajax ) {
if ( !s.async || xhr.readyState === 4 ) { if ( !s.async || xhr.readyState === 4 ) {
callback(); callback();
} else { } else {
// Add to list of active xhrs // Create the active xhrs callbacks list if needed
// and attach the unload handler
if ( !xhrCallbacks ) {
xhrCallbacks = {};
xhrOnUnloadAbort();
}
// Add to list of active xhrs callbacks
handle = xhrId++; handle = xhrId++;
xhrs[ handle ] = xhr; xhr.onreadystatechange = xhrCallbacks[ handle ] = callback;
xhr.onreadystatechange = callback;
} }
}, },

View file

@ -198,6 +198,11 @@ jQuery.fn.extend({
} }
} }
// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
if ( one && !values.length && options.length ) {
return jQuery( options[ index ] ).val();
}
return values; return values;
} }

View file

@ -26,9 +26,6 @@ var jQuery = function( selector, context ) {
trimLeft = /^\s+/, trimLeft = /^\s+/,
trimRight = /\s+$/, trimRight = /\s+$/,
// Check for non-word characters
rnonword = /\W/,
// Check for digits // Check for digits
rdigit = /\d/, rdigit = /\d/,
@ -297,7 +294,7 @@ jQuery.fn = jQuery.prototype = {
jQuery.fn.init.prototype = jQuery.fn; jQuery.fn.init.prototype = jQuery.fn;
jQuery.extend = jQuery.fn.extend = function() { jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone, var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {}, target = arguments[0] || {},
i = 1, i = 1,
length = arguments.length, length = arguments.length,
@ -569,10 +566,8 @@ jQuery.extend({
if ( data && rnotwhite.test(data) ) { if ( data && rnotwhite.test(data) ) {
// Inspired by code by Andrea Giammarchi // Inspired by code by Andrea Giammarchi
// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
var head = document.getElementsByTagName("head")[0] || document.documentElement, var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement,
script = document.createElement("script"); script = document.createElement( "script" );
script.type = "text/javascript";
if ( jQuery.support.scriptEval() ) { if ( jQuery.support.scriptEval() ) {
script.appendChild( document.createTextNode( data ) ); script.appendChild( document.createTextNode( data ) );
@ -895,22 +890,22 @@ jQuery.extend({
isRejected: failDeferred.isResolved, isRejected: failDeferred.isResolved,
// Get a promise for this deferred // Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object // If obj is provided, the promise aspect is added to the object
promise: function( obj , i /* internal */ ) { promise: function( obj ) {
if ( obj == null ) { if ( obj == null ) {
if ( promise ) { if ( promise ) {
return promise; return promise;
} }
promise = obj = {}; promise = obj = {};
} }
i = promiseMethods.length; var i = promiseMethods.length;
while( i-- ) { while( i-- ) {
obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ]; obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
} }
return obj; return obj;
} }
} ); } );
// Make sure only one callback list will be used // Make sure only one callback list will be used
deferred.then( failDeferred.cancel, deferred.cancel ); deferred.done( failDeferred.cancel ).fail( deferred.cancel );
// Unexpose cancel // Unexpose cancel
delete deferred.cancel; delete deferred.cancel;
// Call given func if any // Call given func if any
@ -922,25 +917,34 @@ jQuery.extend({
// Deferred helper // Deferred helper
when: function( object ) { when: function( object ) {
var args = arguments, var lastIndex = arguments.length,
length = args.length, deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ?
deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ?
object : object :
jQuery.Deferred(), jQuery.Deferred(),
promise = deferred.promise(), promise = deferred.promise();
resolveArray;
if ( length > 1 ) { if ( lastIndex > 1 ) {
resolveArray = new Array( length ); var array = slice.call( arguments, 0 ),
jQuery.each( args, function( index, element, args ) { count = lastIndex,
jQuery.when( element ).then( function( value ) { iCallback = function( index ) {
args = arguments; return function( value ) {
resolveArray[ index ] = args.length > 1 ? slice.call( args, 0 ) : value; array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value;
if( ! --length ) { if ( !( --count ) ) {
deferred.resolveWith( promise, resolveArray ); deferred.resolveWith( promise, array );
} }
}, deferred.reject ); };
} ); };
while( ( lastIndex-- ) ) {
object = array[ lastIndex ];
if ( object && jQuery.isFunction( object.promise ) ) {
object.promise().then( iCallback(lastIndex), deferred.reject );
} else {
--count;
}
}
if ( !count ) {
deferred.resolveWith( promise, array );
}
} else if ( deferred !== object ) { } else if ( deferred !== object ) {
deferred.resolve( object ); deferred.resolve( object );
} }
@ -961,18 +965,20 @@ jQuery.extend({
return { browser: match[1] || "", version: match[2] || "0" }; return { browser: match[1] || "", version: match[2] || "0" };
}, },
subclass: function(){ sub: function() {
function jQuerySubclass( selector, context ) { function jQuerySubclass( selector, context ) {
return new jQuerySubclass.fn.init( selector, context ); return new jQuerySubclass.fn.init( selector, context );
} }
jQuery.extend( true, jQuerySubclass, this );
jQuerySubclass.superclass = this; jQuerySubclass.superclass = this;
jQuerySubclass.fn = jQuerySubclass.prototype = this(); jQuerySubclass.fn = jQuerySubclass.prototype = this();
jQuerySubclass.fn.constructor = jQuerySubclass; jQuerySubclass.fn.constructor = jQuerySubclass;
jQuerySubclass.subclass = this.subclass; jQuerySubclass.subclass = this.subclass;
jQuerySubclass.fn.init = function init( selector, context ) { jQuerySubclass.fn.init = function init( selector, context ) {
if (context && context instanceof jQuery && !(context instanceof jQuerySubclass)){ if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) {
context = jQuerySubclass(context); context = jQuerySubclass(context);
} }
return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass ); return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass );
}; };
jQuerySubclass.fn.init.prototype = jQuerySubclass.fn; jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;
@ -1054,6 +1060,6 @@ function doScrollCheck() {
} }
// Expose jQuery to the global object // Expose jQuery to the global object
return (window.jQuery = window.$ = jQuery); return jQuery;
})(); })();

View file

@ -263,7 +263,7 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) {
if ( document.documentElement.currentStyle ) { if ( document.documentElement.currentStyle ) {
currentStyle = function( elem, name ) { currentStyle = function( elem, name ) {
var left, var left,
ret = elem.currentStyle && elem.currentStyle[ name ], ret = elem.currentStyle && elem.currentStyle[ name ],
rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ], rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
style = elem.style; style = elem.style;

View file

@ -24,7 +24,7 @@ jQuery.extend({
hasData: function( elem ) { hasData: function( elem ) {
elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
return !!elem && !jQuery.isEmptyObject(elem); return !!elem && !isEmptyDataObject( elem );
}, },
data: function( elem, name, data, pvt /* Internal Use Only */ ) { data: function( elem, name, data, pvt /* Internal Use Only */ ) {
@ -64,11 +64,18 @@ jQuery.extend({
if ( !cache[ id ] ) { if ( !cache[ id ] ) {
cache[ id ] = {}; cache[ id ] = {};
// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
// metadata on plain JS objects when the object is serialized using
// JSON.stringify
if ( !isNode ) {
cache[ id ].toJSON = jQuery.noop;
}
} }
// An object can be passed to jQuery.data instead of a key/value pair; this gets // An object can be passed to jQuery.data instead of a key/value pair; this gets
// shallow copied over onto the existing cache // shallow copied over onto the existing cache
if ( typeof name === "object" ) { if ( typeof name === "object" || typeof name === "function" ) {
if ( pvt ) { if ( pvt ) {
cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
} else { } else {
@ -130,7 +137,7 @@ jQuery.extend({
// If there is no data left in the cache, we want to continue // If there is no data left in the cache, we want to continue
// and let the cache object itself get destroyed // and let the cache object itself get destroyed
if ( !jQuery.isEmptyObject(thisCache) ) { if ( !isEmptyDataObject(thisCache) ) {
return; return;
} }
} }
@ -142,7 +149,7 @@ jQuery.extend({
// Don't destroy the parent cache unless the internal data object // Don't destroy the parent cache unless the internal data object
// had been the only thing left in it // had been the only thing left in it
if ( !jQuery.isEmptyObject(cache[ id ]) ) { if ( !isEmptyDataObject(cache[ id ]) ) {
return; return;
} }
} }
@ -163,6 +170,13 @@ jQuery.extend({
// data if it existed // data if it existed
if ( internalCache ) { if ( internalCache ) {
cache[ id ] = {}; cache[ id ] = {};
// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
// metadata on plain JS objects when the object is serialized using
// JSON.stringify
if ( !isNode ) {
cache[ id ].toJSON = jQuery.noop;
}
cache[ id ][ internalKey ] = internalCache; cache[ id ][ internalKey ] = internalCache;
// Otherwise, we need to eliminate the expando on the node to avoid // Otherwise, we need to eliminate the expando on the node to avoid
@ -291,4 +305,17 @@ function dataAttr( elem, key, data ) {
return data; return data;
} }
// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON
// property to be considered empty objects; this property always exists in
// order to make sure JSON.stringify does not expose internal metadata
function isEmptyDataObject( obj ) {
for ( var name in obj ) {
if ( name !== "toJSON" ) {
return false;
}
}
return true;
}
})( jQuery ); })( jQuery );

14
src/effects.js vendored
View file

@ -185,11 +185,11 @@ jQuery.fn.extend({
} else { } else {
var parts = rfxnum.exec(val), var parts = rfxnum.exec(val),
start = e.cur() || 0; start = e.cur();
if ( parts ) { if ( parts ) {
var end = parseFloat( parts[2] ), var end = parseFloat( parts[2] ),
unit = parts[3] || "px"; unit = parts[3] || ( jQuery.cssNumber[ name ] ? "" : "px" );
// We need to compute starting value // We need to compute starting value
if ( unit !== "px" ) { if ( unit !== "px" ) {
@ -336,8 +336,12 @@ jQuery.fx.prototype = {
return this.elem[ this.prop ]; return this.elem[ this.prop ];
} }
var r = parseFloat( jQuery.css( this.elem, this.prop ) ); var parsed,
return r || 0; r = jQuery.css( this.elem, this.prop );
// Empty strings, null, undefined and "auto" are converted to 0,
// complex values such as "rotate(1rad)" are returned as is,
// simple values such as "10px" are parsed to Float.
return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
}, },
// Start an animation from one number to another // Start an animation from one number to another
@ -348,7 +352,7 @@ jQuery.fx.prototype = {
this.startTime = jQuery.now(); this.startTime = jQuery.now();
this.start = from; this.start = from;
this.end = to; this.end = to;
this.unit = unit || this.unit || "px"; this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
this.now = this.start; this.now = this.start;
this.pos = this.state = 0; this.pos = this.state = 0;

View file

@ -7,8 +7,7 @@ var rnamespaces = /\.(.*)$/,
rescape = /[^\w\s.|`]/g, rescape = /[^\w\s.|`]/g,
fcleanup = function( nm ) { fcleanup = function( nm ) {
return nm.replace(rescape, "\\$&"); return nm.replace(rescape, "\\$&");
}, };
eventKey = "events";
/* /*
* A number of helper functions used for managing events. * A number of helper functions used for managing events.
@ -24,17 +23,22 @@ jQuery.event = {
return; return;
} }
// For whatever reason, IE has trouble passing the window object // TODO :: Use a try/catch until it's safe to pull this out (likely 1.6)
// around, causing it to be cloned in the process // Minor release fix for bug #8018
if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { try {
elem = window; // For whatever reason, IE has trouble passing the window object
// around, causing it to be cloned in the process
if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
elem = window;
}
} }
catch ( e ) {}
if ( handler === false ) { if ( handler === false ) {
handler = returnFalse; handler = returnFalse;
} else if ( !handler ) { } else if ( !handler ) {
// Fixes bug #7229. Fix recommended by jdalton // Fixes bug #7229. Fix recommended by jdalton
return; return;
} }
var handleObjIn, handleObj; var handleObjIn, handleObj;
@ -58,23 +62,10 @@ jQuery.event = {
return; return;
} }
var events = elemData[ eventKey ], var events = elemData.events,
eventHandle = elemData.handle; eventHandle = elemData.handle;
if ( typeof events === "function" ) { if ( !events ) {
// On plain objects events is a fn that holds the the data
// which prevents this data from being JSON serialized
// the function does not need to be called, it just contains the data
eventHandle = events.handle;
events = events.events;
} else if ( !events ) {
if ( !elem.nodeType ) {
// On plain objects, create a fn that acts as the holder
// of the values to avoid JSON serialization of event data
elemData[ eventKey ] = elemData = function(){};
}
elemData.events = events = {}; elemData.events = events = {};
} }
@ -175,17 +166,12 @@ jQuery.event = {
var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
elemData = jQuery.hasData( elem ) && jQuery._data( elem ), elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
events = elemData && elemData[ eventKey ]; events = elemData && elemData.events;
if ( !elemData || !events ) { if ( !elemData || !events ) {
return; return;
} }
if ( typeof events === "function" ) {
elemData = events;
events = events.events;
}
// types is actually an event object here // types is actually an event object here
if ( types && types.type ) { if ( types && types.type ) {
handler = types.handler; handler = types.handler;
@ -285,10 +271,7 @@ jQuery.event = {
delete elemData.events; delete elemData.events;
delete elemData.handle; delete elemData.handle;
if ( typeof elemData === "function" ) { if ( jQuery.isEmptyObject( elemData ) ) {
jQuery.removeData( elem, eventKey, true );
} else if ( jQuery.isEmptyObject( elemData ) ) {
jQuery.removeData( elem, undefined, true ); jQuery.removeData( elem, undefined, true );
} }
} }
@ -329,7 +312,7 @@ jQuery.event = {
// points to jQuery.expando // points to jQuery.expando
var internalKey = jQuery.expando, var internalKey = jQuery.expando,
internalCache = this[ internalKey ]; internalCache = this[ internalKey ];
if ( internalCache && internalCache.events && internalCache.events[type] ) { if ( internalCache && internalCache.events && internalCache.events[ type ] ) {
jQuery.event.trigger( event, data, internalCache.handle.elem ); jQuery.event.trigger( event, data, internalCache.handle.elem );
} }
}); });
@ -355,9 +338,7 @@ jQuery.event = {
event.currentTarget = elem; event.currentTarget = elem;
// Trigger the event, it is assumed that "handle" is a function // Trigger the event, it is assumed that "handle" is a function
var handle = elem.nodeType ? var handle = jQuery._data( elem, "handle" );
jQuery._data( elem, "handle" ) :
(jQuery._data( elem, eventKey ) || {}).handle;
if ( handle ) { if ( handle ) {
handle.apply( elem, data ); handle.apply( elem, data );
@ -435,11 +416,7 @@ jQuery.event = {
event.namespace = event.namespace || namespace_sort.join("."); event.namespace = event.namespace || namespace_sort.join(".");
events = jQuery._data(this, eventKey); events = jQuery._data(this, "events");
if ( typeof events === "function" ) {
events = events.events;
}
handlers = (events || {})[ event.type ]; handlers = (events || {})[ event.type ];
@ -606,7 +583,7 @@ jQuery.Event = function( src ) {
// Events bubbling up the document may have been marked as prevented // Events bubbling up the document may have been marked as prevented
// by a handler lower down the tree; reflect the correct value. // by a handler lower down the tree; reflect the correct value.
this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
// Event type // Event type
@ -681,6 +658,12 @@ var withinElement = function( event ) {
// Firefox sometimes assigns relatedTarget a XUL element // Firefox sometimes assigns relatedTarget a XUL element
// which we cannot access the parentNode property of // which we cannot access the parentNode property of
try { try {
// Chrome does something similar, the parentNode property
// can be accessed but is null.
if ( parent !== document && !parent.parentNode ) {
return;
}
// Traverse up the tree // Traverse up the tree
while ( parent && parent !== this ) { while ( parent && parent !== this ) {
parent = parent.parentNode; parent = parent.parentNode;
@ -731,8 +714,7 @@ if ( !jQuery.support.submitBubbles ) {
type = elem.type; type = elem.type;
if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
e.liveFired = undefined; trigger( "submit", this, arguments );
return trigger( "submit", this, arguments );
} }
}); });
@ -741,8 +723,7 @@ if ( !jQuery.support.submitBubbles ) {
type = elem.type; type = elem.type;
if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
e.liveFired = undefined; trigger( "submit", this, arguments );
return trigger( "submit", this, arguments );
} }
}); });
@ -805,7 +786,7 @@ if ( !jQuery.support.changeBubbles ) {
if ( data != null || val ) { if ( data != null || val ) {
e.type = "change"; e.type = "change";
e.liveFired = undefined; e.liveFired = undefined;
return jQuery.event.trigger( e, arguments[1], elem ); jQuery.event.trigger( e, arguments[1], elem );
} }
}; };
@ -819,7 +800,7 @@ if ( !jQuery.support.changeBubbles ) {
var elem = e.target, type = elem.type; var elem = e.target, type = elem.type;
if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
return testChange.call( this, e ); testChange.call( this, e );
} }
}, },
@ -831,7 +812,7 @@ if ( !jQuery.support.changeBubbles ) {
if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
(e.keyCode === 32 && (type === "checkbox" || type === "radio")) || (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
type === "select-multiple" ) { type === "select-multiple" ) {
return testChange.call( this, e ); testChange.call( this, e );
} }
}, },
@ -870,8 +851,18 @@ if ( !jQuery.support.changeBubbles ) {
} }
function trigger( type, elem, args ) { function trigger( type, elem, args ) {
args[0].type = type; // Piggyback on a donor event to simulate a different one.
return jQuery.event.handle.apply( elem, args ); // Fake originalEvent to avoid donor's stopPropagation, but if the
// simulated event prevents default then we do the same on the donor.
// Don't pass args or remember liveFired; they apply to the donor event.
var event = jQuery.extend( {}, args[ 0 ] );
event.type = type;
event.originalEvent = {};
event.liveFired = undefined;
jQuery.event.handle.call( elem, event );
if ( event.isDefaultPrevented() ) {
args[ 0 ].preventDefault();
}
} }
// Create "bubbling" focus and blur events // Create "bubbling" focus and blur events
@ -880,8 +871,8 @@ if ( document.addEventListener ) {
jQuery.event.special[ fix ] = { jQuery.event.special[ fix ] = {
setup: function() { setup: function() {
this.addEventListener( orig, handler, true ); this.addEventListener( orig, handler, true );
}, },
teardown: function() { teardown: function() {
this.removeEventListener( orig, handler, true ); this.removeEventListener( orig, handler, true );
} }
}; };
@ -1074,11 +1065,7 @@ function liveHandler( event ) {
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
elems = [], elems = [],
selectors = [], selectors = [],
events = jQuery._data( this, eventKey ); events = jQuery._data( this, "events" );
if ( typeof events === "function" ) {
events = events.events;
}
// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
@ -1112,7 +1099,7 @@ function liveHandler( event ) {
for ( j = 0; j < live.length; j++ ) { for ( j = 0; j < live.length; j++ ) {
handleObj = live[j]; handleObj = live[j];
if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) { if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
elem = close.elem; elem = close.elem;
related = null; related = null;

View file

@ -2,13 +2,13 @@
* jQuery JavaScript Library v@VERSION * jQuery JavaScript Library v@VERSION
* http://jquery.com/ * http://jquery.com/
* *
* Copyright 2010, John Resig * Copyright 2011, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* Includes Sizzle.js * Includes Sizzle.js
* http://sizzlejs.com/ * http://sizzlejs.com/
* Copyright 2010, The Dojo Foundation * Copyright 2011, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses. * Released under the MIT, BSD, and GPL Licenses.
* *
* Date: @DATE * Date: @DATE

View file

@ -7,7 +7,7 @@ var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
rtbody = /<tbody/i, rtbody = /<tbody/i,
rhtml = /<|&#?\w+;/, rhtml = /<|&#?\w+;/,
rnocache = /<(?:script|object|embed|option|style)/i, rnocache = /<(?:script|object|embed|option|style)/i,
// checked="checked" or checked (html5) // checked="checked" or checked
rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
wrapMap = { wrapMap = {
option: [ 1, "<select multiple='multiple'>", "</select>" ], option: [ 1, "<select multiple='multiple'>", "</select>" ],
@ -159,7 +159,7 @@ jQuery.fn.extend({
} }
if ( elem.parentNode ) { if ( elem.parentNode ) {
elem.parentNode.removeChild( elem ); elem.parentNode.removeChild( elem );
} }
} }
} }
@ -184,9 +184,9 @@ jQuery.fn.extend({
}, },
clone: function( dataAndEvents, deepDataAndEvents ) { clone: function( dataAndEvents, deepDataAndEvents ) {
dataAndEvents = dataAndEvents == null ? true : dataAndEvents; dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
return this.map( function () { return this.map( function () {
return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
}); });
@ -311,12 +311,19 @@ jQuery.fn.extend({
if ( first ) { if ( first ) {
table = table && jQuery.nodeName( first, "tr" ); table = table && jQuery.nodeName( first, "tr" );
for ( var i = 0, l = this.length; i < l; i++ ) { for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
callback.call( callback.call(
table ? table ?
root(this[i], first) : root(this[i], first) :
this[i], this[i],
i > 0 || results.cacheable || (this.length > 1 && i > 0) ? // Make sure that we do not leak memory by inadvertently discarding
// the original fragment (which might have attached data) instead of
// using it; in addition, use the original fragment object for the last
// item instead of first because it can end up being emptied incorrectly
// in certain situations (Bug #8070).
// Fragments from the fragment cache must always be cloned and never used
// in place.
results.cacheable || (l > 1 && i < lastIndex) ?
jQuery.clone( fragment, true, true ) : jQuery.clone( fragment, true, true ) :
fragment fragment
); );
@ -346,8 +353,8 @@ function cloneCopyEvent( src, dest ) {
} }
var internalKey = jQuery.expando, var internalKey = jQuery.expando,
oldData = jQuery.data( src ), oldData = jQuery.data( src ),
curData = jQuery.data( dest, oldData ); curData = jQuery.data( dest, oldData );
// Switch to use the internal data object, if it exists, for the next // Switch to use the internal data object, if it exists, for the next
// stage of data copying // stage of data copying
@ -361,7 +368,7 @@ function cloneCopyEvent( src, dest ) {
for ( var type in events ) { for ( var type in events ) {
for ( var i = 0, l = events[ type ].length; i < l; i++ ) { for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
jQuery.event.add( dest, type, events[ type ][ i ], events[ type ][ i ].data ); jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
} }
} }
} }
@ -482,24 +489,39 @@ jQuery.each({
}; };
}); });
function getAll( elem ) {
if ( "getElementsByTagName" in elem ) {
return elem.getElementsByTagName( "*" );
} else if ( "querySelectorAll" in elem ) {
return elem.querySelectorAll( "*" );
} else {
return [];
}
}
jQuery.extend({ jQuery.extend({
clone: function( elem, dataAndEvents, deepDataAndEvents ) { clone: function( elem, dataAndEvents, deepDataAndEvents ) {
var clone = elem.cloneNode(true), var clone = elem.cloneNode(true),
srcElements, srcElements,
destElements, destElements,
i; i;
if ( !jQuery.support.noCloneEvent && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
// IE copies events bound via attachEvent when using cloneNode. // IE copies events bound via attachEvent when using cloneNode.
// Calling detachEvent on the clone will also remove the events // Calling detachEvent on the clone will also remove the events
// from the original. In order to get around this, we use some // from the original. In order to get around this, we use some
// proprietary methods to clear the events. Thanks to MooTools // proprietary methods to clear the events. Thanks to MooTools
// guys for this hotness. // guys for this hotness.
cloneFixAttributes( elem, clone );
// Using Sizzle here is crazy slow, so we use getElementsByTagName // Using Sizzle here is crazy slow, so we use getElementsByTagName
// instead // instead
srcElements = elem.getElementsByTagName("*"); srcElements = getAll( elem );
destElements = clone.getElementsByTagName("*"); destElements = getAll( clone );
// Weird iteration because IE will replace the length property // Weird iteration because IE will replace the length property
// with an element if you are cloning the body and one of the // with an element if you are cloning the body and one of the
@ -507,30 +529,25 @@ jQuery.extend({
for ( i = 0; srcElements[i]; ++i ) { for ( i = 0; srcElements[i]; ++i ) {
cloneFixAttributes( srcElements[i], destElements[i] ); cloneFixAttributes( srcElements[i], destElements[i] );
} }
cloneFixAttributes( elem, clone );
} }
// Copy the events from the original to the clone // Copy the events from the original to the clone
if ( dataAndEvents ) { if ( dataAndEvents ) {
cloneCopyEvent( elem, clone ); cloneCopyEvent( elem, clone );
if ( deepDataAndEvents && "getElementsByTagName" in elem ) { if ( deepDataAndEvents ) {
srcElements = getAll( elem );
destElements = getAll( clone );
srcElements = elem.getElementsByTagName("*"); for ( i = 0; srcElements[i]; ++i ) {
destElements = clone.getElementsByTagName("*"); cloneCopyEvent( srcElements[i], destElements[i] );
if ( srcElements.length ) {
for ( i = 0; srcElements[i]; ++i ) {
cloneCopyEvent( srcElements[i], destElements[i] );
}
} }
} }
} }
// Return the cloned set // Return the cloned set
return clone; return clone;
}, },
clean: function( elems, context, fragment, scripts ) { clean: function( elems, context, fragment, scripts ) {
context = context || document; context = context || document;

View file

@ -275,7 +275,7 @@ jQuery.each( ["Left", "Top"], function( i, name ) {
if ( win ) { if ( win ) {
win.scrollTo( win.scrollTo(
!i ? val : jQuery(win).scrollLeft(), !i ? val : jQuery(win).scrollLeft(),
i ? val : jQuery(win).scrollTop() i ? val : jQuery(win).scrollTop()
); );
} else { } else {

View file

@ -1 +1,2 @@
window.jQuery = window.$ = jQuery;
})(window); })(window);

View file

@ -12,7 +12,8 @@
var all = div.getElementsByTagName("*"), var all = div.getElementsByTagName("*"),
a = div.getElementsByTagName("a")[0], a = div.getElementsByTagName("a")[0],
select = document.createElement("select"), select = document.createElement("select"),
opt = select.appendChild( document.createElement("option") ); opt = select.appendChild( document.createElement("option") ),
input = div.getElementsByTagName("input")[0];
// Can't get basic test support // Can't get basic test support
if ( !all || !all.length || !a ) { if ( !all || !all.length || !a ) {
@ -51,7 +52,7 @@
// Make sure that if no value is specified for a checkbox // Make sure that if no value is specified for a checkbox
// that it defaults to "on". // that it defaults to "on".
// (WebKit defaults to "" instead) // (WebKit defaults to "" instead)
checkOn: div.getElementsByTagName("input")[0].value === "on", checkOn: input.value === "on",
// Make sure that a selected-by-default option has a working selected property. // Make sure that a selected-by-default option has a working selected property.
// (WebKit defaults to false instead of true, IE too, if it's in an optgroup) // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
@ -61,26 +62,29 @@
deleteExpando: true, deleteExpando: true,
optDisabled: false, optDisabled: false,
checkClone: false, checkClone: false,
_scriptEval: null,
noCloneEvent: true, noCloneEvent: true,
noCloneChecked: true,
boxModel: null, boxModel: null,
inlineBlockNeedsLayout: false, inlineBlockNeedsLayout: false,
shrinkWrapBlocks: false, shrinkWrapBlocks: false,
reliableHiddenOffsets: true reliableHiddenOffsets: true
}; };
input.checked = true;
jQuery.support.noCloneChecked = input.cloneNode( true ).checked;
// Make sure that the options inside disabled selects aren't marked as disabled // Make sure that the options inside disabled selects aren't marked as disabled
// (WebKit marks them as diabled) // (WebKit marks them as diabled)
select.disabled = true; select.disabled = true;
jQuery.support.optDisabled = !opt.disabled; jQuery.support.optDisabled = !opt.disabled;
var _scriptEval = null;
jQuery.support.scriptEval = function() { jQuery.support.scriptEval = function() {
if ( jQuery.support._scriptEval === null ) { if ( _scriptEval === null ) {
var root = document.documentElement, var root = document.documentElement,
script = document.createElement("script"), script = document.createElement("script"),
id = "script" + jQuery.now(); id = "script" + jQuery.now();
script.type = "text/javascript";
try { try {
script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
} catch(e) {} } catch(e) {}
@ -91,10 +95,10 @@
// tag with appendChild/createTextNode // tag with appendChild/createTextNode
// (IE doesn't support this, fails, and uses .text instead) // (IE doesn't support this, fails, and uses .text instead)
if ( window[ id ] ) { if ( window[ id ] ) {
jQuery.support._scriptEval = true; _scriptEval = true;
delete window[ id ]; delete window[ id ];
} else { } else {
jQuery.support._scriptEval = false; _scriptEval = false;
} }
root.removeChild( script ); root.removeChild( script );
@ -102,7 +106,7 @@
root = script = id = null; root = script = id = null;
} }
return jQuery.support._scriptEval; return _scriptEval;
}; };
// Test to see if it's possible to delete an expando from an element // Test to see if it's possible to delete an expando from an element
@ -114,7 +118,7 @@
jQuery.support.deleteExpando = false; jQuery.support.deleteExpando = false;
} }
if ( div.attachEvent && div.fireEvent ) { if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
div.attachEvent("onclick", function click() { div.attachEvent("onclick", function click() {
// Cloning a node shouldn't copy over any // Cloning a node shouldn't copy over any
// bound event handlers (IE does this) // bound event handlers (IE does this)

View file

@ -205,11 +205,11 @@ jQuery.each({
}, function( name, fn ) { }, function( name, fn ) {
jQuery.fn[ name ] = function( until, selector ) { jQuery.fn[ name ] = function( until, selector ) {
var ret = jQuery.map( this, fn, until ), var ret = jQuery.map( this, fn, until ),
// The variable 'args' was introduced in // The variable 'args' was introduced in
// https://github.com/jquery/jquery/commit/52a0238 // https://github.com/jquery/jquery/commit/52a0238
// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
// http://code.google.com/p/v8/issues/detail?id=1050 // http://code.google.com/p/v8/issues/detail?id=1050
args = slice.call(arguments); args = slice.call(arguments);
if ( !runtil.test( name ) ) { if ( !runtil.test( name ) ) {
selector = until; selector = until;

View file

@ -1,15 +0,0 @@
<?php
error_reporting(0);
$id = isset ( $_REQUEST['id'] ) ? $_REQUEST['id'] : null;
$wait = isset( $_REQUEST['wait'] ) ? $_REQUEST['wait'] : null;
if ( $wait ) sleep( $wait );
header("Content-type: text/css");
if ( $id ) {
?>
div#<?= $id ?> { margin-left: 27px }
<?php
}
?>

View file

@ -1,6 +1,8 @@
<?php <?php
header( "Sample-Header: Hello World" ); header( "Sample-Header: Hello World" );
header( "Empty-Header: " );
header( "Sample-Header2: Hello World 2" );
$headers = array(); $headers = array();

View file

@ -1 +0,0 @@
json_assigned_obj = { "test" : "worked" };

View file

@ -19,11 +19,6 @@ if($name == 'foo') {
echo "pan"; echo "pan";
die(); die();
} }
$request = apache_request_headers();
$request = $request['X-Custom-Header'];
if(strlen($request) > 0) {
echo $request;
die();
}
echo 'ERROR <script type="text/javascript">ok( true, "name.php executed" );</script>'; echo 'ERROR <script type="text/javascript">ok( true, "name.php executed" );</script>';
?> ?>

View file

@ -1 +0,0 @@
<?php header('HTTP/1.0 304 Not Modified'); exit; ?>

View file

@ -26,7 +26,7 @@
<script src="../../../src/offset.js"></script> <script src="../../../src/offset.js"></script>
<script type="text/javascript" src="../../../dist/jquery.js"></script> <script type="text/javascript" src="../../../dist/jquery.js"></script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
$(function() { jQuery(function($) {
$('.absolute').click(function() { $('.absolute').click(function() {
$('#marker').css( $(this).offset() ); $('#marker').css( $(this).offset() );
var pos = $(this).position(); var pos = $(this).position();

View file

@ -18,7 +18,7 @@
<script src="../../../src/css.js"></script> <script src="../../../src/css.js"></script>
<script src="../../../src/offset.js"></script> <script src="../../../src/offset.js"></script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
$(function() { jQuery(function($) {
$('body').click(function() { $('body').click(function() {
$('#marker').css( $(this).offset() ); $('#marker').css( $(this).offset() );
return false; return false;
@ -29,4 +29,4 @@
<body> <body>
<div id="marker"></div> <div id="marker"></div>
</body> </body>
</html> </html>

View file

@ -22,7 +22,7 @@
<script src="../../../src/css.js"></script> <script src="../../../src/css.js"></script>
<script src="../../../src/offset.js"></script> <script src="../../../src/offset.js"></script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
$(function() { jQuery(function($) {
window.scrollTo(1000,1000); window.scrollTo(1000,1000);
$('.fixed').click(function() { $('.fixed').click(function() {
$('#marker').css( $(this).offset() ); $('#marker').css( $(this).offset() );
@ -38,4 +38,4 @@
<div id="marker"></div> <div id="marker"></div>
<p class="instructions">Click the white box to move the marker to it.</p> <p class="instructions">Click the white box to move the marker to it.</p>
</body> </body>
</html> </html>

View file

@ -20,7 +20,7 @@
<script src="../../../src/css.js"></script> <script src="../../../src/css.js"></script>
<script src="../../../src/offset.js"></script> <script src="../../../src/offset.js"></script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
$(function() { jQuery(function($) {
$('.relative').click(function() { $('.relative').click(function() {
$('#marker').css( $(this).offset() ); $('#marker').css( $(this).offset() );
var pos = $(this).position(); var pos = $(this).position();
@ -36,4 +36,4 @@
<div id="marker"></div> <div id="marker"></div>
<p class="instructions">Click the white box to move the marker to it. Clicking the box also changes the position to absolute (if not already) and sets the position according to the position method.</p> <p class="instructions">Click the white box to move the marker to it. Clicking the box also changes the position to absolute (if not already) and sets the position according to the position method.</p>
</body> </body>
</html> </html>

View file

@ -23,7 +23,7 @@
<script src="../../../src/css.js"></script> <script src="../../../src/css.js"></script>
<script src="../../../src/offset.js"></script> <script src="../../../src/offset.js"></script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
$(function() { jQuery(function($) {
window.scrollTo(1000,1000); window.scrollTo(1000,1000);
$('#scroll-1')[0].scrollLeft = 5; $('#scroll-1')[0].scrollLeft = 5;
$('#scroll-1')[0].scrollTop = 5; $('#scroll-1')[0].scrollTop = 5;
@ -44,4 +44,4 @@
<div id="marker"></div> <div id="marker"></div>
<p class="instructions">Click the white box to move the marker to it.</p> <p class="instructions">Click the white box to move the marker to it.</p>
</body> </body>
</html> </html>

View file

@ -20,7 +20,7 @@
<script src="../../../src/css.js"></script> <script src="../../../src/css.js"></script>
<script src="../../../src/offset.js"></script> <script src="../../../src/offset.js"></script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
$(function() { jQuery(function($) {
$('.static').click(function() { $('.static').click(function() {
$('#marker').css( $(this).offset() ); $('#marker').css( $(this).offset() );
var pos = $(this).position(); var pos = $(this).position();
@ -36,4 +36,4 @@
<div id="marker"></div> <div id="marker"></div>
<p class="instructions">Click the white box to move the marker to it. Clicking the box also changes the position to absolute (if not already) and sets the position according to the position method.</p> <p class="instructions">Click the white box to move the marker to it. Clicking the box also changes the position to absolute (if not already) and sets the position according to the position method.</p>
</body> </body>
</html> </html>

View file

@ -20,7 +20,7 @@
<script src="../../../src/css.js"></script> <script src="../../../src/css.js"></script>
<script src="../../../src/offset.js"></script> <script src="../../../src/offset.js"></script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
$(function() { jQuery(function($) {
$('table, th, td').click(function() { $('table, th, td').click(function() {
$('#marker').css( $(this).offset() ); $('#marker').css( $(this).offset() );
return false; return false;
@ -48,4 +48,4 @@
<div id="marker"></div> <div id="marker"></div>
<p class="instructions">Click the white box to move the marker to it.</p> <p class="instructions">Click the white box to move the marker to it.</p>
</body> </body>
</html> </html>

View file

@ -0,0 +1 @@
var delayedMessage = "It worked!";

View file

@ -0,0 +1,25 @@
// Simple script loader that uses jQuery.readyWait
//Hold on jQuery!
jQuery.readyWait++;
var readyRegExp = /^(complete|loaded)$/;
function assetLoaded( evt ){
var node = evt.currentTarget || evt.srcElement;
if ( evt.type === "load" || readyRegExp.test(node.readyState) ) {
jQuery.ready(true);
}
}
setTimeout( function() {
var script = document.createElement("script");
script.type = "text/javascript";
if ( script.addEventListener ) {
script.addEventListener( "load", assetLoaded, false );
} else {
script.attachEvent( "onreadystatechange", assetLoaded );
}
script.src = "data/readywaitasset.js";
document.getElementsByTagName("head")[0].appendChild(script);
}, 2000 );

View file

@ -1,7 +1,11 @@
<?php <?php
error_reporting(0); error_reporting(0);
if ( $_REQUEST['header'] ) { if ( $_REQUEST['header'] ) {
header("Content-type: text/javascript"); if ( $_REQUEST['header'] == "ecma" ) {
header("Content-type: application/ecmascript");
} else {
header("Content-type: text/javascript");
}
} }
?> ?>
ok( true, "Script executed correctly." ); ok( true, "Script executed correctly." );

View file

@ -11,63 +11,71 @@
<body> <body>
<h2>Change Tests</h2> <h2>Change Tests</h2>
<table> <table>
<tr> <tr>
<td> <td>
Change each: Change each:
</td> </td>
<td> <td>
<select class='select_test'> <select class='select_test'>
<option value='one'>change me 1</option> <option value='one'>change me 1</option>
<option value='two'>change me 2</option> <option value='two'>change me 2</option>
<option value='three'>change me 3</option> <option value='three'>change me 3</option>
</select> </select>
<select class='select_test'> <select class='select_test'>
<option value='one'>change me 1</option> <option value='one'>change me 1</option>
<option value='two' selected="selected">change me 2</option> <option value='two' selected="selected">change me 2</option>
<option value='three'>change me 3</option> <option value='three'>change me 3</option>
</select> </select>
</td> </td>
<td> <td>
<select class='mselect_test' multiple="multiple"> <select class='mselect_test' multiple="multiple">
<option value='one'>change me 1</option> <option value='one'>change me 1</option>
<option value='two'>change me 2</option> <option value='two'>change me 2</option>
<option value='three'>change me 3</option> <option value='three'>change me 3</option>
</select> </select>
</td> </td>
<td> <td>
<input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox1"/> <input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox1"/>
<label for="checkbox1">Checkbox 1</label><br/> <label for="checkbox1">Checkbox 1</label><br/>
<input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox2"/> <input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox2"/>
<label for="checkbox2">Checkbox 2</label> <label for="checkbox2">Checkbox 2</label><br />
<input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox3" disabled="disabled"/> <input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox3" disabled="disabled"/>
<label for="checkbox3">Checkbox 3</label> <label for="checkbox3">Checkbox 3</label>
</td> </td>
</td> <td>
</td> <button class="button_test" name="mybutton1" id="button1">Button</button><br />
<td> <button class="button_test" name="mybutton1" id="button1"><span>Button w/ child</span></button><br />
<input type="radio" class="radio_test" name="myradio" id="radio1"/> <button class="button_test" name="mybutton1" id="button1" disabled="disabled">Button Disabled</button><br />
<label for="radio1">Radio1</label><br/> <button class="button_test" name="mybutton1" id="button1" disabled="disabled"><span disabled="disabled">Button w/ child Dis.</span></button><br />
<input type="radio" class="radio_test" name="myradio" id="radio2"/> </td>
<label for="radio2">Radio2</label> <td>
<input type="radio" class="radio_test" name="myradio" id="radio3" disabled="disabled"/> <input type="radio" class="radio_test" name="myradio" id="radio1"/>
<label for="radio3">Radio3</label> <label for="radio1">Radio1</label><br/>
</td> <input type="radio" class="radio_test" name="myradio" id="radio2"/>
<td> <label for="radio2">Radio2</label><br />
<input class="file_test" id="file1" type="file"/> <input type="radio" class="radio_test" name="myradio" id="radio3" disabled="disabled"/>
<td> <label for="radio3">Radio3</label>
<input class='test' value='' id='input' size='10' /> </td>
<input class='test' value='test' id='input2' size='10' readonly="readonly" /> <td>
</td> <input class="file_test" id="file1" type="file"/>
<td> <td>
<textarea rows='2'></textarea> <input class='test' value='' id='input' size='10' />
</td> <input class='test' value='test' id='input2' size='10' readonly="readonly" />
<td>$(document).bind('change')</td> </td>
</tr> <td>
<textarea rows='2'></textarea>
</td>
</td>
<td>$(document).bind('change')<br />
$(document).bind('click')
</td>
</tr>
<tr> <tr>
<td>Live:</td> <td>Live:</td>
<td id='select' class="red">SELECT</td> <td id='select' class="red">SELECT</td>
<td id='mselect' class="red">MULTI</td> <td id='mselect' class="red">MULTI</td>
<td id='checkbox' class="red">CHECKBOX</td> <td id='checkbox' class="red">CHECKBOX</td>
<td id='button' class="red">BUTTON</td>
<td id='radio' class="red">RADIO</td> <td id='radio' class="red">RADIO</td>
<td id='file' class="red">FILE</td> <td id='file' class="red">FILE</td>
<td id='text' class="red">TEXT</td> <td id='text' class="red">TEXT</td>
@ -79,6 +87,7 @@
<td id='selectbind' class="red">SELECT</td> <td id='selectbind' class="red">SELECT</td>
<td id='mselectbind' class="red">MULTI</td> <td id='mselectbind' class="red">MULTI</td>
<td id='checkboxbind' class="red">CHECKBOX</td> <td id='checkboxbind' class="red">CHECKBOX</td>
<td id='buttonbind' class="red">BUTTON</td>
<td id='radiobind' class="red">RADIO</td> <td id='radiobind' class="red">RADIO</td>
<td id='filebind' class="red">FILE</td> <td id='filebind' class="red">FILE</td>
<td id='textbind' class="red">TEXT</td> <td id='textbind' class="red">TEXT</td>
@ -89,6 +98,7 @@
<td id='selectfocus' class="red">SELECT</td> <td id='selectfocus' class="red">SELECT</td>
<td id='mselectfocus' class="red">MULTI</td> <td id='mselectfocus' class="red">MULTI</td>
<td id='checkboxfocus' class="red">CHECKBOX</td> <td id='checkboxfocus' class="red">CHECKBOX</td>
<td id='buttonfocus' class="red">BUTTON</td>
<td id='radiofocus' class="red">RADIO</td> <td id='radiofocus' class="red">RADIO</td>
<td id='filefocus' class="red">FILE</td> <td id='filefocus' class="red">FILE</td>
<td id='textfocus' class="red">TEXT</td> <td id='textfocus' class="red">TEXT</td>
@ -100,6 +110,7 @@
<td id='selectblur' class="red">SELECT</td> <td id='selectblur' class="red">SELECT</td>
<td id='mselectblur' class="red">MULTI</td> <td id='mselectblur' class="red">MULTI</td>
<td id='checkboxblur' class="red">CHECKBOX</td> <td id='checkboxblur' class="red">CHECKBOX</td>
<td id='buttonblur' class="red">BUTTON</td>
<td id='radioblur' class="red">RADIO</td> <td id='radioblur' class="red">RADIO</td>
<td id='fileblur' class="red">FILE</td> <td id='fileblur' class="red">FILE</td>
<td id='textblur' class="red">TEXT</td> <td id='textblur' class="red">TEXT</td>
@ -111,6 +122,7 @@
<td id='selectlfocus' class="red">SELECT</td> <td id='selectlfocus' class="red">SELECT</td>
<td id='mselectlfocus' class="red">MULTI</td> <td id='mselectlfocus' class="red">MULTI</td>
<td id='checkboxlfocus' class="red">CHECKBOX</td> <td id='checkboxlfocus' class="red">CHECKBOX</td>
<td id='buttonlfocus' class="red">BUTTON</td>
<td id='radiolfocus' class="red">RADIO</td> <td id='radiolfocus' class="red">RADIO</td>
<td id='filelfocus' class="red">FILE</td> <td id='filelfocus' class="red">FILE</td>
<td id='textlfocus' class="red">TEXT</td> <td id='textlfocus' class="red">TEXT</td>
@ -121,11 +133,24 @@
<td id='selectlblur' class="red">SELECT</td> <td id='selectlblur' class="red">SELECT</td>
<td id='mselectlblur' class="red">MULTI</td> <td id='mselectlblur' class="red">MULTI</td>
<td id='checkboxlblur' class="red">CHECKBOX</td> <td id='checkboxlblur' class="red">CHECKBOX</td>
<td id='buttonlblur' class="red">BUTTON</td>
<td id='radiolblur' class="red">RADIO</td> <td id='radiolblur' class="red">RADIO</td>
<td id='filelblur' class="red">FILE</td> <td id='filelblur' class="red">FILE</td>
<td id='textlblur' class="red">TEXT</td> <td id='textlblur' class="red">TEXT</td>
<td id='textarealblur' class="red">TEXTAREA</td> <td id='textarealblur' class="red">TEXTAREA</td>
</tr> </tr>
<tr>
<td>Live Click:</td>
<td id='selectlclick' class="red">SELECT</td>
<td id='mselectlclick' class="red">MULTI</td>
<td id='checkboxlclick' class="red">CHECKBOX</td>
<td id='buttonlclick' class="red">BUTTON</td>
<td id='radiolclick' class="red">RADIO</td>
<td id='filelclick' class="red">FILE</td>
<td id='textlclick' class="red">TEXT</td>
<td id='textarealclick' class="red">TEXTAREA</td>
<td id='boundClick' class="red">DOCUMENT</td>
</tr>
</table> </table>
<h2>Submit Tests</h2> <h2>Submit Tests</h2>
<table> <table>
@ -162,7 +187,7 @@
<ul id="log"></ul> <ul id="log"></ul>
<script type='text/javascript'> <script type='text/javascript'>
jQuery.fn.addChangeTest = function( id, prevent ) { jQuery.fn.addChangeClickTest = function( id, prevent ) {
this.bind("focusin", function(){ this.bind("focusin", function(){
jQuery(id + "focus").blink(); jQuery(id + "focus").blink();
}).bind("focusout", function(){ }).bind("focusout", function(){
@ -183,9 +208,12 @@
} }
jQuery(id).blink(); jQuery(id).blink();
}); }).live("click", function(e){
jQuery(id + "lclick").blink();
});
}; };
jQuery.fn.addSubmitTest = function( id, prevent ) { jQuery.fn.addSubmitTest = function( id, prevent ) {
return this.live("submit", function(e){ return this.live("submit", function(e){
if ( prevent ) { if ( prevent ) {
@ -210,6 +238,10 @@
$(document).bind("focusout", function() { $(document).bind("focusout", function() {
jQuery("#boundBlur").blink(); jQuery("#boundBlur").blink();
}); });
$(document).bind("click", function() {
jQuery("#boundClick").blink();
});
$("td.red").live("hover", function(e) { $("td.red").live("hover", function(e) {
if ( e.type === "mouseenter" ) { if ( e.type === "mouseenter" ) {
@ -219,13 +251,14 @@
} }
}); });
$(".select_test").addChangeTest("#select"); $(".select_test").addChangeClickTest("#select");
$(".mselect_test").addChangeTest("#mselect"); $(".mselect_test").addChangeClickTest("#mselect");
$(".checkbox_test").addChangeTest("#checkbox"); $(".checkbox_test").addChangeClickTest("#checkbox");
$(".radio_test").addChangeTest("#radio"); $(".radio_test").addChangeClickTest("#radio");
$(".file_test").addChangeTest("#file"); $(".file_test").addChangeClickTest("#file");
$('textarea').addChangeTest("#textarea"); $('textarea').addChangeClickTest("#textarea");
$('#input').addChangeTest("#text"); $('#input').addChangeClickTest("#text");
$('button').addChangeClickTest("#button");
$(document).bind("change", function(){ $(document).bind("change", function(){
jQuery("#boundChange").blink(); jQuery("#boundChange").blink();
}); });

View file

@ -35,7 +35,7 @@
<script src="unit/queue.js"></script> <script src="unit/queue.js"></script>
<script src="unit/attributes.js"></script> <script src="unit/attributes.js"></script>
<script src="unit/event.js"></script> <script src="unit/event.js"></script>
<script src="unit/selector.js"></script> <script src="../src/sizzle/test/unit/selector.js"></script>
<script src="unit/traversing.js"></script> <script src="unit/traversing.js"></script>
<script src="unit/manipulation.js"></script> <script src="unit/manipulation.js"></script>
<script src="unit/css.js"></script> <script src="unit/css.js"></script>

92
test/localfile.html Normal file
View file

@ -0,0 +1,92 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr" id="html">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jQuery Local File Test</title>
<!-- Includes -->
<script src="../src/core.js"></script>
<script src="../src/support.js"></script>
<script src="../src/data.js"></script>
<script src="../src/queue.js"></script>
<script src="../src/attributes.js"></script>
<script src="../src/event.js"></script>
<script src="../src/sizzle/sizzle.js"></script>
<script src="../src/sizzle-jquery.js"></script>
<script src="../src/traversing.js"></script>
<script src="../src/manipulation.js"></script>
<script src="../src/css.js"></script>
<script src="../src/ajax.js"></script>
<script src="../src/ajax/jsonp.js"></script>
<script src="../src/ajax/script.js"></script>
<script src="../src/ajax/xhr.js"></script>
<script src="../src/effects.js"></script>
<script src="../src/offset.js"></script>
<script src="../src/dimensions.js"></script>
<style>
.error { color: red; }
.success { color: green; }
</style>
</head>
<body>
<h1>jQuery Local File Test</h1>
<h2>
Introduction
</h2>
<ul>
<li>
Access this file using the "file:" protocol,
</li>
<li>
two green "OK" strings must appear below,
</li>
<li>
Empty local files will issue errors, it's a known limitation.
</li>
</ul>
<h2>
Results
</h2>
<ul>
<li>
Success:
<span id="success">
</span>
</li>
<li>
Error:
<span id="error">
</span>
</li>
</ul>
<h2>
Logs:
</h2>
<ul id="log">
</ul>
<script>
var logUL = jQuery( "#log" );
function doLog( message, args ) {
jQuery( "<li />").appendTo( logUL ).text( message + ': "' + Array.prototype.join.call( args, '" - "' ) + '"' );
}
jQuery.ajax( "./data/badjson.js" , {
context: jQuery( "#success" ),
dataType: "text"
}).success(function( data, _, xhr ) {
doLog( "Success (" + xhr.status + ")" , arguments );
this.addClass( data ? "success" : "error" ).text( "OK" );
}).error(function( xhr ) {
doLog( "Success (" + xhr.status + ")" , arguments );
this.addClass( "error" ).text( "FAIL" );
});
jQuery.ajax( "./data/doesnotexist.ext" , {
context: jQuery( "#error" ),
dataType: "text"
}).error(function( xhr ) {
doLog( "Error (" + xhr.status + ")" , arguments );
this.addClass( "success" ).text( "OK" );
}).success(function( data, _, xhr ) {
doLog( "Error (" + xhr.status + ")" , arguments );
this.addClass( "error" ).text( "FAIL" );
});
</script>
</body>

101
test/networkerror.html Normal file
View file

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html>
<!--
Test for #8135
Thanks John Firebaugh for this test page based on his gist
https://gist.github.com/807090
Access this page through a web server, then stop said server and click the button.
-->
<head>
<title>
jQuery Network Error Test for Firefox
</title>
<style>
div { margin-top: 10px; }
</style>
<script src="../src/core.js"></script>
<script src="../src/support.js"></script>
<script src="../src/data.js"></script>
<script src="../src/queue.js"></script>
<script src="../src/attributes.js"></script>
<script src="../src/event.js"></script>
<script src="../src/sizzle/sizzle.js"></script>
<script src="../src/sizzle-jquery.js"></script>
<script src="../src/traversing.js"></script>
<script src="../src/manipulation.js"></script>
<script src="../src/css.js"></script>
<script src="../src/ajax.js"></script>
<script src="../src/ajax/jsonp.js"></script>
<script src="../src/ajax/script.js"></script>
<script src="../src/ajax/xhr.js"></script>
<script src="../src/effects.js"></script>
<script src="../src/offset.js"></script>
<script src="../src/dimensions.js"></script>
<script type="text/javascript">
$('button').live('click', function () {
$.ajax({
url: '/',
error: function() {
console.log( "abort", arguments );
}
}).abort();
$.ajax({
url: '/',
error: function() {
console.log( "complete", arguments );
}
});
return false;
})
</script>
</head>
<body>
<h1>
jQuery Network Error Test for Firefox
</h1>
<div>
This is a test page for
<a href="http://bugs.jquery.com/ticket/8135">
#8135
</a>
which was reported in Firefox when accessing properties
of an XMLHttpRequest object after a network error occured.
</div>
<div>Take the following steps:</div>
<ol>
<li>
make sure you accessed this page through a web server,
</li>
<li>
stop the web server,
</li>
<li>
open the console,
</li>
<li>
click this
<button>button</button>
,
</li>
<li>
wait for both requests to fail.
</li>
</ol>
<div>
Test passes if you get two log lines:
<ul>
<li>
the first starting with "abort",
</li>
<li>
the second starting with "complete",
</li>
</ul>
</div>
<div>
Test fails if the browser notifies an exception.
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,131 +0,0 @@
// script.aculo.us builder.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Builder = {
NODEMAP: {
AREA: 'map',
CAPTION: 'table',
COL: 'table',
COLGROUP: 'table',
LEGEND: 'fieldset',
OPTGROUP: 'select',
OPTION: 'select',
PARAM: 'object',
TBODY: 'table',
TD: 'table',
TFOOT: 'table',
TH: 'table',
THEAD: 'table',
TR: 'table'
},
// note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
// due to a Firefox bug
node: function(elementName) {
elementName = elementName.toUpperCase();
// try innerHTML approach
var parentTag = this.NODEMAP[elementName] || 'div';
var parentElement = document.createElement(parentTag);
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
} catch(e) {}
var element = parentElement.firstChild || null;
// see if browser added wrapping tags
if(element && (element.tagName.toUpperCase() != elementName))
element = element.getElementsByTagName(elementName)[0];
// fallback to createElement approach
if(!element) element = document.createElement(elementName);
// abort if nothing could be created
if(!element) return;
// attributes (or text)
if(arguments[1])
if(this._isStringOrNumber(arguments[1]) ||
(arguments[1] instanceof Array)) {
this._children(element, arguments[1]);
} else {
var attrs = this._attributes(arguments[1]);
if(attrs.length) {
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
parentElement.innerHTML = "<" +elementName + " " +
attrs + "></" + elementName + ">";
} catch(e) {}
element = parentElement.firstChild || null;
// workaround firefox 1.0.X bug
if(!element) {
element = document.createElement(elementName);
for(attr in arguments[1])
element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
}
if(element.tagName.toUpperCase() != elementName)
element = parentElement.getElementsByTagName(elementName)[0];
}
}
// text, or array of children
if(arguments[2])
this._children(element, arguments[2]);
return element;
},
_text: function(text) {
return document.createTextNode(text);
},
ATTR_MAP: {
'className': 'class',
'htmlFor': 'for'
},
_attributes: function(attributes) {
var attrs = [];
for(attribute in attributes)
attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
'="' + attributes[attribute].toString().escapeHTML() + '"');
return attrs.join(" ");
},
_children: function(element, children) {
if(typeof children=='object') { // array can hold nodes and text
children.flatten().each( function(e) {
if(typeof e=='object')
element.appendChild(e)
else
if(Builder._isStringOrNumber(e))
element.appendChild(Builder._text(e));
});
} else
if(Builder._isStringOrNumber(children))
element.appendChild(Builder._text(children));
},
_isStringOrNumber: function(param) {
return(typeof param=='string' || typeof param=='number');
},
build: function(html) {
var element = this.node('div');
$(element).update(html.strip());
return element.down();
},
dump: function(scope) {
if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
"BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
"FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
"KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
"PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
"TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
tags.each( function(tag){
scope[tag] = function() {
return Builder.node.apply(Builder, [tag].concat($A(arguments)));
}
});
}
}

View file

@ -1,835 +0,0 @@
// script.aculo.us controls.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005, 2006 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
// Rob Wills
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// Autocompleter.Base handles all the autocompletion functionality
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
// Specific autocompleters need to provide, at the very least,
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
//
// Tokenized incremental autocompletion is enabled automatically
// when an autocompleter is instantiated with the 'tokens' option
// in the options parameter, e.g.:
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most
// useful when one of the tokens is \n (a newline), as it
// allows smart autocompletion after linebreaks.
if(typeof Effect == 'undefined')
throw("controls.js requires including script.aculo.us' effects.js library");
var Autocompleter = {}
Autocompleter.Base = function() {};
Autocompleter.Base.prototype = {
baseInitialize: function(element, update, options) {
this.element = $(element);
this.update = $(update);
this.hasFocus = false;
this.changed = false;
this.active = false;
this.index = 0;
this.entryCount = 0;
if(this.setOptions)
this.setOptions(options);
else
this.options = options || {};
this.options.paramName = this.options.paramName || this.element.name;
this.options.tokens = this.options.tokens || [];
this.options.frequency = this.options.frequency || 0.4;
this.options.minChars = this.options.minChars || 1;
this.options.onShow = this.options.onShow ||
function(element, update){
if(!update.style.position || update.style.position=='absolute') {
update.style.position = 'absolute';
Position.clone(element, update, {
setHeight: false,
offsetTop: element.offsetHeight
});
}
Effect.Appear(update,{duration:0.15});
};
this.options.onHide = this.options.onHide ||
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
if(typeof(this.options.tokens) == 'string')
this.options.tokens = new Array(this.options.tokens);
this.observer = null;
this.element.setAttribute('autocomplete','off');
Element.hide(this.update);
Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
},
show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix &&
(navigator.appVersion.indexOf('MSIE')>0) &&
(navigator.userAgent.indexOf('Opera')<0) &&
(Element.getStyle(this.update, 'position')=='absolute')) {
new Insertion.After(this.update,
'<iframe id="' + this.update.id + '_iefix" '+
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
this.iefix = $(this.update.id+'_iefix');
}
if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
},
fixIEOverlapping: function() {
Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
this.iefix.style.zIndex = 1;
this.update.style.zIndex = 2;
Element.show(this.iefix);
},
hide: function() {
this.stopIndicator();
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
if(this.iefix) Element.hide(this.iefix);
},
startIndicator: function() {
if(this.options.indicator) Element.show(this.options.indicator);
},
stopIndicator: function() {
if(this.options.indicator) Element.hide(this.options.indicator);
},
onKeyPress: function(event) {
if(this.active)
switch(event.keyCode) {
case Event.KEY_TAB:
case Event.KEY_RETURN:
this.selectEntry();
Event.stop(event);
case Event.KEY_ESC:
this.hide();
this.active = false;
Event.stop(event);
return;
case Event.KEY_LEFT:
case Event.KEY_RIGHT:
return;
case Event.KEY_UP:
this.markPrevious();
this.render();
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
return;
case Event.KEY_DOWN:
this.markNext();
this.render();
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
return;
}
else
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
(navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;
this.changed = true;
this.hasFocus = true;
if(this.observer) clearTimeout(this.observer);
this.observer =
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
},
activate: function() {
this.changed = false;
this.hasFocus = true;
this.getUpdatedChoices();
},
onHover: function(event) {
var element = Event.findElement(event, 'LI');
if(this.index != element.autocompleteIndex)
{
this.index = element.autocompleteIndex;
this.render();
}
Event.stop(event);
},
onClick: function(event) {
var element = Event.findElement(event, 'LI');
this.index = element.autocompleteIndex;
this.selectEntry();
this.hide();
},
onBlur: function(event) {
// needed to make click events working
setTimeout(this.hide.bind(this), 250);
this.hasFocus = false;
this.active = false;
},
render: function() {
if(this.entryCount > 0) {
for (var i = 0; i < this.entryCount; i++)
this.index==i ?
Element.addClassName(this.getEntry(i),"selected") :
Element.removeClassName(this.getEntry(i),"selected");
if(this.hasFocus) {
this.show();
this.active = true;
}
} else {
this.active = false;
this.hide();
}
},
markPrevious: function() {
if(this.index > 0) this.index--
else this.index = this.entryCount-1;
this.getEntry(this.index).scrollIntoView(true);
},
markNext: function() {
if(this.index < this.entryCount-1) this.index++
else this.index = 0;
this.getEntry(this.index).scrollIntoView(false);
},
getEntry: function(index) {
return this.update.firstChild.childNodes[index];
},
getCurrentEntry: function() {
return this.getEntry(this.index);
},
selectEntry: function() {
this.active = false;
this.updateElement(this.getCurrentEntry());
},
updateElement: function(selectedElement) {
if (this.options.updateElement) {
this.options.updateElement(selectedElement);
return;
}
var value = '';
if (this.options.select) {
var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
} else
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
var lastTokenPos = this.findLastToken();
if (lastTokenPos != -1) {
var newValue = this.element.value.substr(0, lastTokenPos + 1);
var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
if (whitespace)
newValue += whitespace[0];
this.element.value = newValue + value;
} else {
this.element.value = value;
}
this.element.focus();
if (this.options.afterUpdateElement)
this.options.afterUpdateElement(this.element, selectedElement);
},
updateChoices: function(choices) {
if(!this.changed && this.hasFocus) {
this.update.innerHTML = choices;
Element.cleanWhitespace(this.update);
Element.cleanWhitespace(this.update.down());
if(this.update.firstChild && this.update.down().childNodes) {
this.entryCount =
this.update.down().childNodes.length;
for (var i = 0; i < this.entryCount; i++) {
var entry = this.getEntry(i);
entry.autocompleteIndex = i;
this.addObservers(entry);
}
} else {
this.entryCount = 0;
}
this.stopIndicator();
this.index = 0;
if(this.entryCount==1 && this.options.autoSelect) {
this.selectEntry();
this.hide();
} else {
this.render();
}
}
},
addObservers: function(element) {
Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
Event.observe(element, "click", this.onClick.bindAsEventListener(this));
},
onObserverEvent: function() {
this.changed = false;
if(this.getToken().length>=this.options.minChars) {
this.startIndicator();
this.getUpdatedChoices();
} else {
this.active = false;
this.hide();
}
},
getToken: function() {
var tokenPos = this.findLastToken();
if (tokenPos != -1)
var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
else
var ret = this.element.value;
return /\n/.test(ret) ? '' : ret;
},
findLastToken: function() {
var lastTokenPos = -1;
for (var i=0; i<this.options.tokens.length; i++) {
var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
if (thisTokenPos > lastTokenPos)
lastTokenPos = thisTokenPos;
}
return lastTokenPos;
}
}
Ajax.Autocompleter = Class.create();
Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
initialize: function(element, update, url, options) {
this.baseInitialize(element, update, options);
this.options.asynchronous = true;
this.options.onComplete = this.onComplete.bind(this);
this.options.defaultParams = this.options.parameters || null;
this.url = url;
},
getUpdatedChoices: function() {
entry = encodeURIComponent(this.options.paramName) + '=' +
encodeURIComponent(this.getToken());
this.options.parameters = this.options.callback ?
this.options.callback(this.element, entry) : entry;
if(this.options.defaultParams)
this.options.parameters += '&' + this.options.defaultParams;
new Ajax.Request(this.url, this.options);
},
onComplete: function(request) {
this.updateChoices(request.responseText);
}
});
// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
// than sending out Ajax queries, which can be quite slow sometimes.
//
// The constructor takes four parameters. The first two are, as usual,
// the id of the monitored textbox, and id of the autocompletion menu.
// The third is the array you want to autocomplete from, and the fourth
// is the options block.
//
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
// text only at the beginning of strings in the
// autocomplete array. Defaults to true, which will
// match text at the beginning of any *word* in the
// strings in the autocomplete array. If you want to
// search anywhere in the string, additionally set
// the option fullSearch to true (default: off).
//
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partialChars - How many characters to enter before triggering
// a partial match (unlike minChars, which defines
// how many characters are required to do any match
// at all). Defaults to 2.
//
// - ignoreCase - Whether to ignore case when autocompleting.
// Defaults to true.
//
// It's possible to pass in a custom function as the 'selector'
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.
Autocompleter.Local = Class.create();
Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
initialize: function(element, update, array, options) {
this.baseInitialize(element, update, options);
this.options.array = array;
},
getUpdatedChoices: function() {
this.updateChoices(this.options.selector(this));
},
setOptions: function(options) {
this.options = Object.extend({
choices: 10,
partialSearch: true,
partialChars: 2,
ignoreCase: true,
fullSearch: false,
selector: function(instance) {
var ret = []; // Beginning matches
var partial = []; // Inside matches
var entry = instance.getToken();
var count = 0;
for (var i = 0; i < instance.options.array.length &&
ret.length < instance.options.choices ; i++) {
var elem = instance.options.array[i];
var foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase()) :
elem.indexOf(entry);
while (foundPos != -1) {
if (foundPos == 0 && elem.length != entry.length) {
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
elem.substr(entry.length) + "</li>");
break;
} else if (entry.length >= instance.options.partialChars &&
instance.options.partialSearch && foundPos != -1) {
if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
foundPos + entry.length) + "</li>");
break;
}
}
foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
elem.indexOf(entry, foundPos + 1);
}
}
if (partial.length)
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
return "<ul>" + ret.join('') + "</ul>";
}
}, options || {});
}
});
// AJAX in-place editor
//
// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
setTimeout(function() {
Field.activate(field);
}, 1);
}
Ajax.InPlaceEditor = Class.create();
Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
Ajax.InPlaceEditor.prototype = {
initialize: function(element, url, options) {
this.url = url;
this.element = $(element);
this.options = Object.extend({
paramName: "value",
okButton: true,
okText: "ok",
cancelLink: true,
cancelText: "cancel",
savingText: "Saving...",
clickToEditText: "Click to edit",
okText: "ok",
rows: 1,
onComplete: function(transport, element) {
new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
},
onFailure: function(transport) {
alert("Error communicating with the server: " + transport.responseText.stripTags());
},
callback: function(form) {
return Form.serialize(form);
},
handleLineBreaks: true,
loadingText: 'Loading...',
savingClassName: 'inplaceeditor-saving',
loadingClassName: 'inplaceeditor-loading',
formClassName: 'inplaceeditor-form',
highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
highlightendcolor: "#FFFFFF",
externalControl: null,
submitOnBlur: false,
ajaxOptions: {},
evalScripts: false
}, options || {});
if(!this.options.formId && this.element.id) {
this.options.formId = this.element.id + "-inplaceeditor";
if ($(this.options.formId)) {
// there's already a form with that name, don't specify an id
this.options.formId = null;
}
}
if (this.options.externalControl) {
this.options.externalControl = $(this.options.externalControl);
}
this.originalBackground = Element.getStyle(this.element, 'background-color');
if (!this.originalBackground) {
this.originalBackground = "transparent";
}
this.element.title = this.options.clickToEditText;
this.onclickListener = this.enterEditMode.bindAsEventListener(this);
this.mouseoverListener = this.enterHover.bindAsEventListener(this);
this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
Event.observe(this.element, 'click', this.onclickListener);
Event.observe(this.element, 'mouseover', this.mouseoverListener);
Event.observe(this.element, 'mouseout', this.mouseoutListener);
if (this.options.externalControl) {
Event.observe(this.options.externalControl, 'click', this.onclickListener);
Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
}
},
enterEditMode: function(evt) {
if (this.saving) return;
if (this.editing) return;
this.editing = true;
this.onEnterEditMode();
if (this.options.externalControl) {
Element.hide(this.options.externalControl);
}
Element.hide(this.element);
this.createForm();
this.element.parentNode.insertBefore(this.form, this.element);
if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField);
// stop the event to avoid a page refresh in Safari
if (evt) {
Event.stop(evt);
}
return false;
},
createForm: function() {
this.form = document.createElement("form");
this.form.id = this.options.formId;
Element.addClassName(this.form, this.options.formClassName)
this.form.onsubmit = this.onSubmit.bind(this);
this.createEditField();
if (this.options.textarea) {
var br = document.createElement("br");
this.form.appendChild(br);
}
if (this.options.okButton) {
okButton = document.createElement("input");
okButton.type = "submit";
okButton.value = this.options.okText;
okButton.className = 'editor_ok_button';
this.form.appendChild(okButton);
}
if (this.options.cancelLink) {
cancelLink = document.createElement("a");
cancelLink.href = "#";
cancelLink.appendChild(document.createTextNode(this.options.cancelText));
cancelLink.onclick = this.onclickCancel.bind(this);
cancelLink.className = 'editor_cancel';
this.form.appendChild(cancelLink);
}
},
hasHTMLLineBreaks: function(string) {
if (!this.options.handleLineBreaks) return false;
return string.match(/<br/i) || string.match(/<p>/i);
},
convertHTMLLineBreaks: function(string) {
return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
},
createEditField: function() {
var text;
if(this.options.loadTextURL) {
text = this.options.loadingText;
} else {
text = this.getText();
}
var obj = this;
if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
this.options.textarea = false;
var textField = document.createElement("input");
textField.obj = this;
textField.type = "text";
textField.name = this.options.paramName;
textField.value = text;
textField.style.backgroundColor = this.options.highlightcolor;
textField.className = 'editor_field';
var size = this.options.size || this.options.cols || 0;
if (size != 0) textField.size = size;
if (this.options.submitOnBlur)
textField.onblur = this.onSubmit.bind(this);
this.editField = textField;
} else {
this.options.textarea = true;
var textArea = document.createElement("textarea");
textArea.obj = this;
textArea.name = this.options.paramName;
textArea.value = this.convertHTMLLineBreaks(text);
textArea.rows = this.options.rows;
textArea.cols = this.options.cols || 40;
textArea.className = 'editor_field';
if (this.options.submitOnBlur)
textArea.onblur = this.onSubmit.bind(this);
this.editField = textArea;
}
if(this.options.loadTextURL) {
this.loadExternalText();
}
this.form.appendChild(this.editField);
},
getText: function() {
return this.element.innerHTML;
},
loadExternalText: function() {
Element.addClassName(this.form, this.options.loadingClassName);
this.editField.disabled = true;
new Ajax.Request(
this.options.loadTextURL,
Object.extend({
asynchronous: true,
onComplete: this.onLoadedExternalText.bind(this)
}, this.options.ajaxOptions)
);
},
onLoadedExternalText: function(transport) {
Element.removeClassName(this.form, this.options.loadingClassName);
this.editField.disabled = false;
this.editField.value = transport.responseText.stripTags();
Field.scrollFreeActivate(this.editField);
},
onclickCancel: function() {
this.onComplete();
this.leaveEditMode();
return false;
},
onFailure: function(transport) {
this.options.onFailure(transport);
if (this.oldInnerHTML) {
this.element.innerHTML = this.oldInnerHTML;
this.oldInnerHTML = null;
}
return false;
},
onSubmit: function() {
// onLoading resets these so we need to save them away for the Ajax call
var form = this.form;
var value = this.editField.value;
// do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
// which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
// to be displayed indefinitely
this.onLoading();
if (this.options.evalScripts) {
new Ajax.Request(
this.url, Object.extend({
parameters: this.options.callback(form, value),
onComplete: this.onComplete.bind(this),
onFailure: this.onFailure.bind(this),
asynchronous:true,
evalScripts:true
}, this.options.ajaxOptions));
} else {
new Ajax.Updater(
{ success: this.element,
// don't update on failure (this could be an option)
failure: null },
this.url, Object.extend({
parameters: this.options.callback(form, value),
onComplete: this.onComplete.bind(this),
onFailure: this.onFailure.bind(this)
}, this.options.ajaxOptions));
}
// stop the event to avoid a page refresh in Safari
if (arguments.length > 1) {
Event.stop(arguments[0]);
}
return false;
},
onLoading: function() {
this.saving = true;
this.removeForm();
this.leaveHover();
this.showSaving();
},
showSaving: function() {
this.oldInnerHTML = this.element.innerHTML;
this.element.innerHTML = this.options.savingText;
Element.addClassName(this.element, this.options.savingClassName);
this.element.style.backgroundColor = this.originalBackground;
Element.show(this.element);
},
removeForm: function() {
if(this.form) {
if (this.form.parentNode) Element.remove(this.form);
this.form = null;
}
},
enterHover: function() {
if (this.saving) return;
this.element.style.backgroundColor = this.options.highlightcolor;
if (this.effect) {
this.effect.cancel();
}
Element.addClassName(this.element, this.options.hoverClassName)
},
leaveHover: function() {
if (this.options.backgroundColor) {
this.element.style.backgroundColor = this.oldBackground;
}
Element.removeClassName(this.element, this.options.hoverClassName)
if (this.saving) return;
this.effect = new Effect.Highlight(this.element, {
startcolor: this.options.highlightcolor,
endcolor: this.options.highlightendcolor,
restorecolor: this.originalBackground
});
},
leaveEditMode: function() {
Element.removeClassName(this.element, this.options.savingClassName);
this.removeForm();
this.leaveHover();
this.element.style.backgroundColor = this.originalBackground;
Element.show(this.element);
if (this.options.externalControl) {
Element.show(this.options.externalControl);
}
this.editing = false;
this.saving = false;
this.oldInnerHTML = null;
this.onLeaveEditMode();
},
onComplete: function(transport) {
this.leaveEditMode();
this.options.onComplete.bind(this)(transport, this.element);
},
onEnterEditMode: function() {},
onLeaveEditMode: function() {},
dispose: function() {
if (this.oldInnerHTML) {
this.element.innerHTML = this.oldInnerHTML;
}
this.leaveEditMode();
Event.stopObserving(this.element, 'click', this.onclickListener);
Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
if (this.options.externalControl) {
Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
}
}
};
Ajax.InPlaceCollectionEditor = Class.create();
Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
createEditField: function() {
if (!this.cached_selectTag) {
var selectTag = document.createElement("select");
var collection = this.options.collection || [];
var optionTag;
collection.each(function(e,i) {
optionTag = document.createElement("option");
optionTag.value = (e instanceof Array) ? e[0] : e;
if((typeof this.options.value == 'undefined') &&
((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true;
if(this.options.value==optionTag.value) optionTag.selected = true;
optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
selectTag.appendChild(optionTag);
}.bind(this));
this.cached_selectTag = selectTag;
}
this.editField = this.cached_selectTag;
if(this.options.loadTextURL) this.loadExternalText();
this.form.appendChild(this.editField);
this.options.callback = function(form, value) {
return "value=" + encodeURIComponent(value);
}
}
});
// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
Form.Element.DelayedObserver = Class.create();
Form.Element.DelayedObserver.prototype = {
initialize: function(element, delay, callback) {
this.delay = delay || 0.5;
this.element = $(element);
this.callback = callback;
this.timer = null;
this.lastValue = $F(this.element);
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
},
delayedListener: function(event) {
if(this.lastValue == $F(this.element)) return;
if(this.timer) clearTimeout(this.timer);
this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
this.lastValue = $F(this.element);
},
onTimerEvent: function() {
this.timer = null;
this.callback(this.element, $F(this.element));
}
};

View file

@ -1,944 +0,0 @@
// script.aculo.us dragdrop.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005, 2006 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
if(typeof Effect == 'undefined')
throw("dragdrop.js requires including script.aculo.us' effects.js library");
var Droppables = {
drops: [],
remove: function(element) {
this.drops = this.drops.reject(function(d) { return d.element==$(element) });
},
add: function(element) {
element = $(element);
var options = Object.extend({
greedy: true,
hoverclass: null,
tree: false
}, arguments[1] || {});
// cache containers
if(options.containment) {
options._containers = [];
var containment = options.containment;
if((typeof containment == 'object') &&
(containment.constructor == Array)) {
containment.each( function(c) { options._containers.push($(c)) });
} else {
options._containers.push($(containment));
}
}
if(options.accept) options.accept = [options.accept].flatten();
Element.makePositioned(element); // fix IE
options.element = element;
this.drops.push(options);
},
findDeepestChild: function(drops) {
deepest = drops[0];
for (i = 1; i < drops.length; ++i)
if (Element.isParent(drops[i].element, deepest.element))
deepest = drops[i];
return deepest;
},
isContained: function(element, drop) {
var containmentNode;
if(drop.tree) {
containmentNode = element.treeNode;
} else {
containmentNode = element.parentNode;
}
return drop._containers.detect(function(c) { return containmentNode == c });
},
isAffected: function(point, element, drop) {
return (
(drop.element!=element) &&
((!drop._containers) ||
this.isContained(element, drop)) &&
((!drop.accept) ||
(Element.classNames(element).detect(
function(v) { return drop.accept.include(v) } ) )) &&
Position.within(drop.element, point[0], point[1]) );
},
deactivate: function(drop) {
if(drop.hoverclass)
Element.removeClassName(drop.element, drop.hoverclass);
this.last_active = null;
},
activate: function(drop) {
if(drop.hoverclass)
Element.addClassName(drop.element, drop.hoverclass);
this.last_active = drop;
},
show: function(point, element) {
if(!this.drops.length) return;
var affected = [];
if(this.last_active) this.deactivate(this.last_active);
this.drops.each( function(drop) {
if(Droppables.isAffected(point, element, drop))
affected.push(drop);
});
if(affected.length>0) {
drop = Droppables.findDeepestChild(affected);
Position.within(drop.element, point[0], point[1]);
if(drop.onHover)
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
Droppables.activate(drop);
}
},
fire: function(event, element) {
if(!this.last_active) return;
Position.prepare();
if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
if (this.last_active.onDrop)
this.last_active.onDrop(element, this.last_active.element, event);
},
reset: function() {
if(this.last_active)
this.deactivate(this.last_active);
}
}
var Draggables = {
drags: [],
observers: [],
register: function(draggable) {
if(this.drags.length == 0) {
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
this.eventKeypress = this.keyPress.bindAsEventListener(this);
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
Event.observe(document, "keypress", this.eventKeypress);
}
this.drags.push(draggable);
},
unregister: function(draggable) {
this.drags = this.drags.reject(function(d) { return d==draggable });
if(this.drags.length == 0) {
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
Event.stopObserving(document, "keypress", this.eventKeypress);
}
},
activate: function(draggable) {
if(draggable.options.delay) {
this._timeout = setTimeout(function() {
Draggables._timeout = null;
window.focus();
Draggables.activeDraggable = draggable;
}.bind(this), draggable.options.delay);
} else {
window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
this.activeDraggable = draggable;
}
},
deactivate: function() {
this.activeDraggable = null;
},
updateDrag: function(event) {
if(!this.activeDraggable) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
// Mozilla-based browsers fire successive mousemove events with
// the same coordinates, prevent needless redrawing (moz bug?)
if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
this._lastPointer = pointer;
this.activeDraggable.updateDrag(event, pointer);
},
endDrag: function(event) {
if(this._timeout) {
clearTimeout(this._timeout);
this._timeout = null;
}
if(!this.activeDraggable) return;
this._lastPointer = null;
this.activeDraggable.endDrag(event);
this.activeDraggable = null;
},
keyPress: function(event) {
if(this.activeDraggable)
this.activeDraggable.keyPress(event);
},
addObserver: function(observer) {
this.observers.push(observer);
this._cacheObserverCallbacks();
},
removeObserver: function(element) { // element instead of observer fixes mem leaks
this.observers = this.observers.reject( function(o) { return o.element==element });
this._cacheObserverCallbacks();
},
notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
if(this[eventName+'Count'] > 0)
this.observers.each( function(o) {
if(o[eventName]) o[eventName](eventName, draggable, event);
});
if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
},
_cacheObserverCallbacks: function() {
['onStart','onEnd','onDrag'].each( function(eventName) {
Draggables[eventName+'Count'] = Draggables.observers.select(
function(o) { return o[eventName]; }
).length;
});
}
}
/*--------------------------------------------------------------------------*/
var Draggable = Class.create();
Draggable._dragging = {};
Draggable.prototype = {
initialize: function(element) {
var defaults = {
handle: false,
reverteffect: function(element, top_offset, left_offset) {
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
queue: {scope:'_draggable', position:'end'}
});
},
endeffect: function(element) {
var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0;
new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
queue: {scope:'_draggable', position:'end'},
afterFinish: function(){
Draggable._dragging[element] = false
}
});
},
zindex: 1000,
revert: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
delay: 0
};
if(!arguments[1] || typeof arguments[1].endeffect == 'undefined')
Object.extend(defaults, {
starteffect: function(element) {
element._opacity = Element.getOpacity(element);
Draggable._dragging[element] = true;
new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
}
});
var options = Object.extend(defaults, arguments[1] || {});
this.element = $(element);
if(options.handle && (typeof options.handle == 'string'))
this.handle = this.element.down('.'+options.handle, 0);
if(!this.handle) this.handle = $(options.handle);
if(!this.handle) this.handle = this.element;
if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
options.scroll = $(options.scroll);
this._isScrollChild = Element.childOf(this.element, options.scroll);
}
Element.makePositioned(this.element); // fix IE
this.delta = this.currentDelta();
this.options = options;
this.dragging = false;
this.eventMouseDown = this.initDrag.bindAsEventListener(this);
Event.observe(this.handle, "mousedown", this.eventMouseDown);
Draggables.register(this);
},
destroy: function() {
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
Draggables.unregister(this);
},
currentDelta: function() {
return([
parseInt(Element.getStyle(this.element,'left') || '0'),
parseInt(Element.getStyle(this.element,'top') || '0')]);
},
initDrag: function(event) {
if(typeof Draggable._dragging[this.element] != 'undefined' &&
Draggable._dragging[this.element]) return;
if(Event.isLeftClick(event)) {
// abort on form elements, fixes a Firefox issue
var src = Event.element(event);
if((tag_name = src.tagName.toUpperCase()) && (
tag_name=='INPUT' ||
tag_name=='SELECT' ||
tag_name=='OPTION' ||
tag_name=='BUTTON' ||
tag_name=='TEXTAREA')) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var pos = Position.cumulativeOffset(this.element);
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
Draggables.activate(this);
Event.stop(event);
}
},
startDrag: function(event) {
this.dragging = true;
if(this.options.zindex) {
this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
this.element.style.zIndex = this.options.zindex;
}
if(this.options.ghosting) {
this._clone = this.element.cloneNode(true);
Position.absolutize(this.element);
this.element.parentNode.insertBefore(this._clone, this.element);
}
if(this.options.scroll) {
if (this.options.scroll == window) {
var where = this._getWindowScroll(this.options.scroll);
this.originalScrollLeft = where.left;
this.originalScrollTop = where.top;
} else {
this.originalScrollLeft = this.options.scroll.scrollLeft;
this.originalScrollTop = this.options.scroll.scrollTop;
}
}
Draggables.notify('onStart', this, event);
if(this.options.starteffect) this.options.starteffect(this.element);
},
updateDrag: function(event, pointer) {
if(!this.dragging) this.startDrag(event);
Position.prepare();
Droppables.show(pointer, this.element);
Draggables.notify('onDrag', this, event);
this.draw(pointer);
if(this.options.change) this.options.change(this);
if(this.options.scroll) {
this.stopScrolling();
var p;
if (this.options.scroll == window) {
with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
} else {
p = Position.page(this.options.scroll);
p[0] += this.options.scroll.scrollLeft + Position.deltaX;
p[1] += this.options.scroll.scrollTop + Position.deltaY;
p.push(p[0]+this.options.scroll.offsetWidth);
p.push(p[1]+this.options.scroll.offsetHeight);
}
var speed = [0,0];
if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
this.startScrolling(speed);
}
// fix AppleWebKit rendering
if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
Event.stop(event);
},
finishDrag: function(event, success) {
this.dragging = false;
if(this.options.ghosting) {
Position.relativize(this.element);
Element.remove(this._clone);
this._clone = null;
}
if(success) Droppables.fire(event, this.element);
Draggables.notify('onEnd', this, event);
var revert = this.options.revert;
if(revert && typeof revert == 'function') revert = revert(this.element);
var d = this.currentDelta();
if(revert && this.options.reverteffect) {
this.options.reverteffect(this.element,
d[1]-this.delta[1], d[0]-this.delta[0]);
} else {
this.delta = d;
}
if(this.options.zindex)
this.element.style.zIndex = this.originalZ;
if(this.options.endeffect)
this.options.endeffect(this.element);
Draggables.deactivate(this);
Droppables.reset();
},
keyPress: function(event) {
if(event.keyCode!=Event.KEY_ESC) return;
this.finishDrag(event, false);
Event.stop(event);
},
endDrag: function(event) {
if(!this.dragging) return;
this.stopScrolling();
this.finishDrag(event, true);
Event.stop(event);
},
draw: function(point) {
var pos = Position.cumulativeOffset(this.element);
if(this.options.ghosting) {
var r = Position.realOffset(this.element);
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
}
var d = this.currentDelta();
pos[0] -= d[0]; pos[1] -= d[1];
if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
}
var p = [0,1].map(function(i){
return (point[i]-pos[i]-this.offset[i])
}.bind(this));
if(this.options.snap) {
if(typeof this.options.snap == 'function') {
p = this.options.snap(p[0],p[1],this);
} else {
if(this.options.snap instanceof Array) {
p = p.map( function(v, i) {
return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
} else {
p = p.map( function(v) {
return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
}
}}
var style = this.element.style;
if((!this.options.constraint) || (this.options.constraint=='horizontal'))
style.left = p[0] + "px";
if((!this.options.constraint) || (this.options.constraint=='vertical'))
style.top = p[1] + "px";
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
},
stopScrolling: function() {
if(this.scrollInterval) {
clearInterval(this.scrollInterval);
this.scrollInterval = null;
Draggables._lastScrollPointer = null;
}
},
startScrolling: function(speed) {
if(!(speed[0] || speed[1])) return;
this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
this.lastScrolled = new Date();
this.scrollInterval = setInterval(this.scroll.bind(this), 10);
},
scroll: function() {
var current = new Date();
var delta = current - this.lastScrolled;
this.lastScrolled = current;
if(this.options.scroll == window) {
with (this._getWindowScroll(this.options.scroll)) {
if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
var d = delta / 1000;
this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
}
}
} else {
this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
}
Position.prepare();
Droppables.show(Draggables._lastPointer, this.element);
Draggables.notify('onDrag', this);
if (this._isScrollChild) {
Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
if (Draggables._lastScrollPointer[0] < 0)
Draggables._lastScrollPointer[0] = 0;
if (Draggables._lastScrollPointer[1] < 0)
Draggables._lastScrollPointer[1] = 0;
this.draw(Draggables._lastScrollPointer);
}
if(this.options.change) this.options.change(this);
},
_getWindowScroll: function(w) {
var T, L, W, H;
with (w.document) {
if (w.document.documentElement && documentElement.scrollTop) {
T = documentElement.scrollTop;
L = documentElement.scrollLeft;
} else if (w.document.body) {
T = body.scrollTop;
L = body.scrollLeft;
}
if (w.innerWidth) {
W = w.innerWidth;
H = w.innerHeight;
} else if (w.document.documentElement && documentElement.clientWidth) {
W = documentElement.clientWidth;
H = documentElement.clientHeight;
} else {
W = body.offsetWidth;
H = body.offsetHeight
}
}
return { top: T, left: L, width: W, height: H };
}
}
/*--------------------------------------------------------------------------*/
var SortableObserver = Class.create();
SortableObserver.prototype = {
initialize: function(element, observer) {
this.element = $(element);
this.observer = observer;
this.lastValue = Sortable.serialize(this.element);
},
onStart: function() {
this.lastValue = Sortable.serialize(this.element);
},
onEnd: function() {
Sortable.unmark();
if(this.lastValue != Sortable.serialize(this.element))
this.observer(this.element)
}
}
var Sortable = {
SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
sortables: {},
_findRootElement: function(element) {
while (element.tagName.toUpperCase() != "BODY") {
if(element.id && Sortable.sortables[element.id]) return element;
element = element.parentNode;
}
},
options: function(element) {
element = Sortable._findRootElement($(element));
if(!element) return;
return Sortable.sortables[element.id];
},
destroy: function(element){
var s = Sortable.options(element);
if(s) {
Draggables.removeObserver(s.element);
s.droppables.each(function(d){ Droppables.remove(d) });
s.draggables.invoke('destroy');
delete Sortable.sortables[s.element.id];
}
},
create: function(element) {
element = $(element);
var options = Object.extend({
element: element,
tag: 'li', // assumes li children, override with tag: 'tagname'
dropOnEmpty: false,
tree: false,
treeTag: 'ul',
overlap: 'vertical', // one of 'vertical', 'horizontal'
constraint: 'vertical', // one of 'vertical', 'horizontal', false
containment: element, // also takes array of elements (or id's); or false
handle: false, // or a CSS class
only: false,
delay: 0,
hoverclass: null,
ghosting: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
format: this.SERIALIZE_RULE,
onChange: Prototype.emptyFunction,
onUpdate: Prototype.emptyFunction
}, arguments[1] || {});
// clear any old sortable with same element
this.destroy(element);
// build options for the draggables
var options_for_draggable = {
revert: true,
scroll: options.scroll,
scrollSpeed: options.scrollSpeed,
scrollSensitivity: options.scrollSensitivity,
delay: options.delay,
ghosting: options.ghosting,
constraint: options.constraint,
handle: options.handle };
if(options.starteffect)
options_for_draggable.starteffect = options.starteffect;
if(options.reverteffect)
options_for_draggable.reverteffect = options.reverteffect;
else
if(options.ghosting) options_for_draggable.reverteffect = function(element) {
element.style.top = 0;
element.style.left = 0;
};
if(options.endeffect)
options_for_draggable.endeffect = options.endeffect;
if(options.zindex)
options_for_draggable.zindex = options.zindex;
// build options for the droppables
var options_for_droppable = {
overlap: options.overlap,
containment: options.containment,
tree: options.tree,
hoverclass: options.hoverclass,
onHover: Sortable.onHover
}
var options_for_tree = {
onHover: Sortable.onEmptyHover,
overlap: options.overlap,
containment: options.containment,
hoverclass: options.hoverclass
}
// fix for gecko engine
Element.cleanWhitespace(element);
options.draggables = [];
options.droppables = [];
// drop on empty handling
if(options.dropOnEmpty || options.tree) {
Droppables.add(element, options_for_tree);
options.droppables.push(element);
}
(this.findElements(element, options) || []).each( function(e) {
// handles are per-draggable
var handle = options.handle ?
$(e).down('.'+options.handle,0) : e;
options.draggables.push(
new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
Droppables.add(e, options_for_droppable);
if(options.tree) e.treeNode = element;
options.droppables.push(e);
});
if(options.tree) {
(Sortable.findTreeElements(element, options) || []).each( function(e) {
Droppables.add(e, options_for_tree);
e.treeNode = element;
options.droppables.push(e);
});
}
// keep reference
this.sortables[element.id] = options;
// for onupdate
Draggables.addObserver(new SortableObserver(element, options.onUpdate));
},
// return all suitable-for-sortable elements in a guaranteed order
findElements: function(element, options) {
return Element.findChildren(
element, options.only, options.tree ? true : false, options.tag);
},
findTreeElements: function(element, options) {
return Element.findChildren(
element, options.only, options.tree ? true : false, options.treeTag);
},
onHover: function(element, dropon, overlap) {
if(Element.isParent(dropon, element)) return;
if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
return;
} else if(overlap>0.5) {
Sortable.mark(dropon, 'before');
if(dropon.previousSibling != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, dropon);
if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
} else {
Sortable.mark(dropon, 'after');
var nextElement = dropon.nextSibling || null;
if(nextElement != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, nextElement);
if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
}
},
onEmptyHover: function(element, dropon, overlap) {
var oldParentNode = element.parentNode;
var droponOptions = Sortable.options(dropon);
if(!Element.isParent(dropon, element)) {
var index;
var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
var child = null;
if(children) {
var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
for (index = 0; index < children.length; index += 1) {
if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
offset -= Element.offsetSize (children[index], droponOptions.overlap);
} else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
child = index + 1 < children.length ? children[index + 1] : null;
break;
} else {
child = children[index];
break;
}
}
}
dropon.insertBefore(element, child);
Sortable.options(oldParentNode).onChange(element);
droponOptions.onChange(element);
}
},
unmark: function() {
if(Sortable._marker) Sortable._marker.hide();
},
mark: function(dropon, position) {
// mark on ghosting only
var sortable = Sortable.options(dropon.parentNode);
if(sortable && !sortable.ghosting) return;
if(!Sortable._marker) {
Sortable._marker =
($('dropmarker') || Element.extend(document.createElement('DIV'))).
hide().addClassName('dropmarker').setStyle({position:'absolute'});
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
}
var offsets = Position.cumulativeOffset(dropon);
Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
if(position=='after')
if(sortable.overlap == 'horizontal')
Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
else
Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
Sortable._marker.show();
},
_tree: function(element, options, parent) {
var children = Sortable.findElements(element, options) || [];
for (var i = 0; i < children.length; ++i) {
var match = children[i].id.match(options.format);
if (!match) continue;
var child = {
id: encodeURIComponent(match ? match[1] : null),
element: element,
parent: parent,
children: [],
position: parent.children.length,
container: $(children[i]).down(options.treeTag)
}
/* Get the element containing the children and recurse over it */
if (child.container)
this._tree(child.container, options, child)
parent.children.push (child);
}
return parent;
},
tree: function(element) {
element = $(element);
var sortableOptions = this.options(element);
var options = Object.extend({
tag: sortableOptions.tag,
treeTag: sortableOptions.treeTag,
only: sortableOptions.only,
name: element.id,
format: sortableOptions.format
}, arguments[1] || {});
var root = {
id: null,
parent: null,
children: [],
container: element,
position: 0
}
return Sortable._tree(element, options, root);
},
/* Construct a [i] index for a particular node */
_constructIndex: function(node) {
var index = '';
do {
if (node.id) index = '[' + node.position + ']' + index;
} while ((node = node.parent) != null);
return index;
},
sequence: function(element) {
element = $(element);
var options = Object.extend(this.options(element), arguments[1] || {});
return $(this.findElements(element, options) || []).map( function(item) {
return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
});
},
setSequence: function(element, new_sequence) {
element = $(element);
var options = Object.extend(this.options(element), arguments[2] || {});
var nodeMap = {};
this.findElements(element, options).each( function(n) {
if (n.id.match(options.format))
nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
n.parentNode.removeChild(n);
});
new_sequence.each(function(ident) {
var n = nodeMap[ident];
if (n) {
n[1].appendChild(n[0]);
delete nodeMap[ident];
}
});
},
serialize: function(element) {
element = $(element);
var options = Object.extend(Sortable.options(element), arguments[1] || {});
var name = encodeURIComponent(
(arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
if (options.tree) {
return Sortable.tree(element, arguments[1]).children.map( function (item) {
return [name + Sortable._constructIndex(item) + "[id]=" +
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
}).flatten().join('&');
} else {
return Sortable.sequence(element, arguments[1]).map( function(item) {
return name + "[]=" + encodeURIComponent(item);
}).join('&');
}
}
}
// Returns true if child is contained within element
Element.isParent = function(child, element) {
if (!child.parentNode || child == element) return false;
if (child.parentNode == element) return true;
return Element.isParent(child.parentNode, element);
}
Element.findChildren = function(element, only, recursive, tagName) {
if(!element.hasChildNodes()) return null;
tagName = tagName.toUpperCase();
if(only) only = [only].flatten();
var elements = [];
$A(element.childNodes).each( function(e) {
if(e.tagName && e.tagName.toUpperCase()==tagName &&
(!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
elements.push(e);
if(recursive) {
var grandchildren = Element.findChildren(e, only, recursive, tagName);
if(grandchildren) elements.push(grandchildren);
}
});
return (elements.length>0 ? elements.flatten() : []);
}
Element.offsetSize = function (element, type) {
return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
}

File diff suppressed because it is too large Load diff

View file

@ -1,51 +0,0 @@
// script.aculo.us scriptaculous.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Scriptaculous = {
Version: '1.7.0',
require: function(libraryName) {
// inserting via DOM fails in Safari 2.0, so brute force approach
document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
},
load: function() {
if((typeof Prototype=='undefined') ||
(typeof Element == 'undefined') ||
(typeof Element.Methods=='undefined') ||
parseFloat(Prototype.Version.split(".")[0] + "." +
Prototype.Version.split(".")[1]) < 1.5)
throw("script.aculo.us requires the Prototype JavaScript framework >= 1.5.0");
$A(document.getElementsByTagName("script")).findAll( function(s) {
return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
}).each( function(s) {
var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
var includes = s.src.match(/\?.*load=([a-z,]*)/);
(includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each(
function(include) { Scriptaculous.require(path+include+'.js') });
});
}
}
Scriptaculous.load();

View file

@ -1,278 +0,0 @@
// script.aculo.us slider.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
// Copyright (c) 2005, 2006 Marty Haught, Thomas Fuchs
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
if(!Control) var Control = {};
Control.Slider = Class.create();
// options:
// axis: 'vertical', or 'horizontal' (default)
//
// callbacks:
// onChange(value)
// onSlide(value)
Control.Slider.prototype = {
initialize: function(handle, track, options) {
var slider = this;
if(handle instanceof Array) {
this.handles = handle.collect( function(e) { return $(e) });
} else {
this.handles = [$(handle)];
}
this.track = $(track);
this.options = options || {};
this.axis = this.options.axis || 'horizontal';
this.increment = this.options.increment || 1;
this.step = parseInt(this.options.step || '1');
this.range = this.options.range || $R(0,1);
this.value = 0; // assure backwards compat
this.values = this.handles.map( function() { return 0 });
this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
this.options.startSpan = $(this.options.startSpan || null);
this.options.endSpan = $(this.options.endSpan || null);
this.restricted = this.options.restricted || false;
this.maximum = this.options.maximum || this.range.end;
this.minimum = this.options.minimum || this.range.start;
// Will be used to align the handle onto the track, if necessary
this.alignX = parseInt(this.options.alignX || '0');
this.alignY = parseInt(this.options.alignY || '0');
this.trackLength = this.maximumOffset() - this.minimumOffset();
this.handleLength = this.isVertical() ?
(this.handles[0].offsetHeight != 0 ?
this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
(this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
this.handles[0].style.width.replace(/px$/,""));
this.active = false;
this.dragging = false;
this.disabled = false;
if(this.options.disabled) this.setDisabled();
// Allowed values array
this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
if(this.allowedValues) {
this.minimum = this.allowedValues.min();
this.maximum = this.allowedValues.max();
}
this.eventMouseDown = this.startDrag.bindAsEventListener(this);
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.update.bindAsEventListener(this);
// Initialize handles in reverse (make sure first handle is active)
this.handles.each( function(h,i) {
i = slider.handles.length-1-i;
slider.setValue(parseFloat(
(slider.options.sliderValue instanceof Array ?
slider.options.sliderValue[i] : slider.options.sliderValue) ||
slider.range.start), i);
Element.makePositioned(h); // fix IE
Event.observe(h, "mousedown", slider.eventMouseDown);
});
Event.observe(this.track, "mousedown", this.eventMouseDown);
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
this.initialized = true;
},
dispose: function() {
var slider = this;
Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
this.handles.each( function(h) {
Event.stopObserving(h, "mousedown", slider.eventMouseDown);
});
},
setDisabled: function(){
this.disabled = true;
},
setEnabled: function(){
this.disabled = false;
},
getNearestValue: function(value){
if(this.allowedValues){
if(value >= this.allowedValues.max()) return(this.allowedValues.max());
if(value <= this.allowedValues.min()) return(this.allowedValues.min());
var offset = Math.abs(this.allowedValues[0] - value);
var newValue = this.allowedValues[0];
this.allowedValues.each( function(v) {
var currentOffset = Math.abs(v - value);
if(currentOffset <= offset){
newValue = v;
offset = currentOffset;
}
});
return newValue;
}
if(value > this.range.end) return this.range.end;
if(value < this.range.start) return this.range.start;
return value;
},
setValue: function(sliderValue, handleIdx){
if(!this.active) {
this.activeHandleIdx = handleIdx || 0;
this.activeHandle = this.handles[this.activeHandleIdx];
this.updateStyles();
}
handleIdx = handleIdx || this.activeHandleIdx || 0;
if(this.initialized && this.restricted) {
if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
sliderValue = this.values[handleIdx-1];
if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
sliderValue = this.values[handleIdx+1];
}
sliderValue = this.getNearestValue(sliderValue);
this.values[handleIdx] = sliderValue;
this.value = this.values[0]; // assure backwards compat
this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
this.translateToPx(sliderValue);
this.drawSpans();
if(!this.dragging || !this.event) this.updateFinished();
},
setValueBy: function(delta, handleIdx) {
this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
handleIdx || this.activeHandleIdx || 0);
},
translateToPx: function(value) {
return Math.round(
((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
(value - this.range.start)) + "px";
},
translateToValue: function(offset) {
return ((offset/(this.trackLength-this.handleLength) *
(this.range.end-this.range.start)) + this.range.start);
},
getRange: function(range) {
var v = this.values.sortBy(Prototype.K);
range = range || 0;
return $R(v[range],v[range+1]);
},
minimumOffset: function(){
return(this.isVertical() ? this.alignY : this.alignX);
},
maximumOffset: function(){
return(this.isVertical() ?
(this.track.offsetHeight != 0 ? this.track.offsetHeight :
this.track.style.height.replace(/px$/,"")) - this.alignY :
(this.track.offsetWidth != 0 ? this.track.offsetWidth :
this.track.style.width.replace(/px$/,"")) - this.alignY);
},
isVertical: function(){
return (this.axis == 'vertical');
},
drawSpans: function() {
var slider = this;
if(this.spans)
$R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
if(this.options.startSpan)
this.setSpan(this.options.startSpan,
$R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
if(this.options.endSpan)
this.setSpan(this.options.endSpan,
$R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
},
setSpan: function(span, range) {
if(this.isVertical()) {
span.style.top = this.translateToPx(range.start);
span.style.height = this.translateToPx(range.end - range.start + this.range.start);
} else {
span.style.left = this.translateToPx(range.start);
span.style.width = this.translateToPx(range.end - range.start + this.range.start);
}
},
updateStyles: function() {
this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
Element.addClassName(this.activeHandle, 'selected');
},
startDrag: function(event) {
if(Event.isLeftClick(event)) {
if(!this.disabled){
this.active = true;
var handle = Event.element(event);
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var track = handle;
if(track==this.track) {
var offsets = Position.cumulativeOffset(this.track);
this.event = event;
this.setValue(this.translateToValue(
(this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
));
var offsets = Position.cumulativeOffset(this.activeHandle);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
} else {
// find the handle (prevents issues with Safari)
while((this.handles.indexOf(handle) == -1) && handle.parentNode)
handle = handle.parentNode;
if(this.handles.indexOf(handle)!=-1) {
this.activeHandle = handle;
this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
this.updateStyles();
var offsets = Position.cumulativeOffset(this.activeHandle);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
}
}
}
Event.stop(event);
}
},
update: function(event) {
if(this.active) {
if(!this.dragging) this.dragging = true;
this.draw(event);
// fix AppleWebKit rendering
if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
Event.stop(event);
}
},
draw: function(event) {
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var offsets = Position.cumulativeOffset(this.track);
pointer[0] -= this.offsetX + offsets[0];
pointer[1] -= this.offsetY + offsets[1];
this.event = event;
this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
if(this.initialized && this.options.onSlide)
this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
},
endDrag: function(event) {
if(this.active && this.dragging) {
this.finishDrag(event, true);
Event.stop(event);
}
this.active = false;
this.dragging = false;
},
finishDrag: function(event, success) {
this.active = false;
this.dragging = false;
this.updateFinished();
},
updateFinished: function() {
if(this.initialized && this.options.onChange)
this.options.onChange(this.values.length>1 ? this.values : this.value, this);
this.event = null;
}
}

View file

@ -1,564 +0,0 @@
// script.aculo.us unittest.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
// (c) 2005, 2006 Michael Schuerig (http://www.schuerig.de/michael/)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// experimental, Firefox-only
Event.simulateMouse = function(element, eventName) {
var options = Object.extend({
pointerX: 0,
pointerY: 0,
buttons: 0,
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false
}, arguments[2] || {});
var oEvent = document.createEvent("MouseEvents");
oEvent.initMouseEvent(eventName, true, true, document.defaultView,
options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element));
if(this.mark) Element.remove(this.mark);
this.mark = document.createElement('div');
this.mark.appendChild(document.createTextNode(" "));
document.body.appendChild(this.mark);
this.mark.style.position = 'absolute';
this.mark.style.top = options.pointerY + "px";
this.mark.style.left = options.pointerX + "px";
this.mark.style.width = "5px";
this.mark.style.height = "5px;";
this.mark.style.borderTop = "1px solid red;"
this.mark.style.borderLeft = "1px solid red;"
if(this.step)
alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
$(element).dispatchEvent(oEvent);
};
// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
// You need to downgrade to 1.0.4 for now to get this working
// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
Event.simulateKey = function(element, eventName) {
var options = Object.extend({
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false,
keyCode: 0,
charCode: 0
}, arguments[2] || {});
var oEvent = document.createEvent("KeyEvents");
oEvent.initKeyEvent(eventName, true, true, window,
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
options.keyCode, options.charCode );
$(element).dispatchEvent(oEvent);
};
Event.simulateKeys = function(element, command) {
for(var i=0; i<command.length; i++) {
Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
}
};
var Test = {}
Test.Unit = {};
// security exception workaround
Test.Unit.inspect = Object.inspect;
Test.Unit.Logger = Class.create();
Test.Unit.Logger.prototype = {
initialize: function(log) {
this.log = $(log);
if (this.log) {
this._createLogTable();
}
},
start: function(testName) {
if (!this.log) return;
this.testName = testName;
this.lastLogLine = document.createElement('tr');
this.statusCell = document.createElement('td');
this.nameCell = document.createElement('td');
this.nameCell.className = "nameCell";
this.nameCell.appendChild(document.createTextNode(testName));
this.messageCell = document.createElement('td');
this.lastLogLine.appendChild(this.statusCell);
this.lastLogLine.appendChild(this.nameCell);
this.lastLogLine.appendChild(this.messageCell);
this.loglines.appendChild(this.lastLogLine);
},
finish: function(status, summary) {
if (!this.log) return;
this.lastLogLine.className = status;
this.statusCell.innerHTML = status;
this.messageCell.innerHTML = this._toHTML(summary);
this.addLinksToResults();
},
message: function(message) {
if (!this.log) return;
this.messageCell.innerHTML = this._toHTML(message);
},
summary: function(summary) {
if (!this.log) return;
this.logsummary.innerHTML = this._toHTML(summary);
},
_createLogTable: function() {
this.log.innerHTML =
'<div id="logsummary"></div>' +
'<table id="logtable">' +
'<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
'<tbody id="loglines"></tbody>' +
'</table>';
this.logsummary = $('logsummary')
this.loglines = $('loglines');
},
_toHTML: function(txt) {
return txt.escapeHTML().replace(/\n/g,"<br/>");
},
addLinksToResults: function(){
$$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
td.title = "Run only this test"
Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
});
$$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
td.title = "Run all tests"
Event.observe(td, 'click', function(){ window.location.search = "";});
});
}
}
Test.Unit.Runner = Class.create();
Test.Unit.Runner.prototype = {
initialize: function(testcases) {
this.options = Object.extend({
testLog: 'testlog'
}, arguments[1] || {});
this.options.resultsURL = this.parseResultsURLQueryParameter();
this.options.tests = this.parseTestsQueryParameter();
if (this.options.testLog) {
this.options.testLog = $(this.options.testLog) || null;
}
if(this.options.tests) {
this.tests = [];
for(var i = 0; i < this.options.tests.length; i++) {
if(/^test/.test(this.options.tests[i])) {
this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
}
}
} else {
if (this.options.test) {
this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
} else {
this.tests = [];
for(var testcase in testcases) {
if(/^test/.test(testcase)) {
this.tests.push(
new Test.Unit.Testcase(
this.options.context ? ' -> ' + this.options.titles[testcase] : testcase,
testcases[testcase], testcases["setup"], testcases["teardown"]
));
}
}
}
}
this.currentTest = 0;
this.logger = new Test.Unit.Logger(this.options.testLog);
setTimeout(this.runTests.bind(this), 1000);
},
parseResultsURLQueryParameter: function() {
return window.location.search.parseQuery()["resultsURL"];
},
parseTestsQueryParameter: function(){
if (window.location.search.parseQuery()["tests"]){
return window.location.search.parseQuery()["tests"].split(',');
};
},
// Returns:
// "ERROR" if there was an error,
// "FAILURE" if there was a failure, or
// "SUCCESS" if there was neither
getResult: function() {
var hasFailure = false;
for(var i=0;i<this.tests.length;i++) {
if (this.tests[i].errors > 0) {
return "ERROR";
}
if (this.tests[i].failures > 0) {
hasFailure = true;
}
}
if (hasFailure) {
return "FAILURE";
} else {
return "SUCCESS";
}
},
postResults: function() {
if (this.options.resultsURL) {
new Ajax.Request(this.options.resultsURL,
{ method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
}
},
runTests: function() {
var test = this.tests[this.currentTest];
if (!test) {
// finished!
this.postResults();
this.logger.summary(this.summary());
return;
}
if(!test.isWaiting) {
this.logger.start(test.name);
}
test.run();
if(test.isWaiting) {
this.logger.message("Waiting for " + test.timeToWait + "ms");
setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
} else {
this.logger.finish(test.status(), test.summary());
this.currentTest++;
// tail recursive, hopefully the browser will skip the stackframe
this.runTests();
}
},
summary: function() {
var assertions = 0;
var failures = 0;
var errors = 0;
var messages = [];
for(var i=0;i<this.tests.length;i++) {
assertions += this.tests[i].assertions;
failures += this.tests[i].failures;
errors += this.tests[i].errors;
}
return (
(this.options.context ? this.options.context + ': ': '') +
this.tests.length + " tests, " +
assertions + " assertions, " +
failures + " failures, " +
errors + " errors");
}
}
Test.Unit.Assertions = Class.create();
Test.Unit.Assertions.prototype = {
initialize: function() {
this.assertions = 0;
this.failures = 0;
this.errors = 0;
this.messages = [];
},
summary: function() {
return (
this.assertions + " assertions, " +
this.failures + " failures, " +
this.errors + " errors" + "\n" +
this.messages.join("\n"));
},
pass: function() {
this.assertions++;
},
fail: function(message) {
this.failures++;
this.messages.push("Failure: " + message);
},
info: function(message) {
this.messages.push("Info: " + message);
},
error: function(error) {
this.errors++;
this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
},
status: function() {
if (this.failures > 0) return 'failed';
if (this.errors > 0) return 'error';
return 'passed';
},
assert: function(expression) {
var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
try { expression ? this.pass() :
this.fail(message); }
catch(e) { this.error(e); }
},
assertEqual: function(expected, actual) {
var message = arguments[2] || "assertEqual";
try { (expected == actual) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertInspect: function(expected, actual) {
var message = arguments[2] || "assertInspect";
try { (expected == actual.inspect()) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertEnumEqual: function(expected, actual) {
var message = arguments[2] || "assertEnumEqual";
try { $A(expected).length == $A(actual).length &&
expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) +
', actual ' + Test.Unit.inspect(actual)); }
catch(e) { this.error(e); }
},
assertNotEqual: function(expected, actual) {
var message = arguments[2] || "assertNotEqual";
try { (expected != actual) ? this.pass() :
this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertIdentical: function(expected, actual) {
var message = arguments[2] || "assertIdentical";
try { (expected === actual) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertNotIdentical: function(expected, actual) {
var message = arguments[2] || "assertNotIdentical";
try { !(expected === actual) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertNull: function(obj) {
var message = arguments[1] || 'assertNull'
try { (obj==null) ? this.pass() :
this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
catch(e) { this.error(e); }
},
assertMatch: function(expected, actual) {
var message = arguments[2] || 'assertMatch';
var regex = new RegExp(expected);
try { (regex.exec(actual)) ? this.pass() :
this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertHidden: function(element) {
var message = arguments[1] || 'assertHidden';
this.assertEqual("none", element.style.display, message);
},
assertNotNull: function(object) {
var message = arguments[1] || 'assertNotNull';
this.assert(object != null, message);
},
assertType: function(expected, actual) {
var message = arguments[2] || 'assertType';
try {
(actual.constructor == expected) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + (actual.constructor) + '"'); }
catch(e) { this.error(e); }
},
assertNotOfType: function(expected, actual) {
var message = arguments[2] || 'assertNotOfType';
try {
(actual.constructor != expected) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + (actual.constructor) + '"'); }
catch(e) { this.error(e); }
},
assertInstanceOf: function(expected, actual) {
var message = arguments[2] || 'assertInstanceOf';
try {
(actual instanceof expected) ? this.pass() :
this.fail(message + ": object was not an instance of the expected type"); }
catch(e) { this.error(e); }
},
assertNotInstanceOf: function(expected, actual) {
var message = arguments[2] || 'assertNotInstanceOf';
try {
!(actual instanceof expected) ? this.pass() :
this.fail(message + ": object was an instance of the not expected type"); }
catch(e) { this.error(e); }
},
assertRespondsTo: function(method, obj) {
var message = arguments[2] || 'assertRespondsTo';
try {
(obj[method] && typeof obj[method] == 'function') ? this.pass() :
this.fail(message + ": object doesn't respond to [" + method + "]"); }
catch(e) { this.error(e); }
},
assertReturnsTrue: function(method, obj) {
var message = arguments[2] || 'assertReturnsTrue';
try {
var m = obj[method];
if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
m() ? this.pass() :
this.fail(message + ": method returned false"); }
catch(e) { this.error(e); }
},
assertReturnsFalse: function(method, obj) {
var message = arguments[2] || 'assertReturnsFalse';
try {
var m = obj[method];
if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
!m() ? this.pass() :
this.fail(message + ": method returned true"); }
catch(e) { this.error(e); }
},
assertRaise: function(exceptionName, method) {
var message = arguments[2] || 'assertRaise';
try {
method();
this.fail(message + ": exception expected but none was raised"); }
catch(e) {
((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e);
}
},
assertElementsMatch: function() {
var expressions = $A(arguments), elements = $A(expressions.shift());
if (elements.length != expressions.length) {
this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions');
return false;
}
elements.zip(expressions).all(function(pair, index) {
var element = $(pair.first()), expression = pair.last();
if (element.match(expression)) return true;
this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect());
}.bind(this)) && this.pass();
},
assertElementMatches: function(element, expression) {
this.assertElementsMatch([element], expression);
},
benchmark: function(operation, iterations) {
var startAt = new Date();
(iterations || 1).times(operation);
var timeTaken = ((new Date())-startAt);
this.info((arguments[2] || 'Operation') + ' finished ' +
iterations + ' iterations in ' + (timeTaken/1000)+'s' );
return timeTaken;
},
_isVisible: function(element) {
element = $(element);
if(!element.parentNode) return true;
this.assertNotNull(element);
if(element.style && Element.getStyle(element, 'display') == 'none')
return false;
return this._isVisible(element.parentNode);
},
assertNotVisible: function(element) {
this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
},
assertVisible: function(element) {
this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
},
benchmark: function(operation, iterations) {
var startAt = new Date();
(iterations || 1).times(operation);
var timeTaken = ((new Date())-startAt);
this.info((arguments[2] || 'Operation') + ' finished ' +
iterations + ' iterations in ' + (timeTaken/1000)+'s' );
return timeTaken;
}
}
Test.Unit.Testcase = Class.create();
Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
initialize: function(name, test, setup, teardown) {
Test.Unit.Assertions.prototype.initialize.bind(this)();
this.name = name;
if(typeof test == 'string') {
test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,');
test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)');
this.test = function() {
eval('with(this){'+test+'}');
}
} else {
this.test = test || function() {};
}
this.setup = setup || function() {};
this.teardown = teardown || function() {};
this.isWaiting = false;
this.timeToWait = 1000;
},
wait: function(time, nextPart) {
this.isWaiting = true;
this.test = nextPart;
this.timeToWait = time;
},
run: function() {
try {
try {
if (!this.isWaiting) this.setup.bind(this)();
this.isWaiting = false;
this.test.bind(this)();
} finally {
if(!this.isWaiting) {
this.teardown.bind(this)();
}
}
}
catch(e) { this.error(e); }
}
});
// *EXPERIMENTAL* BDD-style testing to please non-technical folk
// This draws many ideas from RSpec http://rspec.rubyforge.org/
Test.setupBDDExtensionMethods = function(){
var METHODMAP = {
shouldEqual: 'assertEqual',
shouldNotEqual: 'assertNotEqual',
shouldEqualEnum: 'assertEnumEqual',
shouldBeA: 'assertType',
shouldNotBeA: 'assertNotOfType',
shouldBeAn: 'assertType',
shouldNotBeAn: 'assertNotOfType',
shouldBeNull: 'assertNull',
shouldNotBeNull: 'assertNotNull',
shouldBe: 'assertReturnsTrue',
shouldNotBe: 'assertReturnsFalse',
shouldRespondTo: 'assertRespondsTo'
};
Test.BDDMethods = {};
for(m in METHODMAP) {
Test.BDDMethods[m] = eval(
'function(){'+
'var args = $A(arguments);'+
'var scope = args.shift();'+
'scope.'+METHODMAP[m]+'.apply(scope,(args || []).concat([this])); }');
}
[Array.prototype, String.prototype, Number.prototype].each(
function(p){ Object.extend(p, Test.BDDMethods) }
);
}
Test.context = function(name, spec, log){
Test.setupBDDExtensionMethods();
var compiledSpec = {};
var titles = {};
for(specName in spec) {
switch(specName){
case "setup":
case "teardown":
compiledSpec[specName] = spec[specName];
break;
default:
var testName = 'test'+specName.gsub(/\s+/,'-').camelize();
var body = spec[specName].toString().split('\n').slice(1);
if(/^\{/.test(body[0])) body = body.slice(1);
body.pop();
body = body.map(function(statement){
return statement.strip()
});
compiledSpec[testName] = body.join('\n');
titles[testName] = specName;
}
}
new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name });
};

View file

@ -1,136 +0,0 @@
// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Builder = {
NODEMAP: {
AREA: 'map',
CAPTION: 'table',
COL: 'table',
COLGROUP: 'table',
LEGEND: 'fieldset',
OPTGROUP: 'select',
OPTION: 'select',
PARAM: 'object',
TBODY: 'table',
TD: 'table',
TFOOT: 'table',
TH: 'table',
THEAD: 'table',
TR: 'table'
},
// note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
// due to a Firefox bug
node: function(elementName) {
elementName = elementName.toUpperCase();
// try innerHTML approach
var parentTag = this.NODEMAP[elementName] || 'div';
var parentElement = document.createElement(parentTag);
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
} catch(e) {}
var element = parentElement.firstChild || null;
// see if browser added wrapping tags
if(element && (element.tagName.toUpperCase() != elementName))
element = element.getElementsByTagName(elementName)[0];
// fallback to createElement approach
if(!element) element = document.createElement(elementName);
// abort if nothing could be created
if(!element) return;
// attributes (or text)
if(arguments[1])
if(this._isStringOrNumber(arguments[1]) ||
(arguments[1] instanceof Array) ||
arguments[1].tagName) {
this._children(element, arguments[1]);
} else {
var attrs = this._attributes(arguments[1]);
if(attrs.length) {
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
parentElement.innerHTML = "<" +elementName + " " +
attrs + "></" + elementName + ">";
} catch(e) {}
element = parentElement.firstChild || null;
// workaround firefox 1.0.X bug
if(!element) {
element = document.createElement(elementName);
for(attr in arguments[1])
element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
}
if(element.tagName.toUpperCase() != elementName)
element = parentElement.getElementsByTagName(elementName)[0];
}
}
// text, or array of children
if(arguments[2])
this._children(element, arguments[2]);
return element;
},
_text: function(text) {
return document.createTextNode(text);
},
ATTR_MAP: {
'className': 'class',
'htmlFor': 'for'
},
_attributes: function(attributes) {
var attrs = [];
for(attribute in attributes)
attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
'="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
return attrs.join(" ");
},
_children: function(element, children) {
if(children.tagName) {
element.appendChild(children);
return;
}
if(typeof children=='object') { // array can hold nodes and text
children.flatten().each( function(e) {
if(typeof e=='object')
element.appendChild(e)
else
if(Builder._isStringOrNumber(e))
element.appendChild(Builder._text(e));
});
} else
if(Builder._isStringOrNumber(children))
element.appendChild(Builder._text(children));
},
_isStringOrNumber: function(param) {
return(typeof param=='string' || typeof param=='number');
},
build: function(html) {
var element = this.node('div');
$(element).update(html.strip());
return element.down();
},
dump: function(scope) {
if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
"BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
"FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
"KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
"PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
"TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
tags.each( function(tag){
scope[tag] = function() {
return Builder.node.apply(Builder, [tag].concat($A(arguments)));
}
});
}
}

View file

@ -1,965 +0,0 @@
// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
// Rob Wills
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// Autocompleter.Base handles all the autocompletion functionality
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
// Specific autocompleters need to provide, at the very least,
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
//
// Tokenized incremental autocompletion is enabled automatically
// when an autocompleter is instantiated with the 'tokens' option
// in the options parameter, e.g.:
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most
// useful when one of the tokens is \n (a newline), as it
// allows smart autocompletion after linebreaks.
if(typeof Effect == 'undefined')
throw("controls.js requires including script.aculo.us' effects.js library");
var Autocompleter = { }
Autocompleter.Base = Class.create({
baseInitialize: function(element, update, options) {
element = $(element)
this.element = element;
this.update = $(update);
this.hasFocus = false;
this.changed = false;
this.active = false;
this.index = 0;
this.entryCount = 0;
this.oldElementValue = this.element.value;
if(this.setOptions)
this.setOptions(options);
else
this.options = options || { };
this.options.paramName = this.options.paramName || this.element.name;
this.options.tokens = this.options.tokens || [];
this.options.frequency = this.options.frequency || 0.4;
this.options.minChars = this.options.minChars || 1;
this.options.onShow = this.options.onShow ||
function(element, update){
if(!update.style.position || update.style.position=='absolute') {
update.style.position = 'absolute';
Position.clone(element, update, {
setHeight: false,
offsetTop: element.offsetHeight
});
}
Effect.Appear(update,{duration:0.15});
};
this.options.onHide = this.options.onHide ||
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
if(typeof(this.options.tokens) == 'string')
this.options.tokens = new Array(this.options.tokens);
// Force carriage returns as token delimiters anyway
if (!this.options.tokens.include('\n'))
this.options.tokens.push('\n');
this.observer = null;
this.element.setAttribute('autocomplete','off');
Element.hide(this.update);
Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
},
show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix &&
(Prototype.Browser.IE) &&
(Element.getStyle(this.update, 'position')=='absolute')) {
new Insertion.After(this.update,
'<iframe id="' + this.update.id + '_iefix" '+
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
this.iefix = $(this.update.id+'_iefix');
}
if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
},
fixIEOverlapping: function() {
Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
this.iefix.style.zIndex = 1;
this.update.style.zIndex = 2;
Element.show(this.iefix);
},
hide: function() {
this.stopIndicator();
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
if(this.iefix) Element.hide(this.iefix);
},
startIndicator: function() {
if(this.options.indicator) Element.show(this.options.indicator);
},
stopIndicator: function() {
if(this.options.indicator) Element.hide(this.options.indicator);
},
onKeyPress: function(event) {
if(this.active)
switch(event.keyCode) {
case Event.KEY_TAB:
case Event.KEY_RETURN:
this.selectEntry();
Event.stop(event);
case Event.KEY_ESC:
this.hide();
this.active = false;
Event.stop(event);
return;
case Event.KEY_LEFT:
case Event.KEY_RIGHT:
return;
case Event.KEY_UP:
this.markPrevious();
this.render();
Event.stop(event);
return;
case Event.KEY_DOWN:
this.markNext();
this.render();
Event.stop(event);
return;
}
else
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
(Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
this.changed = true;
this.hasFocus = true;
if(this.observer) clearTimeout(this.observer);
this.observer =
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
},
activate: function() {
this.changed = false;
this.hasFocus = true;
this.getUpdatedChoices();
},
onHover: function(event) {
var element = Event.findElement(event, 'LI');
if(this.index != element.autocompleteIndex)
{
this.index = element.autocompleteIndex;
this.render();
}
Event.stop(event);
},
onClick: function(event) {
var element = Event.findElement(event, 'LI');
this.index = element.autocompleteIndex;
this.selectEntry();
this.hide();
},
onBlur: function(event) {
// needed to make click events working
setTimeout(this.hide.bind(this), 250);
this.hasFocus = false;
this.active = false;
},
render: function() {
if(this.entryCount > 0) {
for (var i = 0; i < this.entryCount; i++)
this.index==i ?
Element.addClassName(this.getEntry(i),"selected") :
Element.removeClassName(this.getEntry(i),"selected");
if(this.hasFocus) {
this.show();
this.active = true;
}
} else {
this.active = false;
this.hide();
}
},
markPrevious: function() {
if(this.index > 0) this.index--
else this.index = this.entryCount-1;
this.getEntry(this.index).scrollIntoView(true);
},
markNext: function() {
if(this.index < this.entryCount-1) this.index++
else this.index = 0;
this.getEntry(this.index).scrollIntoView(false);
},
getEntry: function(index) {
return this.update.firstChild.childNodes[index];
},
getCurrentEntry: function() {
return this.getEntry(this.index);
},
selectEntry: function() {
this.active = false;
this.updateElement(this.getCurrentEntry());
},
updateElement: function(selectedElement) {
if (this.options.updateElement) {
this.options.updateElement(selectedElement);
return;
}
var value = '';
if (this.options.select) {
var nodes = $(selectedElement).select('.' + this.options.select) || [];
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
} else
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
var bounds = this.getTokenBounds();
if (bounds[0] != -1) {
var newValue = this.element.value.substr(0, bounds[0]);
var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
if (whitespace)
newValue += whitespace[0];
this.element.value = newValue + value + this.element.value.substr(bounds[1]);
} else {
this.element.value = value;
}
this.oldElementValue = this.element.value;
this.element.focus();
if (this.options.afterUpdateElement)
this.options.afterUpdateElement(this.element, selectedElement);
},
updateChoices: function(choices) {
if(!this.changed && this.hasFocus) {
this.update.innerHTML = choices;
Element.cleanWhitespace(this.update);
Element.cleanWhitespace(this.update.down());
if(this.update.firstChild && this.update.down().childNodes) {
this.entryCount =
this.update.down().childNodes.length;
for (var i = 0; i < this.entryCount; i++) {
var entry = this.getEntry(i);
entry.autocompleteIndex = i;
this.addObservers(entry);
}
} else {
this.entryCount = 0;
}
this.stopIndicator();
this.index = 0;
if(this.entryCount==1 && this.options.autoSelect) {
this.selectEntry();
this.hide();
} else {
this.render();
}
}
},
addObservers: function(element) {
Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
Event.observe(element, "click", this.onClick.bindAsEventListener(this));
},
onObserverEvent: function() {
this.changed = false;
this.tokenBounds = null;
if(this.getToken().length>=this.options.minChars) {
this.getUpdatedChoices();
} else {
this.active = false;
this.hide();
}
this.oldElementValue = this.element.value;
},
getToken: function() {
var bounds = this.getTokenBounds();
return this.element.value.substring(bounds[0], bounds[1]).strip();
},
getTokenBounds: function() {
if (null != this.tokenBounds) return this.tokenBounds;
var value = this.element.value;
if (value.strip().empty()) return [-1, 0];
var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
var offset = (diff == this.oldElementValue.length ? 1 : 0);
var prevTokenPos = -1, nextTokenPos = value.length;
var tp;
for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
if (tp > prevTokenPos) prevTokenPos = tp;
tp = value.indexOf(this.options.tokens[index], diff + offset);
if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
}
return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
}
});
Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
var boundary = Math.min(newS.length, oldS.length);
for (var index = 0; index < boundary; ++index)
if (newS[index] != oldS[index])
return index;
return boundary;
};
Ajax.Autocompleter = Class.create(Autocompleter.Base, {
initialize: function(element, update, url, options) {
this.baseInitialize(element, update, options);
this.options.asynchronous = true;
this.options.onComplete = this.onComplete.bind(this);
this.options.defaultParams = this.options.parameters || null;
this.url = url;
},
getUpdatedChoices: function() {
this.startIndicator();
var entry = encodeURIComponent(this.options.paramName) + '=' +
encodeURIComponent(this.getToken());
this.options.parameters = this.options.callback ?
this.options.callback(this.element, entry) : entry;
if(this.options.defaultParams)
this.options.parameters += '&' + this.options.defaultParams;
new Ajax.Request(this.url, this.options);
},
onComplete: function(request) {
this.updateChoices(request.responseText);
}
});
// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
// than sending out Ajax queries, which can be quite slow sometimes.
//
// The constructor takes four parameters. The first two are, as usual,
// the id of the monitored textbox, and id of the autocompletion menu.
// The third is the array you want to autocomplete from, and the fourth
// is the options block.
//
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
// text only at the beginning of strings in the
// autocomplete array. Defaults to true, which will
// match text at the beginning of any *word* in the
// strings in the autocomplete array. If you want to
// search anywhere in the string, additionally set
// the option fullSearch to true (default: off).
//
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partialChars - How many characters to enter before triggering
// a partial match (unlike minChars, which defines
// how many characters are required to do any match
// at all). Defaults to 2.
//
// - ignoreCase - Whether to ignore case when autocompleting.
// Defaults to true.
//
// It's possible to pass in a custom function as the 'selector'
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.
Autocompleter.Local = Class.create(Autocompleter.Base, {
initialize: function(element, update, array, options) {
this.baseInitialize(element, update, options);
this.options.array = array;
},
getUpdatedChoices: function() {
this.updateChoices(this.options.selector(this));
},
setOptions: function(options) {
this.options = Object.extend({
choices: 10,
partialSearch: true,
partialChars: 2,
ignoreCase: true,
fullSearch: false,
selector: function(instance) {
var ret = []; // Beginning matches
var partial = []; // Inside matches
var entry = instance.getToken();
var count = 0;
for (var i = 0; i < instance.options.array.length &&
ret.length < instance.options.choices ; i++) {
var elem = instance.options.array[i];
var foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase()) :
elem.indexOf(entry);
while (foundPos != -1) {
if (foundPos == 0 && elem.length != entry.length) {
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
elem.substr(entry.length) + "</li>");
break;
} else if (entry.length >= instance.options.partialChars &&
instance.options.partialSearch && foundPos != -1) {
if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
foundPos + entry.length) + "</li>");
break;
}
}
foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
elem.indexOf(entry, foundPos + 1);
}
}
if (partial.length)
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
return "<ul>" + ret.join('') + "</ul>";
}
}, options || { });
}
});
// AJAX in-place editor and collection editor
// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
setTimeout(function() {
Field.activate(field);
}, 1);
}
Ajax.InPlaceEditor = Class.create({
initialize: function(element, url, options) {
this.url = url;
this.element = element = $(element);
this.prepareOptions();
this._controls = { };
arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
Object.extend(this.options, options || { });
if (!this.options.formId && this.element.id) {
this.options.formId = this.element.id + '-inplaceeditor';
if ($(this.options.formId))
this.options.formId = '';
}
if (this.options.externalControl)
this.options.externalControl = $(this.options.externalControl);
if (!this.options.externalControl)
this.options.externalControlOnly = false;
this._originalBackground = this.element.getStyle('background-color') || 'transparent';
this.element.title = this.options.clickToEditText;
this._boundCancelHandler = this.handleFormCancellation.bind(this);
this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
this._boundFailureHandler = this.handleAJAXFailure.bind(this);
this._boundSubmitHandler = this.handleFormSubmission.bind(this);
this._boundWrapperHandler = this.wrapUp.bind(this);
this.registerListeners();
},
checkForEscapeOrReturn: function(e) {
if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
if (Event.KEY_ESC == e.keyCode)
this.handleFormCancellation(e);
else if (Event.KEY_RETURN == e.keyCode)
this.handleFormSubmission(e);
},
createControl: function(mode, handler, extraClasses) {
var control = this.options[mode + 'Control'];
var text = this.options[mode + 'Text'];
if ('button' == control) {
var btn = document.createElement('input');
btn.type = 'submit';
btn.value = text;
btn.className = 'editor_' + mode + '_button';
if ('cancel' == mode)
btn.onclick = this._boundCancelHandler;
this._form.appendChild(btn);
this._controls[mode] = btn;
} else if ('link' == control) {
var link = document.createElement('a');
link.href = '#';
link.appendChild(document.createTextNode(text));
link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
link.className = 'editor_' + mode + '_link';
if (extraClasses)
link.className += ' ' + extraClasses;
this._form.appendChild(link);
this._controls[mode] = link;
}
},
createEditField: function() {
var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
var fld;
if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
fld = document.createElement('input');
fld.type = 'text';
var size = this.options.size || this.options.cols || 0;
if (0 < size) fld.size = size;
} else {
fld = document.createElement('textarea');
fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
fld.cols = this.options.cols || 40;
}
fld.name = this.options.paramName;
fld.value = text; // No HTML breaks conversion anymore
fld.className = 'editor_field';
if (this.options.submitOnBlur)
fld.onblur = this._boundSubmitHandler;
this._controls.editor = fld;
if (this.options.loadTextURL)
this.loadExternalText();
this._form.appendChild(this._controls.editor);
},
createForm: function() {
var ipe = this;
function addText(mode, condition) {
var text = ipe.options['text' + mode + 'Controls'];
if (!text || condition === false) return;
ipe._form.appendChild(document.createTextNode(text));
};
this._form = $(document.createElement('form'));
this._form.id = this.options.formId;
this._form.addClassName(this.options.formClassName);
this._form.onsubmit = this._boundSubmitHandler;
this.createEditField();
if ('textarea' == this._controls.editor.tagName.toLowerCase())
this._form.appendChild(document.createElement('br'));
if (this.options.onFormCustomization)
this.options.onFormCustomization(this, this._form);
addText('Before', this.options.okControl || this.options.cancelControl);
this.createControl('ok', this._boundSubmitHandler);
addText('Between', this.options.okControl && this.options.cancelControl);
this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
addText('After', this.options.okControl || this.options.cancelControl);
},
destroy: function() {
if (this._oldInnerHTML)
this.element.innerHTML = this._oldInnerHTML;
this.leaveEditMode();
this.unregisterListeners();
},
enterEditMode: function(e) {
if (this._saving || this._editing) return;
this._editing = true;
this.triggerCallback('onEnterEditMode');
if (this.options.externalControl)
this.options.externalControl.hide();
this.element.hide();
this.createForm();
this.element.parentNode.insertBefore(this._form, this.element);
if (!this.options.loadTextURL)
this.postProcessEditField();
if (e) Event.stop(e);
},
enterHover: function(e) {
if (this.options.hoverClassName)
this.element.addClassName(this.options.hoverClassName);
if (this._saving) return;
this.triggerCallback('onEnterHover');
},
getText: function() {
return this.element.innerHTML;
},
handleAJAXFailure: function(transport) {
this.triggerCallback('onFailure', transport);
if (this._oldInnerHTML) {
this.element.innerHTML = this._oldInnerHTML;
this._oldInnerHTML = null;
}
},
handleFormCancellation: function(e) {
this.wrapUp();
if (e) Event.stop(e);
},
handleFormSubmission: function(e) {
var form = this._form;
var value = $F(this._controls.editor);
this.prepareSubmission();
var params = this.options.callback(form, value) || '';
if (Object.isString(params))
params = params.toQueryParams();
params.editorId = this.element.id;
if (this.options.htmlResponse) {
var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
Object.extend(options, {
parameters: params,
onComplete: this._boundWrapperHandler,
onFailure: this._boundFailureHandler
});
new Ajax.Updater({ success: this.element }, this.url, options);
} else {
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: params,
onComplete: this._boundWrapperHandler,
onFailure: this._boundFailureHandler
});
new Ajax.Request(this.url, options);
}
if (e) Event.stop(e);
},
leaveEditMode: function() {
this.element.removeClassName(this.options.savingClassName);
this.removeForm();
this.leaveHover();
this.element.style.backgroundColor = this._originalBackground;
this.element.show();
if (this.options.externalControl)
this.options.externalControl.show();
this._saving = false;
this._editing = false;
this._oldInnerHTML = null;
this.triggerCallback('onLeaveEditMode');
},
leaveHover: function(e) {
if (this.options.hoverClassName)
this.element.removeClassName(this.options.hoverClassName);
if (this._saving) return;
this.triggerCallback('onLeaveHover');
},
loadExternalText: function() {
this._form.addClassName(this.options.loadingClassName);
this._controls.editor.disabled = true;
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
this._form.removeClassName(this.options.loadingClassName);
var text = transport.responseText;
if (this.options.stripLoadedTextTags)
text = text.stripTags();
this._controls.editor.value = text;
this._controls.editor.disabled = false;
this.postProcessEditField();
}.bind(this),
onFailure: this._boundFailureHandler
});
new Ajax.Request(this.options.loadTextURL, options);
},
postProcessEditField: function() {
var fpc = this.options.fieldPostCreation;
if (fpc)
$(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
},
prepareOptions: function() {
this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
[this._extraDefaultOptions].flatten().compact().each(function(defs) {
Object.extend(this.options, defs);
}.bind(this));
},
prepareSubmission: function() {
this._saving = true;
this.removeForm();
this.leaveHover();
this.showSaving();
},
registerListeners: function() {
this._listeners = { };
var listener;
$H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
listener = this[pair.value].bind(this);
this._listeners[pair.key] = listener;
if (!this.options.externalControlOnly)
this.element.observe(pair.key, listener);
if (this.options.externalControl)
this.options.externalControl.observe(pair.key, listener);
}.bind(this));
},
removeForm: function() {
if (!this._form) return;
this._form.remove();
this._form = null;
this._controls = { };
},
showSaving: function() {
this._oldInnerHTML = this.element.innerHTML;
this.element.innerHTML = this.options.savingText;
this.element.addClassName(this.options.savingClassName);
this.element.style.backgroundColor = this._originalBackground;
this.element.show();
},
triggerCallback: function(cbName, arg) {
if ('function' == typeof this.options[cbName]) {
this.options[cbName](this, arg);
}
},
unregisterListeners: function() {
$H(this._listeners).each(function(pair) {
if (!this.options.externalControlOnly)
this.element.stopObserving(pair.key, pair.value);
if (this.options.externalControl)
this.options.externalControl.stopObserving(pair.key, pair.value);
}.bind(this));
},
wrapUp: function(transport) {
this.leaveEditMode();
// Can't use triggerCallback due to backward compatibility: requires
// binding + direct element
this._boundComplete(transport, this.element);
}
});
Object.extend(Ajax.InPlaceEditor.prototype, {
dispose: Ajax.InPlaceEditor.prototype.destroy
});
Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
initialize: function($super, element, url, options) {
this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
$super(element, url, options);
},
createEditField: function() {
var list = document.createElement('select');
list.name = this.options.paramName;
list.size = 1;
this._controls.editor = list;
this._collection = this.options.collection || [];
if (this.options.loadCollectionURL)
this.loadCollection();
else
this.checkForExternalText();
this._form.appendChild(this._controls.editor);
},
loadCollection: function() {
this._form.addClassName(this.options.loadingClassName);
this.showLoadingText(this.options.loadingCollectionText);
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
var js = transport.responseText.strip();
if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
throw 'Server returned an invalid collection representation.';
this._collection = eval(js);
this.checkForExternalText();
}.bind(this),
onFailure: this.onFailure
});
new Ajax.Request(this.options.loadCollectionURL, options);
},
showLoadingText: function(text) {
this._controls.editor.disabled = true;
var tempOption = this._controls.editor.firstChild;
if (!tempOption) {
tempOption = document.createElement('option');
tempOption.value = '';
this._controls.editor.appendChild(tempOption);
tempOption.selected = true;
}
tempOption.update((text || '').stripScripts().stripTags());
},
checkForExternalText: function() {
this._text = this.getText();
if (this.options.loadTextURL)
this.loadExternalText();
else
this.buildOptionList();
},
loadExternalText: function() {
this.showLoadingText(this.options.loadingText);
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
this._text = transport.responseText.strip();
this.buildOptionList();
}.bind(this),
onFailure: this.onFailure
});
new Ajax.Request(this.options.loadTextURL, options);
},
buildOptionList: function() {
this._form.removeClassName(this.options.loadingClassName);
this._collection = this._collection.map(function(entry) {
return 2 === entry.length ? entry : [entry, entry].flatten();
});
var marker = ('value' in this.options) ? this.options.value : this._text;
var textFound = this._collection.any(function(entry) {
return entry[0] == marker;
}.bind(this));
this._controls.editor.update('');
var option;
this._collection.each(function(entry, index) {
option = document.createElement('option');
option.value = entry[0];
option.selected = textFound ? entry[0] == marker : 0 == index;
option.appendChild(document.createTextNode(entry[1]));
this._controls.editor.appendChild(option);
}.bind(this));
this._controls.editor.disabled = false;
Field.scrollFreeActivate(this._controls.editor);
}
});
//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
//**** This only exists for a while, in order to let ****
//**** users adapt to the new API. Read up on the new ****
//**** API and convert your code to it ASAP! ****
Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
if (!options) return;
function fallback(name, expr) {
if (name in options || expr === undefined) return;
options[name] = expr;
};
fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
options.cancelLink == options.cancelButton == false ? false : undefined)));
fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
options.okLink == options.okButton == false ? false : undefined)));
fallback('highlightColor', options.highlightcolor);
fallback('highlightEndColor', options.highlightendcolor);
};
Object.extend(Ajax.InPlaceEditor, {
DefaultOptions: {
ajaxOptions: { },
autoRows: 3, // Use when multi-line w/ rows == 1
cancelControl: 'link', // 'link'|'button'|false
cancelText: 'cancel',
clickToEditText: 'Click to edit',
externalControl: null, // id|elt
externalControlOnly: false,
fieldPostCreation: 'activate', // 'activate'|'focus'|false
formClassName: 'inplaceeditor-form',
formId: null, // id|elt
highlightColor: '#ffff99',
highlightEndColor: '#ffffff',
hoverClassName: '',
htmlResponse: true,
loadingClassName: 'inplaceeditor-loading',
loadingText: 'Loading...',
okControl: 'button', // 'link'|'button'|false
okText: 'ok',
paramName: 'value',
rows: 1, // If 1 and multi-line, uses autoRows
savingClassName: 'inplaceeditor-saving',
savingText: 'Saving...',
size: 0,
stripLoadedTextTags: false,
submitOnBlur: false,
textAfterControls: '',
textBeforeControls: '',
textBetweenControls: ''
},
DefaultCallbacks: {
callback: function(form) {
return Form.serialize(form);
},
onComplete: function(transport, element) {
// For backward compatibility, this one is bound to the IPE, and passes
// the element directly. It was too often customized, so we don't break it.
new Effect.Highlight(element, {
startcolor: this.options.highlightColor, keepBackgroundImage: true });
},
onEnterEditMode: null,
onEnterHover: function(ipe) {
ipe.element.style.backgroundColor = ipe.options.highlightColor;
if (ipe._effect)
ipe._effect.cancel();
},
onFailure: function(transport, ipe) {
alert('Error communication with the server: ' + transport.responseText.stripTags());
},
onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
onLeaveEditMode: null,
onLeaveHover: function(ipe) {
ipe._effect = new Effect.Highlight(ipe.element, {
startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
restorecolor: ipe._originalBackground, keepBackgroundImage: true
});
}
},
Listeners: {
click: 'enterEditMode',
keydown: 'checkForEscapeOrReturn',
mouseover: 'enterHover',
mouseout: 'leaveHover'
}
});
Ajax.InPlaceCollectionEditor.DefaultOptions = {
loadingCollectionText: 'Loading options...'
};
// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
Form.Element.DelayedObserver = Class.create({
initialize: function(element, delay, callback) {
this.delay = delay || 0.5;
this.element = $(element);
this.callback = callback;
this.timer = null;
this.lastValue = $F(this.element);
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
},
delayedListener: function(event) {
if(this.lastValue == $F(this.element)) return;
if(this.timer) clearTimeout(this.timer);
this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
this.lastValue = $F(this.element);
},
onTimerEvent: function() {
this.timer = null;
this.callback(this.element, $F(this.element));
}
});

View file

@ -1,974 +0,0 @@
// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
if(Object.isUndefined(Effect))
throw("dragdrop.js requires including script.aculo.us' effects.js library");
var Droppables = {
drops: [],
remove: function(element) {
this.drops = this.drops.reject(function(d) { return d.element==$(element) });
},
add: function(element) {
element = $(element);
var options = Object.extend({
greedy: true,
hoverclass: null,
tree: false
}, arguments[1] || { });
// cache containers
if(options.containment) {
options._containers = [];
var containment = options.containment;
if(Object.isArray(containment)) {
containment.each( function(c) { options._containers.push($(c)) });
} else {
options._containers.push($(containment));
}
}
if(options.accept) options.accept = [options.accept].flatten();
Element.makePositioned(element); // fix IE
options.element = element;
this.drops.push(options);
},
findDeepestChild: function(drops) {
deepest = drops[0];
for (i = 1; i < drops.length; ++i)
if (Element.isParent(drops[i].element, deepest.element))
deepest = drops[i];
return deepest;
},
isContained: function(element, drop) {
var containmentNode;
if(drop.tree) {
containmentNode = element.treeNode;
} else {
containmentNode = element.parentNode;
}
return drop._containers.detect(function(c) { return containmentNode == c });
},
isAffected: function(point, element, drop) {
return (
(drop.element!=element) &&
((!drop._containers) ||
this.isContained(element, drop)) &&
((!drop.accept) ||
(Element.classNames(element).detect(
function(v) { return drop.accept.include(v) } ) )) &&
Position.within(drop.element, point[0], point[1]) );
},
deactivate: function(drop) {
if(drop.hoverclass)
Element.removeClassName(drop.element, drop.hoverclass);
this.last_active = null;
},
activate: function(drop) {
if(drop.hoverclass)
Element.addClassName(drop.element, drop.hoverclass);
this.last_active = drop;
},
show: function(point, element) {
if(!this.drops.length) return;
var drop, affected = [];
this.drops.each( function(drop) {
if(Droppables.isAffected(point, element, drop))
affected.push(drop);
});
if(affected.length>0)
drop = Droppables.findDeepestChild(affected);
if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
if (drop) {
Position.within(drop.element, point[0], point[1]);
if(drop.onHover)
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
if (drop != this.last_active) Droppables.activate(drop);
}
},
fire: function(event, element) {
if(!this.last_active) return;
Position.prepare();
if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
if (this.last_active.onDrop) {
this.last_active.onDrop(element, this.last_active.element, event);
return true;
}
},
reset: function() {
if(this.last_active)
this.deactivate(this.last_active);
}
}
var Draggables = {
drags: [],
observers: [],
register: function(draggable) {
if(this.drags.length == 0) {
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
this.eventKeypress = this.keyPress.bindAsEventListener(this);
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
Event.observe(document, "keypress", this.eventKeypress);
}
this.drags.push(draggable);
},
unregister: function(draggable) {
this.drags = this.drags.reject(function(d) { return d==draggable });
if(this.drags.length == 0) {
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
Event.stopObserving(document, "keypress", this.eventKeypress);
}
},
activate: function(draggable) {
if(draggable.options.delay) {
this._timeout = setTimeout(function() {
Draggables._timeout = null;
window.focus();
Draggables.activeDraggable = draggable;
}.bind(this), draggable.options.delay);
} else {
window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
this.activeDraggable = draggable;
}
},
deactivate: function() {
this.activeDraggable = null;
},
updateDrag: function(event) {
if(!this.activeDraggable) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
// Mozilla-based browsers fire successive mousemove events with
// the same coordinates, prevent needless redrawing (moz bug?)
if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
this._lastPointer = pointer;
this.activeDraggable.updateDrag(event, pointer);
},
endDrag: function(event) {
if(this._timeout) {
clearTimeout(this._timeout);
this._timeout = null;
}
if(!this.activeDraggable) return;
this._lastPointer = null;
this.activeDraggable.endDrag(event);
this.activeDraggable = null;
},
keyPress: function(event) {
if(this.activeDraggable)
this.activeDraggable.keyPress(event);
},
addObserver: function(observer) {
this.observers.push(observer);
this._cacheObserverCallbacks();
},
removeObserver: function(element) { // element instead of observer fixes mem leaks
this.observers = this.observers.reject( function(o) { return o.element==element });
this._cacheObserverCallbacks();
},
notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
if(this[eventName+'Count'] > 0)
this.observers.each( function(o) {
if(o[eventName]) o[eventName](eventName, draggable, event);
});
if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
},
_cacheObserverCallbacks: function() {
['onStart','onEnd','onDrag'].each( function(eventName) {
Draggables[eventName+'Count'] = Draggables.observers.select(
function(o) { return o[eventName]; }
).length;
});
}
}
/*--------------------------------------------------------------------------*/
var Draggable = Class.create({
initialize: function(element) {
var defaults = {
handle: false,
reverteffect: function(element, top_offset, left_offset) {
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
queue: {scope:'_draggable', position:'end'}
});
},
endeffect: function(element) {
var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
queue: {scope:'_draggable', position:'end'},
afterFinish: function(){
Draggable._dragging[element] = false
}
});
},
zindex: 1000,
revert: false,
quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
delay: 0
};
if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
Object.extend(defaults, {
starteffect: function(element) {
element._opacity = Element.getOpacity(element);
Draggable._dragging[element] = true;
new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
}
});
var options = Object.extend(defaults, arguments[1] || { });
this.element = $(element);
if(options.handle && Object.isString(options.handle))
this.handle = this.element.down('.'+options.handle, 0);
if(!this.handle) this.handle = $(options.handle);
if(!this.handle) this.handle = this.element;
if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
options.scroll = $(options.scroll);
this._isScrollChild = Element.childOf(this.element, options.scroll);
}
Element.makePositioned(this.element); // fix IE
this.options = options;
this.dragging = false;
this.eventMouseDown = this.initDrag.bindAsEventListener(this);
Event.observe(this.handle, "mousedown", this.eventMouseDown);
Draggables.register(this);
},
destroy: function() {
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
Draggables.unregister(this);
},
currentDelta: function() {
return([
parseInt(Element.getStyle(this.element,'left') || '0'),
parseInt(Element.getStyle(this.element,'top') || '0')]);
},
initDrag: function(event) {
if(!Object.isUndefined(Draggable._dragging[this.element]) &&
Draggable._dragging[this.element]) return;
if(Event.isLeftClick(event)) {
// abort on form elements, fixes a Firefox issue
var src = Event.element(event);
if((tag_name = src.tagName.toUpperCase()) && (
tag_name=='INPUT' ||
tag_name=='SELECT' ||
tag_name=='OPTION' ||
tag_name=='BUTTON' ||
tag_name=='TEXTAREA')) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var pos = Position.cumulativeOffset(this.element);
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
Draggables.activate(this);
Event.stop(event);
}
},
startDrag: function(event) {
this.dragging = true;
if(!this.delta)
this.delta = this.currentDelta();
if(this.options.zindex) {
this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
this.element.style.zIndex = this.options.zindex;
}
if(this.options.ghosting) {
this._clone = this.element.cloneNode(true);
this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
if (!this.element._originallyAbsolute)
Position.absolutize(this.element);
this.element.parentNode.insertBefore(this._clone, this.element);
}
if(this.options.scroll) {
if (this.options.scroll == window) {
var where = this._getWindowScroll(this.options.scroll);
this.originalScrollLeft = where.left;
this.originalScrollTop = where.top;
} else {
this.originalScrollLeft = this.options.scroll.scrollLeft;
this.originalScrollTop = this.options.scroll.scrollTop;
}
}
Draggables.notify('onStart', this, event);
if(this.options.starteffect) this.options.starteffect(this.element);
},
updateDrag: function(event, pointer) {
if(!this.dragging) this.startDrag(event);
if(!this.options.quiet){
Position.prepare();
Droppables.show(pointer, this.element);
}
Draggables.notify('onDrag', this, event);
this.draw(pointer);
if(this.options.change) this.options.change(this);
if(this.options.scroll) {
this.stopScrolling();
var p;
if (this.options.scroll == window) {
with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
} else {
p = Position.page(this.options.scroll);
p[0] += this.options.scroll.scrollLeft + Position.deltaX;
p[1] += this.options.scroll.scrollTop + Position.deltaY;
p.push(p[0]+this.options.scroll.offsetWidth);
p.push(p[1]+this.options.scroll.offsetHeight);
}
var speed = [0,0];
if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
this.startScrolling(speed);
}
// fix AppleWebKit rendering
if(Prototype.Browser.WebKit) window.scrollBy(0,0);
Event.stop(event);
},
finishDrag: function(event, success) {
this.dragging = false;
if(this.options.quiet){
Position.prepare();
var pointer = [Event.pointerX(event), Event.pointerY(event)];
Droppables.show(pointer, this.element);
}
if(this.options.ghosting) {
if (!this.element._originallyAbsolute)
Position.relativize(this.element);
delete this.element._originallyAbsolute;
Element.remove(this._clone);
this._clone = null;
}
var dropped = false;
if(success) {
dropped = Droppables.fire(event, this.element);
if (!dropped) dropped = false;
}
if(dropped && this.options.onDropped) this.options.onDropped(this.element);
Draggables.notify('onEnd', this, event);
var revert = this.options.revert;
if(revert && Object.isFunction(revert)) revert = revert(this.element);
var d = this.currentDelta();
if(revert && this.options.reverteffect) {
if (dropped == 0 || revert != 'failure')
this.options.reverteffect(this.element,
d[1]-this.delta[1], d[0]-this.delta[0]);
} else {
this.delta = d;
}
if(this.options.zindex)
this.element.style.zIndex = this.originalZ;
if(this.options.endeffect)
this.options.endeffect(this.element);
Draggables.deactivate(this);
Droppables.reset();
},
keyPress: function(event) {
if(event.keyCode!=Event.KEY_ESC) return;
this.finishDrag(event, false);
Event.stop(event);
},
endDrag: function(event) {
if(!this.dragging) return;
this.stopScrolling();
this.finishDrag(event, true);
Event.stop(event);
},
draw: function(point) {
var pos = Position.cumulativeOffset(this.element);
if(this.options.ghosting) {
var r = Position.realOffset(this.element);
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
}
var d = this.currentDelta();
pos[0] -= d[0]; pos[1] -= d[1];
if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
}
var p = [0,1].map(function(i){
return (point[i]-pos[i]-this.offset[i])
}.bind(this));
if(this.options.snap) {
if(Object.isFunction(this.options.snap)) {
p = this.options.snap(p[0],p[1],this);
} else {
if(Object.isArray(this.options.snap)) {
p = p.map( function(v, i) {
return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
} else {
p = p.map( function(v) {
return (v/this.options.snap).round()*this.options.snap }.bind(this))
}
}}
var style = this.element.style;
if((!this.options.constraint) || (this.options.constraint=='horizontal'))
style.left = p[0] + "px";
if((!this.options.constraint) || (this.options.constraint=='vertical'))
style.top = p[1] + "px";
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
},
stopScrolling: function() {
if(this.scrollInterval) {
clearInterval(this.scrollInterval);
this.scrollInterval = null;
Draggables._lastScrollPointer = null;
}
},
startScrolling: function(speed) {
if(!(speed[0] || speed[1])) return;
this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
this.lastScrolled = new Date();
this.scrollInterval = setInterval(this.scroll.bind(this), 10);
},
scroll: function() {
var current = new Date();
var delta = current - this.lastScrolled;
this.lastScrolled = current;
if(this.options.scroll == window) {
with (this._getWindowScroll(this.options.scroll)) {
if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
var d = delta / 1000;
this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
}
}
} else {
this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
}
Position.prepare();
Droppables.show(Draggables._lastPointer, this.element);
Draggables.notify('onDrag', this);
if (this._isScrollChild) {
Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
if (Draggables._lastScrollPointer[0] < 0)
Draggables._lastScrollPointer[0] = 0;
if (Draggables._lastScrollPointer[1] < 0)
Draggables._lastScrollPointer[1] = 0;
this.draw(Draggables._lastScrollPointer);
}
if(this.options.change) this.options.change(this);
},
_getWindowScroll: function(w) {
var T, L, W, H;
with (w.document) {
if (w.document.documentElement && documentElement.scrollTop) {
T = documentElement.scrollTop;
L = documentElement.scrollLeft;
} else if (w.document.body) {
T = body.scrollTop;
L = body.scrollLeft;
}
if (w.innerWidth) {
W = w.innerWidth;
H = w.innerHeight;
} else if (w.document.documentElement && documentElement.clientWidth) {
W = documentElement.clientWidth;
H = documentElement.clientHeight;
} else {
W = body.offsetWidth;
H = body.offsetHeight
}
}
return { top: T, left: L, width: W, height: H };
}
});
Draggable._dragging = { };
/*--------------------------------------------------------------------------*/
var SortableObserver = Class.create({
initialize: function(element, observer) {
this.element = $(element);
this.observer = observer;
this.lastValue = Sortable.serialize(this.element);
},
onStart: function() {
this.lastValue = Sortable.serialize(this.element);
},
onEnd: function() {
Sortable.unmark();
if(this.lastValue != Sortable.serialize(this.element))
this.observer(this.element)
}
});
var Sortable = {
SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
sortables: { },
_findRootElement: function(element) {
while (element.tagName.toUpperCase() != "BODY") {
if(element.id && Sortable.sortables[element.id]) return element;
element = element.parentNode;
}
},
options: function(element) {
element = Sortable._findRootElement($(element));
if(!element) return;
return Sortable.sortables[element.id];
},
destroy: function(element){
var s = Sortable.options(element);
if(s) {
Draggables.removeObserver(s.element);
s.droppables.each(function(d){ Droppables.remove(d) });
s.draggables.invoke('destroy');
delete Sortable.sortables[s.element.id];
}
},
create: function(element) {
element = $(element);
var options = Object.extend({
element: element,
tag: 'li', // assumes li children, override with tag: 'tagname'
dropOnEmpty: false,
tree: false,
treeTag: 'ul',
overlap: 'vertical', // one of 'vertical', 'horizontal'
constraint: 'vertical', // one of 'vertical', 'horizontal', false
containment: element, // also takes array of elements (or id's); or false
handle: false, // or a CSS class
only: false,
delay: 0,
hoverclass: null,
ghosting: false,
quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
format: this.SERIALIZE_RULE,
// these take arrays of elements or ids and can be
// used for better initialization performance
elements: false,
handles: false,
onChange: Prototype.emptyFunction,
onUpdate: Prototype.emptyFunction
}, arguments[1] || { });
// clear any old sortable with same element
this.destroy(element);
// build options for the draggables
var options_for_draggable = {
revert: true,
quiet: options.quiet,
scroll: options.scroll,
scrollSpeed: options.scrollSpeed,
scrollSensitivity: options.scrollSensitivity,
delay: options.delay,
ghosting: options.ghosting,
constraint: options.constraint,
handle: options.handle };
if(options.starteffect)
options_for_draggable.starteffect = options.starteffect;
if(options.reverteffect)
options_for_draggable.reverteffect = options.reverteffect;
else
if(options.ghosting) options_for_draggable.reverteffect = function(element) {
element.style.top = 0;
element.style.left = 0;
};
if(options.endeffect)
options_for_draggable.endeffect = options.endeffect;
if(options.zindex)
options_for_draggable.zindex = options.zindex;
// build options for the droppables
var options_for_droppable = {
overlap: options.overlap,
containment: options.containment,
tree: options.tree,
hoverclass: options.hoverclass,
onHover: Sortable.onHover
}
var options_for_tree = {
onHover: Sortable.onEmptyHover,
overlap: options.overlap,
containment: options.containment,
hoverclass: options.hoverclass
}
// fix for gecko engine
Element.cleanWhitespace(element);
options.draggables = [];
options.droppables = [];
// drop on empty handling
if(options.dropOnEmpty || options.tree) {
Droppables.add(element, options_for_tree);
options.droppables.push(element);
}
(options.elements || this.findElements(element, options) || []).each( function(e,i) {
var handle = options.handles ? $(options.handles[i]) :
(options.handle ? $(e).select('.' + options.handle)[0] : e);
options.draggables.push(
new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
Droppables.add(e, options_for_droppable);
if(options.tree) e.treeNode = element;
options.droppables.push(e);
});
if(options.tree) {
(Sortable.findTreeElements(element, options) || []).each( function(e) {
Droppables.add(e, options_for_tree);
e.treeNode = element;
options.droppables.push(e);
});
}
// keep reference
this.sortables[element.id] = options;
// for onupdate
Draggables.addObserver(new SortableObserver(element, options.onUpdate));
},
// return all suitable-for-sortable elements in a guaranteed order
findElements: function(element, options) {
return Element.findChildren(
element, options.only, options.tree ? true : false, options.tag);
},
findTreeElements: function(element, options) {
return Element.findChildren(
element, options.only, options.tree ? true : false, options.treeTag);
},
onHover: function(element, dropon, overlap) {
if(Element.isParent(dropon, element)) return;
if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
return;
} else if(overlap>0.5) {
Sortable.mark(dropon, 'before');
if(dropon.previousSibling != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, dropon);
if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
} else {
Sortable.mark(dropon, 'after');
var nextElement = dropon.nextSibling || null;
if(nextElement != element) {
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, nextElement);
if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
}
},
onEmptyHover: function(element, dropon, overlap) {
var oldParentNode = element.parentNode;
var droponOptions = Sortable.options(dropon);
if(!Element.isParent(dropon, element)) {
var index;
var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
var child = null;
if(children) {
var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
for (index = 0; index < children.length; index += 1) {
if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
offset -= Element.offsetSize (children[index], droponOptions.overlap);
} else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
child = index + 1 < children.length ? children[index + 1] : null;
break;
} else {
child = children[index];
break;
}
}
}
dropon.insertBefore(element, child);
Sortable.options(oldParentNode).onChange(element);
droponOptions.onChange(element);
}
},
unmark: function() {
if(Sortable._marker) Sortable._marker.hide();
},
mark: function(dropon, position) {
// mark on ghosting only
var sortable = Sortable.options(dropon.parentNode);
if(sortable && !sortable.ghosting) return;
if(!Sortable._marker) {
Sortable._marker =
($('dropmarker') || Element.extend(document.createElement('DIV'))).
hide().addClassName('dropmarker').setStyle({position:'absolute'});
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
}
var offsets = Position.cumulativeOffset(dropon);
Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
if(position=='after')
if(sortable.overlap == 'horizontal')
Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
else
Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
Sortable._marker.show();
},
_tree: function(element, options, parent) {
var children = Sortable.findElements(element, options) || [];
for (var i = 0; i < children.length; ++i) {
var match = children[i].id.match(options.format);
if (!match) continue;
var child = {
id: encodeURIComponent(match ? match[1] : null),
element: element,
parent: parent,
children: [],
position: parent.children.length,
container: $(children[i]).down(options.treeTag)
}
/* Get the element containing the children and recurse over it */
if (child.container)
this._tree(child.container, options, child)
parent.children.push (child);
}
return parent;
},
tree: function(element) {
element = $(element);
var sortableOptions = this.options(element);
var options = Object.extend({
tag: sortableOptions.tag,
treeTag: sortableOptions.treeTag,
only: sortableOptions.only,
name: element.id,
format: sortableOptions.format
}, arguments[1] || { });
var root = {
id: null,
parent: null,
children: [],
container: element,
position: 0
}
return Sortable._tree(element, options, root);
},
/* Construct a [i] index for a particular node */
_constructIndex: function(node) {
var index = '';
do {
if (node.id) index = '[' + node.position + ']' + index;
} while ((node = node.parent) != null);
return index;
},
sequence: function(element) {
element = $(element);
var options = Object.extend(this.options(element), arguments[1] || { });
return $(this.findElements(element, options) || []).map( function(item) {
return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
});
},
setSequence: function(element, new_sequence) {
element = $(element);
var options = Object.extend(this.options(element), arguments[2] || { });
var nodeMap = { };
this.findElements(element, options).each( function(n) {
if (n.id.match(options.format))
nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
n.parentNode.removeChild(n);
});
new_sequence.each(function(ident) {
var n = nodeMap[ident];
if (n) {
n[1].appendChild(n[0]);
delete nodeMap[ident];
}
});
},
serialize: function(element) {
element = $(element);
var options = Object.extend(Sortable.options(element), arguments[1] || { });
var name = encodeURIComponent(
(arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
if (options.tree) {
return Sortable.tree(element, arguments[1]).children.map( function (item) {
return [name + Sortable._constructIndex(item) + "[id]=" +
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
}).flatten().join('&');
} else {
return Sortable.sequence(element, arguments[1]).map( function(item) {
return name + "[]=" + encodeURIComponent(item);
}).join('&');
}
}
}
// Returns true if child is contained within element
Element.isParent = function(child, element) {
if (!child.parentNode || child == element) return false;
if (child.parentNode == element) return true;
return Element.isParent(child.parentNode, element);
}
Element.findChildren = function(element, only, recursive, tagName) {
if(!element.hasChildNodes()) return null;
tagName = tagName.toUpperCase();
if(only) only = [only].flatten();
var elements = [];
$A(element.childNodes).each( function(e) {
if(e.tagName && e.tagName.toUpperCase()==tagName &&
(!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
elements.push(e);
if(recursive) {
var grandchildren = Element.findChildren(e, only, recursive, tagName);
if(grandchildren) elements.push(grandchildren);
}
});
return (elements.length>0 ? elements.flatten() : []);
}
Element.offsetSize = function (element, type) {
return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
}

File diff suppressed because it is too large Load diff

View file

@ -1,58 +0,0 @@
// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Scriptaculous = {
Version: '1.8.1',
require: function(libraryName) {
// inserting via DOM fails in Safari 2.0, so brute force approach
document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
},
REQUIRED_PROTOTYPE: '1.6.0',
load: function() {
function convertVersionString(versionString){
var r = versionString.split('.');
return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
}
if((typeof Prototype=='undefined') ||
(typeof Element == 'undefined') ||
(typeof Element.Methods=='undefined') ||
(convertVersionString(Prototype.Version) <
convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
throw("script.aculo.us requires the Prototype JavaScript framework >= " +
Scriptaculous.REQUIRED_PROTOTYPE);
$A(document.getElementsByTagName("script")).findAll( function(s) {
return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
}).each( function(s) {
var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
var includes = s.src.match(/\?.*load=([a-z,]*)/);
(includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
function(include) { Scriptaculous.require(path+include+'.js') });
});
}
}
Scriptaculous.load();

View file

@ -1,275 +0,0 @@
// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
if (!Control) var Control = { };
// options:
// axis: 'vertical', or 'horizontal' (default)
//
// callbacks:
// onChange(value)
// onSlide(value)
Control.Slider = Class.create({
initialize: function(handle, track, options) {
var slider = this;
if (Object.isArray(handle)) {
this.handles = handle.collect( function(e) { return $(e) });
} else {
this.handles = [$(handle)];
}
this.track = $(track);
this.options = options || { };
this.axis = this.options.axis || 'horizontal';
this.increment = this.options.increment || 1;
this.step = parseInt(this.options.step || '1');
this.range = this.options.range || $R(0,1);
this.value = 0; // assure backwards compat
this.values = this.handles.map( function() { return 0 });
this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
this.options.startSpan = $(this.options.startSpan || null);
this.options.endSpan = $(this.options.endSpan || null);
this.restricted = this.options.restricted || false;
this.maximum = this.options.maximum || this.range.end;
this.minimum = this.options.minimum || this.range.start;
// Will be used to align the handle onto the track, if necessary
this.alignX = parseInt(this.options.alignX || '0');
this.alignY = parseInt(this.options.alignY || '0');
this.trackLength = this.maximumOffset() - this.minimumOffset();
this.handleLength = this.isVertical() ?
(this.handles[0].offsetHeight != 0 ?
this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
(this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
this.handles[0].style.width.replace(/px$/,""));
this.active = false;
this.dragging = false;
this.disabled = false;
if (this.options.disabled) this.setDisabled();
// Allowed values array
this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
if (this.allowedValues) {
this.minimum = this.allowedValues.min();
this.maximum = this.allowedValues.max();
}
this.eventMouseDown = this.startDrag.bindAsEventListener(this);
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.update.bindAsEventListener(this);
// Initialize handles in reverse (make sure first handle is active)
this.handles.each( function(h,i) {
i = slider.handles.length-1-i;
slider.setValue(parseFloat(
(Object.isArray(slider.options.sliderValue) ?
slider.options.sliderValue[i] : slider.options.sliderValue) ||
slider.range.start), i);
h.makePositioned().observe("mousedown", slider.eventMouseDown);
});
this.track.observe("mousedown", this.eventMouseDown);
document.observe("mouseup", this.eventMouseUp);
document.observe("mousemove", this.eventMouseMove);
this.initialized = true;
},
dispose: function() {
var slider = this;
Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
this.handles.each( function(h) {
Event.stopObserving(h, "mousedown", slider.eventMouseDown);
});
},
setDisabled: function(){
this.disabled = true;
},
setEnabled: function(){
this.disabled = false;
},
getNearestValue: function(value){
if (this.allowedValues){
if (value >= this.allowedValues.max()) return(this.allowedValues.max());
if (value <= this.allowedValues.min()) return(this.allowedValues.min());
var offset = Math.abs(this.allowedValues[0] - value);
var newValue = this.allowedValues[0];
this.allowedValues.each( function(v) {
var currentOffset = Math.abs(v - value);
if (currentOffset <= offset){
newValue = v;
offset = currentOffset;
}
});
return newValue;
}
if (value > this.range.end) return this.range.end;
if (value < this.range.start) return this.range.start;
return value;
},
setValue: function(sliderValue, handleIdx){
if (!this.active) {
this.activeHandleIdx = handleIdx || 0;
this.activeHandle = this.handles[this.activeHandleIdx];
this.updateStyles();
}
handleIdx = handleIdx || this.activeHandleIdx || 0;
if (this.initialized && this.restricted) {
if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
sliderValue = this.values[handleIdx-1];
if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
sliderValue = this.values[handleIdx+1];
}
sliderValue = this.getNearestValue(sliderValue);
this.values[handleIdx] = sliderValue;
this.value = this.values[0]; // assure backwards compat
this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
this.translateToPx(sliderValue);
this.drawSpans();
if (!this.dragging || !this.event) this.updateFinished();
},
setValueBy: function(delta, handleIdx) {
this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
handleIdx || this.activeHandleIdx || 0);
},
translateToPx: function(value) {
return Math.round(
((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
(value - this.range.start)) + "px";
},
translateToValue: function(offset) {
return ((offset/(this.trackLength-this.handleLength) *
(this.range.end-this.range.start)) + this.range.start);
},
getRange: function(range) {
var v = this.values.sortBy(Prototype.K);
range = range || 0;
return $R(v[range],v[range+1]);
},
minimumOffset: function(){
return(this.isVertical() ? this.alignY : this.alignX);
},
maximumOffset: function(){
return(this.isVertical() ?
(this.track.offsetHeight != 0 ? this.track.offsetHeight :
this.track.style.height.replace(/px$/,"")) - this.alignY :
(this.track.offsetWidth != 0 ? this.track.offsetWidth :
this.track.style.width.replace(/px$/,"")) - this.alignX);
},
isVertical: function(){
return (this.axis == 'vertical');
},
drawSpans: function() {
var slider = this;
if (this.spans)
$R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
if (this.options.startSpan)
this.setSpan(this.options.startSpan,
$R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
if (this.options.endSpan)
this.setSpan(this.options.endSpan,
$R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
},
setSpan: function(span, range) {
if (this.isVertical()) {
span.style.top = this.translateToPx(range.start);
span.style.height = this.translateToPx(range.end - range.start + this.range.start);
} else {
span.style.left = this.translateToPx(range.start);
span.style.width = this.translateToPx(range.end - range.start + this.range.start);
}
},
updateStyles: function() {
this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
Element.addClassName(this.activeHandle, 'selected');
},
startDrag: function(event) {
if (Event.isLeftClick(event)) {
if (!this.disabled){
this.active = true;
var handle = Event.element(event);
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var track = handle;
if (track==this.track) {
var offsets = Position.cumulativeOffset(this.track);
this.event = event;
this.setValue(this.translateToValue(
(this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
));
var offsets = Position.cumulativeOffset(this.activeHandle);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
} else {
// find the handle (prevents issues with Safari)
while((this.handles.indexOf(handle) == -1) && handle.parentNode)
handle = handle.parentNode;
if (this.handles.indexOf(handle)!=-1) {
this.activeHandle = handle;
this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
this.updateStyles();
var offsets = Position.cumulativeOffset(this.activeHandle);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
}
}
}
Event.stop(event);
}
},
update: function(event) {
if (this.active) {
if (!this.dragging) this.dragging = true;
this.draw(event);
if (Prototype.Browser.WebKit) window.scrollBy(0,0);
Event.stop(event);
}
},
draw: function(event) {
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var offsets = Position.cumulativeOffset(this.track);
pointer[0] -= this.offsetX + offsets[0];
pointer[1] -= this.offsetY + offsets[1];
this.event = event;
this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
if (this.initialized && this.options.onSlide)
this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
},
endDrag: function(event) {
if (this.active && this.dragging) {
this.finishDrag(event, true);
Event.stop(event);
}
this.active = false;
this.dragging = false;
},
finishDrag: function(event, success) {
this.active = false;
this.dragging = false;
this.updateFinished();
},
updateFinished: function() {
if (this.initialized && this.options.onChange)
this.options.onChange(this.values.length>1 ? this.values : this.value, this);
this.event = null;
}
});

View file

@ -1,55 +0,0 @@
// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Based on code created by Jules Gravinese (http://www.webveteran.com/)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
Sound = {
tracks: {},
_enabled: true,
template:
new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
enable: function(){
Sound._enabled = true;
},
disable: function(){
Sound._enabled = false;
},
play: function(url){
if(!Sound._enabled) return;
var options = Object.extend({
track: 'global', url: url, replace: false
}, arguments[1] || {});
if(options.replace && this.tracks[options.track]) {
$R(0, this.tracks[options.track].id).each(function(id){
var sound = $('sound_'+options.track+'_'+id);
sound.Stop && sound.Stop();
sound.remove();
})
this.tracks[options.track] = null;
}
if(!this.tracks[options.track])
this.tracks[options.track] = { id: 0 }
else
this.tracks[options.track].id++;
options.id = this.tracks[options.track].id;
$$('body')[0].insert(
Prototype.Browser.IE ? new Element('bgsound',{
id: 'sound_'+options.track+'_'+options.id,
src: options.url, loop: 1, autostart: true
}) : Sound.template.evaluate(options));
}
};
if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
else
Sound.play = function(){}
}

View file

@ -1,568 +0,0 @@
// script.aculo.us unittest.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
// (c) 2005-2007 Michael Schuerig (http://www.schuerig.de/michael/)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// experimental, Firefox-only
Event.simulateMouse = function(element, eventName) {
var options = Object.extend({
pointerX: 0,
pointerY: 0,
buttons: 0,
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false
}, arguments[2] || {});
var oEvent = document.createEvent("MouseEvents");
oEvent.initMouseEvent(eventName, true, true, document.defaultView,
options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element));
if(this.mark) Element.remove(this.mark);
this.mark = document.createElement('div');
this.mark.appendChild(document.createTextNode(" "));
document.body.appendChild(this.mark);
this.mark.style.position = 'absolute';
this.mark.style.top = options.pointerY + "px";
this.mark.style.left = options.pointerX + "px";
this.mark.style.width = "5px";
this.mark.style.height = "5px;";
this.mark.style.borderTop = "1px solid red;"
this.mark.style.borderLeft = "1px solid red;"
if(this.step)
alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
$(element).dispatchEvent(oEvent);
};
// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
// You need to downgrade to 1.0.4 for now to get this working
// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
Event.simulateKey = function(element, eventName) {
var options = Object.extend({
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false,
keyCode: 0,
charCode: 0
}, arguments[2] || {});
var oEvent = document.createEvent("KeyEvents");
oEvent.initKeyEvent(eventName, true, true, window,
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
options.keyCode, options.charCode );
$(element).dispatchEvent(oEvent);
};
Event.simulateKeys = function(element, command) {
for(var i=0; i<command.length; i++) {
Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
}
};
var Test = {}
Test.Unit = {};
// security exception workaround
Test.Unit.inspect = Object.inspect;
Test.Unit.Logger = Class.create();
Test.Unit.Logger.prototype = {
initialize: function(log) {
this.log = $(log);
if (this.log) {
this._createLogTable();
}
},
start: function(testName) {
if (!this.log) return;
this.testName = testName;
this.lastLogLine = document.createElement('tr');
this.statusCell = document.createElement('td');
this.nameCell = document.createElement('td');
this.nameCell.className = "nameCell";
this.nameCell.appendChild(document.createTextNode(testName));
this.messageCell = document.createElement('td');
this.lastLogLine.appendChild(this.statusCell);
this.lastLogLine.appendChild(this.nameCell);
this.lastLogLine.appendChild(this.messageCell);
this.loglines.appendChild(this.lastLogLine);
},
finish: function(status, summary) {
if (!this.log) return;
this.lastLogLine.className = status;
this.statusCell.innerHTML = status;
this.messageCell.innerHTML = this._toHTML(summary);
this.addLinksToResults();
},
message: function(message) {
if (!this.log) return;
this.messageCell.innerHTML = this._toHTML(message);
},
summary: function(summary) {
if (!this.log) return;
this.logsummary.innerHTML = this._toHTML(summary);
},
_createLogTable: function() {
this.log.innerHTML =
'<div id="logsummary"></div>' +
'<table id="logtable">' +
'<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
'<tbody id="loglines"></tbody>' +
'</table>';
this.logsummary = $('logsummary')
this.loglines = $('loglines');
},
_toHTML: function(txt) {
return txt.escapeHTML().replace(/\n/g,"<br/>");
},
addLinksToResults: function(){
$$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
td.title = "Run only this test"
Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
});
$$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
td.title = "Run all tests"
Event.observe(td, 'click', function(){ window.location.search = "";});
});
}
}
Test.Unit.Runner = Class.create();
Test.Unit.Runner.prototype = {
initialize: function(testcases) {
this.options = Object.extend({
testLog: 'testlog'
}, arguments[1] || {});
this.options.resultsURL = this.parseResultsURLQueryParameter();
this.options.tests = this.parseTestsQueryParameter();
if (this.options.testLog) {
this.options.testLog = $(this.options.testLog) || null;
}
if(this.options.tests) {
this.tests = [];
for(var i = 0; i < this.options.tests.length; i++) {
if(/^test/.test(this.options.tests[i])) {
this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
}
}
} else {
if (this.options.test) {
this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
} else {
this.tests = [];
for(var testcase in testcases) {
if(/^test/.test(testcase)) {
this.tests.push(
new Test.Unit.Testcase(
this.options.context ? ' -> ' + this.options.titles[testcase] : testcase,
testcases[testcase], testcases["setup"], testcases["teardown"]
));
}
}
}
}
this.currentTest = 0;
this.logger = new Test.Unit.Logger(this.options.testLog);
setTimeout(this.runTests.bind(this), 1000);
},
parseResultsURLQueryParameter: function() {
return window.location.search.parseQuery()["resultsURL"];
},
parseTestsQueryParameter: function(){
if (window.location.search.parseQuery()["tests"]){
return window.location.search.parseQuery()["tests"].split(',');
};
},
// Returns:
// "ERROR" if there was an error,
// "FAILURE" if there was a failure, or
// "SUCCESS" if there was neither
getResult: function() {
var hasFailure = false;
for(var i=0;i<this.tests.length;i++) {
if (this.tests[i].errors > 0) {
return "ERROR";
}
if (this.tests[i].failures > 0) {
hasFailure = true;
}
}
if (hasFailure) {
return "FAILURE";
} else {
return "SUCCESS";
}
},
postResults: function() {
if (this.options.resultsURL) {
new Ajax.Request(this.options.resultsURL,
{ method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
}
},
runTests: function() {
var test = this.tests[this.currentTest];
if (!test) {
// finished!
this.postResults();
this.logger.summary(this.summary());
return;
}
if(!test.isWaiting) {
this.logger.start(test.name);
}
test.run();
if(test.isWaiting) {
this.logger.message("Waiting for " + test.timeToWait + "ms");
setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
} else {
this.logger.finish(test.status(), test.summary());
this.currentTest++;
// tail recursive, hopefully the browser will skip the stackframe
this.runTests();
}
},
summary: function() {
var assertions = 0;
var failures = 0;
var errors = 0;
var messages = [];
for(var i=0;i<this.tests.length;i++) {
assertions += this.tests[i].assertions;
failures += this.tests[i].failures;
errors += this.tests[i].errors;
}
return (
(this.options.context ? this.options.context + ': ': '') +
this.tests.length + " tests, " +
assertions + " assertions, " +
failures + " failures, " +
errors + " errors");
}
}
Test.Unit.Assertions = Class.create();
Test.Unit.Assertions.prototype = {
initialize: function() {
this.assertions = 0;
this.failures = 0;
this.errors = 0;
this.messages = [];
},
summary: function() {
return (
this.assertions + " assertions, " +
this.failures + " failures, " +
this.errors + " errors" + "\n" +
this.messages.join("\n"));
},
pass: function() {
this.assertions++;
},
fail: function(message) {
this.failures++;
this.messages.push("Failure: " + message);
},
info: function(message) {
this.messages.push("Info: " + message);
},
error: function(error) {
this.errors++;
this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
},
status: function() {
if (this.failures > 0) return 'failed';
if (this.errors > 0) return 'error';
return 'passed';
},
assert: function(expression) {
var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
try { expression ? this.pass() :
this.fail(message); }
catch(e) { this.error(e); }
},
assertEqual: function(expected, actual) {
var message = arguments[2] || "assertEqual";
try { (expected == actual) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertInspect: function(expected, actual) {
var message = arguments[2] || "assertInspect";
try { (expected == actual.inspect()) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertEnumEqual: function(expected, actual) {
var message = arguments[2] || "assertEnumEqual";
try { $A(expected).length == $A(actual).length &&
expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) +
', actual ' + Test.Unit.inspect(actual)); }
catch(e) { this.error(e); }
},
assertNotEqual: function(expected, actual) {
var message = arguments[2] || "assertNotEqual";
try { (expected != actual) ? this.pass() :
this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertIdentical: function(expected, actual) {
var message = arguments[2] || "assertIdentical";
try { (expected === actual) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertNotIdentical: function(expected, actual) {
var message = arguments[2] || "assertNotIdentical";
try { !(expected === actual) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertNull: function(obj) {
var message = arguments[1] || 'assertNull'
try { (obj==null) ? this.pass() :
this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
catch(e) { this.error(e); }
},
assertMatch: function(expected, actual) {
var message = arguments[2] || 'assertMatch';
var regex = new RegExp(expected);
try { (regex.exec(actual)) ? this.pass() :
this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); }
catch(e) { this.error(e); }
},
assertHidden: function(element) {
var message = arguments[1] || 'assertHidden';
this.assertEqual("none", element.style.display, message);
},
assertNotNull: function(object) {
var message = arguments[1] || 'assertNotNull';
this.assert(object != null, message);
},
assertType: function(expected, actual) {
var message = arguments[2] || 'assertType';
try {
(actual.constructor == expected) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + (actual.constructor) + '"'); }
catch(e) { this.error(e); }
},
assertNotOfType: function(expected, actual) {
var message = arguments[2] || 'assertNotOfType';
try {
(actual.constructor != expected) ? this.pass() :
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
'", actual "' + (actual.constructor) + '"'); }
catch(e) { this.error(e); }
},
assertInstanceOf: function(expected, actual) {
var message = arguments[2] || 'assertInstanceOf';
try {
(actual instanceof expected) ? this.pass() :
this.fail(message + ": object was not an instance of the expected type"); }
catch(e) { this.error(e); }
},
assertNotInstanceOf: function(expected, actual) {
var message = arguments[2] || 'assertNotInstanceOf';
try {
!(actual instanceof expected) ? this.pass() :
this.fail(message + ": object was an instance of the not expected type"); }
catch(e) { this.error(e); }
},
assertRespondsTo: function(method, obj) {
var message = arguments[2] || 'assertRespondsTo';
try {
(obj[method] && typeof obj[method] == 'function') ? this.pass() :
this.fail(message + ": object doesn't respond to [" + method + "]"); }
catch(e) { this.error(e); }
},
assertReturnsTrue: function(method, obj) {
var message = arguments[2] || 'assertReturnsTrue';
try {
var m = obj[method];
if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
m() ? this.pass() :
this.fail(message + ": method returned false"); }
catch(e) { this.error(e); }
},
assertReturnsFalse: function(method, obj) {
var message = arguments[2] || 'assertReturnsFalse';
try {
var m = obj[method];
if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
!m() ? this.pass() :
this.fail(message + ": method returned true"); }
catch(e) { this.error(e); }
},
assertRaise: function(exceptionName, method) {
var message = arguments[2] || 'assertRaise';
try {
method();
this.fail(message + ": exception expected but none was raised"); }
catch(e) {
((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e);
}
},
assertElementsMatch: function() {
var expressions = $A(arguments), elements = $A(expressions.shift());
if (elements.length != expressions.length) {
this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions');
return false;
}
elements.zip(expressions).all(function(pair, index) {
var element = $(pair.first()), expression = pair.last();
if (element.match(expression)) return true;
this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect());
}.bind(this)) && this.pass();
},
assertElementMatches: function(element, expression) {
this.assertElementsMatch([element], expression);
},
benchmark: function(operation, iterations) {
var startAt = new Date();
(iterations || 1).times(operation);
var timeTaken = ((new Date())-startAt);
this.info((arguments[2] || 'Operation') + ' finished ' +
iterations + ' iterations in ' + (timeTaken/1000)+'s' );
return timeTaken;
},
_isVisible: function(element) {
element = $(element);
if(!element.parentNode) return true;
this.assertNotNull(element);
if(element.style && Element.getStyle(element, 'display') == 'none')
return false;
return this._isVisible(element.parentNode);
},
assertNotVisible: function(element) {
this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
},
assertVisible: function(element) {
this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
},
benchmark: function(operation, iterations) {
var startAt = new Date();
(iterations || 1).times(operation);
var timeTaken = ((new Date())-startAt);
this.info((arguments[2] || 'Operation') + ' finished ' +
iterations + ' iterations in ' + (timeTaken/1000)+'s' );
return timeTaken;
}
}
Test.Unit.Testcase = Class.create();
Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
initialize: function(name, test, setup, teardown) {
Test.Unit.Assertions.prototype.initialize.bind(this)();
this.name = name;
if(typeof test == 'string') {
test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,');
test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)');
this.test = function() {
eval('with(this){'+test+'}');
}
} else {
this.test = test || function() {};
}
this.setup = setup || function() {};
this.teardown = teardown || function() {};
this.isWaiting = false;
this.timeToWait = 1000;
},
wait: function(time, nextPart) {
this.isWaiting = true;
this.test = nextPart;
this.timeToWait = time;
},
run: function() {
try {
try {
if (!this.isWaiting) this.setup.bind(this)();
this.isWaiting = false;
this.test.bind(this)();
} finally {
if(!this.isWaiting) {
this.teardown.bind(this)();
}
}
}
catch(e) { this.error(e); }
}
});
// *EXPERIMENTAL* BDD-style testing to please non-technical folk
// This draws many ideas from RSpec http://rspec.rubyforge.org/
Test.setupBDDExtensionMethods = function(){
var METHODMAP = {
shouldEqual: 'assertEqual',
shouldNotEqual: 'assertNotEqual',
shouldEqualEnum: 'assertEnumEqual',
shouldBeA: 'assertType',
shouldNotBeA: 'assertNotOfType',
shouldBeAn: 'assertType',
shouldNotBeAn: 'assertNotOfType',
shouldBeNull: 'assertNull',
shouldNotBeNull: 'assertNotNull',
shouldBe: 'assertReturnsTrue',
shouldNotBe: 'assertReturnsFalse',
shouldRespondTo: 'assertRespondsTo'
};
var makeAssertion = function(assertion, args, object) {
this[assertion].apply(this,(args || []).concat([object]));
}
Test.BDDMethods = {};
$H(METHODMAP).each(function(pair) {
Test.BDDMethods[pair.key] = function() {
var args = $A(arguments);
var scope = args.shift();
makeAssertion.apply(scope, [pair.value, args, this]); };
});
[Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
function(p){ Object.extend(p, Test.BDDMethods) }
);
}
Test.context = function(name, spec, log){
Test.setupBDDExtensionMethods();
var compiledSpec = {};
var titles = {};
for(specName in spec) {
switch(specName){
case "setup":
case "teardown":
compiledSpec[specName] = spec[specName];
break;
default:
var testName = 'test'+specName.gsub(/\s+/,'-').camelize();
var body = spec[specName].toString().split('\n').slice(1);
if(/^\{/.test(body[0])) body = body.slice(1);
body.pop();
body = body.map(function(statement){
return statement.strip()
});
compiledSpec[testName] = body.join('\n');
titles[testName] = specName;
}
}
new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name });
};

View file

@ -1,40 +1,76 @@
<?php <?php
if( count($_POST) ){ // second call $baseURL = "http://ajax.googleapis.com/ajax/libs/";
$libraries = array(
"Dojo" => array(
"versions" => array( "1.1.1", "1.2.0", "1.2.3", "1.3.0", "1.3.1", "1.3.2", "1.4.0", "1.4.1", "1.4.3", "1.5.0" ),
"url" => "dojo/XYZ/dojo/dojo.xd.js"
),
"ExtCore" => array(
"versions" => array( "3.0.0", "3.1.0" ),
"url" => "ext-core/XYZ/ext-core.js"
),
"jQuery" => array(
"versions" => array( "1.2.3", "1.2.6", "1.3.0", "1.3.1", "1.3.2", "1.4.0", "1.4.1", "1.4.2", "1.4.3", "1.4.4", "1.5.0" ),
"url" => "jquery/XYZ/jquery.min.js"
),
"jQueryUI" => array(
"versions" => array( "1.5.2", "1.5.3", "1.6.0", "1.7.0", "1.7.1", "1.7.2", "1.7.3", "1.8.0", "1.8.1", "1.8.2", "1.8.4", "1.8.5", "1.8.6", "1.8.7", "1.8.8", "1.8.9" ),
"url" => "jqueryui/XYZ/jquery-ui.min.js"
),
"MooTools" => array(
"versions" => array( "1.1.1", "1.1.2", "1.2.1", "1.2.2", "1.2.3", "1.2.4", "1.2.5", "1.3.0" ),
"url" => "mootools/XYZ/mootools-yui-compressed.js"
),
"Prototype" => array(
"versions" => array( "1.6.0.2", "1.6.0.3", "1.6.1.0", "1.7.0.0" ),
"url" => "prototype/XYZ/prototype.js"
),
"scriptaculous" => array(
"versions" => array( "1.8.1", "1.8.2", "1.8.3" ),
"url" => "scriptaculous/XYZ/scriptaculous.js"
),
"SWFObject" => array(
"versions" => array( "2.1", "2.2" ),
"url" => "swfobject/XYZ/swfobject.js"
),
"YUI" => array(
"versions" => array( "2.6.0", "2.7.0", "2.8.0r4", "2.8.1", "2.8.2", "3.3.0" ),
"url" => "yui/XYZ/build/yui/yui-min.js"
)
);
if( count($_POST) ) {
$includes = array(); $includes = array();
foreach( $_POST as $lib=>$ver ){ foreach( $_POST as $name => $ver ){
if( !$ver ) $url = $libraries[ $name ][ "url" ];
continue; if( $name == "YUI" && $ver[0] == "2" ) {
$include = "<script type='text/javascript' src='otherlibs/$lib/$ver/$lib.js'></script>\n"; $url = str_replace( "/yui", "/yuiloader", $url, $count = 2 );
if( $lib == 'prototype' ) // prototype must be included first }
$include = "<script src='$baseURL".str_replace("XYZ", $ver, $url, $count = 1)."'></script>\n";
if( $lib == "prototype" ) { // prototype must be included first
array_unshift( $includes, $include ); array_unshift( $includes, $include );
else } else {
array_push( $includes, $include ); array_push( $includes, $include );
}
} }
$includes = implode( "\n", $includes ); $includes = implode( "\n", $includes );
$suite = file_get_contents('index.html'); $suite = file_get_contents( "index.html" );
echo str_replace( '<!-- Includes -->', $includes, $suite ); echo str_replace( "<!-- Includes -->", $includes, $suite );
exit; exit;
} }
?> ?>
<!DOCTYPE html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr" id="html">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>jQuery Test Suite</title> <title>Run jQuery Test Suite Polluted</title>
<link rel="Stylesheet" media="screen" href="qunit/testsuite.css" />
<link rel="Stylesheet" media="screen" href="data/otherlibs.css" />
<style type="text/css"> <style type="text/css">
form.otherlibs{ .otherlibs fieldset {
margin: 20px 0 0 30px; width: 400px
} }
form.otherlibs label{ .otherlibs label{
display:block; margin: 5px 0px 5px 20px;
margin: 5px 0 5px 30px;
}
form.otherlibs input.submit{
margin:30px 0 0 0;
} }
</style> </style>
</head> </head>
@ -44,21 +80,20 @@
<h2 id="banner" class="fail"></h2> <h2 id="banner" class="fail"></h2>
<h2 id="userAgent">Choose other libraries to include</h2> <h2 id="userAgent">Choose other libraries to include</h2>
<form class="otherlibs" action="" method="post"> <form class="otherlibs" action="./polluted.php" method="POST">
<?php <?php
$libs = scandir('otherlibs'); foreach( $libraries as $name => $data ) {
foreach( $libs as $lib ){ echo "<fieldset><legend>$name</legend>";
if( $lib[0] == '.' ) $i = 0;
continue; foreach( $data[ "versions" ] as $ver ) {
echo "<h3>$lib</h3>"; $i++;
$vers = scandir( "otherlibs/$lib"); echo "<label><input type='radio' name='$name' value='$ver' />$ver</label>";
foreach( $vers as $ver ){ if( !($i % 4) ) echo "<br />";
if( $ver[0] != '.' )
echo "<label><input type='checkbox' name='$lib' value='$ver'>$ver</label>";
} }
echo "</fieldset>";
} }
?> ?>
<input type="submit" value="Run" class="submit" /> <input type="submit" value=" Run " class="submit" />
</form> </form>
</body> </body>
</html> </html>

85
test/readywait.html Normal file
View file

@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<!--
Test for jQuery.readyWait. Needs to be a
standalone test since it deals with DOM
ready.
-->
<head>
<title>
jQuery.readyWait Test
</title>
<style>
div { margin-top: 10px; }
#output { background-color: green }
#expectedOutput { background-color: green }
</style>
<script src="../src/core.js"></script>
<script src="../src/support.js"></script>
<script src="../src/data.js"></script>
<script src="../src/queue.js"></script>
<script src="../src/attributes.js"></script>
<script src="../src/event.js"></script>
<script src="../src/sizzle/sizzle.js"></script>
<script src="../src/sizzle-jquery.js"></script>
<script src="../src/traversing.js"></script>
<script src="../src/manipulation.js"></script>
<script src="../src/css.js"></script>
<script src="../src/ajax.js"></script>
<script src="../src/ajax/jsonp.js"></script>
<script src="../src/ajax/script.js"></script>
<script src="../src/ajax/xhr.js"></script>
<script src="../src/effects.js"></script>
<script src="../src/offset.js"></script>
<script src="../src/dimensions.js"></script>
<!-- Load the script loader that uses
jQuery.readyWait -->
<script src="data/readywaitloader.js"></script>
<script type="text/javascript">
jQuery(function() {
// The delayedMessage is defined by
// the readywaitasset.js file, so the
// next line will only work if this DOM
// ready callback is called after readyWait
// has been decremented by readywaitloader.js
// If an error occurs.
jQuery("#output").append(delayedMessage);
});
</script>
</head>
<body>
<h1>
jQuery.readyWait Test
</h1>
<p>
This is a test page for jQuery.readyWait, that was
added due to this ticket
<a href="http://bugs.jquery.com/ticket/6781">#6781</a>.
</p>
<p>
Test for jQuery.readyWait, which can be used
by plugins and other scripts to indicate something
important to the page is still loading and needs
to block the DOM ready callbacks that are registered
with jQuery.
</p>
<p>
Script loaders are the most likely kind of script
to use jQuery.readyWait, but it could be used by
other things like a script that loads a CSS file
and wants to pause the DOM ready callbacks.
</p>
<p>
<strong>Expected Result</strong>: The text
<span id="expectedOutput">It Worked!</span>
appears below after about <strong>2 seconds.</strong>
</p>
<p>
If there is an error in the console,
or the text does not show up, then the test failed.
</p>
<div id="output"></div>
</body>
</html>

View file

@ -1,41 +0,0 @@
load( "build/js/writeFile.js", "build/js/parse.js" );
function addParams(name, params) {
if(params.length > 0) {
name += "(";
for ( var i = 0; i < params.length; i++) {
name += params[i].type + ", ";
}
return name.substring(0, name.length - 2) + ")";
} else {
return name + "()";
}
}
function addTestWrapper(name, test) {
return 'test("' + name + '", function() {\n' + test + '\n});';
}
var dir = arguments[1];
var jq = parse( read(arguments[0]) );
var testFile = [];
String.prototype.decode = function() {
return this.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
};
for ( var i = 0; i < jq.length; i++ ) {
if ( jq[i].tests.length > 0 ) {
var method = jq[i];
var name = addParams(method.name, method.params);
for(var j = 0; j < method.tests.length; j++) {
if(j > 0) {
name += "x";
}
testFile[testFile.length] = addTestWrapper(name, method.tests[j].decode()) + "\n";
}
}
}
var indexFile = readFile( "build/test/index.html" );
writeFile( dir + "/index.html", indexFile.replace( /{TESTS}/g, testFile.join("\n") ) );

View file

@ -240,6 +240,68 @@ test("jQuery.ajax() - error callbacks", function() {
}); });
}); });
test( "jQuery.ajax - multiple method signatures introduced in 1.5 ( #8107)", function() {
expect( 4 );
stop();
jQuery.when(
jQuery.ajax().success(function() { ok( true, 'With no arguments' ); }),
jQuery.ajax('data/name.html').success(function() { ok( true, 'With only string URL argument' ); }),
jQuery.ajax('data/name.html', {} ).success(function() { ok( true, 'With string URL param and map' ); }),
jQuery.ajax({ url: 'data/name.html'} ).success(function() { ok( true, 'With only map' ); })
).then( start, start );
});
test("jQuery.ajax() - textStatus and errorThrown values", function() {
var nb = 2;
expect( 2 * nb );
stop();
function startN() {
if ( !( --nb ) ) {
start();
}
}
/*
Safari 3.x returns "OK" instead of "Not Found"
Safari 4.x doesn't have this issue so the test should be re-instated once
we drop support for 3.x
jQuery.ajax({
url: url("data/nonExistingURL"),
error: function( _ , textStatus , errorThrown ){
strictEqual( textStatus, "error", "textStatus is 'error' for 404" );
strictEqual( errorThrown, "Not Found", "errorThrown is 'Not Found' for 404");
startN();
}
});
*/
jQuery.ajax({
url: url("data/name.php?wait=5"),
error: function( _ , textStatus , errorThrown ){
strictEqual( textStatus, "abort", "textStatus is 'abort' for abort" );
strictEqual( errorThrown, "abort", "errorThrown is 'abort' for abort");
startN();
}
}).abort();
jQuery.ajax({
url: url("data/name.php?wait=5"),
error: function( _ , textStatus , errorThrown ){
strictEqual( textStatus, "mystatus", "textStatus is 'mystatus' for abort('mystatus')" );
strictEqual( errorThrown, "mystatus", "errorThrown is 'mystatus' for abort('mystatus')");
startN();
}
}).abort( "mystatus" );
});
test("jQuery.ajax() - responseText on error", function() { test("jQuery.ajax() - responseText on error", function() {
expect( 1 ); expect( 1 );
@ -249,7 +311,7 @@ test("jQuery.ajax() - responseText on error", function() {
jQuery.ajax({ jQuery.ajax({
url: url("data/errorWithText.php"), url: url("data/errorWithText.php"),
error: function(xhr) { error: function(xhr) {
strictEqual( xhr.responseText , "plain text message" , "Test jXHR.responseText is filled for HTTP errors" ); strictEqual( xhr.responseText , "plain text message" , "Test jqXHR.responseText is filled for HTTP errors" );
}, },
complete: function() { complete: function() {
start(); start();
@ -282,14 +344,18 @@ test(".ajax() - retry with jQuery.ajax( this )", function() {
test(".ajax() - headers" , function() { test(".ajax() - headers" , function() {
expect( 2 ); expect( 4 );
stop(); stop();
jQuery('#foo').ajaxSend(function( evt, xhr ) {
xhr.setRequestHeader( "ajax-send", "test" );
});
var requestHeaders = { var requestHeaders = {
siMPle: "value", siMPle: "value",
"SometHing-elsE": "other value", "SometHing-elsE": "other value",
OthEr: "something else" OthEr: "something else"
}, },
list = [], list = [],
i; i;
@ -297,22 +363,31 @@ test(".ajax() - headers" , function() {
for( i in requestHeaders ) { for( i in requestHeaders ) {
list.push( i ); list.push( i );
} }
list.push( "ajax-send" );
jQuery.ajax(url("data/headers.php?keys="+list.join( "_" ) ), { jQuery.ajax(url("data/headers.php?keys="+list.join( "_" ) ), {
headers: requestHeaders, headers: requestHeaders,
success: function( data , _ , xhr ) { success: function( data , _ , xhr ) {
var tmp = []; var tmp = [];
for ( i in requestHeaders ) { for ( i in requestHeaders ) {
tmp.push( i , ": " , requestHeaders[ i ] , "\n" ); tmp.push( i , ": " , requestHeaders[ i ] , "\n" );
} }
tmp.push( "ajax-send: test\n" );
tmp = tmp.join( "" ); tmp = tmp.join( "" );
equals( data , tmp , "Headers were sent" ); strictEqual( data , tmp , "Headers were sent" );
equals( xhr.getResponseHeader( "Sample-Header" ) , "Hello World" , "Sample header received" ); strictEqual( xhr.getResponseHeader( "Sample-Header" ) , "Hello World" , "Sample header received" );
start(); if ( jQuery.browser.mozilla ) {
ok( true, "Firefox doesn't support empty headers" );
} else {
strictEqual( xhr.getResponseHeader( "Empty-Header" ) , "" , "Empty header received" );
}
strictEqual( xhr.getResponseHeader( "Sample-Header2" ) , "Hello World 2" , "Second sample header received" );
}, },
error: function(){ ok(false, "error"); } error: function(){ ok(false, "error"); }
});
}).then( start, start );
}); });
@ -374,6 +449,18 @@ test(".ajax() - contentType" , function() {
}); });
test(".ajax() - protocol-less urls", function() {
expect(1);
jQuery.ajax({
url: "//somedomain.com",
beforeSend: function( xhr, settings ) {
equals(settings.url, location.protocol + "//somedomain.com", "Make sure that the protocol is added.");
return false;
}
});
});
test(".ajax() - hash", function() { test(".ajax() - hash", function() {
expect(3); expect(3);
@ -405,7 +492,7 @@ test(".ajax() - hash", function() {
test("jQuery ajax - cross-domain detection", function() { test("jQuery ajax - cross-domain detection", function() {
expect( 4 ); expect( 5 );
var loc = document.location, var loc = document.location,
otherPort = loc.port === 666 ? 667 : 666, otherPort = loc.port === 666 ? 667 : 666,
@ -420,6 +507,14 @@ test("jQuery ajax - cross-domain detection", function() {
} }
}); });
jQuery.ajax({
url: 'app:/path',
beforeSend: function( _ , s ) {
ok( s.crossDomain , "Adobe AIR app:/ URL detected as cross-domain" );
return false;
}
});
jQuery.ajax({ jQuery.ajax({
dataType: "jsonp", dataType: "jsonp",
url: loc.protocol + '//somewebsitethatdoesnotexist-656329477541.com:' + ( loc.port || 80 ), url: loc.protocol + '//somewebsitethatdoesnotexist-656329477541.com:' + ( loc.port || 80 ),
@ -450,22 +545,7 @@ test("jQuery ajax - cross-domain detection", function() {
}); });
test(".ajax() - 304", function() { test(".load() - 404 error callbacks", function() {
expect( 1 );
stop();
jQuery.ajax({
url: url("data/notmodified.php"),
success: function(){ ok(true, "304 ok"); },
// Do this because opera simply refuses to implement 304 handling :(
// A feature-driven way of detecting this would be appreciated
// See: http://gist.github.com/599419
error: function(){ ok(jQuery.browser.opera, "304 not ok "); },
complete: function(xhr){ start(); }
});
});
test(".load()) - 404 error callbacks", function() {
expect( 6 ); expect( 6 );
stop(); stop();
@ -856,7 +936,7 @@ test("serialize()", function() {
}); });
test("jQuery.param()", function() { test("jQuery.param()", function() {
expect(22); expect(24);
equals( !jQuery.ajaxSettings.traditional, true, "traditional flag, falsy by default" ); equals( !jQuery.ajaxSettings.traditional, true, "traditional flag, falsy by default" );
@ -891,6 +971,9 @@ test("jQuery.param()", function() {
equals( jQuery.param({"foo": {"bar": [], foo: 1} }), "foo%5Bbar%5D=&foo%5Bfoo%5D=1", "Empty array param" ); equals( jQuery.param({"foo": {"bar": [], foo: 1} }), "foo%5Bbar%5D=&foo%5Bfoo%5D=1", "Empty array param" );
equals( jQuery.param({"foo": {"bar": {}} }), "foo%5Bbar%5D=", "Empty object param" ); equals( jQuery.param({"foo": {"bar": {}} }), "foo%5Bbar%5D=", "Empty object param" );
// #7945
equals( jQuery.param({"jquery": "1.4.2"}), "jquery=1.4.2", "Check that object with a jQuery property get serialized correctly" );
jQuery.ajaxSetup({ traditional: true }); jQuery.ajaxSetup({ traditional: true });
var params = {foo:"bar", baz:42, quux:"All your base are belong to us"}; var params = {foo:"bar", baz:42, quux:"All your base are belong to us"};
@ -919,6 +1002,9 @@ test("jQuery.param()", function() {
params = { param1: null }; params = { param1: null };
equals( jQuery.param(params,false), "param1=null", "Make sure that null params aren't traversed." ); equals( jQuery.param(params,false), "param1=null", "Make sure that null params aren't traversed." );
params = {'test': {'length': 3, 'foo': 'bar'} };
equals( jQuery.param( params, false ), "test%5Blength%5D=3&test%5Bfoo%5D=bar", "Sub-object with a length property" );
}); });
test("synchronous request", function() { test("synchronous request", function() {
@ -1124,6 +1210,21 @@ test("load(String, String, Function)", function() {
}); });
}); });
test("jQuery.get(String, Function) - data in ajaxSettings (#8277)", function() {
expect(1);
stop();
jQuery.ajaxSetup({
data: "helloworld"
});
jQuery.get(url('data/echoQuery.php'), function(data) {
ok( /helloworld$/.test( data ), 'Data from ajaxSettings was used');
jQuery.ajaxSetup({
data: null
});
start();
});
});
test("jQuery.get(String, Hash, Function) - parse xml and use text() on nodes", function() { test("jQuery.get(String, Hash, Function) - parse xml and use text() on nodes", function() {
expect(2); expect(2);
stop(); stop();
@ -1139,10 +1240,11 @@ test("jQuery.get(String, Hash, Function) - parse xml and use text() on nodes", f
}); });
test("jQuery.getScript(String, Function) - with callback", function() { test("jQuery.getScript(String, Function) - with callback", function() {
expect(2); expect(3);
stop(); stop();
jQuery.getScript(url("data/test.js"), function() { jQuery.getScript(url("data/test.js"), function( data, _, jqXHR ) {
equals( foobar, "bar", 'Check if script was evaluated' ); equals( foobar, "bar", 'Check if script was evaluated' );
strictEqual( data, jqXHR.responseText, "Same-domain script requests returns the source of the script (#8082)" );
setTimeout(start, 100); setTimeout(start, 100);
}); });
}); });
@ -1158,10 +1260,10 @@ test("jQuery.getScript(String, Function) - no callback", function() {
jQuery.each( [ "Same Domain", "Cross Domain" ] , function( crossDomain , label ) { jQuery.each( [ "Same Domain", "Cross Domain" ] , function( crossDomain , label ) {
test("jQuery.ajax() - JSONP, " + label, function() { test("jQuery.ajax() - JSONP, " + label, function() {
expect(17); expect(20);
var count = 0; var count = 0;
function plus(){ if ( ++count == 17 ) start(); } function plus(){ if ( ++count == 18 ) start(); }
stop(); stop();
@ -1265,23 +1367,6 @@ jQuery.each( [ "Same Domain", "Cross Domain" ] , function( crossDomain , label )
} }
}); });
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
data: {
callback: "?"
},
success: function(data){
ok( data.data, "JSON results returned (GET, processed data callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, processed data callback)" );
plus();
}
});
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
@ -1318,6 +1403,38 @@ jQuery.each( [ "Same Domain", "Cross Domain" ] , function( crossDomain , label )
} }
}); });
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
jsonpCallback: "functionToCleanUp",
success: function(data){
ok( data.data, "JSON results returned (GET, custom callback name to be cleaned up)" );
strictEqual( window.functionToCleanUp, undefined, "Callback was removed (GET, custom callback name to be cleaned up)" );
plus();
var xhr;
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
jsonpCallback: "functionToCleanUp",
beforeSend: function( jqXHR ) {
xhr = jqXHR;
return false;
}
});
xhr.error(function() {
ok( true, "Ajax error JSON (GET, custom callback name to be cleaned up)" );
strictEqual( window.functionToCleanUp, undefined, "Callback was removed after early abort (GET, custom callback name to be cleaned up)" );
plus();
});
},
error: function(data){
ok( false, "Ajax error JSON (GET, custom callback name to be cleaned up)" );
plus();
}
});
jQuery.ajax({ jQuery.ajax({
type: "POST", type: "POST",
url: "data/jsonp.php", url: "data/jsonp.php",
@ -1480,17 +1597,23 @@ test("jQuery.ajax() - malformed JSON", function() {
}); });
test("jQuery.ajax() - script by content-type", function() { test("jQuery.ajax() - script by content-type", function() {
expect(1); expect(2);
stop(); stop();
jQuery.ajax({ jQuery.when(
url: "data/script.php",
data: { header: "script" }, jQuery.ajax({
success: function() { url: "data/script.php",
start(); data: { header: "script" }
} }),
});
jQuery.ajax({
url: "data/script.php",
data: { header: "ecma" }
})
).then( start, start );
}); });
test("jQuery.ajax() - json by content-type", function() { test("jQuery.ajax() - json by content-type", function() {
@ -1593,17 +1716,32 @@ test("jQuery.getJSON(String, Function) - JSON object with absolute url to local
}); });
}); });
test("jQuery.post - data", function() { test("jQuery.post - data", 3, function() {
expect(2);
stop(); stop();
jQuery.post(url("data/name.php"), {xml: "5-2", length: 3}, function(xml){ jQuery.when(
jQuery('math', xml).each(function() { jQuery.post( url( "data/name.php" ), { xml: "5-2", length: 3 }, function( xml ) {
equals( jQuery('calculation', this).text(), '5-2', 'Check for XML' ); jQuery( 'math', xml ).each( function() {
equals( jQuery('result', this).text(), '3', 'Check for XML' ); equals( jQuery( 'calculation', this ).text(), '5-2', 'Check for XML' );
}); equals( jQuery( 'result', this ).text(), '3', 'Check for XML' );
start(); });
}); }),
jQuery.ajax({
url: url('data/echoData.php'),
type: "POST",
data: {
'test': {
'length': 7,
'foo': 'bar'
}
},
success: function( data ) {
strictEqual( data, 'test%5Blength%5D=7&test%5Bfoo%5D=bar', 'Check if a sub-object with a length param is serialized correctly');
}
})
).then( start, start );
}); });
test("jQuery.post(String, Hash, Function) - simple with xml", function() { test("jQuery.post(String, Hash, Function) - simple with xml", function() {
@ -1768,96 +1906,105 @@ test("data option: empty bodies for non-GET requests", function() {
}); });
}); });
test("jQuery.ajax - If-Modified-Since support", function() { var ifModifiedNow = new Date();
expect( 3 );
stop(); jQuery.each( { " (cache)": true, " (no cache)": false }, function( label, cache ) {
var url = "data/if_modified_since.php?ts=" + new Date(); test("jQuery.ajax - If-Modified-Since support" + label, function() {
expect( 3 );
jQuery.ajax({ stop();
url: url,
ifModified: true,
success: function(data, status) {
equals(status, "success");
jQuery.ajax({ var url = "data/if_modified_since.php?ts=" + ifModifiedNow++;
url: url,
ifModified: true, jQuery.ajax({
success: function(data, status) { url: url,
if ( data === "FAIL" ) { ifModified: true,
ok(true, "Opera is incapable of doing .setRequestHeader('If-Modified-Since')."); cache: cache,
ok(true, "Opera is incapable of doing .setRequestHeader('If-Modified-Since')."); success: function(data, status) {
} else { equals(status, "success" );
equals(status, "notmodified");
ok(data == null, "response body should be empty"); jQuery.ajax({
url: url,
ifModified: true,
cache: cache,
success: function(data, status) {
if ( data === "FAIL" ) {
ok(jQuery.browser.opera, "Opera is incapable of doing .setRequestHeader('If-Modified-Since').");
ok(jQuery.browser.opera, "Opera is incapable of doing .setRequestHeader('If-Modified-Since').");
} else {
equals(status, "notmodified");
ok(data == null, "response body should be empty");
}
start();
},
error: function() {
// Do this because opera simply refuses to implement 304 handling :(
// A feature-driven way of detecting this would be appreciated
// See: http://gist.github.com/599419
ok(jQuery.browser.opera, "error");
ok(jQuery.browser.opera, "error");
start();
} }
start(); });
}, },
error: function() { error: function() {
// Do this because opera simply refuses to implement 304 handling :( equals(false, "error");
// A feature-driven way of detecting this would be appreciated // Do this because opera simply refuses to implement 304 handling :(
// See: http://gist.github.com/599419 // A feature-driven way of detecting this would be appreciated
ok(jQuery.browser.opera, "error"); // See: http://gist.github.com/599419
ok(jQuery.browser.opera, "error"); ok(jQuery.browser.opera, "error");
start(); start();
} }
}); });
},
error: function() {
equals(false, "error");
// Do this because opera simply refuses to implement 304 handling :(
// A feature-driven way of detecting this would be appreciated
// See: http://gist.github.com/599419
ok(jQuery.browser.opera, "error");
start();
}
}); });
});
test("jQuery.ajax - Etag support", function() { test("jQuery.ajax - Etag support" + label, function() {
expect( 3 ); expect( 3 );
stop(); stop();
var url = "data/etag.php?ts=" + new Date(); var url = "data/etag.php?ts=" + ifModifiedNow++;
jQuery.ajax({ jQuery.ajax({
url: url, url: url,
ifModified: true, ifModified: true,
success: function(data, status) { cache: cache,
equals(status, "success"); success: function(data, status) {
equals(status, "success" );
jQuery.ajax({ jQuery.ajax({
url: url, url: url,
ifModified: true, ifModified: true,
success: function(data, status) { cache: cache,
if ( data === "FAIL" ) { success: function(data, status) {
ok(true, "Opera is incapable of doing .setRequestHeader('If-None-Match')."); if ( data === "FAIL" ) {
ok(true, "Opera is incapable of doing .setRequestHeader('If-None-Match')."); ok(jQuery.browser.opera, "Opera is incapable of doing .setRequestHeader('If-None-Match').");
} else { ok(jQuery.browser.opera, "Opera is incapable of doing .setRequestHeader('If-None-Match').");
equals(status, "notmodified"); } else {
ok(data == null, "response body should be empty"); equals(status, "notmodified");
ok(data == null, "response body should be empty");
}
start();
},
error: function() {
// Do this because opera simply refuses to implement 304 handling :(
// A feature-driven way of detecting this would be appreciated
// See: http://gist.github.com/599419
ok(jQuery.browser.opera, "error");
ok(jQuery.browser.opera, "error");
start();
} }
start(); });
}, },
error: function() { error: function() {
// Do this because opera simply refuses to implement 304 handling :( // Do this because opera simply refuses to implement 304 handling :(
// A feature-driven way of detecting this would be appreciated // A feature-driven way of detecting this would be appreciated
// See: http://gist.github.com/599419 // See: http://gist.github.com/599419
ok(jQuery.browser.opera, "error"); ok(jQuery.browser.opera, "error");
ok(jQuery.browser.opera, "error"); start();
start(); }
} });
});
},
error: function() {
// Do this because opera simply refuses to implement 304 handling :(
// A feature-driven way of detecting this would be appreciated
// See: http://gist.github.com/599419
ok(jQuery.browser.opera, "error");
start();
}
}); });
}); });
@ -1949,16 +2096,16 @@ test( "jQuery.ajax - statusCode" , function() {
}).statusCode( createStatusCodes( "immediately with method" , isSuccess ) ); }).statusCode( createStatusCodes( "immediately with method" , isSuccess ) );
jQuery.ajax( url( uri ) , { jQuery.ajax( url( uri ) , {
complete: function(jXHR) { complete: function(jqXHR) {
jXHR.statusCode( createStatusCodes( "on complete" , isSuccess ) ); jqXHR.statusCode( createStatusCodes( "on complete" , isSuccess ) );
countComplete(); countComplete();
} }
}); });
jQuery.ajax( url( uri ) , { jQuery.ajax( url( uri ) , {
complete: function(jXHR) { complete: function(jqXHR) {
setTimeout( function() { setTimeout( function() {
jXHR.statusCode( createStatusCodes( "very late binding" , isSuccess ) ); jqXHR.statusCode( createStatusCodes( "very late binding" , isSuccess ) );
countComplete(); countComplete();
} , 100 ); } , 100 );
} }
@ -1966,10 +2113,10 @@ test( "jQuery.ajax - statusCode" , function() {
jQuery.ajax( url( uri ) , { jQuery.ajax( url( uri ) , {
statusCode: createStatusCodes( "all (options)" , isSuccess ), statusCode: createStatusCodes( "all (options)" , isSuccess ),
complete: function(jXHR) { complete: function(jqXHR) {
jXHR.statusCode( createStatusCodes( "all (on complete)" , isSuccess ) ); jqXHR.statusCode( createStatusCodes( "all (on complete)" , isSuccess ) );
setTimeout( function() { setTimeout( function() {
jXHR.statusCode( createStatusCodes( "all (very late binding)" , isSuccess ) ); jqXHR.statusCode( createStatusCodes( "all (very late binding)" , isSuccess ) );
countComplete(); countComplete();
} , 100 ); } , 100 );
} }
@ -1978,22 +2125,22 @@ test( "jQuery.ajax - statusCode" , function() {
var testString = ""; var testString = "";
jQuery.ajax( url( uri ), { jQuery.ajax( url( uri ), {
success: function( a , b , jXHR ) { success: function( a , b , jqXHR ) {
ok( isSuccess , "success" ); ok( isSuccess , "success" );
var statusCode = {}; var statusCode = {};
statusCode[ jXHR.status ] = function() { statusCode[ jqXHR.status ] = function() {
testString += "B"; testString += "B";
}; };
jXHR.statusCode( statusCode ); jqXHR.statusCode( statusCode );
testString += "A"; testString += "A";
}, },
error: function( jXHR ) { error: function( jqXHR ) {
ok( ! isSuccess , "error" ); ok( ! isSuccess , "error" );
var statusCode = {}; var statusCode = {};
statusCode[ jXHR.status ] = function() { statusCode[ jqXHR.status ] = function() {
testString += "B"; testString += "B";
}; };
jXHR.statusCode( statusCode ); jqXHR.statusCode( statusCode );
testString += "A"; testString += "A";
}, },
complete: function() { complete: function() {
@ -2016,12 +2163,12 @@ test("jQuery.ajax - transitive conversions", function() {
jQuery.ajax( url("data/json.php") , { jQuery.ajax( url("data/json.php") , {
converters: { converters: {
"json myjson": function( data ) { "json myJson": function( data ) {
ok( true , "converter called" ); ok( true , "converter called" );
return data; return data;
} }
}, },
dataType: "myjson", dataType: "myJson",
success: function() { success: function() {
ok( true , "Transitive conversion worked" ); ok( true , "Transitive conversion worked" );
strictEqual( this.dataTypes[0] , "text" , "response was retrieved as text" ); strictEqual( this.dataTypes[0] , "text" , "response was retrieved as text" );
@ -2031,13 +2178,13 @@ test("jQuery.ajax - transitive conversions", function() {
jQuery.ajax( url("data/json.php") , { jQuery.ajax( url("data/json.php") , {
converters: { converters: {
"json myjson": function( data ) { "json myJson": function( data ) {
ok( true , "converter called (*)" ); ok( true , "converter called (*)" );
return data; return data;
} }
}, },
contents: false, /* headers are wrong so we ignore them */ contents: false, /* headers are wrong so we ignore them */
dataType: "* myjson", dataType: "* myJson",
success: function() { success: function() {
ok( true , "Transitive conversion worked (*)" ); ok( true , "Transitive conversion worked (*)" );
strictEqual( this.dataTypes[0] , "text" , "response was retrieved as text (*)" ); strictEqual( this.dataTypes[0] , "text" , "response was retrieved as text (*)" );
@ -2049,6 +2196,53 @@ test("jQuery.ajax - transitive conversions", function() {
}); });
test("jQuery.ajax - overrideMimeType", function() {
expect( 2 );
stop();
jQuery.when(
jQuery.ajax( url("data/json.php") , {
beforeSend: function( xhr ) {
xhr.overrideMimeType( "application/json" );
},
success: function( json ) {
ok( json.data , "Mimetype overriden using beforeSend" );
}
}),
jQuery.ajax( url("data/json.php") , {
mimeType: "application/json",
success: function( json ) {
ok( json.data , "Mimetype overriden using mimeType option" );
}
})
).then( start , start );
});
test("jQuery.ajax - abort in prefilter", function() {
expect( 1 );
jQuery.ajaxPrefilter(function( options, _, jqXHR ) {
if ( options.abortInPrefilter ) {
jqXHR.abort();
}
});
strictEqual( jQuery.ajax({
abortInPrefilter: true,
error: function() {
ok( false, "error callback called" );
}
}), false, "Request was properly aborted early by the prefilter" );
});
test("jQuery.ajax - active counter", function() { test("jQuery.ajax - active counter", function() {
ok( jQuery.active == 0, "ajax active counter should be zero: " + jQuery.active ); ok( jQuery.active == 0, "ajax active counter should be zero: " + jQuery.active );
}); });

View file

@ -546,6 +546,25 @@ test("val(Function) with incoming value", function() {
equals( jQuery("#select1").val(), "4", "Should be possible to set the val() to a newly created option" ); equals( jQuery("#select1").val(), "4", "Should be possible to set the val() to a newly created option" );
}); });
// testing if a form.reset() breaks a subsequent call to a select element's .val() (in IE only)
test("val(select) after form.reset() (Bug #2551)", function() {
expect(3);
jQuery('<form id="kk" name="kk"><select id="kkk"><option value="cf">cf</option><option value="gf">gf</option></select></form>').appendTo("#main");
jQuery("#kkk").val( "gf" );
document.kk.reset();
equal( jQuery("#kkk")[0].value, "cf", "Check value of select after form reset." );
equal( jQuery("#kkk").val(), "cf", "Check value of select after form reset." );
// re-verify the multi-select is not broken (after form.reset) by our fix for single-select
same( jQuery('#select3').val(), ['1', '2'], 'Call val() on a multiple="multiple" select' );
jQuery("#kk").remove();
});
var testAddClass = function(valueObj) { var testAddClass = function(valueObj) {
expect(5); expect(5);
var div = jQuery("div"); var div = jQuery("div");

View file

@ -537,29 +537,29 @@ test("end()", function() {
test("length", function() { test("length", function() {
expect(1); expect(1);
equals( jQuery("p").length, 6, "Get Number of Elements Found" ); equals( jQuery("#main p").length, 6, "Get Number of Elements Found" );
}); });
test("size()", function() { test("size()", function() {
expect(1); expect(1);
equals( jQuery("p").size(), 6, "Get Number of Elements Found" ); equals( jQuery("#main p").size(), 6, "Get Number of Elements Found" );
}); });
test("get()", function() { test("get()", function() {
expect(1); expect(1);
same( jQuery("p").get(), q("firstp","ap","sndp","en","sap","first"), "Get All Elements" ); same( jQuery("#main p").get(), q("firstp","ap","sndp","en","sap","first"), "Get All Elements" );
}); });
test("toArray()", function() { test("toArray()", function() {
expect(1); expect(1);
same( jQuery("p").toArray(), same( jQuery("#main p").toArray(),
q("firstp","ap","sndp","en","sap","first"), q("firstp","ap","sndp","en","sap","first"),
"Convert jQuery object to an Array" ) "Convert jQuery object to an Array" )
}) })
test("get(Number)", function() { test("get(Number)", function() {
expect(2); expect(2);
equals( jQuery("p").get(0), document.getElementById("firstp"), "Get A Single Element" ); equals( jQuery("#main p").get(0), document.getElementById("firstp"), "Get A Single Element" );
strictEqual( jQuery("#firstp").get(1), undefined, "Try get with index larger elements count" ); strictEqual( jQuery("#firstp").get(1), undefined, "Try get with index larger elements count" );
}); });
@ -1129,11 +1129,60 @@ test("jQuery.when() - joined", function() {
}); });
}); });
test("jQuery.subclass", function(){ test("jQuery.sub() - Static Methods", function(){
expect(18);
var Subclass = jQuery.sub();
Subclass.extend({
topLevelMethod: function() {return this.debug;},
debug: false,
config: {
locale: 'en_US'
},
setup: function(config) {
this.extend(true, this.config, config);
}
});
Subclass.fn.extend({subClassMethod: function() { return this;}});
//Test Simple Subclass
ok(Subclass.topLevelMethod() === false, 'Subclass.topLevelMethod thought debug was true');
ok(Subclass.config.locale == 'en_US', Subclass.config.locale + ' is wrong!');
same(Subclass.config.test, undefined, 'Subclass.config.test is set incorrectly');
equal(jQuery.ajax, Subclass.ajax, 'The subclass failed to get all top level methods');
//Create a SubSubclass
var SubSubclass = Subclass.sub();
//Make Sure the SubSubclass inherited properly
ok(SubSubclass.topLevelMethod() === false, 'SubSubclass.topLevelMethod thought debug was true');
ok(SubSubclass.config.locale == 'en_US', SubSubclass.config.locale + ' is wrong!');
same(SubSubclass.config.test, undefined, 'SubSubclass.config.test is set incorrectly');
equal(jQuery.ajax, SubSubclass.ajax, 'The subsubclass failed to get all top level methods');
//Modify The Subclass and test the Modifications
SubSubclass.fn.extend({subSubClassMethod: function() { return this;}});
SubSubclass.setup({locale: 'es_MX', test: 'worked'});
SubSubclass.debug = true;
SubSubclass.ajax = function() {return false;};
ok(SubSubclass.topLevelMethod(), 'SubSubclass.topLevelMethod thought debug was false');
same(SubSubclass(document).subClassMethod, Subclass.fn.subClassMethod, 'Methods Differ!');
ok(SubSubclass.config.locale == 'es_MX', SubSubclass.config.locale + ' is wrong!');
ok(SubSubclass.config.test == 'worked', 'SubSubclass.config.test is set incorrectly');
notEqual(jQuery.ajax, SubSubclass.ajax, 'The subsubclass failed to get all top level methods');
//This shows that the modifications to the SubSubClass did not bubble back up to it's superclass
ok(Subclass.topLevelMethod() === false, 'Subclass.topLevelMethod thought debug was true');
ok(Subclass.config.locale == 'en_US', Subclass.config.locale + ' is wrong!');
same(Subclass.config.test, undefined, 'Subclass.config.test is set incorrectly');
same(Subclass(document).subSubClassMethod, undefined, 'subSubClassMethod set incorrectly');
equal(jQuery.ajax, Subclass.ajax, 'The subclass failed to get all top level methods');
});
test("jQuery.sub() - .fn Methods", function(){
expect(378); expect(378);
var Subclass = jQuery.subclass(), var Subclass = jQuery.sub(),
SubclassSubclass = Subclass.subclass(), SubclassSubclass = Subclass.sub(),
jQueryDocument = jQuery(document), jQueryDocument = jQuery(document),
selectors, contexts, methods, method, arg, description; selectors, contexts, methods, method, arg, description;

View file

@ -180,15 +180,28 @@ test(".data()", function() {
var div = jQuery("#foo"); var div = jQuery("#foo");
strictEqual( div.data("foo"), undefined, "Make sure that missing result is undefined" ); strictEqual( div.data("foo"), undefined, "Make sure that missing result is undefined" );
div.data("test", "success"); div.data("test", "success");
same( div.data(), {test: "success"}, "data() get the entire data object" );
var dataObj = div.data();
// TODO: Remove this hack which was introduced in 1.5.1
delete dataObj.toJSON;
same( dataObj, {test: "success"}, "data() get the entire data object" );
strictEqual( div.data("foo"), undefined, "Make sure that missing result is still undefined" ); strictEqual( div.data("foo"), undefined, "Make sure that missing result is still undefined" );
var nodiv = jQuery("#unfound"); var nodiv = jQuery("#unfound");
equals( nodiv.data(), null, "data() on empty set returns null" ); equals( nodiv.data(), null, "data() on empty set returns null" );
var obj = { foo: "bar" }; var obj = { foo: "bar" };
deepEqual( jQuery(obj).data(), {}, "Retrieve data object from a wrapped JS object (#7524)" ); jQuery(obj).data("foo", "baz");
})
dataObj = jQuery.extend(true, {}, jQuery(obj).data());
// TODO: Remove this hack which was introduced for 1.5.1
delete dataObj.toJSON;
deepEqual( dataObj, { foo: "baz" }, "Retrieve data object from a wrapped JS object (#7524)" );
});
test(".data(String) and .data(String, Object)", function() { test(".data(String) and .data(String, Object)", function() {
expect(29); expect(29);
@ -461,4 +474,15 @@ test(".removeData()", function() {
div.removeData("test.foo"); div.removeData("test.foo");
equals( div.data("test.foo"), undefined, "Make sure data is intact" ); equals( div.data("test.foo"), undefined, "Make sure data is intact" );
}); });
if (window.JSON && window.JSON.stringify) {
test("JSON serialization (#8108)", function () {
expect(1);
var obj = { foo: "bar" };
jQuery.data(obj, "hidden", true);
equals( JSON.stringify(obj), '{"foo":"bar"}', "Expando is hidden from JSON.stringify" );
});
}

146
test/unit/effects.js vendored
View file

@ -39,24 +39,23 @@ test("show()", function() {
ok( pass, "Show" ); ok( pass, "Show" );
var speeds = { var speeds = {
"null speed": null, "null speed": null,
"undefined speed": undefined, "undefined speed": undefined,
"empty string speed": "", "empty string speed": "",
"false speed": false "false speed": false
}; };
jQuery.each(speeds, function(name, speed) { jQuery.each(speeds, function(name, speed) {
pass = true; pass = true;
div.hide().show(speed).each(function() { div.hide().show(speed).each(function() {
if ( this.style.display == "none" ) pass = false; if ( this.style.display == "none" ) pass = false;
}); });
ok( pass, "Show with " + name); ok( pass, "Show with " + name);
}); });
jQuery.each(speeds, function(name, speed) { jQuery.each(speeds, function(name, speed) {
pass = true; pass = true;
div.hide().show(speed, function() { div.hide().show(speed, function() {
pass = false; pass = false;
}); });
ok( pass, "Show with " + name + " does not call animate callback" ); ok( pass, "Show with " + name + " does not call animate callback" );
@ -132,9 +131,9 @@ test("show(Number) - other displays", function() {
// Supports #7397 // Supports #7397
test("Persist correct display value", function() { test("Persist correct display value", function() {
expect(3); expect(3);
QUnit.reset(); QUnit.reset();
stop(); stop();
@ -142,31 +141,25 @@ test("Persist correct display value", function() {
jQuery("#main").append('<div id="show-tests"><span style="position:absolute;">foo</span></div>'); jQuery("#main").append('<div id="show-tests"><span style="position:absolute;">foo</span></div>');
var $span = jQuery("#show-tests span"), var $span = jQuery("#show-tests span"),
displayNone = $span.css("display"), displayNone = $span.css("display"),
display = '', num = 0; display = '', num = 0;
$span.show(); $span.show();
display = $span.css("display"); display = $span.css("display");
$span.hide(); $span.hide();
$span.fadeIn(100, function() { $span.fadeIn(100, function() {
equals($span.css("display"), display, "Expecting display: " + display);
equals($span.css("display"), display, "Expecting display: " + display); $span.fadeOut(100, function () {
equals($span.css("display"), displayNone, "Expecting display: " + displayNone);
$span.fadeOut(100, function () { $span.fadeIn(100, function() {
equals($span.css("display"), display, "Expecting display: " + display);
equals($span.css("display"), displayNone, "Expecting display: " + displayNone); start();
});
$span.fadeIn(100, function() { });
});
equals($span.css("display"), display, "Expecting display: " + display);
start();
});
});
});
}); });
test("animate(Hash, Object, Function)", function() { test("animate(Hash, Object, Function)", function() {
@ -565,21 +558,54 @@ jQuery.checkOverflowDisplay = function(){
start(); start();
} }
test("support negative values < -10000 (bug #7193)", function () { test( "jQuery.fx.prototype.cur()", 6, function() {
expect(1); var div = jQuery( "<div></div>" ).appendTo( "#main" ).css({
stop(); color: "#ABC",
border: "5px solid black",
left: "auto",
marginBottom: "-11000px"
})[0];
jQuery.extend(jQuery.fx.step, { equals(
"marginBottom": function(fx) { ( new jQuery.fx( div, {}, "color" ) ).cur(),
equals( fx.cur(), -11000, "Element has margin-bottom of -11000" ); jQuery.css( div, "color" ),
delete jQuery.fx.step.marginBottom; "Return the same value as jQuery.css for complex properties (bug #7912)"
);
strictEqual(
( new jQuery.fx( div, {}, "borderLeftWidth" ) ).cur(),
5,
"Return simple values parsed as Float"
);
// backgroundPosition actually returns 0% 0% in most browser
// this fakes a "" return
jQuery.cssHooks.backgroundPosition = {
get: function() {
ok( true, "hook used" );
return "";
} }
}); };
jQuery("#main").css("marginBottom", "-11000px").animate({ marginBottom: "-11001px" }, { strictEqual(
duration: 1, ( new jQuery.fx( div, {}, "backgroundPosition" ) ).cur(),
complete: start 0,
}); "Return 0 when jQuery.css returns an empty string"
);
delete jQuery.cssHooks.backgroundPosition;
strictEqual(
( new jQuery.fx( div, {}, "left" ) ).cur(),
0,
"Return 0 when jQuery.css returns 'auto'"
);
equals(
( new jQuery.fx( div, {}, "marginBottom" ) ).cur(),
-11000,
"support negative values < -10000 (bug #7193)"
);
}); });
test("JS Overflow and Display", function() { test("JS Overflow and Display", function() {
@ -803,7 +829,7 @@ test("Chain toggle out", function() {
jQuery('#toggleout div').saveState(jQuery.support.shrinkWrapBlocks).toggle('fast').toggle('fast',jQuery.checkState); jQuery('#toggleout div').saveState(jQuery.support.shrinkWrapBlocks).toggle('fast').toggle('fast',jQuery.checkState);
}); });
test("Chain toggle out with easing and callback", function() { test("Chain toggle out with easing and callback", function() {
jQuery('#toggleout div').saveState(jQuery.support.shrinkWrapBlocks).toggle('fast').toggle('fast','linear',jQuery.checkState); jQuery('#toggleout div').saveState(jQuery.support.shrinkWrapBlocks).toggle('fast').toggle('fast','linear',jQuery.checkState);
}); });
test("Chain slideDown slideUp", function() { test("Chain slideDown slideUp", function() {
jQuery('#slidedown div').saveState(jQuery.support.shrinkWrapBlocks).slideDown('fast').slideUp('fast',jQuery.checkState); jQuery('#slidedown div').saveState(jQuery.support.shrinkWrapBlocks).slideDown('fast').slideUp('fast',jQuery.checkState);
@ -850,16 +876,16 @@ jQuery.makeTest.id = 1;
test("jQuery.show('fast') doesn't clear radio buttons (bug #1095)", function () { test("jQuery.show('fast') doesn't clear radio buttons (bug #1095)", function () {
expect(4); expect(4);
stop(); stop();
var $checkedtest = jQuery("#checkedtest"); var $checkedtest = jQuery("#checkedtest");
// IE6 was clearing "checked" in jQuery(elem).show("fast"); // IE6 was clearing "checked" in jQuery(elem).show("fast");
$checkedtest.hide().show("fast", function() { $checkedtest.hide().show("fast", function() {
ok( !! jQuery(":radio:first", $checkedtest).attr("checked"), "Check first radio still checked." ); ok( !! jQuery(":radio:first", $checkedtest).attr("checked"), "Check first radio still checked." );
ok( ! jQuery(":radio:last", $checkedtest).attr("checked"), "Check last radio still NOT checked." ); ok( ! jQuery(":radio:last", $checkedtest).attr("checked"), "Check last radio still NOT checked." );
ok( !! jQuery(":checkbox:first", $checkedtest).attr("checked"), "Check first checkbox still checked." ); ok( !! jQuery(":checkbox:first", $checkedtest).attr("checked"), "Check first checkbox still checked." );
ok( ! jQuery(":checkbox:last", $checkedtest).attr("checked"), "Check last checkbox still NOT checked." ); ok( ! jQuery(":checkbox:last", $checkedtest).attr("checked"), "Check last checkbox still NOT checked." );
start(); start();
}); });
}); });
@ -926,3 +952,13 @@ test("hide hidden elements, with animation (bug #7141)", function() {
}); });
}); });
}); });
test("animate unit-less properties (#4966)", 2, function() {
stop();
var div = jQuery( "<div style='z-index: 0; position: absolute;'></div>" ).appendTo( "#main" );
equal( div.css( "z-index" ), "0", "z-index is 0" );
div.animate({ zIndex: 2 }, function() {
equal( div.css( "z-index" ), "2", "z-index is 2" );
start();
});
});

View file

@ -2,22 +2,16 @@ module("event", { teardown: moduleTeardown });
test("null or undefined handler", function() { test("null or undefined handler", function() {
expect(2); expect(2);
// Supports Fixes bug #7229 // Supports Fixes bug #7229
try { try {
jQuery("#firstp").click(null);
ok(true, "Passing a null handler will not throw an exception");
} catch (e) {}
jQuery("#firstp").click(null); try {
jQuery("#firstp").click(undefined);
ok(true, "Passing a null handler will not throw an exception"); ok(true, "Passing an undefined handler will not throw an exception");
} catch (e) {}
} catch (e) {}
try {
jQuery("#firstp").click(undefined);
ok(true, "Passing an undefined handler will not throw an exception");
} catch (e) {}
}); });
test("bind(), with data", function() { test("bind(), with data", function() {
@ -312,7 +306,7 @@ test("bind/delegate bubbling, isDefaultPrevented", function() {
// Use a native click so we don't get jQuery simulated bubbling // Use a native click so we don't get jQuery simulated bubbling
if ( document.createEvent ) { if ( document.createEvent ) {
var e = document.createEvent( 'MouseEvents' ); var e = document.createEvent( 'MouseEvents' );
e.initEvent( "click", true, true ); e.initEvent( "click", true, true );
$jq[0].dispatchEvent(e); $jq[0].dispatchEvent(e);
} }
else if ( $jq[0].click ) { else if ( $jq[0].click ) {
@ -367,38 +361,47 @@ test("bind(), trigger change on select", function() {
}).trigger('change'); }).trigger('change');
}); });
test("bind(), namespaced events, cloned events", function() { test("bind(), namespaced events, cloned events", 18, function() {
expect(6); var firstp = jQuery( "#firstp" );
jQuery("#firstp").bind("custom.test",function(e){ firstp.bind("custom.test",function(e){
ok(true, "Custom event triggered"); ok(false, "Custom event triggered");
}); });
jQuery("#firstp").bind("click",function(e){ firstp.bind("click",function(e){
ok(true, "Normal click triggered"); ok(true, "Normal click triggered");
equal( e.type + e.namespace, "click", "Check that only click events trigger this fn" );
}); });
jQuery("#firstp").bind("click.test",function(e){ firstp.bind("click.test",function(e){
ok(true, "Namespaced click triggered"); var check = "click";
ok( true, "Namespaced click triggered" );
if ( e.namespace ) {
check += "test";
}
equal( e.type + e.namespace, check, "Check that only click/click.test events trigger this fn" );
}); });
// Trigger both bound fn (2) //clone(true) element to verify events are cloned correctly
jQuery("#firstp").trigger("click"); firstp = firstp.add( firstp.clone( true ).attr( "id", "firstp2" ).insertBefore( firstp ) );
// Trigger one bound fn (1) // Trigger both bound fn (8)
jQuery("#firstp").trigger("click.test"); firstp.trigger("click");
// Trigger one bound fn (4)
firstp.trigger("click.test");
// Remove only the one fn // Remove only the one fn
jQuery("#firstp").unbind("click.test"); firstp.unbind("click.test");
// Trigger the remaining fn (1) // Trigger the remaining fn (4)
jQuery("#firstp").trigger("click"); firstp.trigger("click");
// Remove the remaining fn // Remove the remaining namespaced fn
jQuery("#firstp").unbind(".test"); firstp.unbind(".test");
// Trigger the remaining fn (0) // Try triggering the custom event (0)
jQuery("#firstp").trigger("custom"); firstp.trigger("custom");
// using contents will get comments regular, text, and comment nodes // using contents will get comments regular, text, and comment nodes
jQuery("#nonnodes").contents().bind("tester", function () { jQuery("#nonnodes").contents().bind("tester", function () {
@ -406,7 +409,7 @@ test("bind(), namespaced events, cloned events", function() {
}).trigger("tester"); }).trigger("tester");
// Make sure events stick with appendTo'd elements (which are cloned) #2027 // Make sure events stick with appendTo'd elements (which are cloned) #2027
jQuery("<a href='#fail' class='test'>test</a>").click(function(){ return false; }).appendTo("p"); jQuery("<a href='#fail' class='test'>test</a>").click(function(){ return false; }).appendTo("#main");
ok( jQuery("a.test:first").triggerHandler("click") === false, "Handler is bound to appendTo'd elements" ); ok( jQuery("a.test:first").triggerHandler("click") === false, "Handler is bound to appendTo'd elements" );
}); });
@ -471,7 +474,7 @@ test("bind(), multi-namespaced events", function() {
test("bind(), with same function", function() { test("bind(), with same function", function() {
expect(2) expect(2)
var count = 0 , func = function(){ var count = 0, func = function(){
count++; count++;
}; };
@ -548,7 +551,7 @@ test("bind(name, false), unbind(name, false)", function() {
}); });
test("bind()/trigger()/unbind() on plain object", function() { test("bind()/trigger()/unbind() on plain object", function() {
expect( 8 ); expect( 7 );
var obj = {}; var obj = {};
@ -570,7 +573,6 @@ test("bind()/trigger()/unbind() on plain object", function() {
var events = jQuery._data(obj, "events"); var events = jQuery._data(obj, "events");
ok( events, "Object has events bound." ); ok( events, "Object has events bound." );
equals( obj.events, undefined, "Events object on plain objects is not events" ); equals( obj.events, undefined, "Events object on plain objects is not events" );
equals( typeof events, "function", "'events' expando is a function on plain objects." );
equals( obj.test, undefined, "Make sure that test event is not on the plain object." ); equals( obj.test, undefined, "Make sure that test event is not on the plain object." );
equals( obj.handle, undefined, "Make sure that the event handler is not on the plain object." ); equals( obj.handle, undefined, "Make sure that the event handler is not on the plain object." );
@ -588,7 +590,7 @@ test("bind()/trigger()/unbind() on plain object", function() {
jQuery(obj).unbind("test"); jQuery(obj).unbind("test");
equals( obj && obj[ jQuery.expando ] && equals( obj && obj[ jQuery.expando ] &&
obj[ jQuery.expando ][ jQuery.expando ] && obj[ jQuery.expando ][ jQuery.expando ] &&
obj[ jQuery.expando ][ jQuery.expando ].events, undefined, "Make sure events object is removed" ); obj[ jQuery.expando ][ jQuery.expando ].events, undefined, "Make sure events object is removed" );
}); });
@ -613,18 +615,18 @@ test("unbind(type)", function() {
message = "unbind many with function"; message = "unbind many with function";
$elem.bind('error1 error2',error) $elem.bind('error1 error2',error)
.unbind('error1 error2', error ) .unbind('error1 error2', error )
.trigger('error1').triggerHandler('error2'); .trigger('error1').triggerHandler('error2');
message = "unbind many"; // #3538 message = "unbind many"; // #3538
$elem.bind('error1 error2',error) $elem.bind('error1 error2',error)
.unbind('error1 error2') .unbind('error1 error2')
.trigger('error1').triggerHandler('error2'); .trigger('error1').triggerHandler('error2');
message = "unbind without a type or handler"; message = "unbind without a type or handler";
$elem.bind("error1 error2.test",error) $elem.bind("error1 error2.test",error)
.unbind() .unbind()
.trigger("error1").triggerHandler("error2"); .trigger("error1").triggerHandler("error2");
}); });
test("unbind(eventObject)", function() { test("unbind(eventObject)", function() {
@ -1453,6 +1455,8 @@ test("live with change", function(){
}); });
test("live with submit", function() { test("live with submit", function() {
expect(5);
var count1 = 0, count2 = 0; var count1 = 0, count2 = 0;
jQuery("#testForm").live("submit", function(ev) { jQuery("#testForm").live("submit", function(ev) {
@ -1469,7 +1473,16 @@ test("live with submit", function() {
equals( count1, 1, "Verify form submit." ); equals( count1, 1, "Verify form submit." );
equals( count2, 1, "Verify body submit." ); equals( count2, 1, "Verify body submit." );
jQuery("#testForm input[name=sub1]").live("click", function(ev) {
ok( true, "cancelling submit still calls click handler" );
});
jQuery("#testForm input[name=sub1]")[0].click();
equals( count1, 2, "Verify form submit." );
equals( count2, 2, "Verify body submit." );
jQuery("#testForm").die("submit"); jQuery("#testForm").die("submit");
jQuery("#testForm input[name=sub1]").die("click");
jQuery("body").die("submit"); jQuery("body").die("submit");
}); });

View file

@ -402,7 +402,8 @@ test("append(Function) with incoming value", function() {
}); });
test("append the same fragment with events (Bug #6997, 5566)", function () { test("append the same fragment with events (Bug #6997, 5566)", function () {
expect(2 + (document.fireEvent ? 1 : 0)); var doExtra = !jQuery.support.noCloneEvent && document.fireEvent;
expect(2 + (doExtra ? 1 : 0));
stop(1000); stop(1000);
var element; var element;
@ -410,7 +411,7 @@ test("append the same fragment with events (Bug #6997, 5566)", function () {
// This patch modified the way that cloning occurs in IE; we need to make sure that // This patch modified the way that cloning occurs in IE; we need to make sure that
// native event handlers on the original object don't get disturbed when they are // native event handlers on the original object don't get disturbed when they are
// modified on the clone // modified on the clone
if (!jQuery.support.noCloneEvent && document.fireEvent) { if ( doExtra ) {
element = jQuery("div:first").click(function () { element = jQuery("div:first").click(function () {
ok(true, "Event exists on original after being unbound on clone"); ok(true, "Event exists on original after being unbound on clone");
jQuery(this).unbind('click'); jQuery(this).unbind('click');
@ -883,6 +884,19 @@ test("jQuery.clone() (#8017)", function() {
equals( main.childNodes.length, clone.childNodes.length, "Simple child length to ensure a large dom tree copies correctly" ); equals( main.childNodes.length, clone.childNodes.length, "Simple child length to ensure a large dom tree copies correctly" );
}); });
test("clone() (#8070)", function () {
expect(2);
jQuery('<select class="test8070"></select><select class="test8070"></select>').appendTo('#main');
var selects = jQuery('.test8070');
selects.append('<OPTION>1</OPTION><OPTION>2</OPTION>');
equals( selects[0].childNodes.length, 2, "First select got two nodes" );
equals( selects[1].childNodes.length, 2, "Second select got two nodes" );
selects.remove();
});
test("clone()", function() { test("clone()", function() {
expect(37); expect(37);
equals( 'This is a normal link: Yahoo', jQuery('#en').text(), 'Assert text for #en' ); equals( 'This is a normal link: Yahoo', jQuery('#en').text(), 'Assert text for #en' );
@ -940,6 +954,17 @@ test("clone()", function() {
div.remove(); div.remove();
clone.remove(); clone.remove();
var divEvt = jQuery("<div><ul><li>test</li></ul></div>").click(function(){
ok( false, "Bound event still exists after .clone()." );
}),
cloneEvt = divEvt.clone();
// Make sure that doing .clone() doesn't clone events
cloneEvt.trigger("click");
cloneEvt.remove();
divEvt.remove();
// this is technically an invalid object, but because of the special // this is technically an invalid object, but because of the special
// classid instantiation it is the only kind that IE has trouble with, // classid instantiation it is the only kind that IE has trouble with,
// so let's test with it too. // so let's test with it too.
@ -982,7 +1007,7 @@ test("clone()", function() {
test("clone(form element) (Bug #3879, #6655)", function() { test("clone(form element) (Bug #3879, #6655)", function() {
expect(6); expect(6);
element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>"); var element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" ); equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
@ -991,7 +1016,7 @@ test("clone(form element) (Bug #3879, #6655)", function() {
equals( clone.is(":checked"), element.is(":checked"), "Checked input cloned correctly" ); equals( clone.is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
equals( clone[0].defaultValue, "foo", "Checked input defaultValue cloned correctly" ); equals( clone[0].defaultValue, "foo", "Checked input defaultValue cloned correctly" );
equals( clone[0].defaultChecked, !jQuery.support.noCloneEvent, "Checked input defaultChecked cloned correctly" ); equals( clone[0].defaultChecked, !jQuery.support.noCloneChecked, "Checked input defaultChecked cloned correctly" );
element = jQuery("<input type='text' value='foo'>"); element = jQuery("<input type='text' value='foo'>");
clone = element.clone(); clone = element.clone();
@ -1002,6 +1027,14 @@ test("clone(form element) (Bug #3879, #6655)", function() {
equals( clone[0].defaultValue, "foo", "Textarea defaultValue cloned correctly" ); equals( clone[0].defaultValue, "foo", "Textarea defaultValue cloned correctly" );
}); });
test("clone(multiple selected options) (Bug #8129)", function() {
expect(1);
var element = jQuery("<select><option>Foo</option><option selected>Bar</option><option selected>Baz</option></select>");
equals( element.clone().find("option:selected").length, element.find("option:selected").length, "Multiple selected options cloned correctly" );
});
if (!isLocal) { if (!isLocal) {
test("clone() on XML nodes", function() { test("clone() on XML nodes", function() {
expect(2); expect(2);

View file

@ -1,510 +0,0 @@
module("selector", { teardown: moduleTeardown });
test("element", function() {
expect(21);
QUnit.reset();
ok( jQuery("*").size() >= 30, "Select all" );
var all = jQuery("*"), good = true;
for ( var i = 0; i < all.length; i++ )
if ( all[i].nodeType == 8 )
good = false;
ok( good, "Select all elements, no comment nodes" );
t( "Element Selector", "p", ["firstp","ap","sndp","en","sap","first"] );
t( "Element Selector", "body", ["body"] );
t( "Element Selector", "html", ["html"] );
t( "Parent Element", "div p", ["firstp","ap","sndp","en","sap","first"] );
equals( jQuery("param", "#object1").length, 2, "Object/param as context" );
same( jQuery("p", document.getElementsByTagName("div")).get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a context." );
same( jQuery("p", "div").get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a context." );
same( jQuery("p", jQuery("div")).get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a context." );
same( jQuery("div").find("p").get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a context." );
same( jQuery("#form").find("select").get(), q("select1","select2","select3","select4","select5"), "Finding selects with a context." );
ok( jQuery("#length").length, '&lt;input name="length"&gt; cannot be found under IE, see #945' );
ok( jQuery("#lengthtest input").length, '&lt;input name="length"&gt; cannot be found under IE, see #945' );
// Check for unique-ness and sort order
same( jQuery("p, div p").get(), jQuery("p").get(), "Check for duplicates: p, div p" );
t( "Checking sort order", "h2, h1", ["qunit-header", "qunit-banner", "qunit-userAgent"] );
t( "Checking sort order", "h2:first, h1:first", ["qunit-header", "qunit-banner"] );
t( "Checking sort order", "p, p a", ["firstp", "simon1", "ap", "google", "groups", "anchor1", "mark", "sndp", "en", "yahoo", "sap", "anchor2", "simon", "first"] );
// Test Conflict ID
same( jQuery("#lengthtest").find("#idTest").get(), q("idTest"), "Finding element with id of ID." );
same( jQuery("#lengthtest").find("[name='id']").get(), q("idTest"), "Finding element with id of ID." );
same( jQuery("#lengthtest").find("input[id='idTest']").get(), q("idTest"), "Finding elements with a context." );
});
if ( location.protocol != "file:" ) {
test("XML Document Selectors", function() {
expect(8);
stop();
jQuery.get("data/with_fries.xml", function(xml) {
equals( jQuery("foo_bar", xml).length, 1, "Element Selector with underscore" );
equals( jQuery(".component", xml).length, 1, "Class selector" );
equals( jQuery("[class*=component]", xml).length, 1, "Attribute selector for class" );
equals( jQuery("property[name=prop2]", xml).length, 1, "Attribute selector with name" );
equals( jQuery("[name=prop2]", xml).length, 1, "Attribute selector with name" );
equals( jQuery("#seite1", xml).length, 1, "Attribute selector with ID" );
equals( jQuery("component#seite1", xml).length, 1, "Attribute selector with ID" );
equals( jQuery("component", xml).filter("#seite1").length, 1, "Attribute selector filter with ID" );
start();
});
});
}
test("broken", function() {
expect(19);
function broken(name, selector) {
try {
jQuery(selector);
ok( false, name + ": " + selector );
} catch(e){
ok( typeof e === "string" && e.indexOf("Syntax error") >= 0,
name + ": " + selector );
}
}
broken( "Broken Selector", "[", [] );
broken( "Broken Selector", "(", [] );
broken( "Broken Selector", "{", [] );
broken( "Broken Selector", "<", [] );
broken( "Broken Selector", "()", [] );
broken( "Broken Selector", "<>", [] );
broken( "Broken Selector", "{}", [] );
broken( "Doesn't exist", ":visble", [] );
broken( "Nth-child", ":nth-child", [] );
broken( "Nth-child", ":nth-child(-)", [] );
// Sigh. WebKit thinks this is a real selector in qSA
// They've already fixed this and it'll be coming into
// current browsers soon.
//broken( "Nth-child", ":nth-child(asdf)", [] );
broken( "Nth-child", ":nth-child(2n+-0)", [] );
broken( "Nth-child", ":nth-child(2+0)", [] );
broken( "Nth-child", ":nth-child(- 1n)", [] );
broken( "Nth-child", ":nth-child(-1 n)", [] );
broken( "First-child", ":first-child(n)", [] );
broken( "Last-child", ":last-child(n)", [] );
broken( "Only-child", ":only-child(n)", [] );
// Make sure attribute value quoting works correctly. See: #6093
var attrbad = jQuery('<input type="hidden" value="2" name="foo.baz" id="attrbad1"/><input type="hidden" value="2" name="foo[baz]" id="attrbad2"/>').appendTo("body");
broken( "Attribute not escaped", "input[name=foo.baz]", [] );
broken( "Attribute not escaped", "input[name=foo[baz]]", [] );
attrbad.remove();
});
test("id", function() {
expect(29);
t( "ID Selector", "#body", ["body"] );
t( "ID Selector w/ Element", "body#body", ["body"] );
t( "ID Selector w/ Element", "ul#first", [] );
t( "ID selector with existing ID descendant", "#firstp #simon1", ["simon1"] );
t( "ID selector with non-existant descendant", "#firstp #foobar", [] );
t( "ID selector using UTF8", "#台北Táiběi", ["台北Táiběi"] );
t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", ["台北Táiběi","台北"] );
t( "Descendant ID selector using UTF8", "div #台北", ["台北"] );
t( "Child ID selector using UTF8", "form > #台北", ["台北"] );
t( "Escaped ID", "#foo\\:bar", ["foo:bar"] );
t( "Escaped ID", "#test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Descendant escaped ID", "div #foo\\:bar", ["foo:bar"] );
t( "Descendant escaped ID", "div #test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Child escaped ID", "form > #foo\\:bar", ["foo:bar"] );
t( "Child escaped ID", "form > #test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "ID Selector, child ID present", "#form > #radio1", ["radio1"] ); // bug #267
t( "ID Selector, not an ancestor ID", "#form #first", [] );
t( "ID Selector, not a child ID", "#form > #option1a", [] );
t( "All Children of ID", "#foo > *", ["sndp", "en", "sap"] );
t( "All Children of ID with no children", "#firstUL > *", [] );
var a = jQuery('<div><a name="tName1">tName1 A</a><a name="tName2">tName2 A</a><div id="tName1">tName1 Div</div></div>').appendTo('#main');
equals( jQuery("#tName1")[0].id, 'tName1', "ID selector with same value for a name attribute" );
equals( jQuery("#tName2").length, 0, "ID selector non-existing but name attribute on an A tag" );
a.remove();
t( "ID Selector on Form with an input that has a name of 'id'", "#lengthtest", ["lengthtest"] );
t( "ID selector with non-existant ancestor", "#asdfasdf #foobar", [] ); // bug #986
same( jQuery("body").find("div#form").get(), [], "ID selector within the context of another element" );
//#7533
equal( jQuery("<div id=\"A'B~C.D[E]\"><p>foo</p></div>").find("p").length, 1, "Find where context root is a node and has an ID with CSS3 meta characters" );
t( "Underscore ID", "#types_all", ["types_all"] );
t( "Dash ID", "#fx-queue", ["fx-queue"] );
t( "ID with weird characters in it", "#name\\+value", ["name+value"] );
});
test("class", function() {
expect(22);
t( "Class Selector", ".blog", ["mark","simon"] );
t( "Class Selector", ".GROUPS", ["groups"] );
t( "Class Selector", ".blog.link", ["simon"] );
t( "Class Selector w/ Element", "a.blog", ["mark","simon"] );
t( "Parent Class Selector", "p .blog", ["mark","simon"] );
same( jQuery(".blog", document.getElementsByTagName("p")).get(), q("mark", "simon"), "Finding elements with a context." );
same( jQuery(".blog", "p").get(), q("mark", "simon"), "Finding elements with a context." );
same( jQuery(".blog", jQuery("p")).get(), q("mark", "simon"), "Finding elements with a context." );
same( jQuery("p").find(".blog").get(), q("mark", "simon"), "Finding elements with a context." );
t( "Class selector using UTF8", ".台北Táiběi", ["utf8class1"] );
//t( "Class selector using UTF8", ".台北", ["utf8class1","utf8class2"] );
t( "Class selector using UTF8", ".台北Táiběi.台北", ["utf8class1"] );
t( "Class selector using UTF8", ".台北Táiběi, .台北", ["utf8class1","utf8class2"] );
t( "Descendant class selector using UTF8", "div .台北Táiběi", ["utf8class1"] );
t( "Child class selector using UTF8", "form > .台北Táiběi", ["utf8class1"] );
t( "Escaped Class", ".foo\\:bar", ["foo:bar"] );
t( "Escaped Class", ".test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Descendant scaped Class", "div .foo\\:bar", ["foo:bar"] );
t( "Descendant scaped Class", "div .test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Child escaped Class", "form > .foo\\:bar", ["foo:bar"] );
t( "Child escaped Class", "form > .test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
var div = document.createElement("div");
div.innerHTML = "<div class='test e'></div><div class='test'></div>";
same( jQuery(".e", div).get(), [ div.firstChild ], "Finding a second class." );
div.lastChild.className = "e";
same( jQuery(".e", div).get(), [ div.firstChild, div.lastChild ], "Finding a modified class." );
});
test("name", function() {
expect(15);
t( "Name selector", "input[name=action]", ["text1"] );
t( "Name selector with single quotes", "input[name='action']", ["text1"] );
t( "Name selector with double quotes", 'input[name="action"]', ["text1"] );
t( "Name selector non-input", "[name=test]", ["length", "fx-queue"] );
t( "Name selector non-input", "[name=div]", ["fadein"] );
t( "Name selector non-input", "*[name=iframe]", ["iframe"] );
t( "Name selector for grouped input", "input[name='types[]']", ["types_all", "types_anime", "types_movie"] )
same( jQuery("#form").find("input[name=action]").get(), q("text1"), "Name selector within the context of another element" );
same( jQuery("#form").find("input[name='foo[bar]']").get(), q("hidden2"), "Name selector for grouped form element within the context of another element" );
var form = jQuery("<form><input name='id'/></form>").appendTo("body");
equals( form.find("input").length, 1, "Make sure that rooted queries on forms (with possible expandos) work." );
form.remove();
var a = jQuery('<div><a id="tName1ID" name="tName1">tName1 A</a><a id="tName2ID" name="tName2">tName2 A</a><div id="tName1">tName1 Div</div></div>').appendTo('#main').children();
equals( a.length, 3, "Make sure the right number of elements were inserted." );
equals( a[1].id, "tName2ID", "Make sure the right number of elements were inserted." );
equals( jQuery("[name=tName1]")[0], a[0], "Find elements that have similar IDs" );
equals( jQuery("[name=tName2]")[0], a[1], "Find elements that have similar IDs" );
t( "Find elements that have similar IDs", "#tName2ID", ["tName2ID"] );
a.remove();
});
test("multiple", function() {
expect(4);
t( "Comma Support", "h2, p", ["qunit-banner","qunit-userAgent","firstp","ap","sndp","en","sap","first"]);
t( "Comma Support", "h2 , p", ["qunit-banner","qunit-userAgent","firstp","ap","sndp","en","sap","first"]);
t( "Comma Support", "h2 , p", ["qunit-banner","qunit-userAgent","firstp","ap","sndp","en","sap","first"]);
t( "Comma Support", "h2,p", ["qunit-banner","qunit-userAgent","firstp","ap","sndp","en","sap","first"]);
});
test("child and adjacent", function() {
expect(31);
t( "Child", "p > a", ["simon1","google","groups","mark","yahoo","simon"] );
t( "Child", "p> a", ["simon1","google","groups","mark","yahoo","simon"] );
t( "Child", "p >a", ["simon1","google","groups","mark","yahoo","simon"] );
t( "Child", "p>a", ["simon1","google","groups","mark","yahoo","simon"] );
t( "Child w/ Class", "p > a.blog", ["mark","simon"] );
t( "All Children", "code > *", ["anchor1","anchor2"] );
t( "All Grandchildren", "p > * > *", ["anchor1","anchor2"] );
t( "Adjacent", "#main a + a", ["groups"] );
t( "Adjacent", "#main a +a", ["groups"] );
t( "Adjacent", "#main a+ a", ["groups"] );
t( "Adjacent", "#main a+a", ["groups"] );
t( "Adjacent", "p + p", ["ap","en","sap"] );
t( "Adjacent", "p#firstp + p", ["ap"] );
t( "Adjacent", "p[lang=en] + p", ["sap"] );
t( "Adjacent", "a.GROUPS + code + a", ["mark"] );
t( "Comma, Child, and Adjacent", "#main a + a, code > a", ["groups","anchor1","anchor2"] );
t( "Element Preceded By", "p ~ div", ["foo", "moretests","tabindex-tests", "liveHandlerOrder", "siblingTest"] );
t( "Element Preceded By", "#first ~ div", ["moretests","tabindex-tests", "liveHandlerOrder", "siblingTest"] );
t( "Element Preceded By", "#groups ~ a", ["mark"] );
t( "Element Preceded By", "#length ~ input", ["idTest"] );
t( "Element Preceded By", "#siblingfirst ~ em", ["siblingnext"] );
same( jQuery("#siblingfirst").find("~ em").get(), q("siblingnext"), "Element Preceded By with a context." );
same( jQuery("#siblingfirst").find("+ em").get(), q("siblingnext"), "Element Directly Preceded By with a context." );
var a = jQuery("<div id='foo'></div><p id='bar'></p><p id='bar2'></p>");
same( jQuery("~ p", a[0]).get(), [a[1], a[2]], "Detached Element Directly Preceded By with a context." );
same( jQuery("+ p", a[0]).get(), [a[1]], "Detached Element Preceded By with a context." );
t( "Verify deep class selector", "div.blah > p > a", [] );
t( "No element deep selector", "div.foo > span > a", [] );
same( jQuery("> :first", document.getElementById("nothiddendiv")).get(), q("nothiddendivchild"), "Verify child context positional selctor" );
same( jQuery("> :eq(0)", document.getElementById("nothiddendiv")).get(), q("nothiddendivchild"), "Verify child context positional selctor" );
same( jQuery("> *:first", document.getElementById("nothiddendiv")).get(), q("nothiddendivchild"), "Verify child context positional selctor" );
t( "Non-existant ancestors", ".fototab > .thumbnails > a", [] );
});
test("attributes", function() {
expect(41);
t( "Attribute Exists", "a[title]", ["google"] );
t( "Attribute Exists", "*[title]", ["google"] );
t( "Attribute Exists", "[title]", ["google"] );
t( "Attribute Exists", "a[ title ]", ["google"] );
t( "Attribute Equals", "a[rel='bookmark']", ["simon1"] );
t( "Attribute Equals", 'a[rel="bookmark"]', ["simon1"] );
t( "Attribute Equals", "a[rel=bookmark]", ["simon1"] );
t( "Attribute Equals", "a[href='http://www.google.com/']", ["google"] );
t( "Attribute Equals", "a[ rel = 'bookmark' ]", ["simon1"] );
document.getElementById("anchor2").href = "#2";
t( "href Attribute", "p a[href^=#]", ["anchor2"] );
t( "href Attribute", "p a[href*=#]", ["simon1", "anchor2"] );
t( "for Attribute", "form label[for]", ["label-for"] );
t( "for Attribute in form", "#form [for=action]", ["label-for"] );
t( "Attribute containing []", "input[name^='foo[']", ["hidden2"] );
t( "Attribute containing []", "input[name^='foo[bar]']", ["hidden2"] );
t( "Attribute containing []", "input[name*='[bar]']", ["hidden2"] );
t( "Attribute containing []", "input[name$='bar]']", ["hidden2"] );
t( "Attribute containing []", "input[name$='[bar]']", ["hidden2"] );
t( "Attribute containing []", "input[name$='foo[bar]']", ["hidden2"] );
t( "Attribute containing []", "input[name*='foo[bar]']", ["hidden2"] );
t( "Multiple Attribute Equals", "#form input[type='radio'], #form input[type='hidden']", ["radio1", "radio2", "hidden1"] );
t( "Multiple Attribute Equals", "#form input[type='radio'], #form input[type=\"hidden\"]", ["radio1", "radio2", "hidden1"] );
t( "Multiple Attribute Equals", "#form input[type='radio'], #form input[type=hidden]", ["radio1", "radio2", "hidden1"] );
t( "Attribute selector using UTF8", "span[lang=中文]", ["台北"] );
t( "Attribute Begins With", "a[href ^= 'http://www']", ["google","yahoo"] );
t( "Attribute Ends With", "a[href $= 'org/']", ["mark"] );
t( "Attribute Contains", "a[href *= 'google']", ["google","groups"] );
t( "Attribute Is Not Equal", "#ap a[hreflang!='en']", ["google","groups","anchor1"] );
var opt = document.getElementById("option1a"),
match = (window.Sizzle || window.jQuery.find).matchesSelector;
opt.setAttribute("test", "");
ok( match( opt, "[id*=option1][type!=checkbox]" ), "Attribute Is Not Equal Matches" );
ok( match( opt, "[id*=option1]" ), "Attribute With No Quotes Contains Matches" );
ok( match( opt, "[test=]" ), "Attribute With No Quotes No Content Matches" );
ok( match( opt, "[id=option1a]" ), "Attribute With No Quotes Equals Matches" );
ok( match( document.getElementById("simon1"), "a[href*=#]" ), "Attribute With No Quotes Href Contains Matches" );
t("Empty values", "#select1 option[value='']", ["option1a"]);
t("Empty values", "#select1 option[value!='']", ["option1b","option1c","option1d"]);
t("Select options via :selected", "#select1 option:selected", ["option1a"] );
t("Select options via :selected", "#select2 option:selected", ["option2d"] );
t("Select options via :selected", "#select3 option:selected", ["option3b", "option3c"] );
t( "Grouped Form Elements", "input[name='foo[bar]']", ["hidden2"] );
// Make sure attribute value quoting works correctly. See: #6093
var attrbad = jQuery('<input type="hidden" value="2" name="foo.baz" id="attrbad1"/><input type="hidden" value="2" name="foo[baz]" id="attrbad2"/>').appendTo("body");
t("Find escaped attribute value", "input[name=foo\\.baz]", ["attrbad1"]);
t("Find escaped attribute value", "input[name=foo\\[baz\\]]", ["attrbad2"]);
attrbad.remove();
});
test("pseudo - child", function() {
expect(38);
t( "First Child", "p:first-child", ["firstp","sndp"] );
t( "Last Child", "p:last-child", ["sap"] );
t( "Only Child", "#main a:only-child", ["simon1","anchor1","yahoo","anchor2","liveLink1","liveLink2"] );
t( "Empty", "ul:empty", ["firstUL"] );
t( "Is A Parent", "p:parent", ["firstp","ap","sndp","en","sap","first"] );
t( "First Child", "p:first-child", ["firstp","sndp"] );
t( "Nth Child", "p:nth-child(1)", ["firstp","sndp"] );
t( "Nth Child With Whitespace", "p:nth-child( 1 )", ["firstp","sndp"] );
t( "Not Nth Child", "p:not(:nth-child(1))", ["ap","en","sap","first"] );
// Verify that the child position isn't being cached improperly
jQuery("p:first-child").after("<div></div>");
jQuery("p:first-child").before("<div></div>").next().remove();
t( "First Child", "p:first-child", [] );
QUnit.reset();
t( "Last Child", "p:last-child", ["sap"] );
t( "Last Child", "#main a:last-child", ["simon1","anchor1","mark","yahoo","anchor2","simon","liveLink1","liveLink2"] );
t( "Nth-child", "#main form#form > *:nth-child(2)", ["text1"] );
t( "Nth-child", "#main form#form > :nth-child(2)", ["text1"] );
t( "Nth-child", "#form select:first option:nth-child(-1)", [] );
t( "Nth-child", "#form select:first option:nth-child(3)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(0n+3)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(1n+0)", ["option1a", "option1b", "option1c", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(1n)", ["option1a", "option1b", "option1c", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(n)", ["option1a", "option1b", "option1c", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(+n)", ["option1a", "option1b", "option1c", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(even)", ["option1b", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(odd)", ["option1a", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(2n)", ["option1b", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(2n+1)", ["option1a", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(2n + 1)", ["option1a", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(+2n + 1)", ["option1a", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(3n)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(3n+1)", ["option1a", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(3n+2)", ["option1b"] );
t( "Nth-child", "#form select:first option:nth-child(3n+3)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(3n-1)", ["option1b"] );
t( "Nth-child", "#form select:first option:nth-child(3n-2)", ["option1a", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(3n-3)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(3n+0)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(-1n+3)", ["option1a", "option1b", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(-n+3)", ["option1a", "option1b", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(-1n + 3)", ["option1a", "option1b", "option1c"] );
});
test("pseudo - misc", function() {
expect(7);
t( "Headers", ":header", ["qunit-header", "qunit-banner", "qunit-userAgent"] );
t( "Has Children - :has()", "p:has(a)", ["firstp","ap","en","sap"] );
var select = document.getElementById("select1");
ok( (window.Sizzle || window.jQuery.find).matchesSelector( select, ":has(option)" ), "Has Option Matches" );
t( "Text Contains", "a:contains(Google)", ["google","groups"] );
t( "Text Contains", "a:contains(Google Groups)", ["groups"] );
t( "Text Contains", "a:contains(Google Groups (Link))", ["groups"] );
t( "Text Contains", "a:contains((Link))", ["groups"] );
});
test("pseudo - :not", function() {
expect(24);
t( "Not", "a.blog:not(.link)", ["mark"] );
t( "Not - multiple", "#form option:not(:contains(Nothing),#option1b,:selected)", ["option1c", "option1d", "option2b", "option2c", "option3d", "option3e", "option4e", "option5b", "option5c"] );
t( "Not - recursive", "#form option:not(:not(:selected))[id^='option3']", [ "option3b", "option3c"] );
t( ":not() failing interior", "p:not(.foo)", ["firstp","ap","sndp","en","sap","first"] );
t( ":not() failing interior", "p:not(div.foo)", ["firstp","ap","sndp","en","sap","first"] );
t( ":not() failing interior", "p:not(p.foo)", ["firstp","ap","sndp","en","sap","first"] );
t( ":not() failing interior", "p:not(#blargh)", ["firstp","ap","sndp","en","sap","first"] );
t( ":not() failing interior", "p:not(div#blargh)", ["firstp","ap","sndp","en","sap","first"] );
t( ":not() failing interior", "p:not(p#blargh)", ["firstp","ap","sndp","en","sap","first"] );
t( ":not Multiple", "p:not(a)", ["firstp","ap","sndp","en","sap","first"] );
t( ":not Multiple", "p:not(a, b)", ["firstp","ap","sndp","en","sap","first"] );
t( ":not Multiple", "p:not(a, b, div)", ["firstp","ap","sndp","en","sap","first"] );
t( ":not Multiple", "p:not(p)", [] );
t( ":not Multiple", "p:not(a,p)", [] );
t( ":not Multiple", "p:not(p,a)", [] );
t( ":not Multiple", "p:not(a,p,b)", [] );
t( ":not Multiple", ":input:not(:image,:input,:submit)", [] );
t( "No element not selector", ".container div:not(.excluded) div", [] );
t( ":not() Existing attribute", "#form select:not([multiple])", ["select1", "select2", "select5"]);
t( ":not() Equals attribute", "#form select:not([name=select1])", ["select2", "select3", "select4","select5"]);
t( ":not() Equals quoted attribute", "#form select:not([name='select1'])", ["select2", "select3", "select4", "select5"]);
t( ":not() Multiple Class", "#foo a:not(.blog)", ["yahoo","anchor2"] );
t( ":not() Multiple Class", "#foo a:not(.link)", ["yahoo","anchor2"] );
t( ":not() Multiple Class", "#foo a:not(.blog.link)", ["yahoo","anchor2"] );
});
test("pseudo - position", function() {
expect(25);
t( "nth Element", "p:nth(1)", ["ap"] );
t( "First Element", "p:first", ["firstp"] );
t( "Last Element", "p:last", ["first"] );
t( "Even Elements", "p:even", ["firstp","sndp","sap"] );
t( "Odd Elements", "p:odd", ["ap","en","first"] );
t( "Position Equals", "p:eq(1)", ["ap"] );
t( "Position Greater Than", "p:gt(0)", ["ap","sndp","en","sap","first"] );
t( "Position Less Than", "p:lt(3)", ["firstp","ap","sndp"] );
t( "Check position filtering", "div#nothiddendiv:eq(0)", ["nothiddendiv"] );
t( "Check position filtering", "div#nothiddendiv:last", ["nothiddendiv"] );
t( "Check position filtering", "div#nothiddendiv:not(:gt(0))", ["nothiddendiv"] );
t( "Check position filtering", "#foo > :not(:first)", ["en", "sap"] );
t( "Check position filtering", "select > :not(:gt(2))", ["option1a", "option1b", "option1c"] );
t( "Check position filtering", "select:lt(2) :not(:first)", ["option1b", "option1c", "option1d", "option2a", "option2b", "option2c", "option2d"] );
t( "Check position filtering", "div.nothiddendiv:eq(0)", ["nothiddendiv"] );
t( "Check position filtering", "div.nothiddendiv:last", ["nothiddendiv"] );
t( "Check position filtering", "div.nothiddendiv:not(:lt(0))", ["nothiddendiv"] );
t( "Check element position", "div div:eq(0)", ["nothiddendivchild"] );
t( "Check element position", "div div:eq(5)", ["t2037"] );
t( "Check element position", "div div:eq(28)", ["hide"] );
t( "Check element position", "div div:first", ["nothiddendivchild"] );
t( "Check element position", "div > div:first", ["nothiddendivchild"] );
t( "Check element position", "#dl div:first div:first", ["foo"] );
t( "Check element position", "#dl div:first > div:first", ["foo"] );
t( "Check element position", "div#nothiddendiv:first > div:first", ["nothiddendivchild"] );
});
if ( (window.Sizzle || jQuery.find).selectors.filters.visibility ) {
test("pseudo - visibility", function() {
expect(11);
t( "Is Visible", "#form input:visible", [] );
t( "Is Visible", "div:visible:not(#qunit-testrunner-toolbar):lt(2)", ["nothiddendiv", "nothiddendivchild"] );
t( "Is Hidden", "#form input:hidden", ["text1","text2","radio1","radio2","check1","check2","hidden1","hidden2","name","search"] );
t( "Is Hidden", "#main:hidden", ["main"] );
t( "Is Hidden", "#dl:hidden", ["dl"] );
var $div = jQuery('<div/>').appendTo("body");
$div.css({ fontSize: 0, lineHeight: 0 });// IE also needs to set font-size and line-height to 0
$div.width(1).height(0);
t( "Is Visible", '#nothiddendivchild:visible', ['nothiddendivchild'] );
t( "Is Not Visible", '#nothiddendivchild:hidden', [] );
$div.width(0).height(1);
t( "Is Visible", '#nothiddendivchild:visible', ['nothiddendivchild'] );
t( "Is Not Visible", '#nothiddendivchild:hidden', [] );
$div.width(1).height(1);
t( "Is Visible", '#nothiddendivchild:visible', ['nothiddendivchild'] );
t( "Is Not Visible", '#nothiddendivchild:hidden', [] );
$div.remove();
});
}
test("pseudo - form", function() {
expect(8);
t( "Form element :input", "#form :input", ["text1", "text2", "radio1", "radio2", "check1", "check2", "hidden1", "hidden2", "name", "search", "button", "area1", "select1", "select2", "select3", "select4", "select5"] );
t( "Form element :radio", "#form :radio", ["radio1", "radio2"] );
t( "Form element :checkbox", "#form :checkbox", ["check1", "check2"] );
t( "Form element :text", "#form :text:not(#search)", ["text1", "text2", "hidden2", "name"] );
t( "Form element :radio:checked", "#form :radio:checked", ["radio2"] );
t( "Form element :checkbox:checked", "#form :checkbox:checked", ["check1"] );
t( "Form element :radio:checked, :checkbox:checked", "#form :radio:checked, #form :checkbox:checked", ["radio2", "check1"] );
t( "Selected Option Element", "#form option:selected", ["option1a","option2d","option3b","option3c","option4b","option4c","option4d","option5a"] );
});

View file

@ -147,9 +147,9 @@ test("filter(Selector|undefined)", function() {
test("filter(Function)", function() { test("filter(Function)", function() {
expect(2); expect(2);
same( jQuery("p").filter(function() { return !jQuery("a", this).length }).get(), q("sndp", "first"), "filter(Function)" ); same( jQuery("#main p").filter(function() { return !jQuery("a", this).length }).get(), q("sndp", "first"), "filter(Function)" );
same( jQuery("p").filter(function(i, elem) { return !jQuery("a", elem).length }).get(), q("sndp", "first"), "filter(Function) using arg" ); same( jQuery("#main p").filter(function(i, elem) { return !jQuery("a", elem).length }).get(), q("sndp", "first"), "filter(Function) using arg" );
}); });
test("filter(Element)", function() { test("filter(Element)", function() {
@ -228,7 +228,7 @@ test("not(Element)", function() {
}); });
test("not(Function)", function() { test("not(Function)", function() {
same( jQuery("p").not(function() { return jQuery("a", this).length }).get(), q("sndp", "first"), "not(Function)" ); same( jQuery("#main p").not(function() { return jQuery("a", this).length }).get(), q("sndp", "first"), "not(Function)" );
}); });
test("not(Array)", function() { test("not(Array)", function() {

View file

@ -1 +1 @@
1.5pre 1.5.2pre