mirror of
https://github.com/jquery/jquery-ui.git
synced 2024-11-21 11:04:24 +00:00
All: Stop relying on jquery-patch.js internally, add tests
Avoid relying on jQuery patches. Instead: * use `CSS.escape` instead of `jQuery.escapeSelector` * use `.filter()` with a proper handler instead of `.even()` Keep `jquery-patch.js` for backwards compatibility, though. Also, add tests for jquery-patch. Ref gh-2249
This commit is contained in:
parent
f90eab84b5
commit
9887579b61
@ -35,6 +35,7 @@ var versions = {
|
||||
"Droppable": "droppable/droppable.html",
|
||||
"Effects": "effects/effects.html",
|
||||
"Form Reset Mixin": "form-reset-mixin/form-reset-mixin.html",
|
||||
"jQuery Patch": "jquery-patch/jquery-patch.html",
|
||||
"Menu": "menu/menu.html",
|
||||
"Position": "position/position.html",
|
||||
"Progressbar": "progressbar/progressbar.html",
|
||||
|
8
tests/lib/bootstrap.js
vendored
8
tests/lib/bootstrap.js
vendored
@ -171,14 +171,6 @@ function migrateUrl() {
|
||||
}
|
||||
}
|
||||
|
||||
var jQueryVersion = parseUrl().jquery;
|
||||
|
||||
// Load the jQuery fixes, if necessary
|
||||
if ( !jQueryVersion ||
|
||||
( jQueryVersion.indexOf( "git" ) === -1 && parseFloat( jQueryVersion ) < 4 ) ) {
|
||||
modules.unshift( "ui/jquery-patch" );
|
||||
}
|
||||
|
||||
requireTests( modules, { backCompat: backCompat } );
|
||||
} )();
|
||||
|
||||
|
@ -11,6 +11,7 @@ export const suites = [
|
||||
"droppable",
|
||||
"effects",
|
||||
"form-reset-mixin",
|
||||
"jquery-patch",
|
||||
"menu",
|
||||
"position",
|
||||
"progressbar",
|
||||
|
@ -16,7 +16,17 @@ common.testWidget( "accordion", {
|
||||
disabled: false,
|
||||
event: "click",
|
||||
header: function( elem ) {
|
||||
return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() );
|
||||
return elem
|
||||
.find( "> li > :first-child" )
|
||||
.add(
|
||||
elem.find( "> :not(li)" )
|
||||
|
||||
// Support: jQuery <3.5 only
|
||||
// We could use `.even()` but that's unavailable in older jQuery.
|
||||
.filter( function( i ) {
|
||||
return i % 2 === 0;
|
||||
} )
|
||||
);
|
||||
},
|
||||
heightStyle: "auto",
|
||||
icons: {
|
||||
|
@ -28,6 +28,7 @@
|
||||
"droppable/droppable.html",
|
||||
"effects/effects.html",
|
||||
"form-reset-mixin/form-reset-mixin.html",
|
||||
"jquery-patch/jquery-patch.html",
|
||||
"menu/menu.html",
|
||||
"position/position.html",
|
||||
"progressbar/progressbar.html",
|
||||
|
@ -55,6 +55,7 @@
|
||||
|
||||
<h2>Utilities</h2>
|
||||
<ul>
|
||||
<li><a href="jquery-patch/jquery-patch.html">jQuery Patch</a></li>
|
||||
<li><a href="position/position.html">Position</a></li>
|
||||
</ul>
|
||||
|
||||
|
26
tests/unit/jquery-patch/all.html
Normal file
26
tests/unit/jquery-patch/all.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>jQuery UI Form Reset Mixin Test Suite</title>
|
||||
|
||||
<script src="../../../external/jquery/jquery.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="../../../external/qunit/qunit.css">
|
||||
<link rel="stylesheet" href="../../lib/vendor/qunit-composite/qunit-composite.css">
|
||||
<script src="../../../external/qunit/qunit.js"></script>
|
||||
<script src="../../lib/vendor/qunit-composite/qunit-composite.js"></script>
|
||||
<script src="../subsuite.js"></script>
|
||||
|
||||
<script>
|
||||
testAllVersions( "jquery-patch" );
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture">
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
141
tests/unit/jquery-patch/core.js
vendored
Normal file
141
tests/unit/jquery-patch/core.js
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
define( [
|
||||
"qunit",
|
||||
"jquery",
|
||||
"lib/helper",
|
||||
"ui/jquery-patch"
|
||||
], function( QUnit, $, helper ) {
|
||||
"use strict";
|
||||
|
||||
QUnit.module( "jquery-patch: core", { afterEach: helper.moduleAfterEach } );
|
||||
|
||||
QUnit.test( "jQuery.escapeSelector", function( assert ) {
|
||||
assert.expect( 58 );
|
||||
|
||||
// Edge cases
|
||||
assert.equal( jQuery.escapeSelector(), "undefined", "Converts undefined to string" );
|
||||
assert.equal( jQuery.escapeSelector( "-" ), "\\-", "Escapes standalone dash" );
|
||||
assert.equal( jQuery.escapeSelector( "-a" ), "-a", "Doesn't escape leading dash followed by non-number" );
|
||||
assert.equal( jQuery.escapeSelector( "--" ), "--", "Doesn't escape standalone double dash" );
|
||||
assert.equal( jQuery.escapeSelector( "\uFFFD" ), "\uFFFD",
|
||||
"Doesn't escape standalone replacement character" );
|
||||
assert.equal( jQuery.escapeSelector( "a\uFFFD" ), "a\uFFFD",
|
||||
"Doesn't escape trailing replacement character" );
|
||||
assert.equal( jQuery.escapeSelector( "\uFFFDb" ), "\uFFFDb",
|
||||
"Doesn't escape leading replacement character" );
|
||||
assert.equal( jQuery.escapeSelector( "a\uFFFDb" ), "a\uFFFDb",
|
||||
"Doesn't escape embedded replacement character" );
|
||||
|
||||
// Derived from CSSOM tests
|
||||
// https://test.csswg.org/harness/test/cssom-1_dev/section/7.1/
|
||||
|
||||
// String conversion
|
||||
assert.equal( jQuery.escapeSelector( true ), "true", "Converts boolean true to string" );
|
||||
assert.equal( jQuery.escapeSelector( false ), "false", "Converts boolean true to string" );
|
||||
assert.equal( jQuery.escapeSelector( null ), "null", "Converts null to string" );
|
||||
assert.equal( jQuery.escapeSelector( "" ), "", "Doesn't modify empty string" );
|
||||
|
||||
// Null bytes
|
||||
assert.equal( jQuery.escapeSelector( "\0" ), "\uFFFD",
|
||||
"Escapes null-character input as replacement character" );
|
||||
assert.equal( jQuery.escapeSelector( "a\0" ), "a\uFFFD",
|
||||
"Escapes trailing-null input as replacement character" );
|
||||
assert.equal( jQuery.escapeSelector( "\0b" ), "\uFFFDb",
|
||||
"Escapes leading-null input as replacement character" );
|
||||
assert.equal( jQuery.escapeSelector( "a\0b" ), "a\uFFFDb",
|
||||
"Escapes embedded-null input as replacement character" );
|
||||
|
||||
// Number prefix
|
||||
assert.equal( jQuery.escapeSelector( "0a" ), "\\30 a", "Escapes leading 0" );
|
||||
assert.equal( jQuery.escapeSelector( "1a" ), "\\31 a", "Escapes leading 1" );
|
||||
assert.equal( jQuery.escapeSelector( "2a" ), "\\32 a", "Escapes leading 2" );
|
||||
assert.equal( jQuery.escapeSelector( "3a" ), "\\33 a", "Escapes leading 3" );
|
||||
assert.equal( jQuery.escapeSelector( "4a" ), "\\34 a", "Escapes leading 4" );
|
||||
assert.equal( jQuery.escapeSelector( "5a" ), "\\35 a", "Escapes leading 5" );
|
||||
assert.equal( jQuery.escapeSelector( "6a" ), "\\36 a", "Escapes leading 6" );
|
||||
assert.equal( jQuery.escapeSelector( "7a" ), "\\37 a", "Escapes leading 7" );
|
||||
assert.equal( jQuery.escapeSelector( "8a" ), "\\38 a", "Escapes leading 8" );
|
||||
assert.equal( jQuery.escapeSelector( "9a" ), "\\39 a", "Escapes leading 9" );
|
||||
|
||||
// Letter-number prefix
|
||||
assert.equal( jQuery.escapeSelector( "a0b" ), "a0b", "Doesn't escape embedded 0" );
|
||||
assert.equal( jQuery.escapeSelector( "a1b" ), "a1b", "Doesn't escape embedded 1" );
|
||||
assert.equal( jQuery.escapeSelector( "a2b" ), "a2b", "Doesn't escape embedded 2" );
|
||||
assert.equal( jQuery.escapeSelector( "a3b" ), "a3b", "Doesn't escape embedded 3" );
|
||||
assert.equal( jQuery.escapeSelector( "a4b" ), "a4b", "Doesn't escape embedded 4" );
|
||||
assert.equal( jQuery.escapeSelector( "a5b" ), "a5b", "Doesn't escape embedded 5" );
|
||||
assert.equal( jQuery.escapeSelector( "a6b" ), "a6b", "Doesn't escape embedded 6" );
|
||||
assert.equal( jQuery.escapeSelector( "a7b" ), "a7b", "Doesn't escape embedded 7" );
|
||||
assert.equal( jQuery.escapeSelector( "a8b" ), "a8b", "Doesn't escape embedded 8" );
|
||||
assert.equal( jQuery.escapeSelector( "a9b" ), "a9b", "Doesn't escape embedded 9" );
|
||||
|
||||
// Dash-number prefix
|
||||
assert.equal( jQuery.escapeSelector( "-0a" ), "-\\30 a", "Escapes 0 after leading dash" );
|
||||
assert.equal( jQuery.escapeSelector( "-1a" ), "-\\31 a", "Escapes 1 after leading dash" );
|
||||
assert.equal( jQuery.escapeSelector( "-2a" ), "-\\32 a", "Escapes 2 after leading dash" );
|
||||
assert.equal( jQuery.escapeSelector( "-3a" ), "-\\33 a", "Escapes 3 after leading dash" );
|
||||
assert.equal( jQuery.escapeSelector( "-4a" ), "-\\34 a", "Escapes 4 after leading dash" );
|
||||
assert.equal( jQuery.escapeSelector( "-5a" ), "-\\35 a", "Escapes 5 after leading dash" );
|
||||
assert.equal( jQuery.escapeSelector( "-6a" ), "-\\36 a", "Escapes 6 after leading dash" );
|
||||
assert.equal( jQuery.escapeSelector( "-7a" ), "-\\37 a", "Escapes 7 after leading dash" );
|
||||
assert.equal( jQuery.escapeSelector( "-8a" ), "-\\38 a", "Escapes 8 after leading dash" );
|
||||
assert.equal( jQuery.escapeSelector( "-9a" ), "-\\39 a", "Escapes 9 after leading dash" );
|
||||
|
||||
// Double dash prefix
|
||||
assert.equal( jQuery.escapeSelector( "--a" ), "--a", "Doesn't escape leading double dash" );
|
||||
|
||||
// Miscellany
|
||||
assert.equal( jQuery.escapeSelector( "\x01\x02\x1E\x1F" ), "\\1 \\2 \\1e \\1f ",
|
||||
"Escapes C0 control characters" );
|
||||
assert.equal( jQuery.escapeSelector( "\x80\x2D\x5F\xA9" ), "\x80\x2D\x5F\xA9",
|
||||
"Doesn't escape general punctuation or non-ASCII ISO-8859-1 characters" );
|
||||
assert.equal(
|
||||
jQuery.escapeSelector( "\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90" +
|
||||
"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F" ),
|
||||
"\\7f \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90" +
|
||||
"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F",
|
||||
"Escapes DEL control character"
|
||||
);
|
||||
assert.equal( jQuery.escapeSelector( "\xA0\xA1\xA2" ), "\xA0\xA1\xA2",
|
||||
"Doesn't escape non-ASCII ISO-8859-1 characters" );
|
||||
assert.equal( jQuery.escapeSelector( "a0123456789b" ), "a0123456789b",
|
||||
"Doesn't escape embedded numbers" );
|
||||
assert.equal( jQuery.escapeSelector( "abcdefghijklmnopqrstuvwxyz" ), "abcdefghijklmnopqrstuvwxyz",
|
||||
"Doesn't escape lowercase ASCII letters" );
|
||||
assert.equal( jQuery.escapeSelector( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ), "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
"Doesn't escape uppercase ASCII letters" );
|
||||
assert.equal( jQuery.escapeSelector( "\x20\x21\x78\x79" ), "\\ \\!xy",
|
||||
"Escapes non-word ASCII characters" );
|
||||
|
||||
// Astral symbol (U+1D306 TETRAGRAM FOR CENTRE)
|
||||
assert.equal( jQuery.escapeSelector( "\uD834\uDF06" ), "\uD834\uDF06",
|
||||
"Doesn't escape astral characters" );
|
||||
|
||||
// Lone surrogates
|
||||
assert.equal( jQuery.escapeSelector( "\uDF06" ), "\uDF06", "Doesn't escape lone low surrogate" );
|
||||
assert.equal( jQuery.escapeSelector( "\uD834" ), "\uD834", "Doesn't escape lone high surrogate" );
|
||||
} );
|
||||
|
||||
QUnit.test( "even()/odd()", function( assert ) {
|
||||
assert.expect( 8 );
|
||||
|
||||
var lis,
|
||||
ul = jQuery( "<ul><li>One</li><li>Two</li><li>Three</li><li>Four</li></ul>" ),
|
||||
none = jQuery();
|
||||
|
||||
ul.appendTo( "#qunit-fixture" );
|
||||
|
||||
lis = ul.find( "li" );
|
||||
|
||||
assert.strictEqual( lis.even().length, 2, "even() length" );
|
||||
assert.strictEqual( lis.even().eq( 0 ).text(), "One", "even(): 1st" );
|
||||
assert.strictEqual( lis.even().eq( 1 ).text(), "Three", "even(): 2nd" );
|
||||
|
||||
assert.strictEqual( lis.odd().length, 2, "odd() length" );
|
||||
assert.strictEqual( lis.odd().eq( 0 ).text(), "Two", "odd(): 1st" );
|
||||
assert.strictEqual( lis.odd().eq( 1 ).text(), "Four", "odd(): 2nd" );
|
||||
|
||||
assert.deepEqual( none.even().get(), [], "even() none" );
|
||||
assert.deepEqual( none.odd().get(), [], "odd() none" );
|
||||
} );
|
||||
|
||||
} );
|
26
tests/unit/jquery-patch/jquery-patch.html
Normal file
26
tests/unit/jquery-patch/jquery-patch.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>jQuery UI Form Reset Mixin Test Suite</title>
|
||||
|
||||
<script src="../../../external/requirejs/require.js"></script>
|
||||
<script src="../../lib/css.js"></script>
|
||||
<script src="../../lib/bootstrap.js" data-modules="core">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture">
|
||||
|
||||
<form id="main">
|
||||
<input id="input1">
|
||||
<input id="input2">
|
||||
<input id="input3">
|
||||
<input id="input4">
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -9,7 +9,6 @@ define( [
|
||||
"./focusable",
|
||||
"./keycode",
|
||||
"./labels",
|
||||
"./jquery-patch",
|
||||
"./plugin",
|
||||
"./scroll-parent",
|
||||
"./tabbable",
|
||||
|
31
ui/jquery-patch.js
vendored
31
ui/jquery-patch.js
vendored
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* jQuery UI Support for jQuery core 1.8.x and newer @VERSION
|
||||
* jQuery UI Legacy jQuery Core patches @VERSION
|
||||
* https://jqueryui.com
|
||||
*
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
@ -8,9 +8,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
//>>label: jQuery 1.8+ Support
|
||||
//>>label: Legacy jQuery Core patches
|
||||
//>>group: Core
|
||||
//>>description: Support version 1.8.x and newer of jQuery core
|
||||
//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated)
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
@ -31,29 +31,8 @@
|
||||
// This method has been defined in jQuery 3.0.0.
|
||||
// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
|
||||
if ( !$.escapeSelector ) {
|
||||
|
||||
// CSS string/identifier serialization
|
||||
// https://drafts.csswg.org/cssom/#common-serializing-idioms
|
||||
var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
|
||||
|
||||
var fcssescape = function( ch, asCodePoint ) {
|
||||
if ( asCodePoint ) {
|
||||
|
||||
// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
|
||||
if ( ch === "\0" ) {
|
||||
return "\uFFFD";
|
||||
}
|
||||
|
||||
// Control characters and (dependent upon position) numbers get escaped as code points
|
||||
return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
|
||||
}
|
||||
|
||||
// Other potentially-special ASCII characters get backslash-escaped
|
||||
return "\\" + ch;
|
||||
};
|
||||
|
||||
$.escapeSelector = function( sel ) {
|
||||
return ( sel + "" ).replace( rcssescape, fcssescape );
|
||||
$.escapeSelector = function( id ) {
|
||||
return CSS.escape( id + "" );
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ return $.fn.labels = function() {
|
||||
ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
|
||||
|
||||
// Create a selector for the label based on the id
|
||||
selector = "label[for='" + $.escapeSelector( id ) + "']";
|
||||
selector = "label[for='" + CSS.escape( id ) + "']";
|
||||
|
||||
labels = labels.add( ancestors.find( selector ).addBack( selector ) );
|
||||
|
||||
|
@ -52,7 +52,17 @@ return $.widget( "ui.accordion", {
|
||||
collapsible: false,
|
||||
event: "click",
|
||||
header: function( elem ) {
|
||||
return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() );
|
||||
return elem
|
||||
.find( "> li > :first-child" )
|
||||
.add(
|
||||
elem.find( "> :not(li)" )
|
||||
|
||||
// Support: jQuery <3.5 only
|
||||
// We could use `.even()` but that's unavailable in older jQuery.
|
||||
.filter( function( i ) {
|
||||
return i % 2 === 0;
|
||||
} )
|
||||
);
|
||||
},
|
||||
heightStyle: "auto",
|
||||
icons: {
|
||||
|
@ -156,7 +156,7 @@ $.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
|
||||
_getRadioGroup: function() {
|
||||
var group;
|
||||
var name = this.element[ 0 ].name;
|
||||
var nameSelector = "input[name='" + $.escapeSelector( name ) + "']";
|
||||
var nameSelector = "input[name='" + CSS.escape( name ) + "']";
|
||||
|
||||
if ( !name ) {
|
||||
return $( [] );
|
||||
|
@ -415,7 +415,7 @@ return $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
|
||||
}
|
||||
|
||||
if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
|
||||
$.escapeSelector( this.ids.button ) ).length ) {
|
||||
CSS.escape( this.ids.button ) ).length ) {
|
||||
this.close( event );
|
||||
}
|
||||
}
|
||||
|
@ -722,7 +722,7 @@ $.widget( "ui.tabs", {
|
||||
// meta-function to give users option to provide a href string instead of a numerical index.
|
||||
if ( typeof index === "string" ) {
|
||||
index = this.anchors.index( this.anchors.filter( "[href$='" +
|
||||
$.escapeSelector( index ) + "']" ) );
|
||||
CSS.escape( index ) + "']" ) );
|
||||
}
|
||||
|
||||
return index;
|
||||
|
Loading…
Reference in New Issue
Block a user