define( [
"./core",
"./var/document",
- "./var/rnotwhite",
+ "./var/rnothtmlwhite",
"./ajax/var/location",
"./ajax/var/nonce",
"./ajax/var/rquery",
"./event/trigger",
"./deferred",
"./serialize" // jQuery.param
-], function( jQuery, document, rnotwhite, location, nonce, rquery ) {
+], function( jQuery, document, rnothtmlwhite, location, nonce, rquery ) {
"use strict";
var dataType,
i = 0,
- dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+ dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
if ( jQuery.isFunction( func ) ) {
s.type = options.method || options.type || s.method || s.type;
// Extract dataTypes list
- s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+ s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
// A cross-domain request is in order when the origin doesn't match the current origin.
if ( s.crossDomain == null ) {
define( [
"../core",
+ "../core/stripAndCollapse",
"../core/parseHTML",
"../ajax",
"../traversing",
"../manipulation",
"../selector"
-], function( jQuery ) {
+], function( jQuery, stripAndCollapse ) {
"use strict";
off = url.indexOf( " " );
if ( off > -1 ) {
- selector = jQuery.trim( url.slice( off ) );
+ selector = stripAndCollapse( url.slice( off ) );
url = url.slice( 0, off );
}
"../core",
"../core/access",
"./support",
- "../var/rnotwhite",
+ "../var/rnothtmlwhite",
"../selector"
-], function( jQuery, access, support, rnotwhite ) {
+], function( jQuery, access, support, rnothtmlwhite ) {
"use strict";
removeAttr: function( elem, value ) {
var name,
i = 0,
- attrNames = value && value.match( rnotwhite );
+
+ // Attribute names can contain non-HTML whitespace characters
+ // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
+ attrNames = value && value.match( rnothtmlwhite );
if ( attrNames && elem.nodeType === 1 ) {
while ( ( name = attrNames[ i++ ] ) ) {
define( [
"../core",
- "../var/rnotwhite",
+ "../core/stripAndCollapse",
+ "../var/rnothtmlwhite",
"../data/var/dataPriv",
"../core/init"
-], function( jQuery, rnotwhite, dataPriv ) {
+], function( jQuery, stripAndCollapse, rnothtmlwhite, dataPriv ) {
"use strict";
-var rclass = /[\t\r\n\f]/g;
-
function getClass( elem ) {
return elem.getAttribute && elem.getAttribute( "class" ) || "";
}
}
if ( typeof value === "string" && value ) {
- classes = value.match( rnotwhite ) || [];
+ classes = value.match( rnothtmlwhite ) || [];
while ( ( elem = this[ i++ ] ) ) {
curValue = getClass( elem );
- cur = elem.nodeType === 1 &&
- ( " " + curValue + " " ).replace( rclass, " " );
+ cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
if ( cur ) {
j = 0;
}
// Only assign if different to avoid unneeded rendering.
- finalValue = jQuery.trim( cur );
+ finalValue = stripAndCollapse( cur );
if ( curValue !== finalValue ) {
elem.setAttribute( "class", finalValue );
}
}
if ( typeof value === "string" && value ) {
- classes = value.match( rnotwhite ) || [];
+ classes = value.match( rnothtmlwhite ) || [];
while ( ( elem = this[ i++ ] ) ) {
curValue = getClass( elem );
// This expression is here for better compressibility (see addClass)
- cur = elem.nodeType === 1 &&
- ( " " + curValue + " " ).replace( rclass, " " );
+ cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
if ( cur ) {
j = 0;
}
// Only assign if different to avoid unneeded rendering.
- finalValue = jQuery.trim( cur );
+ finalValue = stripAndCollapse( cur );
if ( curValue !== finalValue ) {
elem.setAttribute( "class", finalValue );
}
// Toggle individual class names
i = 0;
self = jQuery( this );
- classNames = value.match( rnotwhite ) || [];
+ classNames = value.match( rnothtmlwhite ) || [];
while ( ( className = classNames[ i++ ] ) ) {
className = " " + selector + " ";
while ( ( elem = this[ i++ ] ) ) {
if ( elem.nodeType === 1 &&
- ( " " + getClass( elem ) + " " ).replace( rclass, " " )
- .indexOf( className ) > -1
- ) {
- return true;
+ ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
+ return true;
}
}
define( [
"../core",
+ "../core/stripAndCollapse",
"./support",
"../core/init"
-], function( jQuery, support ) {
+], function( jQuery, stripAndCollapse, support ) {
"use strict";
-var rreturn = /\r/g,
- rspaces = /[\x20\t\r\n\f]+/g;
+var rreturn = /\r/g;
jQuery.fn.extend( {
val: function( value ) {
// option.text throws exceptions (#14686, #14858)
// Strip and collapse whitespace
// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
- jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
+ stripAndCollapse( jQuery.text( elem ) );
}
},
select: {
define( [
"./core",
- "./var/rnotwhite"
-], function( jQuery, rnotwhite ) {
+ "./var/rnothtmlwhite"
+], function( jQuery, rnothtmlwhite ) {
"use strict";
// Convert String-formatted options into Object-formatted ones
function createOptions( options ) {
var object = {};
- jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+ jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
object[ flag ] = true;
} );
return object;
--- /dev/null
+define( function() {
+ "use strict";
+
+ // Strip and collapse whitespace according to HTML spec
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace
+ var rhtmlSpace = /[\x20\t\r\n\f]+/g,
+ stripAndCollapse = function( value ) {
+ return ( " " + value + " " ).replace( rhtmlSpace, " " ).slice( 1, -1 );
+ };
+
+ return stripAndCollapse;
+} );
define( [
"../core",
- "../var/rnotwhite",
+ "../var/rnothtmlwhite",
"./var/acceptData"
-], function( jQuery, rnotwhite, acceptData ) {
+], function( jQuery, rnothtmlwhite, acceptData ) {
"use strict";
// Otherwise, create an array by matching non-whitespace
key = key in cache ?
[ key ] :
- ( key.match( rnotwhite ) || [] );
+ ( key.match( rnothtmlwhite ) || [] );
}
i = key.length;
"./core",
"./var/document",
"./var/rcssNum",
- "./var/rnotwhite",
+ "./var/rnothtmlwhite",
"./css/var/cssExpand",
"./css/var/isHiddenWithinTree",
"./css/var/swap",
"./manipulation",
"./css",
"./effects/Tween"
-], function( jQuery, document, rcssNum, rnotwhite, cssExpand, isHiddenWithinTree, swap,
+], function( jQuery, document, rcssNum, rnothtmlwhite, cssExpand, isHiddenWithinTree, swap,
adjustCSS, dataPriv, showHide ) {
"use strict";
callback = props;
props = [ "*" ];
} else {
- props = props.match( rnotwhite );
+ props = props.match( rnothtmlwhite );
}
var prop,
"./core",
"./var/document",
"./var/documentElement",
- "./var/rnotwhite",
+ "./var/rnothtmlwhite",
"./var/slice",
"./data/var/dataPriv",
"./core/init",
"./selector"
-], function( jQuery, document, documentElement, rnotwhite, slice, dataPriv ) {
+], function( jQuery, document, documentElement, rnothtmlwhite, slice, dataPriv ) {
"use strict";
}
// Handle multiple events separated by a space
- types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
t = types.length;
while ( t-- ) {
tmp = rtypenamespace.exec( types[ t ] ) || [];
}
// Once for each type.namespace in types; type may be omitted
- types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
t = types.length;
while ( t-- ) {
tmp = rtypenamespace.exec( types[ t ] ) || [];
--- /dev/null
+define( function() {
+ "use strict";
+
+ // Only count HTML whitespace
+ // Other whitespace should count in values
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#space-character
+ return ( /[^\x20\t\r\n\f]+/g );
+} );
+++ /dev/null
-define( function() {
- "use strict";
-
- return ( /\S+/g );
-} );
<div class="user">This is a user</div>
<div class="teacher">This is a teacher</div>
<div id="superuser">This is a superuser</div>
+<div id="whitespace\xA0">This is a superuser with non-HTML whitespace</div>
} );
} );
+ // Selector should be trimmed to avoid leading spaces (#14773)
+ // Selector should include any valid non-HTML whitespace (#3003)
+ QUnit.test( "jQuery.fn.load( URL_SELECTOR with non-HTML whitespace(#3003) )", function( assert ) {
+ assert.expect( 1 );
+ var done = assert.async();
+ jQuery( "#first" ).load( "data/test3.html #whitespace\\\\xA0 ", function() {
+ assert.strictEqual( jQuery( this ).children( "div" ).length, 1, "Verify that specific elements were injected" );
+ done();
+ } );
+ } );
+
QUnit.asyncTest( "jQuery.fn.load( String, Function ) - simple: inject text into DOM", 2, function( assert ) {
jQuery( "#first" ).load( url( "data/name.html" ), function() {
assert.ok( /^ERROR/.test( jQuery( "#first" ).text() ), "Check if content was injected into the DOM" );
} );
} );
+QUnit.test( "removeAttr(Multi String, non-HTML whitespace is valid in attribute names (gh-3003)", function( assert ) {
+ assert.expect( 8 );
+
+ var div = jQuery( "<div id='a' data-\xA0='b' title='c' rel='d'></div>" );
+ var tests = {
+ id: "a",
+ "data-\xA0": "b",
+ title: "c",
+ rel: "d"
+ };
+
+ jQuery.each( tests, function( key, val ) {
+ assert.equal( div.attr( key ), val, "Attribute \"" + key + "\" exists, and has a value of \"" + val + "\"" );
+ } );
+
+ div.removeAttr( "id data-\xA0 title rel " );
+
+ jQuery.each( tests, function( key ) {
+ assert.equal( div.attr( key ), undefined, "Attribute \"" + key + "\" was removed" );
+ } );
+} );
+
QUnit.test( "prop(String, Object)", function( assert ) {
assert.expect( 17 );
} );
QUnit.test( "select.val(space characters) (gh-2978)", function( assert ) {
- assert.expect( 35 );
+ assert.expect( 37 );
var $select = jQuery( "<select/>" ).appendTo( "#qunit-fixture" ),
spaces = {
html += "<option>" + value + "text</option>";
$select.html( html );
- $select.val( "text" );
- assert.equal( $select.val(), "text", "Value with space character at beginning or end is stripped (" + key + ") selected (text)" );
if ( /^\\u/.test( key ) ) {
+ $select.val( val + "text" );
+ assert.equal( $select.val(), val + "text", "Value with non-HTML space character at beginning is not stripped (" + key + ") selected (" + key + "text)" );
$select.val( "te" + val + "xt" );
assert.equal( $select.val(), "te" + val + "xt", "Value with non-space whitespace character (" + key + ") in the middle selected (text)" );
+ $select.val( "text" + val );
+ assert.equal( $select.val(), "text" + val, "Value with non-HTML space character at end is not stripped (" + key + ") selected (text" + key + ")" );
} else {
+ $select.val( "text" );
+ assert.equal( $select.val(), "text", "Value with HTML space character at beginning or end is stripped (" + key + ") selected (text)" );
$select.val( "te xt" );
assert.equal( $select.val(), "te xt", "Value with space character (" + key + ") in the middle selected (text)" );
}
"Did not find a class when not present" );
} );
+QUnit.test( "addClass, removeClass, hasClass on elements with classes with non-HTML whitespace (gh-3072, gh-3003)", function( assert ) {
+ assert.expect( 9 );
+
+ var $elem = jQuery( "<div class=' test'></div>" );
+
+ function testMatches() {
+ assert.ok( $elem.is( ".\\A0 test" ), "Element matches with collapsed space" );
+ assert.ok( $elem.is( ".\\A0test" ), "Element matches with non-breaking space" );
+ assert.ok( $elem.hasClass( "\xA0test" ), "Element has class with non-breaking space" );
+ }
+
+ testMatches();
+ $elem.addClass( "foo" );
+ testMatches();
+ $elem.removeClass( "foo" );
+ testMatches();
+} );
+
QUnit.test( "contents().hasClass() returns correct values", function( assert ) {
assert.expect( 2 );