diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 5e992599f89..00000000000
--- a/.eslintignore
+++ /dev/null
@@ -1,4 +0,0 @@
-dist/**/*
-external/**/*
-tests/lib/vendor/**/*
-ui/vendor/**/*
diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index e7d67eb0e51..00000000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "root": true,
-
- "extends": "jquery",
-
- // Uncomment to find useless comment disable directives
- // "reportUnusedDisableDirectives": true,
-
- "parserOptions": {
- "ecmaVersion": 2018
- },
-
- "env": {
- "es6": true,
- "node": true
- },
-
- "rules": {
- "strict": [ "error", "global" ]
- }
-}
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 6fff16c7942..aa2f7456527 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -4,3 +4,10 @@ updates:
directory: "/"
schedule:
interval: monthly
+
+ # Group all dependabot version update PRs into one
+ groups:
+ github-actions:
+ applies-to: version-updates
+ patterns:
+ - "*"
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 00000000000..5b2bdead3e8
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,58 @@
+name: "Code scanning - action"
+
+on:
+ pull_request:
+ push:
+ branches-ignore: "dependabot/**"
+ schedule:
+ - cron: "0 4 * * 6"
+
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+jobs:
+ CodeQL-Build:
+ permissions:
+ contents: read # to fetch code (actions/checkout)
+ security-events: write # (github/codeql-action/autobuild)
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ # We must fetch at least the immediate parents so that if this is
+ # a pull request then we can checkout the head.
+ fetch-depth: 2
+
+ # If this run was triggered by a pull request event, then checkout
+ # the head of the pull request instead of the merge commit.
+ - run: git checkout HEAD^2
+ if: ${{ github.event_name == 'pull_request' }}
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
+ # Override language selection by uncommenting this and choosing your languages
+ # with:
+ # languages: go, javascript, csharp, python, cpp, java
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
+
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+ # and modify them (or add more) to build your code if your project
+ # uses a compiled language
+
+ #- run: |
+ # make bootstrap
+ # make release
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
diff --git a/.github/workflows/filestash.yml b/.github/workflows/filestash.yml
index f1016b5b53e..9f0960a4a98 100644
--- a/.github/workflows/filestash.yml
+++ b/.github/workflows/filestash.yml
@@ -13,19 +13,19 @@ jobs:
runs-on: ubuntu-latest
environment: filestash
env:
- NODE_VERSION: 20.x
+ NODE_VERSION: 22.x
name: Update Filestash
steps:
- name: Checkout
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Cache
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
index 18a5faf631a..cccd059d28e 100644
--- a/.github/workflows/node.js.yml
+++ b/.github/workflows/node.js.yml
@@ -12,34 +12,34 @@ permissions:
contents: read
env:
- NODE_VERSION: 20.x
+ NODE_VERSION: 22.x
jobs:
build-and-test:
runs-on: ubuntu-latest
name: |
- ${{ matrix.BROWSER }} | ${{ matrix.JQUERYS.name }}
+ ${{ matrix.BROWSER }} | ${{ matrix.CONFIGS.name }}
strategy:
fail-fast: false
matrix:
BROWSER: [chrome, firefox]
- JQUERYS:
- - versions: --jquery git --jquery 3.x-git
+ CONFIGS:
+ - config: jtr-git.yml
name: jQuery git
- - versions: --jquery 3.7.1 --jquery 3.6.4 --jquery 2.2.4 --jquery 1.12.4
+ - config: jtr-stable.yml
name: jQuery stable
steps:
- name: Checkout
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Cache
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
@@ -49,41 +49,42 @@ jobs:
- name: Install npm dependencies
run: npm install
- - name: Lint
- run: npm run lint
-
- name: Build
run: npm run build
+ # Lint must happen after build as we lint generated files.
+ - name: Lint
+ run: npm run lint
+
- name: Test
run: |
- npm run test:unit -- -h -b ${{ matrix.BROWSER }} \
- ${{ matrix.JQUERYS.versions }} \
- --retries 3 --hard-retries 1
+ npm run test:unit -- \
+ --headless -b ${{ matrix.BROWSER }} \
+ -c ${{ matrix.CONFIGS.config }}
edge:
runs-on: windows-latest
name: |
- edge | ${{ matrix.JQUERYS.name }}
+ edge | ${{ matrix.CONFIGS.name }}
strategy:
fail-fast: false
matrix:
- JQUERYS:
- - versions: --jquery git --jquery 3.x-git
+ CONFIGS:
+ - config: jtr-git.yml
name: jQuery git
- - versions: --jquery 3.7.1 --jquery 3.6.4 --jquery 2.2.4 --jquery 1.12.4
+ - config: jtr-stable.yml
name: jQuery stable
steps:
- name: Checkout
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Cache
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
@@ -97,34 +98,31 @@ jobs:
run: npm run build
- name: Test
- run: |
- npm run test:unit -- -h -b edge `
- ${{ matrix.JQUERYS.versions }} `
- --retries 3 --hard-retries 1
+ run: npm run test:unit -- -- --headless -b edge -c ${{ matrix.CONFIGS.config }}
safari:
runs-on: macos-latest
name: |
- safari | ${{ matrix.JQUERYS.name }}
+ safari | ${{ matrix.CONFIGS.name }}
strategy:
fail-fast: false
matrix:
- JQUERYS:
- - versions: --jquery git --jquery 3.x-git
+ CONFIGS:
+ - config: jtr-git.yml
name: jQuery git
- - versions: --jquery 3.7.1 --jquery 3.6.4 --jquery 2.2.4 --jquery 1.12.4
+ - config: jtr-stable.yml
name: jQuery stable
steps:
- name: Checkout
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Cache
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
@@ -138,7 +136,4 @@ jobs:
run: npm run build
- name: Test
- run: |
- npm run test:unit -- -b safari \
- ${{ matrix.JQUERYS.versions }} \
- --retries 3 --hard-retries 1
+ run: npm run test:unit -- -b safari -c ${{ matrix.CONFIGS.config }}
diff --git a/AUTHORS.txt b/AUTHORS.txt
index 5fcf5d1e439..b855d39997e 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -379,3 +379,6 @@ Timo Tijhof
Timmy Willison
divdeploy <166095818+divdeploy@users.noreply.github.com>
mark van tilburg
+Ralf Koller <1665422+rpkoller@users.noreply.github.com>
+Porter Clevidence <116387727+porterclev@users.noreply.github.com>
+Daniel García <93217193+Daniel-Garmig@users.noreply.github.com>
diff --git a/Gruntfile.js b/Gruntfile.js
index 05e83c9613a..bbb71d33e52 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -51,9 +51,6 @@ const cssFiles = [
// minified files
const minify = {
- options: {
- preserveComments: false
- },
main: {
options: {
banner: createBanner( uiFiles )
@@ -174,7 +171,7 @@ grunt.initConfig( {
}
},
- uglify: minify,
+ minify,
htmllint: {
good: {
options: {
@@ -207,9 +204,12 @@ grunt.initConfig( {
"ui/**/*.js",
"!ui/vendor/**/*.js",
"Gruntfile.js",
+ "dist/jquery-ui.js",
+ "dist/jquery-ui.min.js",
"build/**/*.js",
"tests/unit/**/*.js",
"tests/lib/**/*.js",
+ "!tests/lib/vendor/**/*.js",
"demos/**/*.js"
]
},
@@ -316,13 +316,13 @@ grunt.initConfig( {
"jquery-3.7.1/jquery.js": "jquery-3.7.1/dist/jquery.js",
"jquery-3.7.1/LICENSE.txt": "jquery-3.7.1/LICENSE.txt",
- "jquery-migrate-1.4.1/jquery-migrate.js":
- "jquery-migrate-1.4.1/dist/jquery-migrate.js",
- "jquery-migrate-1.4.1/LICENSE.txt": "jquery-migrate-1.4.1/LICENSE.txt",
+ "jquery-migrate-1.x/jquery-migrate.js":
+ "jquery-migrate-1.x/dist/jquery-migrate.js",
+ "jquery-migrate-1.x/LICENSE.txt": "jquery-migrate-1.x/LICENSE.txt",
- "jquery-migrate-3.4.1/jquery-migrate.js":
- "jquery-migrate-3.4.1/dist/jquery-migrate.js",
- "jquery-migrate-3.4.1/LICENSE.txt": "jquery-migrate-3.4.1/LICENSE.txt"
+ "jquery-migrate-3.x/jquery-migrate.js":
+ "jquery-migrate-3.x/dist/jquery-migrate.js",
+ "jquery-migrate-3.x/LICENSE.txt": "jquery-migrate-3.x/LICENSE.txt"
}
}
},
@@ -403,9 +403,9 @@ grunt.registerTask( "lint", [
"csslint",
"htmllint"
] );
-grunt.registerTask( "build", [ "requirejs", "concat" ] );
-grunt.registerTask( "default", [ "lint", "build" ] );
-grunt.registerTask( "sizer", [ "requirejs:js", "uglify:main", "compare_size:all" ] );
-grunt.registerTask( "sizer_all", [ "requirejs:js", "uglify", "compare_size" ] );
+grunt.registerTask( "build", [ "requirejs", "concat", "minify:main" ] );
+grunt.registerTask( "default", [ "build", "lint" ] );
+grunt.registerTask( "sizer", [ "requirejs:js", "minify:main", "compare_size:all" ] );
+grunt.registerTask( "sizer_all", [ "requirejs:js", "minify", "compare_size" ] );
};
diff --git a/bower.json b/bower.json
index 1efb14ee2f6..eb3187e0c38 100644
--- a/bower.json
+++ b/bower.json
@@ -13,7 +13,7 @@
},
"devDependencies": {
"jquery-color": "3.0.0",
- "jquery-mousewheel": "3.1.12",
+ "jquery-mousewheel": "3.2.2",
"jquery-simulate": "1.1.1",
"qunit": "2.19.4",
"requirejs": "2.1.14",
@@ -38,7 +38,7 @@
"jquery-3.6.4": "jquery#3.6.4",
"jquery-3.7.0": "jquery#3.7.0",
"jquery-3.7.1": "jquery#3.7.1",
- "jquery-migrate-1.4.1": "https://registry.npmjs.org/jquery-migrate/-/jquery-migrate-1.4.1.tgz",
- "jquery-migrate-3.4.1": "https://registry.npmjs.org/jquery-migrate/-/jquery-migrate-3.4.1.tgz"
+ "jquery-migrate-1.x": "https://registry.npmjs.org/jquery-migrate/-/jquery-migrate-1.4.1.tgz",
+ "jquery-migrate-3.x": "https://registry.npmjs.org/jquery-migrate/-/jquery-migrate-3.5.2.tgz"
}
}
diff --git a/build/release.js b/build/release.js
index d9ab580cb16..633dd34d12c 100644
--- a/build/release.js
+++ b/build/release.js
@@ -59,8 +59,8 @@ function addManifest( packager ) {
function buildCDNPackage( callback ) {
console.log( "Building CDN package" );
var JqueryUi = require( "download.jqueryui.com/lib/jquery-ui" );
- var PackageWithoutThemes = require( "download.jqueryui.com/lib/package-1-13" );
- var PackageOfThemes = require( "download.jqueryui.com/lib/package-1-13-themes" );
+ var PackageWithoutThemes = require( "download.jqueryui.com/lib/package" );
+ var PackageOfThemes = require( "download.jqueryui.com/lib/package-themes" );
var Packager = require( "node-packager" );
// PackageOfThemes doesn't contain JS files, PackageWithoutThemes doesn't contain themes;
@@ -153,7 +153,7 @@ Release.define( {
};
module.exports.dependencies = [
- "download.jqueryui.com@2.2.14",
+ "download.jqueryui.com@2.3.12",
"node-packager@0.0.7",
"shelljs@0.8.5"
];
diff --git a/build/tasks/build.js b/build/tasks/build.js
index 48feb7aba1d..bd07364ea36 100644
--- a/build/tasks/build.js
+++ b/build/tasks/build.js
@@ -3,7 +3,7 @@
module.exports = function( grunt ) {
grunt.registerTask( "clean", function() {
- require( "rimraf" ).sync( "dist" );
+ require( "rimraf" ).rimrafSync( "dist" );
} );
grunt.registerTask( "asciilint", function() {
diff --git a/build/tasks/minify.js b/build/tasks/minify.js
new file mode 100644
index 00000000000..6d83831ee3c
--- /dev/null
+++ b/build/tasks/minify.js
@@ -0,0 +1,53 @@
+"use strict";
+
+const swc = require( "@swc/core" );
+
+module.exports = function( grunt ) {
+
+grunt.registerMultiTask( "minify", async function() {
+ const done = this.async();
+ const options = this.options();
+
+ for ( const file of this.files ) {
+ if ( file.src.length === 0 ) {
+ grunt.log.writeln(
+ `No source file found, skipping minification to "${ file.dest }".` );
+ continue;
+ }
+ if ( file.src.length !== 1 ) {
+ grunt.fail.warn( "Minifying multiple source files into one " +
+ "destination file not supported" );
+ }
+
+ const contents = grunt.file.read( file.src[ 0 ] );
+
+ const { code } = await swc.minify(
+ contents,
+ {
+ compress: {
+ ecma: 5,
+ hoist_funs: false,
+ loops: false
+ },
+ format: {
+ ecma: 5,
+ asciiOnly: true,
+ comments: false,
+ preamble: options.banner
+ },
+ inlineSourcesContent: false,
+ mangle: true,
+ module: false,
+ sourceMap: false
+ }
+ );
+
+ grunt.file.write( file.dest, code );
+
+ grunt.log.writeln( `File ${ file.dest } created.` );
+ }
+
+ done();
+} );
+
+};
diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js
deleted file mode 100644
index 8ab2b7643c0..00000000000
--- a/build/tasks/testswarm.js
+++ /dev/null
@@ -1,115 +0,0 @@
-"use strict";
-
-module.exports = function( grunt ) {
-
-var versions = {
- "git": "git",
- "3.x-git": "3.x-git",
- "3.7": "3.7.0",
- "3.6": "3.6.4",
- "3.5": "3.5.1",
- "3.4": "3.4.1",
- "3.3": "3.3.1",
- "3.2": "3.2.1",
- "3.1": "3.1.1",
- "3.0": "3.0.0",
- "2.2": "2.2.4",
- "2.1": "2.1.4",
- "2.0": "2.0.3",
- "1.12": "1.12.4",
- "1.11": "1.11.3",
- "1.10": "1.10.2",
- "1.9": "1.9.1",
- "1.8": "1.8.3"
- },
- tests = {
- "Accordion": "accordion/accordion.html",
- "Autocomplete": "autocomplete/autocomplete.html",
- "Button": "button/button.html",
- "Checkboxradio": "checkboxradio/checkboxradio.html",
- "Controlgroup": "controlgroup/controlgroup.html",
- "Core": "core/core.html",
- "Datepicker": "datepicker/datepicker.html",
- "Dialog": "dialog/dialog.html",
- "Draggable": "draggable/draggable.html",
- "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",
- "Resizable": "resizable/resizable.html",
- "Selectable": "selectable/selectable.html",
- "Selectmenu": "selectmenu/selectmenu.html",
- "Slider": "slider/slider.html",
- "Sortable": "sortable/sortable.html",
- "Spinner": "spinner/spinner.html",
- "Tabs": "tabs/tabs.html",
- "Tooltip": "tooltip/tooltip.html",
- "Widget": "widget/widget.html"
- };
-
-function submit( commit, runs, configFile, browserSets, extra, done ) {
- var testName,
- testswarm = require( "testswarm" ),
- config = grunt.file.readJSON( configFile ).jqueryui,
- commitUrl = "https://github.com/jquery/jquery-ui/commit/" + commit;
-
- browserSets = browserSets || config.browserSets;
- if ( browserSets[ 0 ] === "[" ) {
-
- // We got an array, parse it
- browserSets = JSON.parse( browserSets );
- }
-
- if ( extra ) {
- extra = " (" + extra + ")";
- }
-
- for ( testName in runs ) {
- runs[ testName ] = config.testUrl + commit + "/tests/unit/" + runs[ testName ];
- }
-
- testswarm.createClient( {
- url: config.swarmUrl
- } )
- .addReporter( testswarm.reporters.cli )
- .auth( {
- id: config.authUsername,
- token: config.authToken
- } )
- .addjob( {
- name: "Commit " + commit.substr( 0, 10 ) + "" + extra,
- runs: runs,
- runMax: config.runMax,
- browserSets: browserSets,
- timeout: 1000 * 60 * 30
- }, function( error, passed ) {
- if ( error ) {
- grunt.log.error( error );
- }
- done( passed );
- } );
-}
-
-grunt.registerTask( "testswarm", function( commit, configFile, browserSets ) {
- var test,
- latestTests = {};
- for ( test in tests ) {
- latestTests[ test ] = tests[ test ];
- }
- submit( commit, latestTests, configFile, browserSets, "", this.async() );
-} );
-
-grunt.registerTask( "testswarm-multi-jquery", function( commit, configFile, minor, browserSets ) {
- var allTests = {};
- versions[ minor ].split( " " ).forEach( function( version ) {
- for ( var test in tests ) {
- allTests[ test + "-" + version ] = tests[ test ] + "?jquery=" + version;
- }
- } );
- submit( commit, allTests, configFile, browserSets, "core " + minor, this.async() );
-} );
-
-};
diff --git a/demos/.eslintrc.json b/demos/.eslintrc.json
deleted file mode 100644
index da1cb6b909b..00000000000
--- a/demos/.eslintrc.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "root": true,
-
- "extends": "../ui/.eslintrc.json"
-}
diff --git a/demos/autocomplete/combobox.html b/demos/autocomplete/combobox.html
index 9fc997c11bf..afe30134906 100644
--- a/demos/autocomplete/combobox.html
+++ b/demos/autocomplete/combobox.html
@@ -78,10 +78,8 @@
.tooltip()
.appendTo( this.wrapper )
.button({
- icons: {
- primary: "ui-icon-triangle-1-s"
- },
- text: false
+ icon: "ui-icon-triangle-1-s",
+ showLabel: false
})
.removeClass( "ui-corner-all" )
.addClass( "custom-combobox-toggle ui-corner-right" )
diff --git a/demos/effect/default.html b/demos/effect/default.html
index 7d69abb2d76..289d5df7ff0 100644
--- a/demos/effect/default.html
+++ b/demos/effect/default.html
@@ -11,7 +11,6 @@
#button { padding: .5em 1em; text-decoration: none; }
#effect { width: 240px; height: 170px; padding: 0.4em; position: relative; }
#effect h3 { margin: 0; padding: 0.4em; text-align: center; }
- .ui-effects-transfer { border: 2px dotted gray; }
-
" ).appendTo( "#qunit-fixture" );
+
+ // In some browsers scrollbar may change element size (when "box-sizing: content-box")
+ widthBefore = element.innerWidth();
+ heightBefore = element.innerHeight();
+
+ // Both scrollbars
+ testHelper.drag( handle, 10, 10 );
+ assert.equal( parseFloat( element.innerWidth() ), widthBefore + 10, "element width (both scrollbars)" );
+ assert.equal( parseFloat( element.innerHeight() ), heightBefore + 10, "element height (both scrollbars)" );
+
+ // Single (vertical) scrollbar.
+ elementContent.css( "width", "50px" );
+
+ testHelper.drag( handle, 10, 10 );
+ assert.equal( parseFloat( element.innerWidth() ), widthBefore + 20, "element width (only vertical scrollbar)" );
+ assert.equal( parseFloat( element.innerHeight() ), heightBefore + 20, "element height (only vertical scrollbar)" );
+}
+
} );
diff --git a/tests/unit/resizable/options.js b/tests/unit/resizable/options.js
index add8d803448..b80c051d588 100644
--- a/tests/unit/resizable/options.js
+++ b/tests/unit/resizable/options.js
@@ -542,21 +542,22 @@ QUnit.test( "alsoResize + multiple selection", function( assert ) {
QUnit.test( "alsoResize with box-sizing: border-box", function( assert ) {
assert.expect( 4 );
+ $( "" ).appendTo( "#qunit-fixture" );
+
var other = $( "" )
.css( {
- width: 50,
- height: 50,
- padding: 10,
- border: 5
+ width: "50px",
+ height: "50px",
+ padding: "10px",
+ border: "5px",
+ borderStyle: "solid"
} )
- .appendTo( "body" ),
+ .appendTo( "#qunit-fixture" ),
element = $( "#resizable1" ).resizable( {
alsoResize: other
} ),
handle = ".ui-resizable-se";
- $( "*" ).css( "box-sizing", "border-box" );
-
testHelper.drag( handle, 80, 80 );
assert.equal( element.width(), 180, "resizable width" );
@@ -565,4 +566,51 @@ QUnit.test( "alsoResize with box-sizing: border-box", function( assert ) {
assert.equal( parseFloat( other.css( "height" ) ), 130, "alsoResize height" );
} );
+QUnit.test( "alsoResize with scrollbars and box-sizing: border-box", function( assert ) {
+ assert.expect( 4 );
+ testAlsoResizeWithBoxSizing( assert, {
+ isBorderBox: true
+ } );
+} );
+
+QUnit.test( "alsoResize with scrollbars and box-sizing: content-box", function( assert ) {
+ assert.expect( 4 );
+ testAlsoResizeWithBoxSizing( assert, {
+ isBorderBox: false
+ } );
+} );
+
+function testAlsoResizeWithBoxSizing( assert, options ) {
+ var widthBefore, heightBefore,
+ cssBoxSizing = options.isBorderBox ? "border-box" : "content-box",
+ other = $( "
" )
+ .css( {
+ width: "150px",
+ height: "150px",
+ padding: "10px",
+ border: "5px",
+ borderStyle: "solid",
+ margin: "20px",
+ overflow: "scroll"
+ } )
+ .appendTo( "#qunit-fixture" ),
+ element = $( "#resizable1" ).resizable( {
+ alsoResize: other
+ } ),
+ handle = ".ui-resizable-se";
+
+ $( "" ).appendTo( "#qunit-fixture" );
+
+ // In some browsers scrollbar may change element computed size.
+ widthBefore = other.innerWidth();
+ heightBefore = other.innerHeight();
+
+ testHelper.drag( handle, 80, 80 );
+
+ assert.equal( element.width(), 180, "resizable width" );
+ assert.equal( parseFloat( other.innerWidth() ), widthBefore + 80, "alsoResize width" );
+ assert.equal( element.height(), 180, "resizable height" );
+ assert.equal( parseFloat( other.innerHeight() ), heightBefore + 80, "alsoResize height" );
+}
+
} );
diff --git a/tests/unit/spinner/core.js b/tests/unit/spinner/core.js
index e9f7bc3d218..42bcc7bb58b 100644
--- a/tests/unit/spinner/core.js
+++ b/tests/unit/spinner/core.js
@@ -163,7 +163,47 @@ QUnit.test( "mouse click on up button, increases value not greater than max", fu
assert.equal( element.val(), 0 );
} );
-QUnit.test( "mousewheel on input", function( assert ) {
+QUnit.test( "wheel on input", function( assert ) {
+ var ready = assert.async();
+ assert.expect( 5 );
+
+ var element = $( "#spin" ).val( 0 ).spinner( {
+ step: 2
+ } );
+
+ element.simulate( "focus" );
+ setTimeout( step1 );
+
+ function getWheelEvent( deltaY ) {
+ return jQuery.Event( new WheelEvent( "wheel", { deltaY: deltaY } ) );
+ }
+
+ function step1() {
+ element.trigger( getWheelEvent() );
+ assert.equal( element.val(), 0, "wheel event without delta does not change value" );
+
+ element.trigger( getWheelEvent( -1 ) );
+ assert.equal( element.val(), 2, "delta -1" );
+
+ element.trigger( getWheelEvent( 0.2 ) );
+ assert.equal( element.val(), 0, "delta 0.2" );
+
+ element.trigger( getWheelEvent( 15 ) );
+ assert.equal( element.val(), -2, "delta 15" );
+
+ element.simulate( "blur" );
+ setTimeout( step2 );
+ }
+
+ function step2() {
+ element.trigger( "wheel", -1 );
+ assert.equal( element.val(), -2, "wheel when not focused" );
+
+ ready();
+ }
+} );
+
+QUnit.test( "mousewheel on input (DEPRECATED)", function( assert ) {
var ready = assert.async();
assert.expect( 5 );
@@ -199,6 +239,20 @@ QUnit.test( "mousewheel on input", function( assert ) {
}
} );
+helper.testIframe(
+ "wheel & mousewheel conflicts",
+ "mousewheel-wheel.html",
+ function( assert, jQuery, window, document, values ) {
+ assert.expect( 5 );
+
+ assert.equal( values[ 0 ], 0, "wheel event without delta does not change value" );
+ assert.equal( values[ 1 ], 2, "delta -1" );
+ assert.equal( values[ 2 ], 0, "delta 0.2" );
+ assert.equal( values[ 3 ], -2, "delta 15" );
+ assert.equal( values[ 4 ], -2, "wheel when not focused" );
+ }
+);
+
QUnit.test( "reading HTML5 attributes", function( assert ) {
assert.expect( 6 );
var markup = "
",
diff --git a/tests/unit/spinner/mousewheel-wheel.html b/tests/unit/spinner/mousewheel-wheel.html
new file mode 100644
index 00000000000..e512a36ccbe
--- /dev/null
+++ b/tests/unit/spinner/mousewheel-wheel.html
@@ -0,0 +1,72 @@
+
+
+
+
+
jQuery UI Spinner Test Suite
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/unit/tabs/core.js b/tests/unit/tabs/core.js
index ae670ff4303..1eac3c26834 100644
--- a/tests/unit/tabs/core.js
+++ b/tests/unit/tabs/core.js
@@ -84,6 +84,37 @@ QUnit.test( "non-tab list items", function( assert ) {
"first actual tab is active" );
} );
+QUnit.test( "ID escaping backslashes", function( assert ) {
+ assert.expect( 5 );
+
+ location.hash = "#fragment\b-2";
+
+ var element = $( "#tabs1" )
+ .find( "a[href='#fragment-2']" )
+ .attr( "href", "#fragment\b-2" )
+ .end()
+ .find( "#fragment-2" )
+ .attr( "id", "fragment\b-2" )
+ .end()
+ .tabs();
+ var tabs = element.find( ".ui-tabs-nav li" );
+ var anchors = tabs.find( ".ui-tabs-anchor" );
+ var panels = element.find( ".ui-tabs-panel" );
+
+ assert.strictEqual( element.tabs( "option", "active" ), 1,
+ "should set the active option" );
+
+ assert.strictEqual( anchors.length, 3, "should decorate all anchors" );
+ assert.strictEqual( panels.length, 3, "should decorate all panels" );
+
+ assert.strictEqual( panels.eq( 1 ).attr( "aria-labelledby" ), anchors.eq( 1 ).attr( "id" ),
+ "panel 2 aria-labelledby equals anchor 2 id" );
+ assert.strictEqual( tabs.eq( 1 ).attr( "aria-controls" ), "fragment\b-2",
+ "tab 2 aria-controls" );
+
+ location.hash = "";
+} );
+
QUnit.test( "aria-controls", function( assert ) {
assert.expect( 7 );
var element = $( "#tabs1" ).tabs(),
@@ -716,4 +747,81 @@ QUnit.test( "extra listeners created when tabs are added/removed (trac-15136)",
"No extra listeners after removing all the extra tabs" );
} );
+QUnit.test( "URL-based auth with local tabs (gh-2213)", function( assert ) {
+ assert.expect( 1 );
+
+ var origAjax = $.ajax,
+ element = $( "#tabs1" ),
+ anchor = element.find( "a[href='#fragment-3']" ),
+ url = new URL( anchor.prop( "href" ) );
+
+ try {
+ $.ajax = function() {
+ throw new Error( "Unexpected AJAX call; all tabs are local!" );
+ };
+
+ anchor.attr( "href", url.protocol + "//username:password@" + url.host +
+ url.pathname + url.search + url.hash );
+
+ element.tabs();
+ anchor.trigger( "click" );
+
+ assert.strictEqual( element.tabs( "option", "active" ), 2,
+ "should set the active option" );
+ } finally {
+ $.ajax = origAjax;
+ }
+} );
+
+( function() {
+ function getVerifyTab( assert, element ) {
+ return function verifyTab( index ) {
+ assert.strictEqual(
+ element.tabs( "option", "active" ),
+ index,
+ "should set the active option to " + index );
+ assert.strictEqual(
+ element.find( "[role='tabpanel']:visible" ).text().trim(),
+ "Tab " + ( index + 1 ),
+ "should set the panel to 'Tab " + ( index + 1 ) + "'" );
+ };
+ }
+
+ QUnit.test( "href encoding/decoding (gh-2344)", function( assert ) {
+ assert.expect( 12 );
+
+ location.hash = "#tabs-2";
+
+ var i,
+ element = $( "#tabs10" ).tabs(),
+ tabLinks = element.find( "> ul a" ),
+ verifyTab = getVerifyTab( assert, element );
+
+ for ( i = 0; i < tabLinks.length; i++ ) {
+ tabLinks.eq( i ).trigger( "click" );
+ verifyTab( i );
+ }
+
+ location.hash = "";
+ } );
+
+ QUnit.test( "href encoding/decoding on init (gh-2344)", function( assert ) {
+ assert.expect( 12 );
+
+ var i,
+ element = $( "#tabs10" ),
+ tabLinks = element.find( "> ul a" ),
+ verifyTab = getVerifyTab( assert, element );
+
+ for ( i = 0; i < tabLinks.length; i++ ) {
+ location.hash = tabLinks.eq( i ).attr( "href" );
+ element.tabs();
+ verifyTab( i );
+ element.tabs( "destroy" );
+ }
+
+ location.hash = "";
+ } );
+} )();
+
} );
diff --git a/tests/unit/tabs/helper.js b/tests/unit/tabs/helper.js
index b3fb1d6fd42..4043d86d8fd 100644
--- a/tests/unit/tabs/helper.js
+++ b/tests/unit/tabs/helper.js
@@ -58,8 +58,7 @@ return $.extend( helper, {
var expected = $.makeArray( arguments ).slice( 2 ),
actual = tabs.find( ".ui-tabs-nav li" ).map( function() {
var tab = $( this ),
- panel = $( $.ui.tabs.prototype._sanitizeSelector(
- "#" + tab.attr( "aria-controls" ) ) ),
+ panel = $( "#" + CSS.escape( tab.attr( "aria-controls" ) ) ),
tabIsActive = tab.hasClass( "ui-state-active" ),
panelIsActive = panel.css( "display" ) !== "none";
diff --git a/tests/unit/tabs/tabs.html b/tests/unit/tabs/tabs.html
index cb4e5389f62..3f18fa015f6 100644
--- a/tests/unit/tabs/tabs.html
+++ b/tests/unit/tabs/tabs.html
@@ -125,6 +125,35 @@
+
+