diff --git a/tests/unit/core/selector.js b/tests/unit/core/selector.js index 6d867f634..61f4a2381 100644 --- a/tests/unit/core/selector.js +++ b/tests/unit/core/selector.js @@ -3,7 +3,6 @@ define( [ "jquery", "lib/helper", "ui/data", - "ui/escape-selector", "ui/focusable", "ui/tabbable" ], function( QUnit, $, helper ) { @@ -280,11 +279,4 @@ QUnit.test( "tabbable - dimensionless parent with overflow", function( assert ) assert.isTabbable( "#dimensionlessParent", "input" ); } ); -QUnit.test( "escapeSelector", function( assert ) { - assert.expect( 1 ); - - assert.equal( $( "#" + $.ui.escapeSelector( "weird-['x']-id" ) ).length, 1, - "properly escapes selectors to use as an id" ); -} ); - } ); diff --git a/ui/escape-selector.js b/ui/escape-selector.js deleted file mode 100644 index d43e4f816..000000000 --- a/ui/escape-selector.js +++ /dev/null @@ -1,21 +0,0 @@ -( function( factory ) { - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define( [ "jquery", "./version" ], factory ); - } else { - - // Browser globals - factory( jQuery ); - } -} ( function( $ ) { - -// Internal use only -return $.ui.escapeSelector = ( function() { - var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g; - return function( selector ) { - return selector.replace( selectorEscape, "\\$1" ); - }; -} )(); - -} ) ); diff --git a/ui/jquery-patch.js b/ui/jquery-patch.js index 4d939535e..578c47a3f 100644 --- a/ui/jquery-patch.js +++ b/ui/jquery-patch.js @@ -36,6 +36,36 @@ if ( !$.uniqueSort ) { $.uniqueSort = $.unique; } +// Support: jQuery 2.2.x or older. +// 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 ); + }; +} + // Support: jQuery 3.4.x or older // These methods have been defined in jQuery 3.5.0. if ( !$.fn.even || !$.fn.odd ) { diff --git a/ui/labels.js b/ui/labels.js index 1bf56ac41..216c46a9a 100644 --- a/ui/labels.js +++ b/ui/labels.js @@ -16,7 +16,7 @@ if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. - define( [ "jquery", "./version", "./escape-selector" ], factory ); + define( [ "jquery", "./version" ], factory ); } else { // Browser globals @@ -53,7 +53,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='" + $.ui.escapeSelector( id ) + "']"; + selector = "label[for='" + $.escapeSelector( id ) + "']"; labels = labels.add( ancestors.find( selector ).addBack( selector ) ); diff --git a/ui/widgets/checkboxradio.js b/ui/widgets/checkboxradio.js index 228c9fab9..0cb1a0cf8 100644 --- a/ui/widgets/checkboxradio.js +++ b/ui/widgets/checkboxradio.js @@ -23,7 +23,6 @@ // AMD. Register as an anonymous module. define( [ "jquery", - "../escape-selector", "../form-reset-mixin", "../labels", "../widget" @@ -149,7 +148,7 @@ $.widget( "ui.checkboxradio", [ $.ui.formResetMixin, { _getRadioGroup: function() { var group; var name = this.element[ 0 ].name; - var nameSelector = "input[name='" + $.ui.escapeSelector( name ) + "']"; + var nameSelector = "input[name='" + $.escapeSelector( name ) + "']"; if ( !name ) { return $( [] ); diff --git a/ui/widgets/selectmenu.js b/ui/widgets/selectmenu.js index 79e97816b..cc98ecbbf 100644 --- a/ui/widgets/selectmenu.js +++ b/ui/widgets/selectmenu.js @@ -25,7 +25,6 @@ define( [ "jquery", "./menu", - "../escape-selector", "../form-reset-mixin", "../keycode", "../labels", @@ -425,7 +424,7 @@ return $.widget( "ui.selectmenu", [ $.ui.formResetMixin, { } if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + - $.ui.escapeSelector( this.ids.button ) ).length ) { + $.escapeSelector( this.ids.button ) ).length ) { this.close( event ); } } diff --git a/ui/widgets/tabs.js b/ui/widgets/tabs.js index 0eb69ebe1..7a53767dd 100644 --- a/ui/widgets/tabs.js +++ b/ui/widgets/tabs.js @@ -22,7 +22,6 @@ // AMD. Register as an anonymous module. define( [ "jquery", - "../escape-selector", "../keycode", "../safe-active-element", "../unique-id", @@ -733,7 +732,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$='" + - $.ui.escapeSelector( index ) + "']" ) ); + $.escapeSelector( index ) + "']" ) ); } return index;