diff --git a/H5Study.WebApp/H5Study.WebApp.csproj b/H5Study.WebApp/H5Study.WebApp.csproj new file mode 100644 index 0000000..c78c9c7 --- /dev/null +++ b/H5Study.WebApp/H5Study.WebApp.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + enable + enable + + + diff --git a/H5Study.WebApp/Program.cs b/H5Study.WebApp/Program.cs new file mode 100644 index 0000000..173dae0 --- /dev/null +++ b/H5Study.WebApp/Program.cs @@ -0,0 +1,18 @@ +namespace H5Study.WebApp +{ + public class Program + { + public static void Main(string[] args) + { + var builder = WebApplication.CreateBuilder(args); + var app = builder.Build(); + + app.UseDefaultFiles(); + app.UseStaticFiles(); + + app.MapGet("/", () => "Hello World!"); + + app.Run(); + } + } +} \ No newline at end of file diff --git a/H5Study.WebApp/Properties/launchSettings.json b/H5Study.WebApp/Properties/launchSettings.json new file mode 100644 index 0000000..bd73fac --- /dev/null +++ b/H5Study.WebApp/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:42979", + "sslPort": 0 + } + }, + "profiles": { + "WebApp": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5155", + "launchUrl": "Index.html", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/H5Study.WebApp/appsettings.Development.json b/H5Study.WebApp/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/H5Study.WebApp/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/H5Study.WebApp/appsettings.json b/H5Study.WebApp/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/H5Study.WebApp/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/H5Study.WebApp/wwwroot/CssStudy/Index.html b/H5Study.WebApp/wwwroot/CssStudy/Index.html new file mode 100644 index 0000000..52f7105 --- /dev/null +++ b/H5Study.WebApp/wwwroot/CssStudy/Index.html @@ -0,0 +1,18 @@ + + + + + + + CSS 学习 + + + +
+ +
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/CssStudy/flex布局/.editorconfig b/H5Study.WebApp/wwwroot/CssStudy/flex布局/.editorconfig new file mode 100644 index 0000000..b9c127d --- /dev/null +++ b/H5Study.WebApp/wwwroot/CssStudy/flex布局/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = crlf +charset = utf-8 +trim_trailing_whitespace = false +insert_final_newline = false \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/CssStudy/flex布局/index.html b/H5Study.WebApp/wwwroot/CssStudy/flex布局/index.html new file mode 100644 index 0000000..800faf6 --- /dev/null +++ b/H5Study.WebApp/wwwroot/CssStudy/flex布局/index.html @@ -0,0 +1,67 @@ + + + + + + + 垂直剧中 + + + +
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/01.宽高已知.单行居中.html b/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/01.宽高已知.单行居中.html new file mode 100644 index 0000000..e6494b9 --- /dev/null +++ b/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/01.宽高已知.单行居中.html @@ -0,0 +1,52 @@ + + + + + + + + 垂直居中-宽高已知-设置行高与高度相等 + + + + +
+
+ 垂直居中-宽高已知-设置行高与高度相等 +
+
+

垂直居中:设置行高与高度相等

+

只适用于单行文本

+
+ +
+ +
+ + 垂直与水平居中 + +
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/Index.html b/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/Index.html new file mode 100644 index 0000000..9146184 --- /dev/null +++ b/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/Index.html @@ -0,0 +1,159 @@ + + + + + + + + 垂直居中-目录 + + + + +
+
+ 垂直居中方法-目录 +
+
+ +
+ +
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/InfoBox.html b/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/InfoBox.html new file mode 100644 index 0000000..ad903ba --- /dev/null +++ b/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/InfoBox.html @@ -0,0 +1,47 @@ + + + + + + + 信息框 + + + +
+
+ 信息框标题 +
+
+ 信息框内容 +
+ +
+ +
+
+ 信息框标题 +
+
+ 信息框内容 +
+ +
+ +
+
+ 信息框标题 +
+
+ 信息框内容 +
+ +
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/css/box.css b/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/css/box.css new file mode 100644 index 0000000..6680cf6 --- /dev/null +++ b/H5Study.WebApp/wwwroot/CssStudy/垂直居中汇总/css/box.css @@ -0,0 +1,165 @@ +/* 信息框样式 */ + +/* #region 实现方式一 */ +/* 实现方式一:外层无边框等设置,框形由 "内上的左、上、右边框"、"内中的左与右边框"及 "内下的左、右、下边框" 组成 */ +.info-box { + --info-box-main-color:#6f42c1; + --info-box-text-color:#ffffff; + --info-box-body-bgcolor:#afa1c9; + --info-box-footer-bgcolor:#a78adc; + + margin: 10px; + padding: 0; + + font-size: 16px; + font-weight: bold; + color: var(--info-box-text-color); +} + +.info-box .info-box-item { + box-sizing: border-box; + padding: 10px; +} + +.info-box .info-box-header { + height: 50px; + line-height: 28px; + background-color: var(--info-box-main-color); + + border-top: 2px solid var(--info-box-main-color); + border-left: 2px solid var(--info-box-main-color); + border-right: 2px solid var(--info-box-main-color); + border-top-left-radius: 10px; + border-top-right-radius: 10px; +} + +.info-box .info-box-body { + min-height: 200px;; + background-color: var(--info-box-body-bgcolor); + + border-left: 2px solid var(--info-box-main-color); + border-right: 2px solid var(--info-box-main-color); +} + +.info-box .info-box-footer { + height: 40px; + line-height: 18px; + + background-color: var(--info-box-footer-bgcolor); + border-bottom: 2px solid var(--info-box-main-color); + border-left: 2px solid var(--info-box-main-color); + border-right: 2px solid var(--info-box-main-color); + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; +} +/* #endregion */ + +/* #region 实现方式二 */ +/* 实现方式二:框形由 外层边框形成,内上、内中、内下配合各相应角的形状 */ +.msg { + --msg-text-color:#ffffff; + --msg-main-color: green; + --msg-body-bgcolor:rgba(154, 176, 154, 0.726); + --msg-footer-bgcolor: rgb(98, 145, 98); + + margin: 10px; + padding: 0; + + /* 外层必须背景颜色且与连框颜色相同,否则四角稍内会有月牙形"漏洞" */ + background-color: var(--msg-main-color); + + border: 2px solid var(--msg-main-color); + border-radius: 10px; +} + +.msg .msg-item { + color: var(--msg-text-color); + font-weight: bold; + padding-left: 10px; + padding-right: 10px; + box-sizing: border-box; +} + +.msg .msg-header { + height: 50px; + line-height: 48px; + background-color: var(--msg-main-color); + + border-top-left-radius: 10px; + border-top-right-radius: 10px; + + border-bottom: 2px solid var(--msg-main-color); +} + +.msg .msg-body { + height: 200px; + background-color: var(--msg-body-bgcolor); + + padding: 10px; +} + +.msg .msg-footer { + height: 39px; + line-height: 38px; + + background-color: var(--msg-footer-bgcolor); + + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; +} +/* #endregion */ + +/* #region 默认信息框 */ +/* 默认信息框:基于"实现方式二" */ +.default-info { + --default-info-text-color:#000000; + --default-info-main-color: rgb(206, 212, 218); + --default-info-body-bgcolor:rgb(248, 249, 250); + --default-info-footer-bgcolor: rgb(233, 236, 239); + + margin: 10px; + padding: 0; + /* 外层必须背景颜色且与连框颜色相同,否则四角稍内会有月牙形"漏洞" */ + background-color: var(--default-info-main-color); + + border: 2px solid var(--default-info-main-color); + border-radius: 10px; +} + +.default-info-item { + color: var(--default-info-text-color); + font-weight: bold; + + padding-left: 10px; + padding-right: 10px; + + box-sizing: border-box; +} + +.default-info-header { + height: 50px; + line-height: 50px; + background-color: var(--default-info-main-color); + border-top-left-radius: 10px; + border-top-right-radius: 10px; + border-bottom: 2px solid var(--default-info-main-color); +} + +.default-info-body { + min-height: 200px; + background-color: var(--default-info-body-bgcolor); + + padding: 10px; +} + +.default-info-footer { + height: 40px; + line-height: 38px; + background-color: var(--default-info-footer-bgcolor); + + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; + + /* border-bottom: 2px solid (206, 212, 218); */ +} +/* #endregion*/ \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/H5Study/Index.html b/H5Study.WebApp/wwwroot/H5Study/Index.html new file mode 100644 index 0000000..aa95ce3 --- /dev/null +++ b/H5Study.WebApp/wwwroot/H5Study/Index.html @@ -0,0 +1,20 @@ + + + + + + + H5学习 + + + +
+ H5学习 +
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/Import.html b/H5Study.WebApp/wwwroot/Html中引用html文件方法/Import.html new file mode 100644 index 0000000..8b7b2fd --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/Import.html @@ -0,0 +1,13 @@ + + +
+

引入html文件

+ 首页 + 使用 iframe + 使用 object + 使用 link + 使用 bootstrap 等框架 + 使用 js + 使用 jquery + 使用 动态网页技术 +
\ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/ImportIframe.html b/H5Study.WebApp/wwwroot/Html中引用html文件方法/ImportIframe.html new file mode 100644 index 0000000..85d5620 --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/ImportIframe.html @@ -0,0 +1,23 @@ + + + + + + + 使用 iframe + + + +
+

引入html文件

+ 首页 + 使用 iframe + 使用 object + 使用 link + 使用 bootstrap 等框架 + 使用 js + 使用 jquery + 使用 动态网页技术 +
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/Index.html b/H5Study.WebApp/wwwroot/Html中引用html文件方法/Index.html new file mode 100644 index 0000000..5864895 --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/Index.html @@ -0,0 +1,26 @@ + + + + + + + 主页面 + + + +
+ +
+ 经比较,使用js或jQuery库最方便! +
+
+ + + + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseIframe.html b/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseIframe.html new file mode 100644 index 0000000..08bb845 --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseIframe.html @@ -0,0 +1,23 @@ + + + + + + + 使用 iframe + + + +
+ +
+ iframe 内容区 +
+
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseJquery.html b/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseJquery.html new file mode 100644 index 0000000..5a47fc3 --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseJquery.html @@ -0,0 +1,28 @@ + + + + + + + 使用jQuery + + + + + +
+ +
+ 主页内容区 +
+
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseJs.html b/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseJs.html new file mode 100644 index 0000000..f040d7d --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseJs.html @@ -0,0 +1,27 @@ + + + + + + + 使用js + + + +
+ +
+ 主页内容区 +
+
+ + + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseLink.html b/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseLink.html new file mode 100644 index 0000000..5013314 --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseLink.html @@ -0,0 +1,32 @@ + + + + + + + 使用 import + + + + + +
+ +
+ 使用Link.Import 内容区 +
+
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseObject.html b/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseObject.html new file mode 100644 index 0000000..264150f --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/UseObject.html @@ -0,0 +1,23 @@ + + + + + + + 使用 Object + + + +
+ +
+ 使用 Object 内容区 +
+
+ + \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/css/Import.css b/H5Study.WebApp/wwwroot/Html中引用html文件方法/css/Import.css new file mode 100644 index 0000000..a455a69 --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/css/Import.css @@ -0,0 +1,26 @@ +body.iframe-body +{ + margin: 0; + padding: 0; +} + +.import-box { + margin: 0; + padding: 1px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; +} + +.import-box h2 { + text-align: left; + align-self: center; +} + +.import-box a { + margin: 0 20px; + padding: 5px 5px; + text-align: left; + text-decoration: none; +} \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/css/app.css b/H5Study.WebApp/wwwroot/Html中引用html文件方法/css/app.css new file mode 100644 index 0000000..df43a69 --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/css/app.css @@ -0,0 +1,71 @@ +html { + margin: 0; + padding: 0; +} +body { + margin: 10px; + padding: 0; +} +.container { + margin: 15px auto; + padding: 15px; + min-height: 400px; + background-color: #aca8a8; + border: 1px solid rebeccapurple; + border-radius: 15px; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-evenly; + align-items: stretch; +} + +.menu { + margin-right: 10px; + padding: 11px; + width: 250px; + background-color: #5ccb8c; + border: 2px solid rebeccapurple; + border-radius: 15px; + + /*便于计算*/ + background-origin: border-box; +} + +iframe { + overflow-clip-margin: content-box !important; + margin: 0; + padding: 0; + width: 100%; + height: 100%; + border-width: 0px; +} + +object { + overflow-clip-margin: content-box !important; + margin: 0; + padding: 0; + width: 100%; + height: 100%; + border-width: 0px; +} + +.context { + width: calc(100% - 200px); + padding: 10px; + background-color: #7b96cf; + border: 2px solid rebeccapurple; + border-radius: 15px; + margin-left: auto; + text-align: center; + font-size: 50px; + + /*便于计算*/ + background-origin: border-box; + + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content:flex-start; + align-items: center; +} \ No newline at end of file diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/favicon.ico b/H5Study.WebApp/wwwroot/Html中引用html文件方法/favicon.ico new file mode 100644 index 0000000..fb5aaf3 Binary files /dev/null and b/H5Study.WebApp/wwwroot/Html中引用html文件方法/favicon.ico differ diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/html引用html方法.md b/H5Study.WebApp/wwwroot/Html中引用html文件方法/html引用html方法.md new file mode 100644 index 0000000..24895aa --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/html引用html方法.md @@ -0,0 +1,214 @@ +在 `html` 中引用 `html` 或 `html片断` 的方式 +============================================ +在静态站点的制作中,有些像通用菜单、头部、页脚等是统一的,如果在各页页中都复制一分对于修改是个空难级影响。 +以下是几种在html中引用另一个 html 文件的方式。 + +本示例中被引用的html片断文件为 import.html;方便起见,引用和被引用的html文件牌同一目录(当然也可以不同)。 + +## 纯 `html` 方式 ++ 使用:ifreame 标签 +``` html + + + + + + 使用iframe标签引用html文件 + + + + +
+ 其它内容 +
+ + +
+ 其它内容 +
+ + + + +```` ++ 使用:object 标签 +``` html + + + + + + 使用 "object标签" 引用html文件 + + + +
+ 其它内容 +
+ + + style="border:0px" + type="text/x-scriptlet" + data="import.html" + width=100% + height=30 > + +
+ 其它内容 +
+ + + + +```` ++ 使用:link 标签 [实现困难] +``` html + + + + + + 使用iframe标签引用html文件 + + + + + +
+ 其它内容 +
+ +
+ 其它内容 +
+ + + + +```` + ++ bootstrap 的 panel 组件,或者 easyui 的 window 组件 +``` html + + +```` +## 使用 js 配合 ++ 原生 js +``` html + + + + + + + + 使用js + + + +
+ +
+ 主页内容区 +
+
+ + + + + + +```` ++ 使用:jquery +``` html + + + + + + + 使用jQuery + + + + + +
+ +
+ 主页内容区 +
+
+ + + + + +```` + +## 动态网页技术 + 比如 asp.net webform、mvc、razor、blazor等技术中,都有一个类似"模板页"的概述,可以很方便的实现。 diff --git a/H5Study.WebApp/wwwroot/Html中引用html文件方法/jquery/jquery-3.6.4.js b/H5Study.WebApp/wwwroot/Html中引用html文件方法/jquery/jquery-3.6.4.js new file mode 100644 index 0000000..7f35c11 --- /dev/null +++ b/H5Study.WebApp/wwwroot/Html中引用html文件方法/jquery/jquery-3.6.4.js @@ -0,0 +1,10965 @@ +/*! + * jQuery JavaScript Library v3.6.4 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2023-03-08T15:28Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket trac-14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.4", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.10 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2023-02-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rleadingCombinator = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + 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; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rleadingCombinator.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + // Support: Chrome 105 - 110+, Safari 15.4 - 16.3+ + // Make sure the the `:has()` argument is parsed unforgivingly. + // We include `*` in the test to detect buggy implementations that are + // _selectively_ forgiving (specifically when the list includes at least + // one valid selector). + // Note that we treat complete lack of support for `:has()` as if it were + // spec-compliant support, which is fine because use of `:has()` in such + // environments will fail in the qSA path and fall back to jQuery traversal + // anyway. + support.cssHas = assert( function() { + try { + document.querySelector( ":has(*,:jqfake)" ); + return false; + } catch ( e ) { + return true; + } + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + if ( !support.cssHas ) { + + // Support: Chrome 105 - 110+, Safari 15.4 - 16.3+ + // Our regular `try-catch` mechanism fails to detect natively-unsupported + // pseudo-classes inside `:has()` (such as `:has(:contains("Foo"))`) + // in browsers that parse the `:has()` argument as a forgiving selector list. + // https://drafts.csswg.org/selectors/#relational now requires the argument + // to be parsed unforgivingly, but browsers have not yet fully adjusted. + rbuggyQSA.push( ":has" ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + + // Support: IE <9 only + // IE doesn't have `contains` on `document` so we need to check for + // `documentElement` presence. + // We need to fall back to `a` when `documentElement` is missing + // as `ownerDocument` of elements within `