From 5e0da0e8b35735e4dc0e99d00d495836ca58c321 Mon Sep 17 00:00:00 2001 From: ix <0x00fi@protonmail.com> Date: Mon, 6 Sep 2021 19:42:13 +0200 Subject: [PATCH] okay it's done i think --- .../templates/ctfs/.ctfs_list.html.swp | Bin 0 -> 12288 bytes .../templates/templates/ctfs/ctf_info.html | 81 + .../templates/templates/ctfs/ctfs_list.html | 53 + src/project/settings.py | 37 +- src/statics/admin/css/autocomplete.css | 57 +- src/statics/admin/css/base.css | 355 +- src/statics/admin/css/changelists.css | 143 +- src/statics/admin/css/dashboard.css | 1 - src/statics/admin/css/forms.css | 67 +- src/statics/admin/css/login.css | 41 +- src/statics/admin/css/nav_sidebar.css | 120 + src/statics/admin/css/responsive.css | 105 +- src/statics/admin/css/responsive_rtl.css | 20 +- src/statics/admin/css/rtl.css | 48 +- .../css/vendor/select2/LICENSE-SELECT2.md | 2 +- .../admin/css/vendor/select2/select2.css | 19 +- .../admin/css/vendor/select2/select2.min.css | 2 +- src/statics/admin/css/widgets.css | 87 +- src/statics/admin/js/SelectBox.js | 106 +- src/statics/admin/js/SelectFilter2.js | 132 +- src/statics/admin/js/actions.js | 321 +- .../admin/js/admin/DateTimeShortcuts.js | 130 +- .../admin/js/admin/RelatedObjectLookups.js | 86 +- src/statics/admin/js/autocomplete.js | 20 +- src/statics/admin/js/calendar.js | 63 +- src/statics/admin/js/cancel.js | 34 +- src/statics/admin/js/change_form.js | 32 +- src/statics/admin/js/collapse.js | 44 +- src/statics/admin/js/core.js | 102 +- src/statics/admin/js/inlines.js | 278 +- src/statics/admin/js/jquery.init.js | 6 +- src/statics/admin/js/nav_sidebar.js | 39 + src/statics/admin/js/popup_response.js | 8 +- src/statics/admin/js/prepopulate.js | 13 +- src/statics/admin/js/prepopulate_init.js | 9 +- src/statics/admin/js/urlify.js | 77 +- .../admin/js/vendor/jquery/LICENSE.txt | 8 +- src/statics/admin/js/vendor/jquery/jquery.js | 1793 +++-- .../admin/js/vendor/jquery/jquery.min.js | 4 +- .../admin/js/vendor/select2/LICENSE.md | 2 +- .../admin/js/vendor/select2/i18n/af.js | 3 + .../admin/js/vendor/select2/i18n/ar.js | 4 +- .../admin/js/vendor/select2/i18n/az.js | 4 +- .../admin/js/vendor/select2/i18n/bg.js | 4 +- .../admin/js/vendor/select2/i18n/bn.js | 3 + .../admin/js/vendor/select2/i18n/bs.js | 3 + .../admin/js/vendor/select2/i18n/ca.js | 4 +- .../admin/js/vendor/select2/i18n/cs.js | 4 +- .../admin/js/vendor/select2/i18n/da.js | 4 +- .../admin/js/vendor/select2/i18n/de.js | 4 +- .../admin/js/vendor/select2/i18n/dsb.js | 3 + .../admin/js/vendor/select2/i18n/el.js | 4 +- .../admin/js/vendor/select2/i18n/en.js | 4 +- .../admin/js/vendor/select2/i18n/es.js | 4 +- .../admin/js/vendor/select2/i18n/et.js | 4 +- .../admin/js/vendor/select2/i18n/eu.js | 4 +- .../admin/js/vendor/select2/i18n/fa.js | 4 +- .../admin/js/vendor/select2/i18n/fi.js | 4 +- .../admin/js/vendor/select2/i18n/fr.js | 4 +- .../admin/js/vendor/select2/i18n/gl.js | 4 +- .../admin/js/vendor/select2/i18n/he.js | 4 +- .../admin/js/vendor/select2/i18n/hi.js | 4 +- .../admin/js/vendor/select2/i18n/hr.js | 4 +- .../admin/js/vendor/select2/i18n/hsb.js | 3 + .../admin/js/vendor/select2/i18n/hu.js | 4 +- .../admin/js/vendor/select2/i18n/hy.js | 3 + .../admin/js/vendor/select2/i18n/id.js | 4 +- .../admin/js/vendor/select2/i18n/is.js | 4 +- .../admin/js/vendor/select2/i18n/it.js | 4 +- .../admin/js/vendor/select2/i18n/ja.js | 4 +- .../admin/js/vendor/select2/i18n/ka.js | 3 + .../admin/js/vendor/select2/i18n/km.js | 4 +- .../admin/js/vendor/select2/i18n/ko.js | 4 +- .../admin/js/vendor/select2/i18n/lt.js | 4 +- .../admin/js/vendor/select2/i18n/lv.js | 4 +- .../admin/js/vendor/select2/i18n/mk.js | 4 +- .../admin/js/vendor/select2/i18n/ms.js | 4 +- .../admin/js/vendor/select2/i18n/nb.js | 4 +- .../admin/js/vendor/select2/i18n/ne.js | 3 + .../admin/js/vendor/select2/i18n/nl.js | 4 +- .../admin/js/vendor/select2/i18n/pl.js | 4 +- .../admin/js/vendor/select2/i18n/ps.js | 3 + .../admin/js/vendor/select2/i18n/pt-BR.js | 4 +- .../admin/js/vendor/select2/i18n/pt.js | 4 +- .../admin/js/vendor/select2/i18n/ro.js | 4 +- .../admin/js/vendor/select2/i18n/ru.js | 4 +- .../admin/js/vendor/select2/i18n/sk.js | 4 +- .../admin/js/vendor/select2/i18n/sl.js | 3 + .../admin/js/vendor/select2/i18n/sq.js | 3 + .../admin/js/vendor/select2/i18n/sr-Cyrl.js | 4 +- .../admin/js/vendor/select2/i18n/sr.js | 4 +- .../admin/js/vendor/select2/i18n/sv.js | 4 +- .../admin/js/vendor/select2/i18n/th.js | 4 +- .../admin/js/vendor/select2/i18n/tk.js | 3 + .../admin/js/vendor/select2/i18n/tr.js | 4 +- .../admin/js/vendor/select2/i18n/uk.js | 4 +- .../admin/js/vendor/select2/i18n/vi.js | 4 +- .../admin/js/vendor/select2/i18n/zh-CN.js | 4 +- .../admin/js/vendor/select2/i18n/zh-TW.js | 4 +- .../admin/js/vendor/select2/select2.full.js | 956 ++- .../js/vendor/select2/select2.full.min.js | 5 +- .../admin/js/vendor/xregexp/LICENSE.txt | 2 +- .../admin/js/vendor/xregexp/xregexp.js | 6646 +++++++++++------ .../admin/js/vendor/xregexp/xregexp.min.js | 178 +- src/templates/ctfs/.ctfs_list.html.swp | Bin 0 -> 12288 bytes src/templates/ctfs/ctf_info.html | 81 + src/templates/ctfs/ctfs_list.html | 53 + 107 files changed, 8276 insertions(+), 4414 deletions(-) create mode 100755 src/ctfs/templates/templates/ctfs/.ctfs_list.html.swp create mode 100755 src/ctfs/templates/templates/ctfs/ctf_info.html create mode 100755 src/ctfs/templates/templates/ctfs/ctfs_list.html create mode 100644 src/statics/admin/css/nav_sidebar.css create mode 100644 src/statics/admin/js/nav_sidebar.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/af.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/bn.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/bs.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/dsb.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/hsb.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/hy.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/ka.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/ne.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/ps.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/sl.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/sq.js create mode 100644 src/statics/admin/js/vendor/select2/i18n/tk.js create mode 100755 src/templates/ctfs/.ctfs_list.html.swp create mode 100755 src/templates/ctfs/ctf_info.html create mode 100755 src/templates/ctfs/ctfs_list.html diff --git a/src/ctfs/templates/templates/ctfs/.ctfs_list.html.swp b/src/ctfs/templates/templates/ctfs/.ctfs_list.html.swp new file mode 100755 index 0000000000000000000000000000000000000000..de319841c709fc7b65160961366a32629afaed84 GIT binary patch literal 12288 zcmeI2&u`pB6vroA5I@==kPxVs!BrD+@OqO?QPVn$5DgVVv=O0598l!7XV;^6Z8I}Y z2vL9=7vR#rfdh9WPDs7bKLBy#&Xo&S5Z@WcUT@H@%CXY3^v(LsyqP!id2d!)Wk&sv z-hH3n==B+%7a05J(N~|WK75)TuP|1oQC2A1vHZEcyZ_#Y_xAk#!CQN8T)(r>`HOnO zU~4lrl47lOquz0z`la5CI}U1c(3;AOcT50aLE9FR_iM&bP94{)wOe?rA>HP5K}L zM1Tko0U|&IhyW2F0z`la5CI}U1fDq0gZl`T)8Ey#oDpiLoD`@1R}ib?9a2&*w27`W8BbcA;%( z4SE&246Q)FJ;&H1=x68~sD!qmb!Zj(1#ABi`W}+d$Iw0K9q3KS?k#}mAp%5z2oM1x zKm>>Y5%}K(PEW6Kktd_9h!6R-GZqGkJQ_02+ZX#FE5 zt1p+Hp7OY-vueW6&b*{nmWkW`ZU08<(XqCQ69B zjWSpq#TIs(wWi>02&@2oN_<)gT*$7pP(7&+qRONqH`1QiWab{uiUH%?Awmh-V}vW+ zja%5MDZ6VCwY33ruA181fS5PjcO^9ss +
+
+
+

{{ ctf.name }}

+ {% trans "Published date" %} : {{ ctf.pub_date }} +
+
+ {{ ctf.description|safe }} +
+ +
+
+

{% trans "Solved by" %}

+ {% if solved_list %} + + + + + + + + + + + {% for s in solved_list %} + + + + + + + {% endfor %} + +
{% trans "Username" %}{% trans "Website" %}{% trans "Score" %}{% trans "Date" %}
{{ s.user.username }}{{ s.user.userprofileinfo.portfolio_site }}{{ s.user.userprofileinfo.score }}{{ s.flag_date }}
+ {% else %} +

{% trans "Nobody have solved this CTF." %}

+ {% endif %} +
+
+ + +{% endblock %} + diff --git a/src/ctfs/templates/templates/ctfs/ctfs_list.html b/src/ctfs/templates/templates/ctfs/ctfs_list.html new file mode 100755 index 0000000..3356b15 --- /dev/null +++ b/src/ctfs/templates/templates/ctfs/ctfs_list.html @@ -0,0 +1,53 @@ +{% extends 'base.html' %} +{% block content %} +{% load i18n %} +
+
+

{{ cat.name }}

+ {% if ctfs %} + + + + + + + + + + + {% for ctf in ctfs %} + + {% if request.user.is_authenticated %} + {% if ctf.solved %} + + {% else %} + + {% endif %} + {% else %} + + {% endif %} + + + + + {% endfor %} + +
{% trans "Username" %}{% trans "Score" %}{% trans "Solved" %}
{{ ctf.name }}{{ ctf.points }}{{ ctf.solved_num }}
+ {% else %} +

{% trans "No ctf available for this category." %}

+ {% endif %} +
+ +
+{% endblock %} diff --git a/src/project/settings.py b/src/project/settings.py index e3866ed..3aa24e9 100644 --- a/src/project/settings.py +++ b/src/project/settings.py @@ -1,4 +1,4 @@ -"" +""" Django settings for project project. Generated by 'django-admin startproject' using Django 2.2.5. @@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/2.2/ref/settings/ """ import os +from django.utils.translation import gettext_lazy as _ # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -20,7 +21,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'secret_key_for_dev' +SECRET_KEY = 'secret' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True @@ -46,6 +47,7 @@ INSTALLED_APPS = [ MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', @@ -109,6 +111,21 @@ AUTH_PASSWORD_VALIDATORS = [ LANGUAGE_CODE = 'en-us' +LANGUAGE_COOKIE_NAME = 'django_language' + +USE_I18N = True + +LANGUAGES = ( + ('en', _("English")), + ('de', _('German')), + ('fr', _('French')), + ('ru', _('Russian')), +) + +LOCALE_PATHS = ( + os.path.join(BASE_DIR, 'locale'), +) + TIME_ZONE = 'UTC' USE_I18N = True @@ -123,9 +140,23 @@ USE_TZ = True SITE_ID = 1 + STATIC_URL = '/static/' -STATICFILES_DIRS = (os.path.join(BASE_DIR, 'statics'),) +STATIC_ROOT = '' +if DEBUG: + #STATIC_ROOT = os.path.join(BASE_DIR, 'statics') + STATICFILES_DIRS = (os.path.join(BASE_DIR, 'statics'),) +else: + STATIC_ROOT = '/home/user/42ctf/src/statics' TEMPLATES[0]['OPTIONS']['context_processors'].append("ctfs.context_processors.cat_processor") MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') LOGIN_URL = '/accounts/signin/' +EMAIL_BACKEND = 'django_mailjet.backends.MailjetBackend' +EMAIL_HOST = 'in-v3.mailjet.com' +EMAIL_PORT = 587 +DEFAULT_FROM_EMAIL = '42ctf ' +MAILJET_API_KEY = '' +MAILJET_API_SECRET = '' + + diff --git a/src/statics/admin/css/autocomplete.css b/src/statics/admin/css/autocomplete.css index 3ef95d1..69c94e7 100644 --- a/src/statics/admin/css/autocomplete.css +++ b/src/statics/admin/css/autocomplete.css @@ -14,7 +14,7 @@ select.admin-autocomplete { .select2-container--admin-autocomplete.select2-container--focus .select2-selection, .select2-container--admin-autocomplete.select2-container--open .select2-selection { - border-color: #999; + border-color: var(--body-quiet-color); min-height: 30px; } @@ -29,13 +29,13 @@ select.admin-autocomplete { } .select2-container--admin-autocomplete .select2-selection--single { - background-color: #fff; - border: 1px solid #ccc; + background-color: var(--body-bg); + border: 1px solid var(--border-color); border-radius: 4px; } .select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered { - color: #444; + color: var(--body-fg); line-height: 30px; } @@ -46,7 +46,7 @@ select.admin-autocomplete { } .select2-container--admin-autocomplete .select2-selection--single .select2-selection__placeholder { - color: #999; + color: var(--body-quiet-color); } .select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow { @@ -80,7 +80,7 @@ select.admin-autocomplete { } .select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single { - background-color: #eee; + background-color: var(--darkened-bg); cursor: default; } @@ -94,8 +94,8 @@ select.admin-autocomplete { } .select2-container--admin-autocomplete .select2-selection--multiple { - background-color: white; - border: 1px solid #ccc; + background-color: var(--body-bg); + border: 1px solid var(--border-color); border-radius: 4px; cursor: text; } @@ -104,8 +104,10 @@ select.admin-autocomplete { box-sizing: border-box; list-style: none; margin: 0; - padding: 0 5px; + padding: 0 10px 5px 5px; width: 100%; + display: flex; + flex-wrap: wrap; } .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered li { @@ -113,7 +115,7 @@ select.admin-autocomplete { } .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__placeholder { - color: #999; + color: var(--body-quiet-color); margin-top: 5px; float: left; } @@ -123,11 +125,13 @@ select.admin-autocomplete { float: right; font-weight: bold; margin: 5px; + position: absolute; + right: 0; } .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice { - background-color: #e4e4e4; - border: 1px solid #ccc; + background-color: var(--darkened-bg); + border: 1px solid var(--border-color); border-radius: 4px; cursor: default; float: left; @@ -137,7 +141,7 @@ select.admin-autocomplete { } .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove { - color: #999; + color: var(--body-quiet-color); cursor: pointer; display: inline-block; font-weight: bold; @@ -145,7 +149,7 @@ select.admin-autocomplete { } .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove:hover { - color: #333; + color: var(--body-fg); } .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-search--inline { @@ -163,12 +167,12 @@ select.admin-autocomplete { } .select2-container--admin-autocomplete.select2-container--focus .select2-selection--multiple { - border: solid #999 1px; + border: solid var(--body-quiet-color) 1px; outline: 0; } .select2-container--admin-autocomplete.select2-container--disabled .select2-selection--multiple { - background-color: #eee; + background-color: var(--darkened-bg); cursor: default; } @@ -186,12 +190,20 @@ select.admin-autocomplete { border-bottom-right-radius: 0; } +.select2-container--admin-autocomplete .select2-search--dropdown { + background: var(--darkened-bg); +} + .select2-container--admin-autocomplete .select2-search--dropdown .select2-search__field { - border: 1px solid #ccc; + background: var(--body-bg); + color: var(--body-fg); + border: 1px solid var(--border-color); + border-radius: 4px; } .select2-container--admin-autocomplete .select2-search--inline .select2-search__field { background: transparent; + color: var(--body-fg); border: none; outline: 0; box-shadow: none; @@ -201,6 +213,8 @@ select.admin-autocomplete { .select2-container--admin-autocomplete .select2-results > .select2-results__options { max-height: 200px; overflow-y: auto; + color: var(--body-fg); + background: var(--body-bg); } .select2-container--admin-autocomplete .select2-results__option[role=group] { @@ -208,11 +222,12 @@ select.admin-autocomplete { } .select2-container--admin-autocomplete .select2-results__option[aria-disabled=true] { - color: #999; + color: var(--body-quiet-color); } .select2-container--admin-autocomplete .select2-results__option[aria-selected=true] { - background-color: #ddd; + background-color: var(--selected-bg); + color: var(--body-fg); } .select2-container--admin-autocomplete .select2-results__option .select2-results__option { @@ -249,8 +264,8 @@ select.admin-autocomplete { } .select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] { - background-color: #79aec8; - color: white; + background-color: var(--primary); + color: var(--primary-fg); } .select2-container--admin-autocomplete .select2-results__group { diff --git a/src/statics/admin/css/base.css b/src/statics/admin/css/base.css index fd011a3..1cb3acd 100644 --- a/src/statics/admin/css/base.css +++ b/src/statics/admin/css/base.css @@ -4,24 +4,116 @@ @import url(fonts.css); +/* VARIABLE DEFINITIONS */ +:root { + --primary: #79aec8; + --secondary: #417690; + --accent: #f5dd5d; + --primary-fg: #fff; + + --body-fg: #333; + --body-bg: #fff; + --body-quiet-color: #666; + --body-loud-color: #000; + + --header-color: #ffc; + --header-branding-color: var(--accent); + --header-bg: var(--secondary); + --header-link-color: var(--primary-fg); + + --breadcrumbs-fg: #c4dce8; + --breadcrumbs-link-fg: var(--body-bg); + --breadcrumbs-bg: var(--primary); + + --link-fg: #447e9b; + --link-hover-color: #036; + --link-selected-fg: #5b80b2; + + --hairline-color: #e8e8e8; + --border-color: #ccc; + + --error-fg: #ba2121; + + --message-success-bg: #dfd; + --message-warning-bg: #ffc; + --message-error-bg: #ffefef; + + --darkened-bg: #f8f8f8; /* A bit darker than --body-bg */ + --selected-bg: #e4e4e4; /* E.g. selected table cells */ + --selected-row: #ffc; + + --button-fg: #fff; + --button-bg: var(--primary); + --button-hover-bg: #609ab6; + --default-button-bg: var(--secondary); + --default-button-hover-bg: #205067; + --close-button-bg: #888; /* Previously #bbb, contrast 1.92 */ + --close-button-hover-bg: #747474; + --delete-button-bg: #ba2121; + --delete-button-hover-bg: #a41515; + + --object-tools-fg: var(--button-fg); + --object-tools-bg: var(--close-button-bg); + --object-tools-hover-bg: var(--close-button-hover-bg); +} + +@media (prefers-color-scheme: dark) { + :root { + --primary: #264b5d; + --primary-fg: #eee; + + --body-fg: #eeeeee; + --body-bg: #121212; + --body-quiet-color: #e0e0e0; + --body-loud-color: #ffffff; + + --breadcrumbs-link-fg: #e0e0e0; + --breadcrumbs-bg: var(--primary); + + --link-fg: #81d4fa; + --link-hover-color: #4ac1f7; + --link-selected-fg: #6f94c6; + + --hairline-color: #272727; + --border-color: #353535; + + --error-fg: #e35f5f; + --message-success-bg: #006b1b; + --message-warning-bg: #583305; + --message-error-bg: #570808; + + --darkened-bg: #212121; + --selected-bg: #1b1b1b; + --selected-row: #00363a; + + --close-button-bg: #333333; + --close-button-hover-bg: #666666; + } +} + +html, body { + height: 100%; +} + body { margin: 0; padding: 0; font-size: 14px; font-family: "Roboto","Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; - color: #333; - background: #fff; + color: var(--body-fg); + background: var(--body-bg); } /* LINKS */ a:link, a:visited { - color: #447e9b; + color: var(--link-fg); text-decoration: none; + transition: color 0.15s, background 0.15s; } a:focus, a:hover { - color: #036; + color: var(--link-hover-color); } a:focus { @@ -33,7 +125,7 @@ a img { } a.section:link, a.section:visited { - color: #fff; + color: var(--header-link-color); text-decoration: none; } @@ -60,7 +152,7 @@ h1 { margin: 0 0 20px; font-weight: 300; font-size: 20px; - color: #666; + color: var(--body-quiet-color); } h2 { @@ -76,7 +168,7 @@ h2.subhead { h3 { font-size: 14px; margin: .8em 0 .3em 0; - color: #666; + color: var(--body-quiet-color); font-weight: bold; } @@ -89,12 +181,12 @@ h4 { h5 { font-size: 10px; margin: 1.5em 0 .5em 0; - color: #666; + color: var(--body-quiet-color); text-transform: uppercase; letter-spacing: 1px; } -ul li { +ul > li { list-style-type: square; padding: 1px 0; } @@ -124,9 +216,10 @@ form { fieldset { margin: 0; + min-width: 0; padding: 0; border: none; - border-top: 1px solid #eee; + border-top: 1px solid var(--hairline-color); } blockquote { @@ -139,13 +232,14 @@ blockquote { code, pre { font-family: "Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; - color: #666; + color: var(--body-quiet-color); font-size: 12px; + overflow-x: auto; } pre.literal-block { margin: 10px; - background: #eee; + background: var(--darkened-bg); padding: 6px 8px; } @@ -155,8 +249,8 @@ code strong { hr { clear: both; - color: #eee; - background-color: #eee; + color: var(--hairline-color); + background-color: var(--hairline-color); height: 1px; border: none; margin: 0; @@ -171,25 +265,13 @@ hr { font-size: 11px; } -.tiny { - font-size: 10px; -} - -p.tiny { - margin-top: -2px; -} - .mini { font-size: 10px; } -p.mini { - margin-top: -3px; -} - .help, p.help, form p.help, div.help, form div.help, div.help li { font-size: 11px; - color: #999; + color: var(--body-quiet-color); } div.help ul { @@ -205,54 +287,35 @@ p img, h1 img, h2 img, h3 img, h4 img, td img { } .quiet, a.quiet:link, a.quiet:visited { - color: #999; + color: var(--body-quiet-color); font-weight: normal; } -.float-right { - float: right; -} - -.float-left { - float: left; -} - .clear { clear: both; } -.align-left { - text-align: left; -} - -.align-right { - text-align: right; -} - -.example { - margin: 10px 0; - padding: 5px 10px; - background: #efefef; -} - .nowrap { white-space: nowrap; } +.hidden { + display: none; +} + /* TABLES */ table { border-collapse: collapse; - border-color: #ccc; + border-color: var(--border-color); } td, th { font-size: 13px; line-height: 16px; - border-bottom: 1px solid #eee; + border-bottom: 1px solid var(--hairline-color); vertical-align: top; padding: 8px; - font-family: "Roboto", "Lucida Grande", Verdana, Arial, sans-serif; } th { @@ -262,34 +325,37 @@ th { thead th, tfoot td { - color: #666; + color: var(--body-quiet-color); padding: 5px 10px; font-size: 11px; - background: #fff; + background: var(--body-bg); border: none; - border-top: 1px solid #eee; - border-bottom: 1px solid #eee; + border-top: 1px solid var(--hairline-color); + border-bottom: 1px solid var(--hairline-color); } tfoot td { border-bottom: none; - border-top: 1px solid #eee; + border-top: 1px solid var(--hairline-color); } thead th.required { - color: #000; + color: var(--body-loud-color); } tr.alt { - background: #f6f6f6; + background: var(--darkened-bg); } -.row1 { - background: #fff; +tr:nth-child(odd), .row-form-errors { + background: var(--body-bg); } -.row2 { - background: #f9f9f9; +tr:nth-child(even), +tr:nth-child(even) .errorlist, +tr:nth-child(odd) + .row-form-errors, +tr:nth-child(odd) + .row-form-errors .errorlist { + background: var(--darkened-bg); } /* SORTABLE TABLES */ @@ -298,15 +364,15 @@ thead th { padding: 5px 10px; line-height: normal; text-transform: uppercase; - background: #f6f6f6; + background: var(--darkened-bg); } thead th a:link, thead th a:visited { - color: #666; + color: var(--body-quiet-color); } thead th.sorted { - background: #eee; + background: var(--selected-bg); } thead th.sorted .text { @@ -325,7 +391,7 @@ table thead th .text a { } table thead th .text a:focus, table thead th .text a:hover { - background: #eee; + background: var(--selected-bg); } thead th.sorted a.sortremove { @@ -372,12 +438,12 @@ table thead th.sorted .sortoptions a.sortremove:after { left: 3px; font-weight: 200; font-size: 18px; - color: #999; + color: var(--body-quiet-color); } table thead th.sorted .sortoptions a.sortremove:focus:after, table thead th.sorted .sortoptions a.sortremove:hover:after { - color: #447e9b; + color: var(--link-fg); } table thead th.sorted .sortoptions a.sortremove:focus, @@ -424,16 +490,18 @@ textarea { input[type=text], input[type=password], input[type=email], input[type=url], input[type=number], input[type=tel], textarea, select, .vTextField { - border: 1px solid #ccc; + border: 1px solid var(--border-color); border-radius: 4px; padding: 5px 6px; margin-top: 0; + color: var(--body-fg); + background-color: var(--body-bg); } input[type=text]:focus, input[type=password]:focus, input[type=email]:focus, input[type=url]:focus, input[type=number]:focus, input[type=tel]:focus, textarea:focus, select:focus, .vTextField:focus { - border-color: #999; + border-color: var(--body-quiet-color); } select { @@ -449,12 +517,13 @@ select[multiple] { /* FORM BUTTONS */ .button, input[type=submit], input[type=button], .submit-row input, a.button { - background: #79aec8; + background: var(--button-bg); padding: 10px 15px; border: none; border-radius: 4px; - color: #fff; + color: var(--button-fg); cursor: pointer; + transition: background 0.15s; } a.button { @@ -464,7 +533,7 @@ a.button { .button:active, input[type=submit]:active, input[type=button]:active, .button:focus, input[type=submit]:focus, input[type=button]:focus, .button:hover, input[type=submit]:hover, input[type=button]:hover { - background: #609ab6; + background: var(--button-hover-bg); } .button[disabled], input[type=submit][disabled], input[type=button][disabled] { @@ -475,13 +544,13 @@ a.button { float: right; border: none; font-weight: 400; - background: #417690; + background: var(--default-button-bg); } .button.default:active, input[type=submit].default:active, .button.default:focus, input[type=submit].default:focus, .button.default:hover, input[type=submit].default:hover { - background: #205067; + background: var(--default-button-hover-bg); } .button[disabled].default, @@ -496,7 +565,7 @@ input[type=button][disabled].default { .module { border: none; margin-bottom: 30px; - background: #fff; + background: var(--body-bg); } .module p, .module ul, .module h3, .module h4, .module dl, .module pre { @@ -522,8 +591,8 @@ input[type=button][disabled].default { font-weight: 400; font-size: 13px; text-align: left; - background: #79aec8; - color: #fff; + background: var(--primary); + color: var(--header-link-color); } .module caption, @@ -550,18 +619,18 @@ ul.messagelist li { font-size: 13px; padding: 10px 10px 10px 65px; margin: 0 0 10px 0; - background: #dfd url(../img/icon-yes.svg) 40px 12px no-repeat; + background: var(--message-success-bg) url(../img/icon-yes.svg) 40px 12px no-repeat; background-size: 16px auto; - color: #333; + color: var(--body-fg); } ul.messagelist li.warning { - background: #ffc url(../img/icon-alert.svg) 40px 14px no-repeat; + background: var(--message-warning-bg) url(../img/icon-alert.svg) 40px 14px no-repeat; background-size: 14px auto; } ul.messagelist li.error { - background: #ffefef url(../img/icon-no.svg) 40px 12px no-repeat; + background: var(--message-error-bg) url(../img/icon-no.svg) 40px 12px no-repeat; background-size: 16px auto; } @@ -571,24 +640,26 @@ ul.messagelist li.error { display: block; padding: 10px 12px; margin: 0 0 10px 0; - color: #ba2121; - border: 1px solid #ba2121; + color: var(--error-fg); + border: 1px solid var(--error-fg); border-radius: 4px; - background-color: #fff; + background-color: var(--body-bg); background-position: 5px 12px; + overflow-wrap: break-word; } ul.errorlist { margin: 0 0 4px; padding: 0; - color: #ba2121; - background: #fff; + color: var(--error-fg); + background: var(--body-bg); } ul.errorlist li { font-size: 13px; display: block; margin-bottom: 4px; + overflow-wrap: break-word; } ul.errorlist li:first-child { @@ -612,7 +683,7 @@ td ul.errorlist li { .form-row.errors { margin: 0; border: none; - border-bottom: 1px solid #eee; + border-bottom: 1px solid var(--hairline-color); background: none; } @@ -620,22 +691,9 @@ td ul.errorlist li { padding-left: 0; } -.errors input, .errors select, .errors textarea { - border: 1px solid #ba2121; -} - -div.system-message { - background: #ffc; - margin: 10px; - padding: 6px 8px; - font-size: .8em; -} - -div.system-message p.system-message-title { - padding: 4px 5px 4px 25px; - margin: 0; - color: #c11; - background: #ffefef url(../img/icon-no.svg) 5px 5px no-repeat; +.errors input, .errors select, .errors textarea, +td ul.errorlist + input, td ul.errorlist + select, td ul.errorlist + textarea { + border: 1px solid var(--error-fg); } .description { @@ -646,20 +704,19 @@ div.system-message p.system-message-title { /* BREADCRUMBS */ div.breadcrumbs { - background: #79aec8; + background: var(--breadcrumbs-bg); padding: 10px 40px; border: none; - font-size: 14px; - color: #c4dce8; + color: var(--breadcrumbs-fg); text-align: left; } div.breadcrumbs a { - color: #fff; + color: var(--breadcrumbs-link-fg); } div.breadcrumbs a:focus, div.breadcrumbs a:hover { - color: #c4dce8; + color: var(--breadcrumbs-fg); } /* ACTION ICONS */ @@ -685,11 +742,11 @@ div.breadcrumbs a:focus, div.breadcrumbs a:hover { } a.deletelink:link, a.deletelink:visited { - color: #CC3434; + color: #CC3434; /* XXX Probably unused? */ } a.deletelink:focus, a.deletelink:hover { - color: #993333; + color: #993333; /* XXX Probably unused? */ text-decoration: none; } @@ -704,14 +761,6 @@ a.deletelink:focus, a.deletelink:hover { margin-top: -48px; } -.form-row .object-tools { - margin-top: 5px; - margin-bottom: 5px; - float: none; - height: 2em; - padding-left: 3.5em; -} - .object-tools li { display: block; float: left; @@ -727,29 +776,29 @@ a.deletelink:focus, a.deletelink:hover { display: block; float: left; padding: 3px 12px; - background: #999; + background: var(--object-tools-bg); + color: var(--object-tools-fg); font-weight: 400; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; - color: #fff; } .object-tools a:focus, .object-tools a:hover { - background-color: #417690; + background-color: var(--object-tools-hover-bg); } .object-tools a:focus{ text-decoration: none; } -.object-tools a.viewsitelink, .object-tools a.golink,.object-tools a.addlink { +.object-tools a.viewsitelink, .object-tools a.addlink { background-repeat: no-repeat; background-position: right 7px center; padding-right: 26px; } -.object-tools a.viewsitelink, .object-tools a.golink { +.object-tools a.viewsitelink { background-image: url(../img/tooltag-arrowright.svg); } @@ -774,6 +823,23 @@ table#change-history tbody th { width: 100%; min-width: 980px; padding: 0; + display: flex; + flex-direction: column; + height: 100%; +} + +#container > div { + flex-shrink: 0; +} + +#container > .main { + display: flex; + flex: 1 0 auto; +} + +.main > .content { + flex: 1 0; + max-width: 100%; } #content { @@ -834,13 +900,13 @@ table#change-history tbody th { justify-content: space-between; align-items: center; padding: 10px 40px; - background: #417690; - color: #ffc; + background: var(--header-bg); + color: var(--header-color); overflow: hidden; } #header a:link, #header a:visited { - color: #fff; + color: var(--header-link-color); } #header a:focus , #header a:hover { @@ -856,11 +922,11 @@ table#change-history tbody th { margin: 0 20px 0 0; font-weight: 300; font-size: 24px; - color: #f5dd5d; + color: var(--accent); } #branding h1, #branding h1 a:link, #branding h1 a:visited { - color: #f5dd5d; + color: var(--accent); } #branding h2 { @@ -868,7 +934,7 @@ table#change-history tbody th { font-size: 14px; margin: -8px 0 8px 0; font-weight: normal; - color: #ffc; + color: var(--header-color); } #branding a:hover { @@ -892,14 +958,14 @@ table#change-history tbody th { #user-tools a:focus, #user-tools a:hover { text-decoration: none; - border-bottom-color: #79aec8; - color: #79aec8; + border-bottom-color: var(--primary); + color: var(--primary); } /* SIDEBAR */ #content-related { - background: #f8f8f8; + background: var(--darkened-bg); } #content-related .module { @@ -907,8 +973,7 @@ table#change-history tbody th { } #content-related h3 { - font-size: 14px; - color: #666; + color: var(--body-quiet-color); padding: 0 16px; margin: 0 0 16px; } @@ -937,22 +1002,22 @@ table#change-history tbody th { background: none; padding: 16px; margin-bottom: 16px; - border-bottom: 1px solid #eaeaea; + border-bottom: 1px solid var(--hairline-color); font-size: 18px; - color: #333; + color: var(--body-fg); } .delete-confirmation form input[type="submit"] { - background: #ba2121; + background: var(--delete-button-bg); border-radius: 4px; padding: 10px 15px; - color: #fff; + color: var(--button-fg); } .delete-confirmation form input[type="submit"]:active, .delete-confirmation form input[type="submit"]:focus, .delete-confirmation form input[type="submit"]:hover { - background: #a41515; + background: var(--delete-button-hover-bg); } .delete-confirmation form .cancel-link { @@ -960,17 +1025,17 @@ table#change-history tbody th { vertical-align: middle; height: 15px; line-height: 15px; - background: #ddd; border-radius: 4px; padding: 10px 15px; - color: #333; + color: var(--button-fg); + background: var(--close-button-bg); margin: 0 0 0 10px; } .delete-confirmation form .cancel-link:active, .delete-confirmation form .cancel-link:focus, .delete-confirmation form .cancel-link:hover { - background: #ccc; + background: var(--close-button-hover-bg); } /* POPUP */ diff --git a/src/statics/admin/css/changelists.css b/src/statics/admin/css/changelists.css index 17690a3..b4a1557 100644 --- a/src/statics/admin/css/changelists.css +++ b/src/statics/admin/css/changelists.css @@ -1,8 +1,14 @@ /* CHANGELISTS */ #changelist { - position: relative; - width: 100%; + display: flex; + align-items: flex-start; + justify-content: space-between; +} + +#changelist .changelist-form-container { + flex: 1 1 auto; + min-width: 0; } #changelist table { @@ -21,7 +27,6 @@ .change-list .filtered .results, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { - margin-right: 280px; width: auto; } @@ -30,17 +35,18 @@ } #changelist-form .results { - overflow-x: auto; + overflow-x: auto; + width: 100%; } #changelist .toplinks { - border-bottom: 1px solid #ddd; + border-bottom: 1px solid var(--hairline-color); } #changelist .paginator { - color: #666; - border-bottom: 1px solid #eee; - background: #fff; + color: var(--body-quiet-color); + border-bottom: 1px solid var(--hairline-color); + background: var(--body-bg); overflow: hidden; } @@ -62,57 +68,59 @@ } #changelist table tfoot { - color: #666; + color: var(--body-quiet-color); } /* TOOLBAR */ -#changelist #toolbar { +#toolbar { padding: 8px 10px; margin-bottom: 15px; - border-top: 1px solid #eee; - border-bottom: 1px solid #eee; - background: #f8f8f8; - color: #666; + border-top: 1px solid var(--hairline-color); + border-bottom: 1px solid var(--hairline-color); + background: var(--darkened-bg); + color: var(--body-quiet-color); } -#changelist #toolbar form input { +#toolbar form input { border-radius: 4px; font-size: 14px; padding: 5px; - color: #333; + color: var(--body-fg); } -#changelist #toolbar form #searchbar { +#toolbar #searchbar { height: 19px; - border: 1px solid #ccc; + border: 1px solid var(--border-color); padding: 2px 5px; margin: 0; vertical-align: top; font-size: 13px; + max-width: 100%; } -#changelist #toolbar form #searchbar:focus { - border-color: #999; +#toolbar #searchbar:focus { + border-color: var(--body-quiet-color); } -#changelist #toolbar form input[type="submit"] { - border: 1px solid #ccc; - padding: 2px 10px; +#toolbar form input[type="submit"] { + border: 1px solid var(--border-color); + font-size: 13px; + padding: 4px 8px; margin: 0; vertical-align: middle; - background: #fff; + background: var(--body-bg); box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; cursor: pointer; - color: #333; + color: var(--body-fg); } -#changelist #toolbar form input[type="submit"]:focus, -#changelist #toolbar form input[type="submit"]:hover { - border-color: #999; +#toolbar form input[type="submit"]:focus, +#toolbar form input[type="submit"]:hover { + border-color: var(--body-quiet-color); } -#changelist #changelist-search img { +#changelist-search img { vertical-align: middle; margin-right: 4px; } @@ -120,14 +128,11 @@ /* FILTER COLUMN */ #changelist-filter { - position: absolute; - top: 0; - right: 0; - z-index: 1000; - width: 240px; - background: #f8f8f8; + flex: 0 0 240px; + order: 1; + background: var(--darkened-bg); border-left: none; - margin: 0; + margin: 0 0 0 30px; } #changelist-filter h2 { @@ -141,7 +146,6 @@ #changelist-filter h3 { font-weight: 400; - font-size: 14px; padding: 0 15px; margin-bottom: 10px; } @@ -149,12 +153,11 @@ #changelist-filter ul { margin: 5px 0; padding: 0 15px 15px; - border-bottom: 1px solid #eaeaea; + border-bottom: 1px solid var(--hairline-color); } #changelist-filter ul:last-child { border-bottom: none; - padding-bottom: none; } #changelist-filter li { @@ -165,25 +168,31 @@ #changelist-filter a { display: block; - color: #999; + color: var(--body-quiet-color); text-overflow: ellipsis; overflow-x: hidden; } #changelist-filter li.selected { - border-left: 5px solid #eaeaea; + border-left: 5px solid var(--hairline-color); padding-left: 10px; margin-left: -15px; } #changelist-filter li.selected a { - color: #5b80b2; + color: var(--link-selected-fg); } #changelist-filter a:focus, #changelist-filter a:hover, #changelist-filter li.selected a:focus, #changelist-filter li.selected a:hover { - color: #036; + color: var(--link-hover-color); +} + +#changelist-filter #changelist-filter-clear a { + font-size: 13px; + padding-bottom: 10px; + border-bottom: 1px solid var(--hairline-color); } /* DATE DRILLDOWN */ @@ -204,12 +213,12 @@ } .change-list ul.toplinks .date-back a { - color: #999; + color: var(--body-quiet-color); } .change-list ul.toplinks .date-back a:focus, .change-list ul.toplinks .date-back a:hover { - color: #036; + color: var(--link-hover-color); } /* PAGINATOR */ @@ -220,26 +229,26 @@ padding-bottom: 10px; line-height: 22px; margin: 0; - border-top: 1px solid #ddd; + border-top: 1px solid var(--hairline-color); + width: 100%; } .paginator a:link, .paginator a:visited { padding: 2px 6px; - background: #79aec8; + background: var(--button-bg); text-decoration: none; - color: #fff; + color: var(--button-fg); } .paginator a.showall { - padding: 0; border: none; background: none; - color: #5b80b2; + color: var(--link-fg); } .paginator a.showall:focus, .paginator a.showall:hover { background: none; - color: #036; + color: var(--link-hover-color); } .paginator .end { @@ -255,13 +264,12 @@ .paginator a:focus, .paginator a:hover { color: white; - background: #036; + background: var(--link-hover-color); } /* ACTIONS */ .filtered .actions { - margin-right: 280px; border-right: none; } @@ -271,21 +279,22 @@ } #changelist table tbody tr.selected { - background-color: #FFFFCC; + background-color: var(--selected-row); } #changelist .actions { padding: 10px; - background: #fff; + background: var(--body-bg); border-top: none; border-bottom: none; line-height: 24px; - color: #999; + color: var(--body-quiet-color); + width: 100%; } -#changelist .actions.selected { - background: #fffccf; - border-top: 1px solid #fffee8; +#changelist .actions.selected { /* XXX Probably unused? */ + background: var(--body-bg); + border-top: 1px solid var(--body-bg); border-bottom: 1px solid #edecd6; } @@ -295,7 +304,6 @@ #changelist .actions span.question { font-size: 13px; margin: 0 0.5em; - display: none; } #changelist .actions:last-child { @@ -305,9 +313,8 @@ #changelist .actions select { vertical-align: top; height: 24px; - background: none; - color: #000; - border: 1px solid #ccc; + color: var(--body-fg); + border: 1px solid var(--border-color); border-radius: 4px; font-size: 14px; padding: 0 0 0 4px; @@ -316,7 +323,7 @@ } #changelist .actions select:focus { - border-color: #999; + border-color: var(--body-quiet-color); } #changelist .actions label { @@ -327,18 +334,18 @@ #changelist .actions .button { font-size: 13px; - border: 1px solid #ccc; + border: 1px solid var(--border-color); border-radius: 4px; - background: #fff; + background: var(--body-bg); box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; cursor: pointer; height: 24px; line-height: 1; padding: 4px 8px; margin: 0; - color: #333; + color: var(--body-fg); } #changelist .actions .button:focus, #changelist .actions .button:hover { - border-color: #999; + border-color: var(--body-quiet-color); } diff --git a/src/statics/admin/css/dashboard.css b/src/statics/admin/css/dashboard.css index 1560c7b..91d6efd 100644 --- a/src/statics/admin/css/dashboard.css +++ b/src/statics/admin/css/dashboard.css @@ -23,5 +23,4 @@ ul.actionlist li { list-style-type: none; overflow: hidden; text-overflow: ellipsis; - -o-text-overflow: ellipsis; } diff --git a/src/statics/admin/css/forms.css b/src/statics/admin/css/forms.css index 62a093f..89b2270 100644 --- a/src/statics/admin/css/forms.css +++ b/src/statics/admin/css/forms.css @@ -6,7 +6,7 @@ overflow: hidden; padding: 10px; font-size: 13px; - border-bottom: 1px solid #eee; + border-bottom: 1px solid var(--hairline-color); } .form-row img, .form-row input { @@ -22,21 +22,17 @@ form .form-row p { padding-left: 0; } -.hidden { - display: none; -} - /* FORM LABELS */ label { font-weight: normal; - color: #666; + color: var(--body-quiet-color); font-size: 13px; } .required label, label.required { font-weight: bold; - color: #333; + color: var(--body-fg); } /* RADIO BUTTONS */ @@ -219,24 +215,24 @@ fieldset.collapsed h2, fieldset.collapsed { } fieldset.collapsed { - border: 1px solid #eee; + border: 1px solid var(--hairline-color); border-radius: 4px; overflow: hidden; } fieldset.collapsed h2 { - background: #f8f8f8; - color: #666; + background: var(--darkened-bg); + color: var(--body-quiet-color); } fieldset .collapse-toggle { - color: #fff; + color: var(--header-link-color); } fieldset.collapsed .collapse-toggle { background: transparent; display: inline; - color: #447e9b; + color: var(--link-fg); } /* MONOSPACE TEXTAREAS */ @@ -250,8 +246,8 @@ fieldset.monospace textarea { .submit-row { padding: 12px 14px; margin: 0 0 20px; - background: #f8f8f8; - border: 1px solid #eee; + background: var(--darkened-bg); + border: 1px solid var(--hairline-color); border-radius: 4px; text-align: right; overflow: hidden; @@ -283,35 +279,35 @@ body.popup .submit-row { .submit-row a.deletelink { display: block; - background: #ba2121; + background: var(--delete-button-bg); border-radius: 4px; padding: 10px 15px; height: 15px; line-height: 15px; - color: #fff; + color: var(--button-fg); } .submit-row a.closelink { display: inline-block; - background: #bbbbbb; + background: var(--close-button-bg); border-radius: 4px; padding: 10px 15px; height: 15px; line-height: 15px; margin: 0 0 0 5px; - color: #fff; + color: var(--button-fg); } .submit-row a.deletelink:focus, .submit-row a.deletelink:hover, .submit-row a.deletelink:active { - background: #a41515; + background: var(--delete-button-hover-bg); } .submit-row a.closelink:focus, .submit-row a.closelink:hover, .submit-row a.closelink:active { - background: #aaaaaa; + background: var(--close-button-hover-bg); } /* CUSTOM FORM FIELDS */ @@ -390,12 +386,12 @@ body.popup .submit-row { .inline-related h3 { margin: 0; - color: #666; + color: var(--body-quiet-color); padding: 5px; font-size: 13px; - background: #f8f8f8; - border-top: 1px solid #eee; - border-bottom: 1px solid #eee; + background: var(--darkened-bg); + border-top: 1px solid var(--hairline-color); + border-bottom: 1px solid var(--hairline-color); } .inline-related h3 span.delete { @@ -409,7 +405,7 @@ body.popup .submit-row { .inline-related fieldset { margin: 0; - background: #fff; + background: var(--body-bg); border: none; width: 100%; } @@ -421,7 +417,7 @@ body.popup .submit-row { text-align: left; font-weight: bold; background: #bcd; - color: #fff; + color: var(--body-bg); } .inline-group .tabular fieldset.module { @@ -430,6 +426,7 @@ body.popup .submit-row { .inline-related.tabular fieldset.module table { width: 100%; + overflow-x: scroll; } .last-related fieldset { @@ -459,7 +456,7 @@ body.popup .submit-row { overflow: hidden; font-size: 9px; font-weight: bold; - color: #666; + color: var(--body-quiet-color); _width: 700px; } @@ -476,15 +473,15 @@ body.popup .submit-row { .inline-group div.add-row, .inline-group .tabular tr.add-row td { - color: #666; - background: #f8f8f8; + color: var(--body-quiet-color); + background: var(--darkened-bg); padding: 8px 10px; - border-bottom: 1px solid #eee; + border-bottom: 1px solid var(--hairline-color); } .inline-group .tabular tr.add-row td { padding: 8px 10px; - border-bottom: 1px solid #eee; + border-bottom: 1px solid var(--hairline-color); } .inline-group ul.tools a.add, @@ -501,7 +498,7 @@ body.popup .submit-row { /* RELATED FIELD ADD ONE / LOOKUP */ -.add-another, .related-lookup { +.related-lookup { margin-left: 5px; display: inline-block; vertical-align: middle; @@ -509,12 +506,6 @@ body.popup .submit-row { background-size: 14px; } -.add-another { - width: 16px; - height: 16px; - background-image: url(../img/icon-addlink.svg); -} - .related-lookup { width: 16px; height: 16px; diff --git a/src/statics/admin/css/login.css b/src/statics/admin/css/login.css index 2ec241c..10d9d22 100644 --- a/src/statics/admin/css/login.css +++ b/src/statics/admin/css/login.css @@ -1,7 +1,8 @@ /* LOGIN FORM */ -body.login { - background: #f8f8f8; +.login { + background: var(--darkened-bg); + height: auto; } .login #header { @@ -15,7 +16,7 @@ body.login { } .login #header h1 a { - color: #fff; + color: var(--header-link-color); } .login #content { @@ -23,55 +24,35 @@ body.login { } .login #container { - background: #fff; - border: 1px solid #eaeaea; + background: var(--body-bg); + border: 1px solid var(--hairline-color); border-radius: 4px; overflow: hidden; width: 28em; min-width: 300px; margin: 100px auto; -} - -.login #content-main { - width: 100%; + height: auto; } .login .form-row { padding: 4px 0; - float: left; - width: 100%; - border-bottom: none; } .login .form-row label { - padding-right: 0.5em; + display: block; line-height: 2em; - font-size: 1em; - clear: both; - color: #333; } .login .form-row #id_username, .login .form-row #id_password { - clear: both; padding: 8px; width: 100%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.login span.help { - font-size: 10px; - display: block; + box-sizing: border-box; } .login .submit-row { - clear: both; - padding: 1em 0 0 9.4em; + padding: 1em 0 0 0; margin: 0; - border: none; - background: none; - text-align: left; + text-align: center; } .login .password-reset-link { diff --git a/src/statics/admin/css/nav_sidebar.css b/src/statics/admin/css/nav_sidebar.css new file mode 100644 index 0000000..f3c2fd8 --- /dev/null +++ b/src/statics/admin/css/nav_sidebar.css @@ -0,0 +1,120 @@ +.sticky { + position: sticky; + top: 0; + max-height: 100vh; +} + +.toggle-nav-sidebar { + z-index: 20; + left: 0; + display: flex; + align-items: center; + justify-content: center; + flex: 0 0 23px; + width: 23px; + border: 0; + border-right: 1px solid var(--hairline-color); + background-color: var(--body-bg); + cursor: pointer; + font-size: 20px; + color: var(--link-fg); + padding: 0; +} + +[dir="rtl"] .toggle-nav-sidebar { + border-left: 1px solid var(--hairline-color); + border-right: 0; +} + +.toggle-nav-sidebar:hover, +.toggle-nav-sidebar:focus { + background-color: var(--darkened-bg); +} + +#nav-sidebar { + z-index: 15; + flex: 0 0 275px; + left: -276px; + margin-left: -276px; + border-top: 1px solid transparent; + border-right: 1px solid var(--hairline-color); + background-color: var(--body-bg); + overflow: auto; +} + +[dir="rtl"] #nav-sidebar { + border-left: 1px solid var(--hairline-color); + border-right: 0; + left: 0; + margin-left: 0; + right: -276px; + margin-right: -276px; +} + +.toggle-nav-sidebar::before { + content: '\00BB'; +} + +.main.shifted .toggle-nav-sidebar::before { + content: '\00AB'; +} + +.main.shifted > #nav-sidebar { + left: 24px; + margin-left: 0; +} + +[dir="rtl"] .main.shifted > #nav-sidebar { + left: 0; + right: 24px; + margin-right: 0; +} + +#nav-sidebar .module th { + width: 100%; + overflow-wrap: anywhere; +} + +#nav-sidebar .module th, +#nav-sidebar .module caption { + padding-left: 16px; +} + +#nav-sidebar .module td { + white-space: nowrap; +} + +[dir="rtl"] #nav-sidebar .module th, +[dir="rtl"] #nav-sidebar .module caption { + padding-left: 8px; + padding-right: 16px; +} + +#nav-sidebar .current-app .section:link, +#nav-sidebar .current-app .section:visited { + color: var(--header-color); + font-weight: bold; +} + +#nav-sidebar .current-model { + background: var(--selected-row); +} + +.main > #nav-sidebar + .content { + max-width: calc(100% - 23px); +} + +.main.shifted > #nav-sidebar + .content { + max-width: calc(100% - 299px); +} + +@media (max-width: 767px) { + #nav-sidebar, #toggle-nav-sidebar { + display: none; + } + + .main > #nav-sidebar + .content, + .main.shifted > #nav-sidebar + .content { + max-width: 100%; + } +} diff --git a/src/statics/admin/css/responsive.css b/src/statics/admin/css/responsive.css index 5b0d1ec..8c6dd81 100644 --- a/src/statics/admin/css/responsive.css +++ b/src/statics/admin/css/responsive.css @@ -93,16 +93,14 @@ input[type="submit"], button { /* Changelist */ - #changelist #toolbar { + #toolbar { border: none; padding: 15px; } #changelist-search > div { - display: -webkit-flex; display: flex; - -webkit-flex-wrap: wrap; - flex-wrap: wrap; + flex-wrap: nowrap; max-width: 480px; } @@ -110,16 +108,20 @@ input[type="submit"], button { line-height: 22px; } - #changelist #toolbar form #searchbar { - -webkit-flex: 1 0 auto; + #toolbar form #searchbar { flex: 1 0 auto; width: 0; height: 22px; margin: 0 10px 0 6px; } + #toolbar form input[type=submit] { + flex: 0 1 auto; + } + #changelist-search .quiet { - width: 100%; + width: 0; + flex: 1 0 auto; margin: 5px 0 0 25px; } @@ -138,7 +140,7 @@ input[type="submit"], button { } #changelist .actions select { - background: #fff; + background: var(--body-bg); } #changelist .actions .button { @@ -155,19 +157,16 @@ input[type="submit"], button { } #changelist-filter { - width: 200px; + flex-basis: 200px; } .change-list .filtered .results, .change-list .filtered .paginator, .filtered #toolbar, .filtered .actions, - .filtered div.xfull { - margin-right: 230px; - } #changelist .paginator { - border-top-color: #eee; + border-top-color: var(--hairline-color); /* XXX Is this used at all? */ } #changelist .results + .paginator { @@ -214,11 +213,11 @@ input[type="submit"], button { fieldset .fieldBox + .fieldBox { margin-top: 10px; padding-top: 10px; - border-top: 1px solid #eee; + border-top: 1px solid var(--hairline-color); } textarea { - max-width: 518px; + max-width: 100%; max-height: 120px; } @@ -226,7 +225,6 @@ input[type="submit"], button { padding-top: 6px; } - .aligned .add-another, .aligned .related-lookup, .aligned .datetimeshortcuts, .aligned .related-lookup + strong { @@ -354,6 +352,14 @@ input[type="submit"], button { } .stacked .active.selector-add { + background-position: 0 -40px; + } + + .active.selector-add:focus, .active.selector-add:hover { + background-position: 0 -140px; + } + + .stacked .active.selector-add:focus, .stacked .active.selector-add:hover { background-position: 0 -60px; } @@ -362,6 +368,14 @@ input[type="submit"], button { } .stacked .active.selector-remove { + background-position: 0 0; + } + + .active.selector-remove:focus, .active.selector-remove:hover { + background-position: 0 -100px; + } + + .stacked .active.selector-remove:focus, .stacked .active.selector-remove:hover { background-position: 0 -20px; } @@ -385,11 +399,15 @@ input[type="submit"], button { .datetime .timezonewarning { display: block; font-size: 11px; - color: #999; + color: var(--body-quiet-color); } .datetimeshortcuts { - color: #ccc; + color: var(--border-color); /* XXX Redundant, .datetime span also sets #ccc */ + } + + .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField { + width: 75%; } .inline-group { @@ -484,25 +502,16 @@ input[type="submit"], button { /* Changelist */ #changelist { - display: flex; + align-items: stretch; flex-direction: column; } - #changelist #toolbar { - order: 1; + #toolbar { padding: 10px; } - #changelist .xfull { - order: 2; - } - - #changelist-form { - order: 3; - } - #changelist-filter { - order: 4; + margin-left: 0; } #changelist .actions label { @@ -518,11 +527,6 @@ input[type="submit"], button { flex: 1 0 100%; } - .change-list .filtered .results, .change-list .filtered .paginator, - .filtered #toolbar, .filtered .actions, .filtered div.xfull { - margin-right: 0; - } - #changelist-filter { position: static; width: auto; @@ -651,7 +655,7 @@ input[type="submit"], button { margin-bottom: -3px; } - form .aligned ul.radiolist li + li { + form .aligned ul.radiolist:not(.inline) li + li { margin-top: 5px; } @@ -721,14 +725,22 @@ input[type="submit"], button { background-position: 0 0; } + .active.selector-remove:focus, .active.selector-remove:hover { + background-position: 0 -20px; + } + .selector-add { background-position: 0 -40px; } + .active.selector-add:focus, .active.selector-add:hover { + background-position: 0 -60px; + } + /* Inlines */ .inline-group[data-inline-type="stacked"] .inline-related { - border: 2px solid #eee; + border: 1px solid var(--hairline-color); border-radius: 4px; margin-top: 15px; overflow: auto; @@ -738,18 +750,19 @@ input[type="submit"], button { box-sizing: border-box; } - .inline-group[data-inline-type="stacked"] .inline-related + .inline-related { - margin-top: 30px; - } - .inline-group[data-inline-type="stacked"] .inline-related .module { padding: 0 10px; } - .inline-group[data-inline-type="stacked"] .inline-related .module .form-row:last-child { + .inline-group[data-inline-type="stacked"] .inline-related .module .form-row { + border-top: 1px solid var(--hairline-color); border-bottom: none; } + .inline-group[data-inline-type="stacked"] .inline-related .module .form-row:first-child { + border-top: none; + } + .inline-group[data-inline-type="stacked"] .inline-related h3 { padding: 10px; border-top-width: 0; @@ -779,7 +792,7 @@ input[type="submit"], button { .inline-group[data-inline-type="stacked"] div.add-row { margin-top: 15px; - border: 1px solid #eee; + border: 1px solid var(--hairline-color); border-radius: 4px; } @@ -873,9 +886,7 @@ input[type="submit"], button { } .login .form-row label { - display: block; margin: 0 0 5px; - padding: 0; line-height: 1.2; } @@ -883,7 +894,7 @@ input[type="submit"], button { padding: 15px 0 0; } - .login br, .login .submit-row label { + .login br { display: none; } @@ -951,7 +962,7 @@ input[type="submit"], button { } .timelist a { - background: #fff; + background: var(--body-bg); padding: 4px; } diff --git a/src/statics/admin/css/responsive_rtl.css b/src/statics/admin/css/responsive_rtl.css index f999cb1..66d3c2f 100644 --- a/src/statics/admin/css/responsive_rtl.css +++ b/src/statics/admin/css/responsive_rtl.css @@ -23,9 +23,9 @@ [dir="rtl"] .change-list .filtered .paginator, [dir="rtl"] .filtered #toolbar, [dir="rtl"] .filtered div.xfull, - [dir="rtl"] .filtered .actions { - margin-right: 0; - margin-left: 230px; + [dir="rtl"] .filtered .actions, + [dir="rtl"] #changelist-filter { + margin-left: 0; } [dir="rtl"] .inline-group ul.tools a.add, @@ -63,15 +63,6 @@ /* MOBILE */ @media (max-width: 767px) { - [dir="rtl"] .change-list .filtered .results, - [dir="rtl"] .change-list .filtered .paginator, - [dir="rtl"] .filtered #toolbar, - [dir="rtl"] .filtered div.xfull, - [dir="rtl"] .filtered .actions { - margin-left: 0; - } - - [dir="rtl"] .aligned .add-another, [dir="rtl"] .aligned .related-lookup, [dir="rtl"] .aligned .datetimeshortcuts { margin-left: 0; @@ -81,4 +72,9 @@ [dir="rtl"] .aligned ul { margin-right: 0; } + + [dir="rtl"] #changelist-filter { + margin-left: 0; + margin-right: 0; + } } diff --git a/src/statics/admin/css/rtl.css b/src/statics/admin/css/rtl.css index b9e26bf..0447f89 100644 --- a/src/statics/admin/css/rtl.css +++ b/src/statics/admin/css/rtl.css @@ -1,25 +1,3 @@ -body { - direction: rtl; -} - -/* LOGIN */ - -.login .form-row { - float: right; -} - -.login .form-row label { - float: right; - padding-left: 0.5em; - padding-right: 0; - text-align: left; -} - -.login .submit-row { - clear: both; - padding: 1em 9.4em 0 0; -} - /* GLOBAL */ th { @@ -109,31 +87,21 @@ thead th.sorted .text { } #changelist-filter { - right: auto; - left: 0; border-left: none; border-right: none; -} - -.change-list .filtered .results, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { - margin-right: 0; - margin-left: 280px; + margin-left: 0; + margin-right: 30px; } #changelist-filter li.selected { border-left: none; padding-left: 10px; margin-left: 0; - border-right: 5px solid #eaeaea; + border-right: 5px solid var(--hairline-color); padding-right: 10px; margin-right: -15px; } -.filtered .actions { - margin-left: 280px; - margin-right: 0; -} - #changelist table tbody td:first-child, #changelist table tbody th:first-child { border-right: none; border-left: none; @@ -257,13 +225,3 @@ form .form-row p.datetime { margin-left: inherit; margin-right: 2px; } - -/* IE7 specific bug fixes */ - -div.colM { - position: relative; -} - -.submit-row input { - float: left; -} diff --git a/src/statics/admin/css/vendor/select2/LICENSE-SELECT2.md b/src/statics/admin/css/vendor/select2/LICENSE-SELECT2.md index 86c7c29..8cb8a2b 100644 --- a/src/statics/admin/css/vendor/select2/LICENSE-SELECT2.md +++ b/src/statics/admin/css/vendor/select2/LICENSE-SELECT2.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2012-2015 Kevin Brown, Igor Vaynberg, and Select2 contributors +Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/statics/admin/css/vendor/select2/select2.css b/src/statics/admin/css/vendor/select2/select2.css index 447b2b8..750b320 100644 --- a/src/statics/admin/css/vendor/select2/select2.css +++ b/src/statics/admin/css/vendor/select2/select2.css @@ -118,12 +118,14 @@ .select2-hidden-accessible { border: 0 !important; clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; height: 1px !important; - margin: -1px !important; overflow: hidden !important; padding: 0 !important; position: absolute !important; - width: 1px !important; } + width: 1px !important; + white-space: nowrap !important; } .select2-container--default .select2-selection--single { background-color: #fff; @@ -186,16 +188,13 @@ width: 100%; } .select2-container--default .select2-selection--multiple .select2-selection__rendered li { list-style: none; } - .select2-container--default .select2-selection--multiple .select2-selection__placeholder { - color: #999; - margin-top: 5px; - float: left; } .select2-container--default .select2-selection--multiple .select2-selection__clear { cursor: pointer; float: right; font-weight: bold; margin-top: 5px; - margin-right: 10px; } + margin-right: 10px; + padding: 1px; } .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #e4e4e4; border: 1px solid #aaa; @@ -214,7 +213,7 @@ .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #333; } -.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline { +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline { float: right; } .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice { @@ -420,9 +419,7 @@ color: #555; } .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { - float: right; } - -.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + float: right; margin-left: 5px; margin-right: auto; } diff --git a/src/statics/admin/css/vendor/select2/select2.min.css b/src/statics/admin/css/vendor/select2/select2.min.css index 76de04d..7c18ad5 100644 --- a/src/statics/admin/css/vendor/select2/select2.min.css +++ b/src/statics/admin/css/vendor/select2/select2.min.css @@ -1 +1 @@ -.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;height:1px !important;margin:-1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:#999;margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} +.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} diff --git a/src/statics/admin/css/widgets.css b/src/statics/admin/css/widgets.css index d3bd67a..c7d6456 100644 --- a/src/statics/admin/css/widgets.css +++ b/src/statics/admin/css/widgets.css @@ -22,26 +22,25 @@ } .selector-available h2, .selector-chosen h2 { - border: 1px solid #ccc; + border: 1px solid var(--border-color); border-radius: 4px 4px 0 0; } .selector-chosen h2 { - background: #79aec8; - color: #fff; + background: var(--primary); + color: var(--header-link-color); } .selector .selector-available h2 { - background: #f8f8f8; - color: #666; + background: var(--darkened-bg); + color: var(--body-quiet-color); } .selector .selector-filter { - background: white; - border: 1px solid #ccc; + border: 1px solid var(--border-color); border-width: 0 1px; padding: 8px; - color: #999; + color: var(--body-quiet-color); font-size: 10px; margin: 0; text-align: left; @@ -66,7 +65,7 @@ .selector ul.selector-chooser { float: left; width: 22px; - background-color: #eee; + background-color: var(--selected-bg); border-radius: 10px; margin: 10em 5px 0 5px; padding: 0; @@ -91,7 +90,7 @@ text-indent: -3000px; overflow: hidden; cursor: default; - opacity: 0.3; + opacity: 0.55; } .active.selector-add, .active.selector-remove { @@ -126,14 +125,14 @@ a.selector-chooseall, a.selector-clearall { overflow: hidden; font-weight: bold; line-height: 16px; - color: #666; + color: var(--body-quiet-color); text-decoration: none; - opacity: 0.3; + opacity: 0.55; } a.active.selector-chooseall:focus, a.active.selector-clearall:focus, a.active.selector-chooseall:hover, a.active.selector-clearall:hover { - color: #447e9b; + color: var(--link-fg); } a.active.selector-chooseall, a.active.selector-clearall { @@ -211,6 +210,11 @@ a.active.selector-clearall:focus, a.active.selector-clearall:hover { } .stacked .active.selector-add { + background-position: 0 -32px; + cursor: pointer; +} + +.stacked .active.selector-add:focus, .stacked .active.selector-add:hover { background-position: 0 -48px; cursor: pointer; } @@ -221,6 +225,11 @@ a.active.selector-clearall:focus, a.active.selector-clearall:hover { } .stacked .active.selector-remove { + background-position: 0 0px; + cursor: pointer; +} + +.stacked .active.selector-remove:focus, .stacked .active.selector-remove:hover { background-position: 0 -16px; cursor: pointer; } @@ -251,7 +260,7 @@ p.datetime { line-height: 20px; margin: 0; padding: 0; - color: #666; + color: var(--body-quiet-color); font-weight: bold; } @@ -259,11 +268,10 @@ p.datetime { white-space: nowrap; font-weight: normal; font-size: 11px; - color: #ccc; + color: var(--body-quiet-color); } .datetime input, .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField { - min-width: 0; margin-left: 5px; margin-bottom: 4px; } @@ -304,7 +312,7 @@ table p.datetime { .timezonewarning { font-size: 11px; - color: #999; + color: var(--body-quiet-color); } /* URL */ @@ -313,7 +321,7 @@ p.url { line-height: 20px; margin: 0; padding: 0; - color: #666; + color: var(--body-quiet-color); font-size: 11px; font-weight: bold; } @@ -328,7 +336,7 @@ p.file-upload { line-height: 20px; margin: 0; padding: 0; - color: #666; + color: var(--body-quiet-color); font-size: 11px; font-weight: bold; } @@ -346,7 +354,7 @@ p.file-upload { } span.clearable-file-input label { - color: #333; + color: var(--body-fg); font-size: 11px; display: inline; float: none; @@ -359,8 +367,9 @@ span.clearable-file-input label { font-size: 12px; width: 19em; text-align: center; - background: white; - border: 1px solid #ddd; + background: var(--body-bg); + color: var(--body-fg); + border: 1px solid var(--hairline-color); border-radius: 4px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); overflow: hidden; @@ -388,20 +397,20 @@ span.clearable-file-input label { margin: 0; text-align: center; border-top: none; - background: #f5dd5d; font-weight: 700; font-size: 12px; color: #333; + background: var(--accent); } .calendar th { padding: 8px 5px; - background: #f8f8f8; - border-bottom: 1px solid #ddd; + background: var(--darkened-bg); + border-bottom: 1px solid var(--border-color); font-weight: 400; font-size: 12px; text-align: center; - color: #666; + color: var(--body-quiet-color); } .calendar td { @@ -409,17 +418,17 @@ span.clearable-file-input label { font-size: 12px; text-align: center; padding: 0; - border-top: 1px solid #eee; + border-top: 1px solid var(--hairline-color); border-bottom: none; } .calendar td.selected a { - background: #79aec8; - color: #fff; + background: var(--primary); + color: var(--button-fg); } .calendar td.nonday { - background: #f8f8f8; + background: var(--darkened-bg); } .calendar td.today a { @@ -431,17 +440,17 @@ span.clearable-file-input label { font-weight: 400; padding: 6px; text-decoration: none; - color: #444; + color: var(--body-quiet-color); } .calendar td a:focus, .timelist a:focus, .calendar td a:hover, .timelist a:hover { - background: #79aec8; + background: var(--primary); color: white; } .calendar td a:active, .timelist a:active { - background: #417690; + background: var(--header-bg); color: white; } @@ -455,16 +464,16 @@ span.clearable-file-input label { .calendarnav a:link, #calendarnav a:visited, #calendarnav a:focus, #calendarnav a:hover { - color: #999; + color: var(--body-quiet-color); } .calendar-shortcuts { - background: white; + background: var(--body-bg); + color: var(--body-quiet-color); font-size: 11px; line-height: 11px; - border-top: 1px solid #eee; + border-top: 1px solid var(--hairline-color); padding: 8px 0; - color: #ccc; } .calendarbox .calendarnav-previous, .calendarbox .calendarnav-next { @@ -502,8 +511,8 @@ span.clearable-file-input label { padding: 4px 0; font-size: 12px; background: #eee; - border-top: 1px solid #ddd; - color: #333; + border-top: 1px solid var(--border-color); + color: var(--body-fg); } .calendar-cancel:focus, .calendar-cancel:hover { diff --git a/src/statics/admin/js/SelectBox.js b/src/statics/admin/js/SelectBox.js index 2073f03..ace6d9d 100644 --- a/src/statics/admin/js/SelectBox.js +++ b/src/statics/admin/js/SelectBox.js @@ -1,52 +1,39 @@ -(function($) { - 'use strict'; - var SelectBox = { +'use strict'; +{ + const SelectBox = { cache: {}, init: function(id) { - var box = document.getElementById(id); - var node; + const box = document.getElementById(id); SelectBox.cache[id] = []; - var cache = SelectBox.cache[id]; - var boxOptions = box.options; - var boxOptionsLength = boxOptions.length; - for (var i = 0, j = boxOptionsLength; i < j; i++) { - node = boxOptions[i]; + const cache = SelectBox.cache[id]; + for (const node of box.options) { cache.push({value: node.value, text: node.text, displayed: 1}); } }, redisplay: function(id) { // Repopulate HTML select box from cache - var box = document.getElementById(id); - var node; - $(box).empty(); // clear all options - var new_options = box.outerHTML.slice(0, -9); // grab just the opening tag - var cache = SelectBox.cache[id]; - for (var i = 0, j = cache.length; i < j; i++) { - node = cache[i]; + const box = document.getElementById(id); + const scroll_value_from_top = box.scrollTop; + box.innerHTML = ''; + for (const node of SelectBox.cache[id]) { if (node.displayed) { - var new_option = new Option(node.text, node.value, false, false); + const new_option = new Option(node.text, node.value, false, false); // Shows a tooltip when hovering over the option - new_option.setAttribute("title", node.text); - new_options += new_option.outerHTML; + new_option.title = node.text; + box.appendChild(new_option); } } - new_options += ''; - box.outerHTML = new_options; + box.scrollTop = scroll_value_from_top; }, filter: function(id, text) { // Redisplay the HTML select box, displaying only the choices containing ALL // the words in text. (It's an AND search.) - var tokens = text.toLowerCase().split(/\s+/); - var node, token; - var cache = SelectBox.cache[id]; - for (var i = 0, j = cache.length; i < j; i++) { - node = cache[i]; + const tokens = text.toLowerCase().split(/\s+/); + for (const node of SelectBox.cache[id]) { node.displayed = 1; - var node_text = node.text.toLowerCase(); - var numTokens = tokens.length; - for (var k = 0; k < numTokens; k++) { - token = tokens[k]; - if (node_text.indexOf(token) === -1) { + const node_text = node.text.toLowerCase(); + for (const token of tokens) { + if (!node_text.includes(token)) { node.displayed = 0; break; // Once the first token isn't found we're done } @@ -55,10 +42,9 @@ SelectBox.redisplay(id); }, delete_from_cache: function(id, value) { - var node, delete_index = null; - var cache = SelectBox.cache[id]; - for (var i = 0, j = cache.length; i < j; i++) { - node = cache[i]; + let delete_index = null; + const cache = SelectBox.cache[id]; + for (const [i, node] of cache.entries()) { if (node.value === value) { delete_index = i; break; @@ -71,10 +57,7 @@ }, cache_contains: function(id, value) { // Check if an item is contained in the cache - var node; - var cache = SelectBox.cache[id]; - for (var i = 0, j = cache.length; i < j; i++) { - node = cache[i]; + for (const node of SelectBox.cache[id]) { if (node.value === value) { return true; } @@ -82,13 +65,9 @@ return false; }, move: function(from, to) { - var from_box = document.getElementById(from); - var option; - var boxOptions = from_box.options; - var boxOptionsLength = boxOptions.length; - for (var i = 0, j = boxOptionsLength; i < j; i++) { - option = boxOptions[i]; - var option_value = option.value; + const from_box = document.getElementById(from); + for (const option of from_box.options) { + const option_value = option.value; if (option.selected && SelectBox.cache_contains(from, option_value)) { SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1}); SelectBox.delete_from_cache(from, option_value); @@ -98,13 +77,9 @@ SelectBox.redisplay(to); }, move_all: function(from, to) { - var from_box = document.getElementById(from); - var option; - var boxOptions = from_box.options; - var boxOptionsLength = boxOptions.length; - for (var i = 0, j = boxOptionsLength; i < j; i++) { - option = boxOptions[i]; - var option_value = option.value; + const from_box = document.getElementById(from); + for (const option of from_box.options) { + const option_value = option.value; if (SelectBox.cache_contains(from, option_value)) { SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1}); SelectBox.delete_from_cache(from, option_value); @@ -117,28 +92,21 @@ SelectBox.cache[id].sort(function(a, b) { a = a.text.toLowerCase(); b = b.text.toLowerCase(); - try { - if (a > b) { - return 1; - } - if (a < b) { - return -1; - } + if (a > b) { + return 1; } - catch (e) { - // silently fail on IE 'unknown' exception + if (a < b) { + return -1; } return 0; } ); }, select_all: function(id) { - var box = document.getElementById(id); - var boxOptions = box.options; - var boxOptionsLength = boxOptions.length; - for (var i = 0; i < boxOptionsLength; i++) { - boxOptions[i].selected = 'selected'; + const box = document.getElementById(id); + for (const option of box.options) { + option.selected = true; } } }; window.SelectBox = SelectBox; -})(django.jQuery); +} diff --git a/src/statics/admin/js/SelectFilter2.js b/src/statics/admin/js/SelectFilter2.js index 4221778..6c709a0 100644 --- a/src/statics/admin/js/SelectFilter2.js +++ b/src/statics/admin/js/SelectFilter2.js @@ -2,49 +2,40 @@ /* SelectFilter2 - Turns a multiple-select box into a filter interface. -Requires jQuery, core.js, and SelectBox.js. +Requires core.js and SelectBox.js. */ -(function($) { - 'use strict'; - function findForm(node) { - // returns the node of the form containing the given node - if (node.tagName.toLowerCase() !== 'form') { - return findForm(node.parentNode); - } - return node; - } - +'use strict'; +{ window.SelectFilter = { init: function(field_id, field_name, is_stacked) { if (field_id.match(/__prefix__/)) { // Don't initialize on empty forms. return; } - var from_box = document.getElementById(field_id); + const from_box = document.getElementById(field_id); from_box.id += '_from'; // change its ID from_box.className = 'filtered'; - var ps = from_box.parentNode.getElementsByTagName('p'); - for (var i = 0; i < ps.length; i++) { - if (ps[i].className.indexOf("info") !== -1) { + for (const p of from_box.parentNode.getElementsByTagName('p')) { + if (p.classList.contains("info")) { // Remove

, because it just gets in the way. - from_box.parentNode.removeChild(ps[i]); - } else if (ps[i].className.indexOf("help") !== -1) { + from_box.parentNode.removeChild(p); + } else if (p.classList.contains("help")) { // Move help text up to the top so it isn't below the select // boxes or wrapped off on the side to the right of the add // button: - from_box.parentNode.insertBefore(ps[i], from_box.parentNode.firstChild); + from_box.parentNode.insertBefore(p, from_box.parentNode.firstChild); } } //

or
- var selector_div = quickElement('div', from_box.parentNode); + const selector_div = quickElement('div', from_box.parentNode); selector_div.className = is_stacked ? 'selector stacked' : 'selector'; //
- var selector_available = quickElement('div', selector_div); + const selector_available = quickElement('div', selector_div); selector_available.className = 'selector-available'; - var title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name])); + const title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name])); quickElement( 'span', title_available, '', 'class', 'help help-tooltip help-icon', @@ -58,10 +49,10 @@ Requires jQuery, core.js, and SelectBox.js. ) ); - var filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter'); + const filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter'); filter_p.className = 'selector-filter'; - var search_filter_label = quickElement('label', filter_p, '', 'for', field_id + '_input'); + const search_filter_label = quickElement('label', filter_p, '', 'for', field_id + '_input'); quickElement( 'span', search_filter_label, '', @@ -71,25 +62,25 @@ Requires jQuery, core.js, and SelectBox.js. filter_p.appendChild(document.createTextNode(' ')); - var filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter")); + const filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter")); filter_input.id = field_id + '_input'; selector_available.appendChild(from_box); - var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', '#', 'id', field_id + '_add_all_link'); + const choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', '#', 'id', field_id + '_add_all_link'); choose_all.className = 'selector-chooseall'; //
    - var selector_chooser = quickElement('ul', selector_div); + const selector_chooser = quickElement('ul', selector_div); selector_chooser.className = 'selector-chooser'; - var add_link = quickElement('a', quickElement('li', selector_chooser), gettext('Choose'), 'title', gettext('Choose'), 'href', '#', 'id', field_id + '_add_link'); + const add_link = quickElement('a', quickElement('li', selector_chooser), gettext('Choose'), 'title', gettext('Choose'), 'href', '#', 'id', field_id + '_add_link'); add_link.className = 'selector-add'; - var remove_link = quickElement('a', quickElement('li', selector_chooser), gettext('Remove'), 'title', gettext('Remove'), 'href', '#', 'id', field_id + '_remove_link'); + const remove_link = quickElement('a', quickElement('li', selector_chooser), gettext('Remove'), 'title', gettext('Remove'), 'href', '#', 'id', field_id + '_remove_link'); remove_link.className = 'selector-remove'; //
    - var selector_chosen = quickElement('div', selector_div); + const selector_chosen = quickElement('div', selector_div); selector_chosen.className = 'selector-chosen'; - var title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name])); + const title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name])); quickElement( 'span', title_chosen, '', 'class', 'help help-tooltip help-icon', @@ -103,16 +94,16 @@ Requires jQuery, core.js, and SelectBox.js. ) ); - var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name')); + const to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', '', 'size', from_box.size, 'name', from_box.name); to_box.className = 'filtered'; - var clear_all = quickElement('a', selector_chosen, gettext('Remove all'), 'title', interpolate(gettext('Click to remove all chosen %s at once.'), [field_name]), 'href', '#', 'id', field_id + '_remove_all_link'); + const clear_all = quickElement('a', selector_chosen, gettext('Remove all'), 'title', interpolate(gettext('Click to remove all chosen %s at once.'), [field_name]), 'href', '#', 'id', field_id + '_remove_all_link'); clear_all.className = 'selector-clearall'; - from_box.setAttribute('name', from_box.getAttribute('name') + '_old'); + from_box.name = from_box.name + '_old'; // Set up the JavaScript event handlers for the select box filter interface - var move_selection = function(e, elem, move_func, from, to) { - if (elem.className.indexOf('active') !== -1) { + const move_selection = function(e, elem, move_func, from, to) { + if (elem.classList.contains('active')) { move_func(from, to); SelectFilter.refresh_icons(field_id); } @@ -154,7 +145,7 @@ Requires jQuery, core.js, and SelectBox.js. SelectFilter.refresh_icons(field_id); } }); - findForm(from_box).addEventListener('submit', function() { + from_box.closest('form').addEventListener('submit', function() { SelectBox.select_all(field_id + '_to'); }); SelectBox.init(field_id + '_from'); @@ -164,64 +155,66 @@ Requires jQuery, core.js, and SelectBox.js. if (!is_stacked) { // In horizontal mode, give the same height to the two boxes. - var j_from_box = $('#' + field_id + '_from'); - var j_to_box = $('#' + field_id + '_to'); - j_to_box.height($(filter_p).outerHeight() + j_from_box.outerHeight()); + const j_from_box = document.getElementById(field_id + '_from'); + const j_to_box = document.getElementById(field_id + '_to'); + let height = filter_p.offsetHeight + j_from_box.offsetHeight; + + const j_to_box_style = window.getComputedStyle(j_to_box); + if (j_to_box_style.getPropertyValue('box-sizing') === 'border-box') { + // Add the padding and border to the final height. + height += parseInt(j_to_box_style.getPropertyValue('padding-top'), 10) + + parseInt(j_to_box_style.getPropertyValue('padding-bottom'), 10) + + parseInt(j_to_box_style.getPropertyValue('border-top-width'), 10) + + parseInt(j_to_box_style.getPropertyValue('border-bottom-width'), 10); + } + + j_to_box.style.height = height + 'px'; } // Initial icon refresh SelectFilter.refresh_icons(field_id); }, any_selected: function(field) { - var any_selected = false; - try { - // Temporarily add the required attribute and check validity. - // This is much faster in WebKit browsers than the fallback. - field.attr('required', 'required'); - any_selected = field.is(':valid'); - field.removeAttr('required'); - } catch (e) { - // Browsers that don't support :valid (IE < 10) - any_selected = field.find('option:selected').length > 0; - } + // Temporarily add the required attribute and check validity. + field.required = true; + const any_selected = field.checkValidity(); + field.required = false; return any_selected; }, refresh_icons: function(field_id) { - var from = $('#' + field_id + '_from'); - var to = $('#' + field_id + '_to'); + const from = document.getElementById(field_id + '_from'); + const to = document.getElementById(field_id + '_to'); // Active if at least one item is selected - $('#' + field_id + '_add_link').toggleClass('active', SelectFilter.any_selected(from)); - $('#' + field_id + '_remove_link').toggleClass('active', SelectFilter.any_selected(to)); + document.getElementById(field_id + '_add_link').classList.toggle('active', SelectFilter.any_selected(from)); + document.getElementById(field_id + '_remove_link').classList.toggle('active', SelectFilter.any_selected(to)); // Active if the corresponding box isn't empty - $('#' + field_id + '_add_all_link').toggleClass('active', from.find('option').length > 0); - $('#' + field_id + '_remove_all_link').toggleClass('active', to.find('option').length > 0); + document.getElementById(field_id + '_add_all_link').classList.toggle('active', from.querySelector('option')); + document.getElementById(field_id + '_remove_all_link').classList.toggle('active', to.querySelector('option')); }, filter_key_press: function(event, field_id) { - var from = document.getElementById(field_id + '_from'); + const from = document.getElementById(field_id + '_from'); // don't submit form if user pressed Enter if ((event.which && event.which === 13) || (event.keyCode && event.keyCode === 13)) { from.selectedIndex = 0; SelectBox.move(field_id + '_from', field_id + '_to'); from.selectedIndex = 0; event.preventDefault(); - return false; } }, filter_key_up: function(event, field_id) { - var from = document.getElementById(field_id + '_from'); - var temp = from.selectedIndex; + const from = document.getElementById(field_id + '_from'); + const temp = from.selectedIndex; SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value); from.selectedIndex = temp; - return true; }, filter_key_down: function(event, field_id) { - var from = document.getElementById(field_id + '_from'); + const from = document.getElementById(field_id + '_from'); // right arrow -- move across if ((event.which && event.which === 39) || (event.keyCode && event.keyCode === 39)) { - var old_index = from.selectedIndex; + const old_index = from.selectedIndex; SelectBox.move(field_id + '_from', field_id + '_to'); from.selectedIndex = (old_index === from.length) ? from.length - 1 : old_index; - return false; + return; } // down arrow -- wrap around if ((event.which && event.which === 40) || (event.keyCode && event.keyCode === 40)) { @@ -231,16 +224,13 @@ Requires jQuery, core.js, and SelectBox.js. if ((event.which && event.which === 38) || (event.keyCode && event.keyCode === 38)) { from.selectedIndex = (from.selectedIndex === 0) ? from.length - 1 : from.selectedIndex - 1; } - return true; } }; window.addEventListener('load', function(e) { - $('select.selectfilter, select.selectfilterstacked').each(function() { - var $el = $(this), - data = $el.data(); - SelectFilter.init($el.attr('id'), data.fieldName, parseInt(data.isStacked, 10)); + document.querySelectorAll('select.selectfilter, select.selectfilterstacked').forEach(function(el) { + const data = el.dataset; + SelectFilter.init(el.id, data.fieldName, parseInt(data.isStacked, 10)); }); }); - -})(django.jQuery); +} diff --git a/src/statics/admin/js/actions.js b/src/statics/admin/js/actions.js index 27c60a6..da1c310 100644 --- a/src/statics/admin/js/actions.js +++ b/src/statics/admin/js/actions.js @@ -1,153 +1,196 @@ /*global gettext, interpolate, ngettext*/ -(function($) { - 'use strict'; - var lastChecked; +'use strict'; +{ + function show(selector) { + document.querySelectorAll(selector).forEach(function(el) { + el.classList.remove('hidden'); + }); + } - $.fn.actions = function(opts) { - var options = $.extend({}, $.fn.actions.defaults, opts); - var actionCheckboxes = $(this); - var list_editable_changed = false; - var showQuestion = function() { - $(options.acrossClears).hide(); - $(options.acrossQuestions).show(); - $(options.allContainer).hide(); - }, - showClear = function() { - $(options.acrossClears).show(); - $(options.acrossQuestions).hide(); - $(options.actionContainer).toggleClass(options.selectedClass); - $(options.allContainer).show(); - $(options.counterContainer).hide(); - }, - reset = function() { - $(options.acrossClears).hide(); - $(options.acrossQuestions).hide(); - $(options.allContainer).hide(); - $(options.counterContainer).show(); - }, - clearAcross = function() { - reset(); - $(options.acrossInput).val(0); - $(options.actionContainer).removeClass(options.selectedClass); - }, - checker = function(checked) { - if (checked) { - showQuestion(); - } else { - reset(); - } - $(actionCheckboxes).prop("checked", checked) - .parent().parent().toggleClass(options.selectedClass, checked); - }, - updateCounter = function() { - var sel = $(actionCheckboxes).filter(":checked").length; - // data-actions-icnt is defined in the generated HTML - // and contains the total amount of objects in the queryset - var actions_icnt = $('.action-counter').data('actionsIcnt'); - $(options.counterContainer).html(interpolate( - ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), { - sel: sel, - cnt: actions_icnt - }, true)); - $(options.allToggle).prop("checked", function() { - var value; - if (sel === actionCheckboxes.length) { - value = true; - showQuestion(); - } else { - value = false; - clearAcross(); - } - return value; - }); - }; - // Show counter by default - $(options.counterContainer).show(); - // Check state of checkboxes and reinit state if needed - $(this).filter(":checked").each(function(i) { - $(this).parent().parent().toggleClass(options.selectedClass); - updateCounter(); - if ($(options.acrossInput).val() === 1) { - showClear(); - } + function hide(selector) { + document.querySelectorAll(selector).forEach(function(el) { + el.classList.add('hidden'); }); - $(options.allToggle).show().on('click', function() { - checker($(this).prop("checked")); - updateCounter(); + } + + function showQuestion(options) { + hide(options.acrossClears); + show(options.acrossQuestions); + hide(options.allContainer); + } + + function showClear(options) { + show(options.acrossClears); + hide(options.acrossQuestions); + document.querySelector(options.actionContainer).classList.remove(options.selectedClass); + show(options.allContainer); + hide(options.counterContainer); + } + + function reset(options) { + hide(options.acrossClears); + hide(options.acrossQuestions); + hide(options.allContainer); + show(options.counterContainer); + } + + function clearAcross(options) { + reset(options); + document.querySelector(options.acrossInput).value = 0; + document.querySelector(options.actionContainer).classList.remove(options.selectedClass); + } + + function checker(actionCheckboxes, options, checked) { + if (checked) { + showQuestion(options); + } else { + reset(options); + } + actionCheckboxes.forEach(function(el) { + el.checked = checked; + el.closest('tr').classList.toggle(options.selectedClass, checked); }); - $("a", options.acrossQuestions).on('click', function(event) { - event.preventDefault(); - $(options.acrossInput).val(1); - showClear(); - }); - $("a", options.acrossClears).on('click', function(event) { - event.preventDefault(); - $(options.allToggle).prop("checked", false); - clearAcross(); - checker(0); - updateCounter(); - }); - lastChecked = null; - $(actionCheckboxes).on('click', function(event) { - if (!event) { event = window.event; } - var target = event.target ? event.target : event.srcElement; - if (lastChecked && $.data(lastChecked) !== $.data(target) && event.shiftKey === true) { - var inrange = false; - $(lastChecked).prop("checked", target.checked) - .parent().parent().toggleClass(options.selectedClass, target.checked); - $(actionCheckboxes).each(function() { - if ($.data(this) === $.data(lastChecked) || $.data(this) === $.data(target)) { - inrange = (inrange) ? false : true; - } - if (inrange) { - $(this).prop("checked", target.checked) - .parent().parent().toggleClass(options.selectedClass, target.checked); - } - }); - } - $(target).parent().parent().toggleClass(options.selectedClass, target.checked); - lastChecked = target; - updateCounter(); - }); - $('form#changelist-form table#result_list tr').on('change', 'td:gt(0) :input', function() { - list_editable_changed = true; - }); - $('form#changelist-form button[name="index"]').on('click', function(event) { - if (list_editable_changed) { - return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.")); - } - }); - $('form#changelist-form input[name="_save"]').on('click', function(event) { - var action_changed = false; - $('select option:selected', options.actionContainer).each(function() { - if ($(this).val()) { - action_changed = true; - } - }); - if (action_changed) { - if (list_editable_changed) { - return confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.")); - } else { - return confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.")); - } - } - }); - }; - /* Setup plugin defaults */ - $.fn.actions.defaults = { + } + + function updateCounter(actionCheckboxes, options) { + const sel = Array.from(actionCheckboxes).filter(function(el) { + return el.checked; + }).length; + const counter = document.querySelector(options.counterContainer); + // data-actions-icnt is defined in the generated HTML + // and contains the total amount of objects in the queryset + const actions_icnt = Number(counter.dataset.actionsIcnt); + counter.textContent = interpolate( + ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), { + sel: sel, + cnt: actions_icnt + }, true); + const allToggle = document.getElementById(options.allToggleId); + allToggle.checked = sel === actionCheckboxes.length; + if (allToggle.checked) { + showQuestion(options); + } else { + clearAcross(options); + } + } + + const defaults = { actionContainer: "div.actions", counterContainer: "span.action-counter", allContainer: "div.actions span.all", acrossInput: "div.actions input.select-across", acrossQuestions: "div.actions span.question", acrossClears: "div.actions span.clear", - allToggle: "#action-toggle", + allToggleId: "action-toggle", selectedClass: "selected" }; - $(document).ready(function() { - var $actionsEls = $('tr input.action-select'); - if ($actionsEls.length > 0) { - $actionsEls.actions(); + + window.Actions = function(actionCheckboxes, options) { + options = Object.assign({}, defaults, options); + let list_editable_changed = false; + let lastChecked = null; + let shiftPressed = false; + + document.addEventListener('keydown', (event) => { + shiftPressed = event.shiftKey; + }); + + document.addEventListener('keyup', (event) => { + shiftPressed = event.shiftKey; + }); + + document.getElementById(options.allToggleId).addEventListener('click', function(event) { + checker(actionCheckboxes, options, this.checked); + updateCounter(actionCheckboxes, options); + }); + + document.querySelectorAll(options.acrossQuestions + " a").forEach(function(el) { + el.addEventListener('click', function(event) { + event.preventDefault(); + const acrossInput = document.querySelector(options.acrossInput); + acrossInput.value = 1; + showClear(options); + }); + }); + + document.querySelectorAll(options.acrossClears + " a").forEach(function(el) { + el.addEventListener('click', function(event) { + event.preventDefault(); + document.getElementById(options.allToggleId).checked = false; + clearAcross(options); + checker(actionCheckboxes, options, false); + updateCounter(actionCheckboxes, options); + }); + }); + + function affectedCheckboxes(target, withModifier) { + const multiSelect = (lastChecked && withModifier && lastChecked !== target); + if (!multiSelect) { + return [target]; + } + const checkboxes = Array.from(actionCheckboxes); + const targetIndex = checkboxes.findIndex(el => el === target); + const lastCheckedIndex = checkboxes.findIndex(el => el === lastChecked); + const startIndex = Math.min(targetIndex, lastCheckedIndex); + const endIndex = Math.max(targetIndex, lastCheckedIndex); + const filtered = checkboxes.filter((el, index) => (startIndex <= index) && (index <= endIndex)); + return filtered; + }; + + Array.from(document.getElementById('result_list').tBodies).forEach(function(el) { + el.addEventListener('change', function(event) { + const target = event.target; + if (target.classList.contains('action-select')) { + const checkboxes = affectedCheckboxes(target, shiftPressed); + checker(checkboxes, options, target.checked); + updateCounter(actionCheckboxes, options); + lastChecked = target; + } else { + list_editable_changed = true; + } + }); + }); + + document.querySelector('#changelist-form button[name=index]').addEventListener('click', function() { + if (list_editable_changed) { + const confirmed = confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.")); + if (!confirmed) { + event.preventDefault(); + } + } + }); + + const el = document.querySelector('#changelist-form input[name=_save]'); + // The button does not exist if no fields are editable. + if (el) { + el.addEventListener('click', function(event) { + if (document.querySelector('[name=action]').value) { + const text = list_editable_changed + ? gettext("You have selected an action, but you haven’t saved your changes to individual fields yet. Please click OK to save. You’ll need to re-run the action.") + : gettext("You have selected an action, and you haven’t made any changes on individual fields. You’re probably looking for the Go button rather than the Save button."); + if (!confirm(text)) { + event.preventDefault(); + } + } + }); + } + }; + + // Call function fn when the DOM is loaded and ready. If it is already + // loaded, call the function now. + // http://youmightnotneedjquery.com/#ready + function ready(fn) { + if (document.readyState !== 'loading') { + fn(); + } else { + document.addEventListener('DOMContentLoaded', fn); + } + } + + ready(function() { + const actionsEls = document.querySelectorAll('tr input.action-select'); + if (actionsEls.length > 0) { + Actions(actionsEls); } }); -})(django.jQuery); +} diff --git a/src/statics/admin/js/admin/DateTimeShortcuts.js b/src/statics/admin/js/admin/DateTimeShortcuts.js index 1ee7c2a..9bad0f5 100644 --- a/src/statics/admin/js/admin/DateTimeShortcuts.js +++ b/src/statics/admin/js/admin/DateTimeShortcuts.js @@ -1,10 +1,10 @@ -/*global Calendar, findPosX, findPosY, getStyle, get_format, gettext, gettext_noop, interpolate, ngettext, quickElement*/ +/*global Calendar, findPosX, findPosY, get_format, gettext, gettext_noop, interpolate, ngettext, quickElement*/ // Inserts shortcut buttons after all of the following: // // -(function() { - 'use strict'; - var DateTimeShortcuts = { +'use strict'; +{ + const DateTimeShortcuts = { calendars: [], calendarInputs: [], clockInputs: [], @@ -28,21 +28,18 @@ timezoneWarningClass: 'timezonewarning', // class of the warning for timezone mismatch timezoneOffset: 0, init: function() { - var body = document.getElementsByTagName('body')[0]; - var serverOffset = body.getAttribute('data-admin-utc-offset'); + const serverOffset = document.body.dataset.adminUtcOffset; if (serverOffset) { - var localOffset = new Date().getTimezoneOffset() * -60; + const localOffset = new Date().getTimezoneOffset() * -60; DateTimeShortcuts.timezoneOffset = localOffset - serverOffset; } - var inputs = document.getElementsByTagName('input'); - for (var i = 0; i < inputs.length; i++) { - var inp = inputs[i]; - if (inp.getAttribute('type') === 'text' && inp.className.match(/vTimeField/)) { + for (const inp of document.getElementsByTagName('input')) { + if (inp.type === 'text' && inp.classList.contains('vTimeField')) { DateTimeShortcuts.addClock(inp); DateTimeShortcuts.addTimezoneWarning(inp); } - else if (inp.getAttribute('type') === 'text' && inp.className.match(/vDateField/)) { + else if (inp.type === 'text' && inp.classList.contains('vDateField')) { DateTimeShortcuts.addCalendar(inp); DateTimeShortcuts.addTimezoneWarning(inp); } @@ -50,11 +47,10 @@ }, // Return the current time while accounting for the server timezone. now: function() { - var body = document.getElementsByTagName('body')[0]; - var serverOffset = body.getAttribute('data-admin-utc-offset'); + const serverOffset = document.body.dataset.adminUtcOffset; if (serverOffset) { - var localNow = new Date(); - var localOffset = localNow.getTimezoneOffset() * -60; + const localNow = new Date(); + const localOffset = localNow.getTimezoneOffset() * -60; localNow.setTime(localNow.getTime() + 1000 * (serverOffset - localOffset)); return localNow; } else { @@ -63,8 +59,8 @@ }, // Add a warning when the time zone in the browser and backend do not match. addTimezoneWarning: function(inp) { - var warningClass = DateTimeShortcuts.timezoneWarningClass; - var timezoneOffset = DateTimeShortcuts.timezoneOffset / 3600; + const warningClass = DateTimeShortcuts.timezoneWarningClass; + let timezoneOffset = DateTimeShortcuts.timezoneOffset / 3600; // Only warn if there is a time zone mismatch. if (!timezoneOffset) { @@ -76,7 +72,7 @@ return; } - var message; + let message; if (timezoneOffset > 0) { message = ngettext( 'Note: You are %s hour ahead of server time.', @@ -94,7 +90,7 @@ } message = interpolate(message, [timezoneOffset]); - var warning = document.createElement('span'); + const warning = document.createElement('span'); warning.className = warningClass; warning.textContent = message; inp.parentNode.appendChild(document.createElement('br')); @@ -102,23 +98,23 @@ }, // Add clock widget to a given field addClock: function(inp) { - var num = DateTimeShortcuts.clockInputs.length; + const num = DateTimeShortcuts.clockInputs.length; DateTimeShortcuts.clockInputs[num] = inp; DateTimeShortcuts.dismissClockFunc[num] = function() { DateTimeShortcuts.dismissClock(num); return true; }; // Shortcut links (clock icon and "Now" link) - var shortcuts_span = document.createElement('span'); + const shortcuts_span = document.createElement('span'); shortcuts_span.className = DateTimeShortcuts.shortCutsClass; inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling); - var now_link = document.createElement('a'); - now_link.setAttribute('href', "#"); + const now_link = document.createElement('a'); + now_link.href = "#"; now_link.textContent = gettext('Now'); now_link.addEventListener('click', function(e) { e.preventDefault(); DateTimeShortcuts.handleClockQuicklink(num, -1); }); - var clock_link = document.createElement('a'); - clock_link.setAttribute('href', '#'); + const clock_link = document.createElement('a'); + clock_link.href = '#'; clock_link.id = DateTimeShortcuts.clockLinkName + num; clock_link.addEventListener('click', function(e) { e.preventDefault(); @@ -152,32 +148,32 @@ //

    Cancel

    //
    - var clock_box = document.createElement('div'); + const clock_box = document.createElement('div'); clock_box.style.display = 'none'; clock_box.style.position = 'absolute'; clock_box.className = 'clockbox module'; - clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num); + clock_box.id = DateTimeShortcuts.clockDivName + num; document.body.appendChild(clock_box); clock_box.addEventListener('click', function(e) { e.stopPropagation(); }); quickElement('h2', clock_box, gettext('Choose a time')); - var time_list = quickElement('ul', clock_box); + const time_list = quickElement('ul', clock_box); time_list.className = 'timelist'; // The list of choices can be overridden in JavaScript like this: // DateTimeShortcuts.clockHours.name = [['3 a.m.', 3]]; // where name is the name attribute of the . - var name = typeof DateTimeShortcuts.clockHours[inp.name] === 'undefined' ? 'default_' : inp.name; + const name = typeof DateTimeShortcuts.clockHours[inp.name] === 'undefined' ? 'default_' : inp.name; DateTimeShortcuts.clockHours[name].forEach(function(element) { - var time_link = quickElement('a', quickElement('li', time_list), gettext(element[0]), 'href', '#'); + const time_link = quickElement('a', quickElement('li', time_list), gettext(element[0]), 'href', '#'); time_link.addEventListener('click', function(e) { e.preventDefault(); DateTimeShortcuts.handleClockQuicklink(num, element[1]); }); }); - var cancel_p = quickElement('p', clock_box); + const cancel_p = quickElement('p', clock_box); cancel_p.className = 'calendar-cancel'; - var cancel_link = quickElement('a', cancel_p, gettext('Cancel'), 'href', '#'); + const cancel_link = quickElement('a', cancel_p, gettext('Cancel'), 'href', '#'); cancel_link.addEventListener('click', function(e) { e.preventDefault(); DateTimeShortcuts.dismissClock(num); @@ -192,19 +188,17 @@ }); }, openClock: function(num) { - var clock_box = document.getElementById(DateTimeShortcuts.clockDivName + num); - var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName + num); + const clock_box = document.getElementById(DateTimeShortcuts.clockDivName + num); + const clock_link = document.getElementById(DateTimeShortcuts.clockLinkName + num); // Recalculate the clockbox position // is it left-to-right or right-to-left layout ? - if (getStyle(document.body, 'direction') !== 'rtl') { + if (window.getComputedStyle(document.body).direction !== 'rtl') { clock_box.style.left = findPosX(clock_link) + 17 + 'px'; } else { // since style's width is in em, it'd be tough to calculate // px value of it. let's use an estimated px for now - // TODO: IE returns wrong value for findPosX when in rtl mode - // (it returns as it was left aligned), needs to be fixed. clock_box.style.left = findPosX(clock_link) - 110 + 'px'; } clock_box.style.top = Math.max(0, findPosY(clock_link) - 30) + 'px'; @@ -218,7 +212,7 @@ document.removeEventListener('click', DateTimeShortcuts.dismissClockFunc[num]); }, handleClockQuicklink: function(num, val) { - var d; + let d; if (val === -1) { d = DateTimeShortcuts.now(); } @@ -231,24 +225,24 @@ }, // Add calendar widget to a given field. addCalendar: function(inp) { - var num = DateTimeShortcuts.calendars.length; + const num = DateTimeShortcuts.calendars.length; DateTimeShortcuts.calendarInputs[num] = inp; DateTimeShortcuts.dismissCalendarFunc[num] = function() { DateTimeShortcuts.dismissCalendar(num); return true; }; // Shortcut links (calendar icon and "Today" link) - var shortcuts_span = document.createElement('span'); + const shortcuts_span = document.createElement('span'); shortcuts_span.className = DateTimeShortcuts.shortCutsClass; inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling); - var today_link = document.createElement('a'); - today_link.setAttribute('href', '#'); + const today_link = document.createElement('a'); + today_link.href = '#'; today_link.appendChild(document.createTextNode(gettext('Today'))); today_link.addEventListener('click', function(e) { e.preventDefault(); DateTimeShortcuts.handleCalendarQuickLink(num, 0); }); - var cal_link = document.createElement('a'); - cal_link.setAttribute('href', '#'); + const cal_link = document.createElement('a'); + cal_link.href = '#'; cal_link.id = DateTimeShortcuts.calendarLinkName + num; cal_link.addEventListener('click', function(e) { e.preventDefault(); @@ -283,24 +277,24 @@ //
//

Cancel

//
- var cal_box = document.createElement('div'); + const cal_box = document.createElement('div'); cal_box.style.display = 'none'; cal_box.style.position = 'absolute'; cal_box.className = 'calendarbox module'; - cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num); + cal_box.id = DateTimeShortcuts.calendarDivName1 + num; document.body.appendChild(cal_box); cal_box.addEventListener('click', function(e) { e.stopPropagation(); }); // next-prev links - var cal_nav = quickElement('div', cal_box); - var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', '#'); + const cal_nav = quickElement('div', cal_box); + const cal_nav_prev = quickElement('a', cal_nav, '<', 'href', '#'); cal_nav_prev.className = 'calendarnav-previous'; cal_nav_prev.addEventListener('click', function(e) { e.preventDefault(); DateTimeShortcuts.drawPrev(num); }); - var cal_nav_next = quickElement('a', cal_nav, '>', 'href', '#'); + const cal_nav_next = quickElement('a', cal_nav, '>', 'href', '#'); cal_nav_next.className = 'calendarnav-next'; cal_nav_next.addEventListener('click', function(e) { e.preventDefault(); @@ -308,15 +302,15 @@ }); // main box - var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num); + const cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num); cal_main.className = 'calendar'; DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num)); DateTimeShortcuts.calendars[num].drawCurrent(); // calendar shortcuts - var shortcuts = quickElement('div', cal_box); + const shortcuts = quickElement('div', cal_box); shortcuts.className = 'calendar-shortcuts'; - var day_link = quickElement('a', shortcuts, gettext('Yesterday'), 'href', '#'); + let day_link = quickElement('a', shortcuts, gettext('Yesterday'), 'href', '#'); day_link.addEventListener('click', function(e) { e.preventDefault(); DateTimeShortcuts.handleCalendarQuickLink(num, -1); @@ -335,9 +329,9 @@ }); // cancel bar - var cancel_p = quickElement('p', cal_box); + const cancel_p = quickElement('p', cal_box); cancel_p.className = 'calendar-cancel'; - var cancel_link = quickElement('a', cancel_p, gettext('Cancel'), 'href', '#'); + const cancel_link = quickElement('a', cancel_p, gettext('Cancel'), 'href', '#'); cancel_link.addEventListener('click', function(e) { e.preventDefault(); DateTimeShortcuts.dismissCalendar(num); @@ -351,18 +345,18 @@ }); }, openCalendar: function(num) { - var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1 + num); - var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName + num); - var inp = DateTimeShortcuts.calendarInputs[num]; + const cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1 + num); + const cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName + num); + const inp = DateTimeShortcuts.calendarInputs[num]; // Determine if the current value in the input has a valid date. // If so, draw the calendar with that date's year and month. if (inp.value) { - var format = get_format('DATE_INPUT_FORMATS')[0]; - var selected = inp.value.strptime(format); - var year = selected.getUTCFullYear(); - var month = selected.getUTCMonth() + 1; - var re = /\d{4}/; + const format = get_format('DATE_INPUT_FORMATS')[0]; + const selected = inp.value.strptime(format); + const year = selected.getUTCFullYear(); + const month = selected.getUTCMonth() + 1; + const re = /\d{4}/; if (re.test(year.toString()) && month >= 1 && month <= 12) { DateTimeShortcuts.calendars[num].drawDate(month, year, selected); } @@ -370,14 +364,12 @@ // Recalculate the clockbox position // is it left-to-right or right-to-left layout ? - if (getStyle(document.body, 'direction') !== 'rtl') { + if (window.getComputedStyle(document.body).direction !== 'rtl') { cal_box.style.left = findPosX(cal_link) + 17 + 'px'; } else { // since style's width is in em, it'd be tough to calculate // px value of it. let's use an estimated px for now - // TODO: IE returns wrong value for findPosX when in rtl mode - // (it returns as it was left aligned), needs to be fixed. cal_box.style.left = findPosX(cal_link) - 180 + 'px'; } cal_box.style.top = Math.max(0, findPosY(cal_link) - 75) + 'px'; @@ -396,7 +388,7 @@ DateTimeShortcuts.calendars[num].drawNextMonth(); }, handleCalendarCallback: function(num) { - var format = get_format('DATE_INPUT_FORMATS')[0]; + let format = get_format('DATE_INPUT_FORMATS')[0]; // the format needs to be escaped a little format = format.replace('\\', '\\\\') .replace('\r', '\\r') @@ -410,7 +402,7 @@ }; }, handleCalendarQuickLink: function(num, offset) { - var d = DateTimeShortcuts.now(); + const d = DateTimeShortcuts.now(); d.setDate(d.getDate() + offset); DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]); DateTimeShortcuts.calendarInputs[num].focus(); @@ -420,4 +412,4 @@ window.addEventListener('load', DateTimeShortcuts.init); window.DateTimeShortcuts = DateTimeShortcuts; -})(); +} diff --git a/src/statics/admin/js/admin/RelatedObjectLookups.js b/src/statics/admin/js/admin/RelatedObjectLookups.js index f4c57c4..289e1ce 100644 --- a/src/statics/admin/js/admin/RelatedObjectLookups.js +++ b/src/statics/admin/js/admin/RelatedObjectLookups.js @@ -1,38 +1,17 @@ /*global SelectBox, interpolate*/ // Handles related-objects functionality: lookup link for raw_id_fields // and Add Another links. - -(function($) { - 'use strict'; - - // IE doesn't accept periods or dashes in the window name, but the element IDs - // we use to generate popup window names may contain them, therefore we map them - // to allowed characters in a reversible way so that we can locate the correct - // element when the popup window is dismissed. - function id_to_windowname(text) { - text = text.replace(/\./g, '__dot__'); - text = text.replace(/\-/g, '__dash__'); - return text; - } - - function windowname_to_id(text) { - text = text.replace(/__dot__/g, '.'); - text = text.replace(/__dash__/g, '-'); - return text; - } +'use strict'; +{ + const $ = django.jQuery; function showAdminPopup(triggeringLink, name_regexp, add_popup) { - var name = triggeringLink.id.replace(name_regexp, ''); - name = id_to_windowname(name); - var href = triggeringLink.href; + const name = triggeringLink.id.replace(name_regexp, ''); + const href = new URL(triggeringLink.href); if (add_popup) { - if (href.indexOf('?') === -1) { - href += '?_popup=1'; - } else { - href += '&_popup=1'; - } + href.searchParams.set('_popup', 1); } - var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); + const win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); win.focus(); return false; } @@ -42,9 +21,9 @@ } function dismissRelatedLookupPopup(win, chosenId) { - var name = windowname_to_id(win.name); - var elem = document.getElementById(name); - if (elem.className.indexOf('vManyToManyRawIdAdminField') !== -1 && elem.value) { + const name = win.name; + const elem = document.getElementById(name); + if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) { elem.value += ',' + chosenId; } else { document.getElementById(name).value = chosenId; @@ -57,15 +36,15 @@ } function updateRelatedObjectLinks(triggeringLink) { - var $this = $(triggeringLink); - var siblings = $this.nextAll('.view-related, .change-related, .delete-related'); + const $this = $(triggeringLink); + const siblings = $this.nextAll('.view-related, .change-related, .delete-related'); if (!siblings.length) { return; } - var value = $this.val(); + const value = $this.val(); if (value) { siblings.each(function() { - var elm = $(this); + const elm = $(this); elm.attr('href', elm.attr('data-href-template').replace('__fk__', value)); }); } else { @@ -74,14 +53,14 @@ } function dismissAddRelatedObjectPopup(win, newId, newRepr) { - var name = windowname_to_id(win.name); - var elem = document.getElementById(name); + const name = win.name; + const elem = document.getElementById(name); if (elem) { - var elemName = elem.nodeName.toUpperCase(); + const elemName = elem.nodeName.toUpperCase(); if (elemName === 'SELECT') { elem.options[elem.options.length] = new Option(newRepr, newId, true, true); } else if (elemName === 'INPUT') { - if (elem.className.indexOf('vManyToManyRawIdAdminField') !== -1 && elem.value) { + if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) { elem.value += ',' + newId; } else { elem.value = newId; @@ -90,8 +69,8 @@ // Trigger a change event to update related links if required. $(elem).trigger('change'); } else { - var toId = name + "_to"; - var o = new Option(newRepr, newId); + const toId = name + "_to"; + const o = new Option(newRepr, newId); SelectBox.add_to_cache(toId, o); SelectBox.redisplay(toId); } @@ -99,9 +78,9 @@ } function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) { - var id = windowname_to_id(win.name).replace(/^edit_/, ''); - var selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); - var selects = $(selectsSelector); + const id = win.name.replace(/^edit_/, ''); + const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); + const selects = $(selectsSelector); selects.find('option').each(function() { if (this.value === objId) { this.textContent = newRepr; @@ -118,9 +97,9 @@ } function dismissDeleteRelatedObjectPopup(win, objId) { - var id = windowname_to_id(win.name).replace(/^delete_/, ''); - var selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); - var selects = $(selectsSelector); + const id = win.name.replace(/^delete_/, ''); + const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); + const selects = $(selectsSelector); selects.find('option').each(function() { if (this.value === objId) { $(this).remove(); @@ -129,10 +108,6 @@ win.close(); } - // Global for testing purposes - window.id_to_windowname = id_to_windowname; - window.windowname_to_id = windowname_to_id; - window.showRelatedObjectLookupPopup = showRelatedObjectLookupPopup; window.dismissRelatedLookupPopup = dismissRelatedLookupPopup; window.showRelatedObjectPopup = showRelatedObjectPopup; @@ -153,7 +128,7 @@ $('body').on('click', '.related-widget-wrapper-link', function(e) { e.preventDefault(); if (this.href) { - var event = $.Event('django:show-related', {href: this.href}); + const event = $.Event('django:show-related', {href: this.href}); $(this).trigger(event); if (!event.isDefaultPrevented()) { showRelatedObjectPopup(this); @@ -161,7 +136,7 @@ } }); $('body').on('change', '.related-widget-wrapper select', function(e) { - var event = $.Event('django:update-related'); + const event = $.Event('django:update-related'); $(this).trigger(event); if (!event.isDefaultPrevented()) { updateRelatedObjectLinks(this); @@ -170,12 +145,11 @@ $('.related-widget-wrapper select').trigger('change'); $('body').on('click', '.related-lookup', function(e) { e.preventDefault(); - var event = $.Event('django:lookup-related'); + const event = $.Event('django:lookup-related'); $(this).trigger(event); if (!event.isDefaultPrevented()) { showRelatedObjectLookupPopup(this); } }); }); - -})(django.jQuery); +} diff --git a/src/statics/admin/js/autocomplete.js b/src/statics/admin/js/autocomplete.js index 65c0702..c55eee1 100644 --- a/src/statics/admin/js/autocomplete.js +++ b/src/statics/admin/js/autocomplete.js @@ -1,12 +1,16 @@ -(function($) { - 'use strict'; - var init = function($element, options) { - var settings = $.extend({ +'use strict'; +{ + const $ = django.jQuery; + const init = function($element, options) { + const settings = $.extend({ ajax: { data: function(params) { return { term: params.term, - page: params.page + page: params.page, + app_label: $element.data('app-label'), + model_name: $element.data('model-name'), + field_name: $element.data('field-name') }; } } @@ -15,9 +19,9 @@ }; $.fn.djangoAdminSelect2 = function(options) { - var settings = $.extend({}, options); + const settings = $.extend({}, options); $.each(this, function(i, element) { - var $element = $(element); + const $element = $(element); init($element, settings); }); return this; @@ -34,4 +38,4 @@ return $newFormset.find('.admin-autocomplete').djangoAdminSelect2(); }; })(this)); -}(django.jQuery)); +} diff --git a/src/statics/admin/js/calendar.js b/src/statics/admin/js/calendar.js index a4c047a..a62d10a 100644 --- a/src/statics/admin/js/calendar.js +++ b/src/statics/admin/js/calendar.js @@ -3,11 +3,10 @@ calendar.js - Calendar functions by Adrian Holovaty depends on core.js for utility functions like removeChildren or quickElement */ - -(function() { - 'use strict'; +'use strict'; +{ // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions - var CalendarNamespace = { + const CalendarNamespace = { monthsOfYear: [ gettext('January'), gettext('February'), @@ -22,6 +21,20 @@ depends on core.js for utility functions like removeChildren or quickElement gettext('November'), gettext('December') ], + monthsOfYearAbbrev: [ + pgettext('abbrev. month January', 'Jan'), + pgettext('abbrev. month February', 'Feb'), + pgettext('abbrev. month March', 'Mar'), + pgettext('abbrev. month April', 'Apr'), + pgettext('abbrev. month May', 'May'), + pgettext('abbrev. month June', 'Jun'), + pgettext('abbrev. month July', 'Jul'), + pgettext('abbrev. month August', 'Aug'), + pgettext('abbrev. month September', 'Sep'), + pgettext('abbrev. month October', 'Oct'), + pgettext('abbrev. month November', 'Nov'), + pgettext('abbrev. month December', 'Dec') + ], daysOfWeek: [ pgettext('one letter Sunday', 'S'), pgettext('one letter Monday', 'M'), @@ -36,7 +49,7 @@ depends on core.js for utility functions like removeChildren or quickElement return (((year % 4) === 0) && ((year % 100) !== 0 ) || ((year % 400) === 0)); }, getDaysInMonth: function(month, year) { - var days; + let days; if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) { days = 31; } @@ -52,11 +65,11 @@ depends on core.js for utility functions like removeChildren or quickElement return days; }, draw: function(month, year, div_id, callback, selected) { // month = 1-12, year = 1-9999 - var today = new Date(); - var todayDay = today.getDate(); - var todayMonth = today.getMonth() + 1; - var todayYear = today.getFullYear(); - var todayClass = ''; + const today = new Date(); + const todayDay = today.getDate(); + const todayMonth = today.getMonth() + 1; + const todayYear = today.getFullYear(); + let todayClass = ''; // Use UTC functions here because the date field does not contain time // and using the UTC function variants prevent the local time offset @@ -69,33 +82,33 @@ depends on core.js for utility functions like removeChildren or quickElement // // The day variable above will be 1 instead of 2 in, say, US Pacific time // zone. - var isSelectedMonth = false; + let isSelectedMonth = false; if (typeof selected !== 'undefined') { isSelectedMonth = (selected.getUTCFullYear() === year && (selected.getUTCMonth() + 1) === month); } month = parseInt(month); year = parseInt(year); - var calDiv = document.getElementById(div_id); + const calDiv = document.getElementById(div_id); removeChildren(calDiv); - var calTable = document.createElement('table'); + const calTable = document.createElement('table'); quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month - 1] + ' ' + year); - var tableBody = quickElement('tbody', calTable); + const tableBody = quickElement('tbody', calTable); // Draw days-of-week header - var tableRow = quickElement('tr', tableBody); - for (var i = 0; i < 7; i++) { + let tableRow = quickElement('tr', tableBody); + for (let i = 0; i < 7; i++) { quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]); } - var startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay(); - var days = CalendarNamespace.getDaysInMonth(month, year); + const startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay(); + const days = CalendarNamespace.getDaysInMonth(month, year); - var nonDayCell; + let nonDayCell; // Draw blanks before first of month tableRow = quickElement('tr', tableBody); - for (i = 0; i < startingPos; i++) { + for (let i = 0; i < startingPos; i++) { nonDayCell = quickElement('td', tableRow, ' '); nonDayCell.className = "nonday"; } @@ -109,8 +122,8 @@ depends on core.js for utility functions like removeChildren or quickElement } // Draw days of month - var currentDay = 1; - for (i = startingPos; currentDay <= days; i++) { + let currentDay = 1; + for (let i = startingPos; currentDay <= days; i++) { if (i % 7 === 0 && currentDay !== 1) { tableRow = quickElement('tr', tableBody); } @@ -128,8 +141,8 @@ depends on core.js for utility functions like removeChildren or quickElement todayClass += "selected"; } - var cell = quickElement('td', tableRow, '', 'class', todayClass); - var link = quickElement('a', cell, currentDay, 'href', '#'); + const cell = quickElement('td', tableRow, '', 'class', todayClass); + const link = quickElement('a', cell, currentDay, 'href', '#'); link.addEventListener('click', calendarMonth(year, month)); currentDay++; } @@ -205,4 +218,4 @@ depends on core.js for utility functions like removeChildren or quickElement }; window.Calendar = Calendar; window.CalendarNamespace = CalendarNamespace; -})(); +} diff --git a/src/statics/admin/js/cancel.js b/src/statics/admin/js/cancel.js index 8809ee7..3069c6f 100644 --- a/src/statics/admin/js/cancel.js +++ b/src/statics/admin/js/cancel.js @@ -1,13 +1,29 @@ -(function($) { - 'use strict'; - $(function() { - $('.cancel-link').on('click', function(e) { - e.preventDefault(); - if (window.location.search.indexOf('&_popup=1') === -1) { - window.history.back(); // Go back if not a popup. +'use strict'; +{ + // Call function fn when the DOM is loaded and ready. If it is already + // loaded, call the function now. + // http://youmightnotneedjquery.com/#ready + function ready(fn) { + if (document.readyState !== 'loading') { + fn(); + } else { + document.addEventListener('DOMContentLoaded', fn); + } + } + + ready(function() { + function handleClick(event) { + event.preventDefault(); + const params = new URLSearchParams(window.location.search); + if (params.has('_popup')) { + window.close(); // Close the popup. } else { - window.close(); // Otherwise, close the popup. + window.history.back(); // Otherwise, go back. } + } + + document.querySelectorAll('.cancel-link').forEach(function(el) { + el.addEventListener('click', handleClick); }); }); -})(django.jQuery); +} diff --git a/src/statics/admin/js/change_form.js b/src/statics/admin/js/change_form.js index 4797383..96a4c62 100644 --- a/src/statics/admin/js/change_form.js +++ b/src/statics/admin/js/change_form.js @@ -1,20 +1,16 @@ -/*global showAddAnotherPopup, showRelatedObjectLookupPopup showRelatedObjectPopup updateRelatedObjectLinks*/ - -(function($) { - 'use strict'; - $(document).ready(function() { - var modelName = $('#django-admin-form-add-constants').data('modelName'); - $('body').on('click', '.add-another', function(e) { - e.preventDefault(); - var event = $.Event('django:add-another-related'); - $(this).trigger(event); - if (!event.isDefaultPrevented()) { - showAddAnotherPopup(this); +'use strict'; +{ + const inputTags = ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA']; + const modelName = document.getElementById('django-admin-form-add-constants').dataset.modelName; + if (modelName) { + const form = document.getElementById(modelName + '_form'); + for (const element of form.elements) { + // HTMLElement.offsetParent returns null when the element is not + // rendered. + if (inputTags.includes(element.tagName) && !element.disabled && element.offsetParent) { + element.focus(); + break; } - }); - - if (modelName) { - $('form#' + modelName + '_form :input:visible:enabled:first').focus(); } - }); -})(django.jQuery); + } +} diff --git a/src/statics/admin/js/collapse.js b/src/statics/admin/js/collapse.js index 20e7030..c6c7b0f 100644 --- a/src/statics/admin/js/collapse.js +++ b/src/statics/admin/js/collapse.js @@ -1,29 +1,18 @@ /*global gettext*/ -(function() { - 'use strict'; - var closestElem = function(elem, tagName) { - if (elem.nodeName === tagName.toUpperCase()) { - return elem; - } - if (elem.parentNode.nodeName === 'BODY') { - return null; - } - return elem.parentNode && closestElem(elem.parentNode, tagName); - }; - +'use strict'; +{ window.addEventListener('load', function() { // Add anchor tag for Show/Hide link - var fieldsets = document.querySelectorAll('fieldset.collapse'); - for (var i = 0; i < fieldsets.length; i++) { - var elem = fieldsets[i]; + const fieldsets = document.querySelectorAll('fieldset.collapse'); + for (const [i, elem] of fieldsets.entries()) { // Don't hide if fields in this fieldset have errors - if (elem.querySelectorAll('div.errors').length === 0) { + if (elem.querySelectorAll('div.errors, ul.errorlist').length === 0) { elem.classList.add('collapsed'); - var h2 = elem.querySelector('h2'); - var link = document.createElement('a'); - link.setAttribute('id', 'fieldsetcollapser' + i); - link.setAttribute('class', 'collapse-toggle'); - link.setAttribute('href', '#'); + const h2 = elem.querySelector('h2'); + const link = document.createElement('a'); + link.id = 'fieldsetcollapser' + i; + link.className = 'collapse-toggle'; + link.href = '#'; link.textContent = gettext('Show'); h2.appendChild(document.createTextNode(' (')); h2.appendChild(link); @@ -31,11 +20,11 @@ } } // Add toggle to hide/show anchor tag - var toggleFunc = function(ev) { + const toggleFunc = function(ev) { if (ev.target.matches('.collapse-toggle')) { ev.preventDefault(); ev.stopPropagation(); - var fieldset = closestElem(ev.target, 'fieldset'); + const fieldset = ev.target.closest('fieldset'); if (fieldset.classList.contains('collapsed')) { // Show ev.target.textContent = gettext('Hide'); @@ -47,9 +36,8 @@ } } }; - var inlineDivs = document.querySelectorAll('fieldset.module'); - for (i = 0; i < inlineDivs.length; i++) { - inlineDivs[i].addEventListener('click', toggleFunc); - } + document.querySelectorAll('fieldset.module').forEach(function(el) { + el.addEventListener('click', toggleFunc); + }); }); -})(); +} diff --git a/src/statics/admin/js/core.js b/src/statics/admin/js/core.js index 4f2fe13..3a2e4aa 100644 --- a/src/statics/admin/js/core.js +++ b/src/statics/admin/js/core.js @@ -1,19 +1,15 @@ // Core javascript helper functions - -// basic browser identification & version -var isOpera = (navigator.userAgent.indexOf("Opera") >= 0) && parseFloat(navigator.appVersion); -var isIE = ((document.all) && (!isOpera)) && parseFloat(navigator.appVersion.split("MSIE ")[1].split(";")[0]); +'use strict'; // quickElement(tagType, parentReference [, textInChildNode, attribute, attributeValue ...]); function quickElement() { - 'use strict'; - var obj = document.createElement(arguments[0]); + const obj = document.createElement(arguments[0]); if (arguments[2]) { - var textNode = document.createTextNode(arguments[2]); + const textNode = document.createTextNode(arguments[2]); obj.appendChild(textNode); } - var len = arguments.length; - for (var i = 3; i < len; i += 2) { + const len = arguments.length; + for (let i = 3; i < len; i += 2) { obj.setAttribute(arguments[i], arguments[i + 1]); } arguments[1].appendChild(obj); @@ -22,7 +18,6 @@ function quickElement() { // "a" is reference to an object function removeChildren(a) { - 'use strict'; while (a.hasChildNodes()) { a.removeChild(a.lastChild); } @@ -33,16 +28,11 @@ function removeChildren(a) { // See https://www.quirksmode.org/js/findpos.html // ---------------------------------------------------------------------------- function findPosX(obj) { - 'use strict'; - var curleft = 0; + let curleft = 0; if (obj.offsetParent) { while (obj.offsetParent) { - curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft); - obj = obj.offsetParent; - } - // IE offsetParent does not include the top-level - if (isIE && obj.parentElement) { curleft += obj.offsetLeft - obj.scrollLeft; + obj = obj.offsetParent; } } else if (obj.x) { curleft += obj.x; @@ -51,16 +41,11 @@ function findPosX(obj) { } function findPosY(obj) { - 'use strict'; - var curtop = 0; + let curtop = 0; if (obj.offsetParent) { while (obj.offsetParent) { - curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop); - obj = obj.offsetParent; - } - // IE offsetParent does not include the top-level - if (isIE && obj.parentElement) { curtop += obj.offsetTop - obj.scrollTop; + obj = obj.offsetParent; } } else if (obj.y) { curtop += obj.y; @@ -71,16 +56,9 @@ function findPosY(obj) { //----------------------------------------------------------------------------- // Date object extensions // ---------------------------------------------------------------------------- -(function() { - 'use strict'; +{ Date.prototype.getTwelveHours = function() { - var hours = this.getHours(); - if (hours === 0) { - return 12; - } - else { - return hours <= 12 ? hours : hours - 12; - } + return this.getHours() % 12 || 12; }; Date.prototype.getTwoDigitMonth = function() { @@ -107,12 +85,10 @@ function findPosY(obj) { return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds(); }; - Date.prototype.getHourMinute = function() { - return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute(); - }; - - Date.prototype.getHourMinuteSecond = function() { - return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond(); + Date.prototype.getAbbrevMonthName = function() { + return typeof window.CalendarNamespace === "undefined" + ? this.getTwoDigitMonth() + : window.CalendarNamespace.monthsOfYearAbbrev[this.getMonth()]; }; Date.prototype.getFullMonthName = function() { @@ -122,7 +98,8 @@ function findPosY(obj) { }; Date.prototype.strftime = function(format) { - var fields = { + const fields = { + b: this.getAbbrevMonthName(), B: this.getFullMonthName(), c: this.toString(), d: this.getTwoDigitDate(), @@ -139,7 +116,7 @@ function findPosY(obj) { Y: '' + this.getFullYear(), '%': '%' }; - var result = '', i = 0; + let result = '', i = 0; while (i < format.length) { if (format.charAt(i) === '%') { result = result + fields[format.charAt(i + 1)]; @@ -156,19 +133,11 @@ function findPosY(obj) { // ---------------------------------------------------------------------------- // String object extensions // ---------------------------------------------------------------------------- - String.prototype.pad_left = function(pad_length, pad_string) { - var new_string = this; - for (var i = 0; new_string.length < pad_length; i++) { - new_string = pad_string + new_string; - } - return new_string; - }; - String.prototype.strptime = function(format) { - var split_format = format.split(/[.\-/]/); - var date = this.split(/[.\-/]/); - var i = 0; - var day, month, year; + const split_format = format.split(/[.\-/]/); + const date = this.split(/[.\-/]/); + let i = 0; + let day, month, year; while (i < split_format.length) { switch (split_format[i]) { case "%d": @@ -181,7 +150,14 @@ function findPosY(obj) { year = date[i]; break; case "%y": - year = date[i]; + // A %y value in the range of [00, 68] is in the current + // century, while [69, 99] is in the previous century, + // according to the Open Group Specification. + if (parseInt(date[i], 10) >= 69) { + year = date[i]; + } else { + year = (new Date(Date.UTC(date[i], 0))).getUTCFullYear() + 100; + } break; } ++i; @@ -191,22 +167,4 @@ function findPosY(obj) { // date extraction. return new Date(Date.UTC(year, month, day)); }; - -})(); -// ---------------------------------------------------------------------------- -// Get the computed style for and element -// ---------------------------------------------------------------------------- -function getStyle(oElm, strCssRule) { - 'use strict'; - var strValue = ""; - if(document.defaultView && document.defaultView.getComputedStyle) { - strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule); - } - else if(oElm.currentStyle) { - strCssRule = strCssRule.replace(/\-(\w)/g, function(strMatch, p1) { - return p1.toUpperCase(); - }); - strValue = oElm.currentStyle[strCssRule]; - } - return strValue; } diff --git a/src/statics/admin/js/inlines.js b/src/statics/admin/js/inlines.js index ba8c9cd..82ec027 100644 --- a/src/statics/admin/js/inlines.js +++ b/src/statics/admin/js/inlines.js @@ -15,15 +15,16 @@ * Licensed under the New BSD License * See: https://opensource.org/licenses/bsd-license.php */ -(function($) { - 'use strict'; +'use strict'; +{ + const $ = django.jQuery; $.fn.formset = function(opts) { - var options = $.extend({}, $.fn.formset.defaults, opts); - var $this = $(this); - var $parent = $this.parent(); - var updateElementIndex = function(el, prefix, ndx) { - var id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))"); - var replacement = prefix + "-" + ndx; + const options = $.extend({}, $.fn.formset.defaults, opts); + const $this = $(this); + const $parent = $this.parent(); + const updateElementIndex = function(el, prefix, ndx) { + const id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))"); + const replacement = prefix + "-" + ndx; if ($(el).prop("for")) { $(el).prop("for", $(el).prop("for").replace(id_regex, replacement)); } @@ -34,22 +35,21 @@ el.name = el.name.replace(id_regex, replacement); } }; - var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off"); - var nextIndex = parseInt(totalForms.val(), 10); - var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off"); - // only show the add button if we are allowed to add more items, - // note that max_num = None translates to a blank string. - var showAddButton = maxForms.val() === '' || (maxForms.val() - totalForms.val()) > 0; - $this.each(function(i) { - $(this).not("." + options.emptyCssClass).addClass(options.formCssClass); - }); - if ($this.length && showAddButton) { - var addButton = options.addButton; + const totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off"); + let nextIndex = parseInt(totalForms.val(), 10); + const maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off"); + const minForms = $("#id_" + options.prefix + "-MIN_NUM_FORMS").prop("autocomplete", "off"); + let addButton; + + /** + * The "Add another MyModel" button below the inline forms. + */ + const addInlineAddButton = function() { if (addButton === null) { if ($this.prop("tagName") === "TR") { // If forms are laid out as table rows, insert the // "add" button in a new table row: - var numCols = this.eq(-1).children().length; + const numCols = $this.eq(-1).children().length; $parent.append('' + options.addText + ""); addButton = $parent.find("tr:last a"); } else { @@ -58,74 +58,131 @@ addButton = $this.filter(":last").next().find("a"); } } - addButton.on('click', function(e) { - e.preventDefault(); - var template = $("#" + options.prefix + "-empty"); - var row = template.clone(true); - row.removeClass(options.emptyCssClass) - .addClass(options.formCssClass) - .attr("id", options.prefix + "-" + nextIndex); - if (row.is("tr")) { - // If the forms are laid out in table rows, insert - // the remove button into the last table cell: - row.children(":last").append('"); - } else if (row.is("ul") || row.is("ol")) { - // If they're laid out as an ordered/unordered list, - // insert an
  • after the last list item: - row.append('
  • ' + options.deleteText + "
  • "); - } else { - // Otherwise, just insert the remove button as the - // last child element of the form's container: - row.children(":first").append('' + options.deleteText + ""); - } - row.find("*").each(function() { - updateElementIndex(this, options.prefix, totalForms.val()); - }); - // Insert the new form when it has been fully edited - row.insertBefore($(template)); - // Update number of total forms - $(totalForms).val(parseInt(totalForms.val(), 10) + 1); - nextIndex += 1; - // Hide add button in case we've hit the max, except we want to add infinitely - if ((maxForms.val() !== '') && (maxForms.val() - totalForms.val()) <= 0) { - addButton.parent().hide(); - } - // The delete button of each row triggers a bunch of other things - row.find("a." + options.deleteCssClass).on('click', function(e1) { - e1.preventDefault(); - // Remove the parent form containing this button: - row.remove(); - nextIndex -= 1; - // If a post-delete callback was provided, call it with the deleted form: - if (options.removed) { - options.removed(row); - } - $(document).trigger('formset:removed', [row, options.prefix]); - // Update the TOTAL_FORMS form count. - var forms = $("." + options.formCssClass); - $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length); - // Show add button again once we drop below max - if ((maxForms.val() === '') || (maxForms.val() - forms.length) > 0) { - addButton.parent().show(); - } - // Also, update names and ids for all remaining form controls - // so they remain in sequence: - var i, formCount; - var updateElementCallback = function() { - updateElementIndex(this, options.prefix, i); - }; - for (i = 0, formCount = forms.length; i < formCount; i++) { - updateElementIndex($(forms).get(i), options.prefix, i); - $(forms.get(i)).find("*").each(updateElementCallback); - } - }); - // If a post-add callback was supplied, call it with the added form: - if (options.added) { - options.added(row); - } - $(document).trigger('formset:added', [row, options.prefix]); + addButton.on('click', addInlineClickHandler); + }; + + const addInlineClickHandler = function(e) { + e.preventDefault(); + const template = $("#" + options.prefix + "-empty"); + const row = template.clone(true); + row.removeClass(options.emptyCssClass) + .addClass(options.formCssClass) + .attr("id", options.prefix + "-" + nextIndex); + addInlineDeleteButton(row); + row.find("*").each(function() { + updateElementIndex(this, options.prefix, totalForms.val()); }); + // Insert the new form when it has been fully edited. + row.insertBefore($(template)); + // Update number of total forms. + $(totalForms).val(parseInt(totalForms.val(), 10) + 1); + nextIndex += 1; + // Hide the add button if there's a limit and it's been reached. + if ((maxForms.val() !== '') && (maxForms.val() - totalForms.val()) <= 0) { + addButton.parent().hide(); + } + // Show the remove buttons if there are more than min_num. + toggleDeleteButtonVisibility(row.closest('.inline-group')); + + // Pass the new form to the post-add callback, if provided. + if (options.added) { + options.added(row); + } + $(document).trigger('formset:added', [row, options.prefix]); + }; + + /** + * The "X" button that is part of every unsaved inline. + * (When saved, it is replaced with a "Delete" checkbox.) + */ + const addInlineDeleteButton = function(row) { + if (row.is("tr")) { + // If the forms are laid out in table rows, insert + // the remove button into the last table cell: + row.children(":last").append('"); + } else if (row.is("ul") || row.is("ol")) { + // If they're laid out as an ordered/unordered list, + // insert an
  • after the last list item: + row.append('
  • ' + options.deleteText + "
  • "); + } else { + // Otherwise, just insert the remove button as the + // last child element of the form's container: + row.children(":first").append('' + options.deleteText + ""); + } + // Add delete handler for each row. + row.find("a." + options.deleteCssClass).on('click', inlineDeleteHandler.bind(this)); + }; + + const inlineDeleteHandler = function(e1) { + e1.preventDefault(); + const deleteButton = $(e1.target); + const row = deleteButton.closest('.' + options.formCssClass); + const inlineGroup = row.closest('.inline-group'); + // Remove the parent form containing this button, + // and also remove the relevant row with non-field errors: + const prevRow = row.prev(); + if (prevRow.length && prevRow.hasClass('row-form-errors')) { + prevRow.remove(); + } + row.remove(); + nextIndex -= 1; + // Pass the deleted form to the post-delete callback, if provided. + if (options.removed) { + options.removed(row); + } + $(document).trigger('formset:removed', [row, options.prefix]); + // Update the TOTAL_FORMS form count. + const forms = $("." + options.formCssClass); + $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length); + // Show add button again once below maximum number. + if ((maxForms.val() === '') || (maxForms.val() - forms.length) > 0) { + addButton.parent().show(); + } + // Hide the remove buttons if at min_num. + toggleDeleteButtonVisibility(inlineGroup); + // Also, update names and ids for all remaining form controls so + // they remain in sequence: + let i, formCount; + const updateElementCallback = function() { + updateElementIndex(this, options.prefix, i); + }; + for (i = 0, formCount = forms.length; i < formCount; i++) { + updateElementIndex($(forms).get(i), options.prefix, i); + $(forms.get(i)).find("*").each(updateElementCallback); + } + }; + + const toggleDeleteButtonVisibility = function(inlineGroup) { + if ((minForms.val() !== '') && (minForms.val() - totalForms.val()) >= 0) { + inlineGroup.find('.inline-deletelink').hide(); + } else { + inlineGroup.find('.inline-deletelink').show(); + } + }; + + $this.each(function(i) { + $(this).not("." + options.emptyCssClass).addClass(options.formCssClass); + }); + + // Create the delete buttons for all unsaved inlines: + $this.filter('.' + options.formCssClass + ':not(.has_original):not(.' + options.emptyCssClass + ')').each(function() { + addInlineDeleteButton($(this)); + }); + toggleDeleteButtonVisibility($this); + + // Create the add button, initially hidden. + addButton = options.addButton; + addInlineAddButton(); + + // Show the add button if allowed to add more items. + // Note that max_num = None translates to a blank string. + const showAddButton = maxForms.val() === '' || (maxForms.val() - totalForms.val()) > 0; + if ($this.length && showAddButton) { + addButton.parent().show(); + } else { + addButton.parent().hide(); } + return this; }; @@ -146,14 +203,9 @@ // Tabular inlines --------------------------------------------------------- $.fn.tabularFormset = function(selector, options) { - var $rows = $(this); - var alternatingRows = function(row) { - $(selector).not(".add-row").removeClass("row1 row2") - .filter(":even").addClass("row1").end() - .filter(":odd").addClass("row2"); - }; + const $rows = $(this); - var reinitDateTimeShortCuts = function() { + const reinitDateTimeShortCuts = function() { // Reinitialize the calendar and clock widgets by force if (typeof DateTimeShortcuts !== "undefined") { $(".datetimeshortcuts").remove(); @@ -161,24 +213,24 @@ } }; - var updateSelectFilter = function() { + const updateSelectFilter = function() { // If any SelectFilter widgets are a part of the new form, // instantiate a new SelectFilter instance for it. if (typeof SelectFilter !== 'undefined') { $('.selectfilter').each(function(index, value) { - var namearr = value.name.split('-'); + const namearr = value.name.split('-'); SelectFilter.init(value.id, namearr[namearr.length - 1], false); }); $('.selectfilterstacked').each(function(index, value) { - var namearr = value.name.split('-'); + const namearr = value.name.split('-'); SelectFilter.init(value.id, namearr[namearr.length - 1], true); }); } }; - var initPrepopulatedFields = function(row) { + const initPrepopulatedFields = function(row) { row.find('.prepopulated_field').each(function() { - var field = $(this), + const field = $(this), input = field.find('input, select, textarea'), dependency_list = input.data('dependency_list') || [], dependencies = []; @@ -198,12 +250,10 @@ deleteCssClass: "inline-deletelink", deleteText: options.deleteText, emptyCssClass: "empty-form", - removed: alternatingRows, added: function(row) { initPrepopulatedFields(row); reinitDateTimeShortCuts(); updateSelectFilter(); - alternatingRows(row); }, addButton: options.addButton }); @@ -213,15 +263,15 @@ // Stacked inlines --------------------------------------------------------- $.fn.stackedFormset = function(selector, options) { - var $rows = $(this); - var updateInlineLabel = function(row) { + const $rows = $(this); + const updateInlineLabel = function(row) { $(selector).find(".inline_label").each(function(i) { - var count = i + 1; + const count = i + 1; $(this).html($(this).html().replace(/(#\d+)/g, "#" + count)); }); }; - var reinitDateTimeShortCuts = function() { + const reinitDateTimeShortCuts = function() { // Reinitialize the calendar and clock widgets by force, yuck. if (typeof DateTimeShortcuts !== "undefined") { $(".datetimeshortcuts").remove(); @@ -229,23 +279,23 @@ } }; - var updateSelectFilter = function() { + const updateSelectFilter = function() { // If any SelectFilter widgets were added, instantiate a new instance. if (typeof SelectFilter !== "undefined") { $(".selectfilter").each(function(index, value) { - var namearr = value.name.split('-'); + const namearr = value.name.split('-'); SelectFilter.init(value.id, namearr[namearr.length - 1], false); }); $(".selectfilterstacked").each(function(index, value) { - var namearr = value.name.split('-'); + const namearr = value.name.split('-'); SelectFilter.init(value.id, namearr[namearr.length - 1], true); }); } }; - var initPrepopulatedFields = function(row) { + const initPrepopulatedFields = function(row) { row.find('.prepopulated_field').each(function() { - var field = $(this), + const field = $(this), input = field.find('input, select, textarea'), dependency_list = input.data('dependency_list') || [], dependencies = []; @@ -280,19 +330,19 @@ $(document).ready(function() { $(".js-inline-admin-formset").each(function() { - var data = $(this).data(), - inlineOptions = data.inlineFormset, - selector; + const data = $(this).data(), + inlineOptions = data.inlineFormset; + let selector; switch(data.inlineType) { case "stacked": selector = inlineOptions.name + "-group .inline-related"; $(selector).stackedFormset(selector, inlineOptions.options); break; case "tabular": - selector = inlineOptions.name + "-group .tabular.inline-related tbody:first > tr"; + selector = inlineOptions.name + "-group .tabular.inline-related tbody:first > tr.form-row"; $(selector).tabularFormset(selector, inlineOptions.options); break; } }); }); -})(django.jQuery); +} diff --git a/src/statics/admin/js/jquery.init.js b/src/statics/admin/js/jquery.init.js index f3ac162..f40b27f 100644 --- a/src/statics/admin/js/jquery.init.js +++ b/src/statics/admin/js/jquery.init.js @@ -1,8 +1,8 @@ -/*global django:true, jQuery:false*/ +/*global jQuery:false*/ +'use strict'; /* Puts the included jQuery into our own namespace using noConflict and passing * it 'true'. This ensures that the included jQuery doesn't pollute the global * namespace (i.e. this preserves pre-existing values for both window.$ and * window.jQuery). */ -var django = django || {}; -django.jQuery = jQuery.noConflict(true); +window.django = {jQuery: jQuery.noConflict(true)}; diff --git a/src/statics/admin/js/nav_sidebar.js b/src/statics/admin/js/nav_sidebar.js new file mode 100644 index 0000000..efaa721 --- /dev/null +++ b/src/statics/admin/js/nav_sidebar.js @@ -0,0 +1,39 @@ +'use strict'; +{ + const toggleNavSidebar = document.getElementById('toggle-nav-sidebar'); + if (toggleNavSidebar !== null) { + const navLinks = document.querySelectorAll('#nav-sidebar a'); + function disableNavLinkTabbing() { + for (const navLink of navLinks) { + navLink.tabIndex = -1; + } + } + function enableNavLinkTabbing() { + for (const navLink of navLinks) { + navLink.tabIndex = 0; + } + } + + const main = document.getElementById('main'); + let navSidebarIsOpen = localStorage.getItem('django.admin.navSidebarIsOpen'); + if (navSidebarIsOpen === null) { + navSidebarIsOpen = 'true'; + } + if (navSidebarIsOpen === 'false') { + disableNavLinkTabbing(); + } + main.classList.toggle('shifted', navSidebarIsOpen === 'true'); + + toggleNavSidebar.addEventListener('click', function() { + if (navSidebarIsOpen === 'true') { + navSidebarIsOpen = 'false'; + disableNavLinkTabbing(); + } else { + navSidebarIsOpen = 'true'; + enableNavLinkTabbing(); + } + localStorage.setItem('django.admin.navSidebarIsOpen', navSidebarIsOpen); + main.classList.toggle('shifted'); + }); + } +} diff --git a/src/statics/admin/js/popup_response.js b/src/statics/admin/js/popup_response.js index b4a07e7..2b1d3dd 100644 --- a/src/statics/admin/js/popup_response.js +++ b/src/statics/admin/js/popup_response.js @@ -1,7 +1,7 @@ /*global opener */ -(function() { - 'use strict'; - var initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse); +'use strict'; +{ + const initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse); switch(initData.action) { case 'change': opener.dismissChangeRelatedObjectPopup(window, initData.value, initData.obj, initData.new_value); @@ -13,4 +13,4 @@ opener.dismissAddRelatedObjectPopup(window, initData.value, initData.obj); break; } -})(); +} diff --git a/src/statics/admin/js/prepopulate.js b/src/statics/admin/js/prepopulate.js index bef45a3..89e95ab 100644 --- a/src/statics/admin/js/prepopulate.js +++ b/src/statics/admin/js/prepopulate.js @@ -1,6 +1,7 @@ /*global URLify*/ -(function($) { - 'use strict'; +'use strict'; +{ + const $ = django.jQuery; $.fn.prepopulate = function(dependencies, maxLength, allowUnicode) { /* Depends on urlify.js @@ -11,15 +12,15 @@ allowUnicode - Unicode support of the URLify'd string */ return this.each(function() { - var prepopulatedField = $(this); + const prepopulatedField = $(this); - var populate = function() { + const populate = function() { // Bail if the field's value has been changed by the user if (prepopulatedField.data('_changed')) { return; } - var values = []; + const values = []; $.each(dependencies, function(i, field) { field = $(field); if (field.val().length > 0) { @@ -39,4 +40,4 @@ } }); }; -})(django.jQuery); +} diff --git a/src/statics/admin/js/prepopulate_init.js b/src/statics/admin/js/prepopulate_init.js index 184df92..72ebdcf 100644 --- a/src/statics/admin/js/prepopulate_init.js +++ b/src/statics/admin/js/prepopulate_init.js @@ -1,10 +1,11 @@ -(function($) { - 'use strict'; - var fields = $('#django-admin-prepopulated-fields-constants').data('prepopulatedFields'); +'use strict'; +{ + const $ = django.jQuery; + const fields = $('#django-admin-prepopulated-fields-constants').data('prepopulatedFields'); $.each(fields, function(index, field) { $('.empty-form .form-row .field-' + field.name + ', .empty-form.form-row .field-' + field.name).addClass('prepopulated_field'); $(field.id).data('dependency_list', field.dependency_list).prepopulate( field.dependency_ids, field.maxLength, field.allowUnicode ); }); -})(django.jQuery); +} diff --git a/src/statics/admin/js/urlify.js b/src/statics/admin/js/urlify.js index c3342b9..61dedb2 100644 --- a/src/statics/admin/js/urlify.js +++ b/src/statics/admin/js/urlify.js @@ -1,8 +1,7 @@ /*global XRegExp*/ -(function() { - 'use strict'; - - var LATIN_MAP = { +'use strict'; +{ + const LATIN_MAP = { 'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç': 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I', 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', @@ -14,10 +13,10 @@ 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y' }; - var LATIN_SYMBOLS_MAP = { + const LATIN_SYMBOLS_MAP = { '©': '(c)' }; - var GREEK_MAP = { + const GREEK_MAP = { 'α': 'a', 'β': 'b', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'h', 'θ': '8', 'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': '3', 'ο': 'o', 'π': 'p', 'ρ': 'r', 'σ': 's', 'τ': 't', 'υ': 'y', 'φ': 'f', @@ -29,15 +28,15 @@ 'Φ': 'F', 'Χ': 'X', 'Ψ': 'PS', 'Ω': 'W', 'Ά': 'A', 'Έ': 'E', 'Ί': 'I', 'Ό': 'O', 'Ύ': 'Y', 'Ή': 'H', 'Ώ': 'W', 'Ϊ': 'I', 'Ϋ': 'Y' }; - var TURKISH_MAP = { + const TURKISH_MAP = { 'ş': 's', 'Ş': 'S', 'ı': 'i', 'İ': 'I', 'ç': 'c', 'Ç': 'C', 'ü': 'u', 'Ü': 'U', 'ö': 'o', 'Ö': 'O', 'ğ': 'g', 'Ğ': 'G' }; - var ROMANIAN_MAP = { + const ROMANIAN_MAP = { 'ă': 'a', 'î': 'i', 'ș': 's', 'ț': 't', 'â': 'a', 'Ă': 'A', 'Î': 'I', 'Ș': 'S', 'Ț': 'T', 'Â': 'A' }; - var RUSSIAN_MAP = { + const RUSSIAN_MAP = { 'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo', 'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm', 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u', @@ -49,16 +48,16 @@ 'Ф': 'F', 'Х': 'H', 'Ц': 'C', 'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Sh', 'Ъ': '', 'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu', 'Я': 'Ya' }; - var UKRAINIAN_MAP = { + const UKRAINIAN_MAP = { 'Є': 'Ye', 'І': 'I', 'Ї': 'Yi', 'Ґ': 'G', 'є': 'ye', 'і': 'i', 'ї': 'yi', 'ґ': 'g' }; - var CZECH_MAP = { + const CZECH_MAP = { 'č': 'c', 'ď': 'd', 'ě': 'e', 'ň': 'n', 'ř': 'r', 'š': 's', 'ť': 't', 'ů': 'u', 'ž': 'z', 'Č': 'C', 'Ď': 'D', 'Ě': 'E', 'Ň': 'N', 'Ř': 'R', 'Š': 'S', 'Ť': 'T', 'Ů': 'U', 'Ž': 'Z' }; - var SLOVAK_MAP = { + const SLOVAK_MAP = { 'á': 'a', 'ä': 'a', 'č': 'c', 'ď': 'd', 'é': 'e', 'í': 'i', 'ľ': 'l', 'ĺ': 'l', 'ň': 'n', 'ó': 'o', 'ô': 'o', 'ŕ': 'r', 'š': 's', 'ť': 't', 'ú': 'u', 'ý': 'y', 'ž': 'z', @@ -66,40 +65,40 @@ 'Ĺ': 'L', 'Ň': 'N', 'Ó': 'O', 'Ô': 'O', 'Ŕ': 'R', 'Š': 'S', 'Ť': 'T', 'Ú': 'U', 'Ý': 'Y', 'Ž': 'Z' }; - var POLISH_MAP = { + const POLISH_MAP = { 'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's', 'ź': 'z', 'ż': 'z', 'Ą': 'A', 'Ć': 'C', 'Ę': 'E', 'Ł': 'L', 'Ń': 'N', 'Ó': 'O', 'Ś': 'S', 'Ź': 'Z', 'Ż': 'Z' }; - var LATVIAN_MAP = { + const LATVIAN_MAP = { 'ā': 'a', 'č': 'c', 'ē': 'e', 'ģ': 'g', 'ī': 'i', 'ķ': 'k', 'ļ': 'l', 'ņ': 'n', 'š': 's', 'ū': 'u', 'ž': 'z', 'Ā': 'A', 'Č': 'C', 'Ē': 'E', 'Ģ': 'G', 'Ī': 'I', 'Ķ': 'K', 'Ļ': 'L', 'Ņ': 'N', 'Š': 'S', 'Ū': 'U', 'Ž': 'Z' }; - var ARABIC_MAP = { + const ARABIC_MAP = { 'أ': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'g', 'ح': 'h', 'خ': 'kh', 'د': 'd', 'ذ': 'th', 'ر': 'r', 'ز': 'z', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': 't', 'ظ': 'th', 'ع': 'aa', 'غ': 'gh', 'ف': 'f', 'ق': 'k', 'ك': 'k', 'ل': 'l', 'م': 'm', 'ن': 'n', 'ه': 'h', 'و': 'o', 'ي': 'y' }; - var LITHUANIAN_MAP = { + const LITHUANIAN_MAP = { 'ą': 'a', 'č': 'c', 'ę': 'e', 'ė': 'e', 'į': 'i', 'š': 's', 'ų': 'u', 'ū': 'u', 'ž': 'z', 'Ą': 'A', 'Č': 'C', 'Ę': 'E', 'Ė': 'E', 'Į': 'I', 'Š': 'S', 'Ų': 'U', 'Ū': 'U', 'Ž': 'Z' }; - var SERBIAN_MAP = { + const SERBIAN_MAP = { 'ђ': 'dj', 'ј': 'j', 'љ': 'lj', 'њ': 'nj', 'ћ': 'c', 'џ': 'dz', 'đ': 'dj', 'Ђ': 'Dj', 'Ј': 'j', 'Љ': 'Lj', 'Њ': 'Nj', 'Ћ': 'C', 'Џ': 'Dz', 'Đ': 'Dj' }; - var AZERBAIJANI_MAP = { + const AZERBAIJANI_MAP = { 'ç': 'c', 'ə': 'e', 'ğ': 'g', 'ı': 'i', 'ö': 'o', 'ş': 's', 'ü': 'u', 'Ç': 'C', 'Ə': 'E', 'Ğ': 'G', 'İ': 'I', 'Ö': 'O', 'Ş': 'S', 'Ü': 'U' }; - var GEORGIAN_MAP = { + const GEORGIAN_MAP = { 'ა': 'a', 'ბ': 'b', 'გ': 'g', 'დ': 'd', 'ე': 'e', 'ვ': 'v', 'ზ': 'z', 'თ': 't', 'ი': 'i', 'კ': 'k', 'ლ': 'l', 'მ': 'm', 'ნ': 'n', 'ო': 'o', 'პ': 'p', 'ჟ': 'j', 'რ': 'r', 'ს': 's', 'ტ': 't', 'უ': 'u', 'ფ': 'f', @@ -107,7 +106,7 @@ 'წ': 'w', 'ჭ': 'ch', 'ხ': 'x', 'ჯ': 'j', 'ჰ': 'h' }; - var ALL_DOWNCODE_MAPS = [ + const ALL_DOWNCODE_MAPS = [ LATIN_MAP, LATIN_SYMBOLS_MAP, GREEK_MAP, @@ -126,27 +125,16 @@ GEORGIAN_MAP ]; - var Downcoder = { + const Downcoder = { 'Initialize': function() { if (Downcoder.map) { // already made return; } Downcoder.map = {}; - Downcoder.chars = []; - for (var i = 0; i < ALL_DOWNCODE_MAPS.length; i++) { - var lookup = ALL_DOWNCODE_MAPS[i]; - for (var c in lookup) { - if (lookup.hasOwnProperty(c)) { - Downcoder.map[c] = lookup[c]; - } - } + for (const lookup of ALL_DOWNCODE_MAPS) { + Object.assign(Downcoder.map, lookup); } - for (var k in Downcoder.map) { - if (Downcoder.map.hasOwnProperty(k)) { - Downcoder.chars.push(k); - } - } - Downcoder.regex = new RegExp(Downcoder.chars.join('|'), 'g'); + Downcoder.regex = new RegExp(Object.keys(Downcoder.map).join('|'), 'g'); } }; @@ -160,23 +148,10 @@ function URLify(s, num_chars, allowUnicode) { // changes, e.g., "Petty theft" to "petty-theft" - // remove all these words from the string before urlifying if (!allowUnicode) { s = downcode(s); } - var hasUnicodeChars = /[^\u0000-\u007f]/.test(s); - // Remove English words only if the string contains ASCII (English) - // characters. - if (!hasUnicodeChars) { - var removeList = [ - "a", "an", "as", "at", "before", "but", "by", "for", "from", - "is", "in", "into", "like", "of", "off", "on", "onto", "per", - "since", "than", "the", "this", "that", "to", "up", "via", - "with" - ]; - var r = new RegExp('\\b(' + removeList.join('|') + ')\\b', 'gi'); - s = s.replace(r, ''); - } + s = s.toLowerCase(); // convert to lowercase // if downcode doesn't hit, the char will be stripped here if (allowUnicode) { // Keep Unicode letters including both lowercase and uppercase @@ -189,7 +164,7 @@ s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens s = s.substring(0, num_chars); // trim to first num_chars chars s = s.replace(/-+$/g, ''); // trim any trailing hyphens - return s.toLowerCase(); // convert to lowercase + return s; } window.URLify = URLify; -})(); +} diff --git a/src/statics/admin/js/vendor/jquery/LICENSE.txt b/src/statics/admin/js/vendor/jquery/LICENSE.txt index d930e62..e3dbacb 100644 --- a/src/statics/admin/js/vendor/jquery/LICENSE.txt +++ b/src/statics/admin/js/vendor/jquery/LICENSE.txt @@ -1,10 +1,4 @@ -Copyright jQuery Foundation and other contributors, https://jquery.org/ - -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/jquery/jquery - -==== +Copyright JS Foundation and other contributors, https://js.foundation/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/src/statics/admin/js/vendor/jquery/jquery.js b/src/statics/admin/js/vendor/jquery/jquery.js index 34a5703..5093733 100644 --- a/src/statics/admin/js/vendor/jquery/jquery.js +++ b/src/statics/admin/js/vendor/jquery/jquery.js @@ -1,5 +1,5 @@ /*! - * jQuery JavaScript Library v3.3.1 + * jQuery JavaScript Library v3.5.1 * https://jquery.com/ * * Includes Sizzle.js @@ -9,7 +9,7 @@ * Released under the MIT license * https://jquery.org/license * - * Date: 2018-01-20T17:24Z + * Date: 2020-05-04T22:49Z */ ( function( global, factory ) { @@ -47,13 +47,16 @@ var arr = []; -var document = window.document; - var getProto = Object.getPrototypeOf; var slice = arr.slice; -var concat = arr.concat; +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + var push = arr.push; @@ -86,25 +89,40 @@ var isWindow = function isWindow( obj ) { }; +var document = window.document; + var preservedScriptAttributes = { type: true, src: true, + nonce: true, noModule: true }; - function DOMEval( code, doc, node ) { + function DOMEval( code, node, doc ) { doc = doc || document; - var i, + var i, val, script = doc.createElement( "script" ); script.text = code; if ( node ) { for ( i in preservedScriptAttributes ) { - if ( node[ i ] ) { - script[ i ] = node[ i ]; + + // 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 ); } } } @@ -129,7 +147,7 @@ function toType( obj ) { var - version = "3.3.1", + version = "3.5.1", // Define a local copy of jQuery jQuery = function( selector, context ) { @@ -137,11 +155,7 @@ var // 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 ); - }, - - // Support: Android <=4.0 only - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + }; jQuery.fn = jQuery.prototype = { @@ -207,6 +221,18 @@ jQuery.fn = jQuery.prototype = { 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 ); @@ -258,7 +284,6 @@ jQuery.extend = jQuery.fn.extend = function() { // Extend the base object for ( name in options ) { - src = target[ name ]; copy = options[ name ]; // Prevent Object.prototype pollution @@ -270,14 +295,17 @@ jQuery.extend = jQuery.fn.extend = function() { // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject( copy ) || ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; - if ( copyIsArray ) { - copyIsArray = false; - clone = src && Array.isArray( src ) ? src : []; - + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; } else { - clone = src && jQuery.isPlainObject( src ) ? src : {}; + clone = src; } + copyIsArray = false; // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); @@ -330,9 +358,6 @@ jQuery.extend( { }, isEmptyObject: function( obj ) { - - /* eslint-disable no-unused-vars */ - // See https://github.com/eslint/eslint/issues/6125 var name; for ( name in obj ) { @@ -341,9 +366,10 @@ jQuery.extend( { return true; }, - // Evaluates a script in a global context - globalEval: function( code ) { - DOMEval( code ); + // 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 ) { @@ -367,13 +393,6 @@ jQuery.extend( { return obj; }, - // Support: Android <=4.0 only - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - // results is for internal usage only makeArray: function( arr, results ) { var ret = results || []; @@ -460,7 +479,7 @@ jQuery.extend( { } // Flatten any nested arrays - return concat.apply( [], ret ); + return flat( ret ); }, // A global GUID counter for objects @@ -477,7 +496,7 @@ if ( typeof Symbol === "function" ) { // Populate the class2type map jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( i, name ) { +function( _i, name ) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); } ); @@ -499,17 +518,16 @@ function isArrayLike( obj ) { } var Sizzle = /*! - * Sizzle CSS Selector Engine v2.3.3 + * Sizzle CSS Selector Engine v2.3.5 * https://sizzlejs.com/ * - * Copyright jQuery Foundation and other contributors + * Copyright JS Foundation and other contributors * Released under the MIT license - * http://jquery.org/license + * https://js.foundation/ * - * Date: 2016-08-08 + * Date: 2020-03-14 */ -(function( window ) { - +( function( window ) { var i, support, Expr, @@ -540,6 +558,7 @@ var i, classCache = createCache(), tokenCache = createCache(), compilerCache = createCache(), + nonnativeSelectorCache = createCache(), sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; @@ -548,61 +567,71 @@ var i, }, // Instance methods - hasOwn = ({}).hasOwnProperty, + hasOwn = ( {} ).hasOwnProperty, arr = [], pop = arr.pop, - push_native = arr.push, + 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 ) { + 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", + 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]", - // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + // 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 + - "*\\]", + + // "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" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), rpseudo = new RegExp( pseudos ), ridentifier = new RegExp( "^" + identifier + "$" ), @@ -613,16 +642,19 @@ var i, "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" ), + "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" ) + "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, @@ -635,18 +667,21 @@ var i, // CSS escapes // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : + 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 ? - // BMP codepoint String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); }, @@ -662,7 +697,8 @@ var i, } // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; } // Other potentially-special ASCII characters get backslash-escaped @@ -677,9 +713,9 @@ var i, setDocument(); }, - disabledAncestor = addCombinator( + inDisabledFieldset = addCombinator( function( elem ) { - return elem.disabled === true && ("form" in elem || "label" in elem); + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; }, { dir: "parentNode", next: "legend" } ); @@ -687,18 +723,20 @@ var i, // Optimize for push.apply( _, NodeList ) try { push.apply( - (arr = slice.call( preferredDoc.childNodes )), + ( 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 ) { - push_native.apply( target, slice.call(els) ); + pushNative.apply( target, slice.call( els ) ); } : // Support: IE<9 @@ -706,8 +744,9 @@ try { function( target, els ) { var j = target.length, i = 0; + // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} + while ( ( target[ j++ ] = els[ i++ ] ) ) {} target.length = j - 1; } }; @@ -731,24 +770,21 @@ function Sizzle( selector, context, results, seed ) { // Try to shortcut find operations (as opposed to filters) in HTML documents if ( !seed ) { - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } + 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 )) ) { + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { // ID selector - if ( (m = match[1]) ) { + if ( ( m = match[ 1 ] ) ) { // Document context if ( nodeType === 9 ) { - if ( (elem = context.getElementById( m )) ) { + if ( ( elem = context.getElementById( m ) ) ) { // Support: IE, Opera, Webkit // TODO: identify versions @@ -767,7 +803,7 @@ function Sizzle( selector, context, results, seed ) { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID - if ( newContext && (elem = newContext.getElementById( m )) && + if ( newContext && ( elem = newContext.getElementById( m ) ) && contains( context, elem ) && elem.id === m ) { @@ -777,12 +813,12 @@ function Sizzle( selector, context, results, seed ) { } // Type selector - } else if ( match[2] ) { + } else if ( match[ 2 ] ) { push.apply( results, context.getElementsByTagName( selector ) ); return results; // Class selector - } else if ( (m = match[3]) && support.getElementsByClassName && + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && context.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); @@ -792,50 +828,62 @@ function Sizzle( selector, context, results, seed ) { // Take advantage of querySelectorAll if ( support.qsa && - !compilerCache[ selector + " " ] && - (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && - if ( nodeType !== 1 ) { - newContext = context; - newSelector = selector; - - // qSA looks outside Element context, which is not what we want - // Thanks to Andrew Dupont for this workaround technique - // Support: IE <=8 + // Support: IE 8 only // Exclude object elements - } else if ( context.nodeName.toLowerCase() !== "object" ) { + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { - // 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) ); + 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 ) || rcombinators.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 + " " + toSelector( groups[i] ); + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); } newSelector = groups.join( "," ); - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; } - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); } } } @@ -856,12 +904,14 @@ 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[ key + " " ] = value ); } return cache; } @@ -880,17 +930,19 @@ function markFunction( fn ) { * @param {Function} fn Passed the created element and returns a boolean result */ function assert( fn ) { - var el = document.createElement("fieldset"); + var el = document.createElement( "fieldset" ); try { return !!fn( el ); - } catch (e) { + } catch ( e ) { return false; } finally { + // Remove from its parent by default if ( el.parentNode ) { el.parentNode.removeChild( el ); } + // release memory in IE el = null; } @@ -902,11 +954,11 @@ function assert( fn ) { * @param {Function} handler The method that will be applied */ function addHandle( attrs, handler ) { - var arr = attrs.split("|"), + var arr = attrs.split( "|" ), i = arr.length; while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; + Expr.attrHandle[ arr[ i ] ] = handler; } } @@ -928,7 +980,7 @@ function siblingCheck( a, b ) { // Check if b follows a if ( cur ) { - while ( (cur = cur.nextSibling) ) { + while ( ( cur = cur.nextSibling ) ) { if ( cur === b ) { return -1; } @@ -956,7 +1008,7 @@ function createInputPseudo( type ) { function createButtonPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; + return ( name === "input" || name === "button" ) && elem.type === type; }; } @@ -999,7 +1051,7 @@ function createDisabledPseudo( disabled ) { // Where there is no isDisabled, check manually /* jshint -W018 */ elem.isDisabled !== !disabled && - disabledAncestor( elem ) === disabled; + inDisabledFieldset( elem ) === disabled; } return elem.disabled === disabled; @@ -1021,21 +1073,21 @@ function createDisabledPseudo( disabled ) { * @param {Function} fn */ function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { + return markFunction( function( argument ) { argument = +argument; - return markFunction(function( seed, matches ) { + 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]); + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); } } - }); - }); + } ); + } ); } /** @@ -1056,10 +1108,13 @@ support = Sizzle.support = {}; * @returns {Boolean} True iff elem is a non-HTML XML node */ isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; + var namespace = elem.namespaceURI, + docElem = ( 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" ); }; /** @@ -1072,7 +1127,11 @@ setDocument = Sizzle.setDocument = function( node ) { doc = node ? node.ownerDocument || node : preferredDoc; // Return early if doc is invalid or already selected - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + // 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; } @@ -1081,10 +1140,14 @@ setDocument = Sizzle.setDocument = function( node ) { docElem = document.documentElement; documentIsHTML = !isXML( document ); - // Support: IE 9-11, Edge + // Support: IE 9 - 11+, Edge 12 - 18+ // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - if ( preferredDoc !== document && - (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + // 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 ) { @@ -1096,25 +1159,36 @@ setDocument = Sizzle.setDocument = function( node ) { } } + // 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; + } ); + /* Attributes ---------------------------------------------------------------------- */ // Support: IE<8 // Verify that getAttribute really returns attributes and not properties // (excepting IE8 booleans) - support.attributes = assert(function( el ) { + support.attributes = assert( function( el ) { el.className = "i"; - return !el.getAttribute("className"); - }); + 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.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); // Support: IE<9 support.getElementsByClassName = rnative.test( document.getElementsByClassName ); @@ -1123,38 +1197,38 @@ setDocument = Sizzle.setDocument = function( node ) { // 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 ) { + 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 ) { + Expr.filter[ "ID" ] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { - return elem.getAttribute("id") === attrId; + return elem.getAttribute( "id" ) === attrId; }; }; - Expr.find["ID"] = function( id, context ) { + 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 ) { + Expr.filter[ "ID" ] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode("id"); + 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 ) { + Expr.find[ "ID" ] = function( id, context ) { if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var node, i, elems, elem = context.getElementById( id ); @@ -1162,7 +1236,7 @@ setDocument = Sizzle.setDocument = function( node ) { if ( elem ) { // Verify the id attribute - node = elem.getAttributeNode("id"); + node = elem.getAttributeNode( "id" ); if ( node && node.value === id ) { return [ elem ]; } @@ -1170,8 +1244,8 @@ setDocument = Sizzle.setDocument = function( node ) { // Fall back on getElementsByName elems = context.getElementsByName( id ); i = 0; - while ( (elem = elems[i++]) ) { - node = elem.getAttributeNode("id"); + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); if ( node && node.value === id ) { return [ elem ]; } @@ -1184,7 +1258,7 @@ setDocument = Sizzle.setDocument = function( node ) { } // Tag - Expr.find["TAG"] = support.getElementsByTagName ? + Expr.find[ "TAG" ] = support.getElementsByTagName ? function( tag, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( tag ); @@ -1199,12 +1273,13 @@ setDocument = Sizzle.setDocument = function( node ) { 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++]) ) { + while ( ( elem = results[ i++ ] ) ) { if ( elem.nodeType === 1 ) { tmp.push( elem ); } @@ -1216,7 +1291,7 @@ setDocument = Sizzle.setDocument = function( node ) { }; // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { return context.getElementsByClassName( className ); } @@ -1237,10 +1312,14 @@ setDocument = Sizzle.setDocument = function( node ) { // See https://bugs.jquery.com/ticket/13378 rbuggyQSA = []; - if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + // Build QSA regex // Regex strategy adopted from Diego Perini - assert(function( el ) { + 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, @@ -1254,78 +1333,98 @@ setDocument = Sizzle.setDocument = function( node ) { // 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 ) { + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); } // Support: IE8 // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll("[selected]").length ) { + 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("~="); + 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"); + 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(".#.+[+~]"); + rbuggyQSA.push( ".#.+[+~]" ); } - }); - assert(function( el ) { + // 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"); + 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 ) { + 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 ) { + 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 ) { + 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(",.*:"); - }); + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); } - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { - assert(function( el ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9) support.disconnectedMatch = matches.call( el, "*" ); @@ -1334,11 +1433,11 @@ setDocument = Sizzle.setDocument = function( node ) { // Gecko does not error, returns false instead matches.call( el, "[s!='']:x" ); rbuggyMatches.push( "!=", pseudos ); - }); + } ); } - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); /* Contains ---------------------------------------------------------------------- */ @@ -1355,11 +1454,11 @@ setDocument = Sizzle.setDocument = function( node ) { adown.contains ? adown.contains( bup ) : a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); + ) ); } : function( a, b ) { if ( b ) { - while ( (b = b.parentNode) ) { + while ( ( b = b.parentNode ) ) { if ( b === a ) { return true; } @@ -1388,7 +1487,11 @@ setDocument = Sizzle.setDocument = function( node ) { } // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + // 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 + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? a.compareDocumentPosition( b ) : // Otherwise we know they are disconnected @@ -1396,13 +1499,24 @@ setDocument = Sizzle.setDocument = function( node ) { // Disconnected nodes if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { // Choose the first element that is related to our preferred document - if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + // 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 ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { return -1; } - if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + + // 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 ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { return 1; } @@ -1415,6 +1529,7 @@ setDocument = Sizzle.setDocument = function( node ) { return compare & 4 ? -1 : 1; } : function( a, b ) { + // Exit early if the nodes are identical if ( a === b ) { hasDuplicate = true; @@ -1430,8 +1545,14 @@ setDocument = Sizzle.setDocument = function( node ) { // Parentless nodes are either documents or disconnected if ( !aup || !bup ) { - return a === document ? -1 : - b === document ? 1 : + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ aup ? -1 : bup ? 1 : sortInput ? @@ -1445,26 +1566,32 @@ setDocument = Sizzle.setDocument = function( node ) { // Otherwise we need full lists of their ancestors for comparison cur = a; - while ( (cur = cur.parentNode) ) { + while ( ( cur = cur.parentNode ) ) { ap.unshift( cur ); } cur = b; - while ( (cur = cur.parentNode) ) { + while ( ( cur = cur.parentNode ) ) { bp.unshift( cur ); } // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { + while ( ap[ i ] === bp[ i ] ) { i++; } return i ? + // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : + siblingCheck( ap[ i ], bp[ i ] ) : // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ 0; }; @@ -1476,16 +1603,10 @@ Sizzle.matches = function( expr, elements ) { }; Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); + setDocument( elem ); if ( support.matchesSelector && documentIsHTML && - !compilerCache[ expr + " " ] && + !nonnativeSelectorCache[ expr + " " ] && ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { @@ -1494,32 +1615,46 @@ Sizzle.matchesSelector = function( elem, expr ) { // IE 9's matchesSelector returns false on disconnected nodes if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { return ret; } - } catch (e) {} + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } } return Sizzle( expr, document, null, [ elem ] ).length > 0; }; Sizzle.contains = function( context, elem ) { + // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { + // 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 ( ( context.ownerDocument || context ) != document ) { setDocument( context ); } return contains( context, elem ); }; Sizzle.attr = function( elem, name ) { + // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { + // 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 ( ( elem.ownerDocument || elem ) != document ) { setDocument( elem ); } var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? fn( elem, name, !documentIsHTML ) : @@ -1529,13 +1664,13 @@ Sizzle.attr = function( elem, name ) { val : support.attributes || !documentIsHTML ? elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? + ( val = elem.getAttributeNode( name ) ) && val.specified ? val.value : null; }; Sizzle.escape = function( sel ) { - return (sel + "").replace( rcssescape, fcssescape ); + return ( sel + "" ).replace( rcssescape, fcssescape ); }; Sizzle.error = function( msg ) { @@ -1558,7 +1693,7 @@ Sizzle.uniqueSort = function( results ) { results.sort( sortOrder ); if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { + while ( ( elem = results[ i++ ] ) ) { if ( elem === results[ i ] ) { j = duplicates.push( i ); } @@ -1586,17 +1721,21 @@ getText = Sizzle.getText = function( elem ) { nodeType = elem.nodeType; if ( !nodeType ) { + // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { + while ( ( node = elem[ i++ ] ) ) { + // Do not traverse comment nodes ret += getText( node ); } } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements // innerText usage removed for consistency of new lines (jQuery #11153) if ( typeof elem.textContent === "string" ) { return elem.textContent; } else { + // Traverse its children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { ret += getText( elem ); @@ -1605,6 +1744,7 @@ getText = Sizzle.getText = function( elem ) { } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } + // Do not include comment or processing instruction nodes return ret; @@ -1632,19 +1772,21 @@ Expr = Sizzle.selectors = { preFilter: { "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; } return match.slice( 0, 4 ); }, "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] 1 type (only|nth|...) 2 what (child|of-type) @@ -1655,22 +1797,25 @@ Expr = Sizzle.selectors = { 7 sign of y-component 8 y of y-component */ - match[1] = match[1].toLowerCase(); + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { - if ( match[1].slice( 0, 3 ) === "nth" ) { // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); } // numeric x and y parameters for Expr.filter.CHILD // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); } return match; @@ -1678,26 +1823,28 @@ Expr = Sizzle.selectors = { "PSEUDO": function( match ) { var excess, - unquoted = !match[6] && match[2]; + unquoted = !match[ 6 ] && match[ 2 ]; - if ( matchExpr["CHILD"].test( match[0] ) ) { + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { return null; } // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; // Strip excess characters from unquoted arguments } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && + ( excess = tokenize( unquoted, true ) ) && + // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); } // Return only captures needed by the pseudo filter method (type and argument) @@ -1710,7 +1857,9 @@ Expr = Sizzle.selectors = { "TAG": function( nodeNameSelector ) { var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); return nodeNameSelector === "*" ? - function() { return true; } : + function() { + return true; + } : function( elem ) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; }; @@ -1720,10 +1869,16 @@ Expr = Sizzle.selectors = { var pattern = classCache[ className + " " ]; return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); - }); + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); }, "ATTR": function( name, operator, check ) { @@ -1739,6 +1894,8 @@ Expr = Sizzle.selectors = { result += ""; + /* eslint-disable max-len */ + return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf( check ) === 0 : @@ -1747,10 +1904,12 @@ Expr = Sizzle.selectors = { operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : false; + /* eslint-enable max-len */ + }; }, - "CHILD": function( type, what, argument, first, last ) { + "CHILD": function( type, what, _argument, first, last ) { var simple = type.slice( 0, 3 ) !== "nth", forward = type.slice( -4 ) !== "last", ofType = what === "of-type"; @@ -1762,7 +1921,7 @@ Expr = Sizzle.selectors = { return !!elem.parentNode; } : - function( elem, context, xml ) { + function( elem, _context, xml ) { var cache, uniqueCache, outerCache, node, nodeIndex, start, dir = simple !== forward ? "nextSibling" : "previousSibling", parent = elem.parentNode, @@ -1776,7 +1935,7 @@ Expr = Sizzle.selectors = { if ( simple ) { while ( dir ) { node = elem; - while ( (node = node[ dir ]) ) { + while ( ( node = node[ dir ] ) ) { if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { @@ -1784,6 +1943,7 @@ Expr = Sizzle.selectors = { return false; } } + // Reverse direction for :only-* (if we haven't yet done so) start = dir = type === "only" && !start && "nextSibling"; } @@ -1799,22 +1959,22 @@ Expr = Sizzle.selectors = { // ...in a gzip-friendly way node = parent; - outerCache = node[ expando ] || (node[ expando ] = {}); + outerCache = node[ expando ] || ( node[ expando ] = {} ); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); + ( outerCache[ node.uniqueID ] = {} ); cache = uniqueCache[ type ] || []; nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; diff = nodeIndex && cache[ 2 ]; node = nodeIndex && parent.childNodes[ nodeIndex ]; - while ( (node = ++nodeIndex && node && node[ dir ] || + while ( ( node = ++nodeIndex && node && node[ dir ] || // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { + ( diff = nodeIndex = 0 ) || start.pop() ) ) { // When found, cache indexes on `parent` and break if ( node.nodeType === 1 && ++diff && node === elem ) { @@ -1824,16 +1984,18 @@ Expr = Sizzle.selectors = { } } else { + // Use previously-cached element index if available if ( useCache ) { + // ...in a gzip-friendly way node = elem; - outerCache = node[ expando ] || (node[ expando ] = {}); + outerCache = node[ expando ] || ( node[ expando ] = {} ); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); + ( outerCache[ node.uniqueID ] = {} ); cache = uniqueCache[ type ] || []; nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; @@ -1843,9 +2005,10 @@ Expr = Sizzle.selectors = { // xml :nth-child(...) // or :nth-last-child(...) or :nth(-last)?-of-type(...) if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { if ( ( ofType ? node.nodeName.toLowerCase() === name : @@ -1854,12 +2017,13 @@ Expr = Sizzle.selectors = { // Cache the index of each encountered element if ( useCache ) { - outerCache = node[ expando ] || (node[ expando ] = {}); + outerCache = node[ expando ] || + ( node[ expando ] = {} ); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); + ( outerCache[ node.uniqueID ] = {} ); uniqueCache[ type ] = [ dirruns, diff ]; } @@ -1880,6 +2044,7 @@ Expr = Sizzle.selectors = { }, "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive // http://www.w3.org/TR/selectors/#pseudo-classes // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters @@ -1899,15 +2064,15 @@ Expr = Sizzle.selectors = { if ( fn.length > 1 ) { args = [ pseudo, pseudo, "", argument ]; return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { + markFunction( function( seed, matches ) { var idx, matched = fn( seed, argument ), i = matched.length; while ( i-- ) { - idx = indexOf( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); } - }) : + } ) : function( elem ) { return fn( elem, 0, args ); }; @@ -1918,8 +2083,10 @@ Expr = Sizzle.selectors = { }, pseudos: { + // Potentially complex pseudos - "not": markFunction(function( selector ) { + "not": markFunction( function( selector ) { + // Trim the selector passed to compile // to avoid treating leading and trailing // spaces as combinators @@ -1928,39 +2095,40 @@ Expr = Sizzle.selectors = { matcher = compile( selector.replace( rtrim, "$1" ) ); return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { + markFunction( function( seed, matches, _context, xml ) { var elem, unmatched = matcher( seed, null, xml, [] ), i = seed.length; // Match elements unmatched by `matcher` while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); } } - }) : - function( elem, context, xml ) { - input[0] = elem; + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; matcher( input, null, xml, results ); + // Don't keep the element (issue #299) - input[0] = null; + input[ 0 ] = null; return !results.pop(); }; - }), + } ), - "has": markFunction(function( selector ) { + "has": markFunction( function( selector ) { return function( elem ) { return Sizzle( selector, elem ).length > 0; }; - }), + } ), - "contains": markFunction(function( text ) { + "contains": markFunction( function( text ) { text = text.replace( runescape, funescape ); return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; }; - }), + } ), // "Whether an element is represented by a :lang() selector // is based solely on the element's language value @@ -1970,25 +2138,26 @@ Expr = Sizzle.selectors = { // The identifier C does not have to be a valid language name." // http://www.w3.org/TR/selectors/#lang-pseudo "lang": markFunction( function( lang ) { + // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { + if ( !ridentifier.test( lang || "" ) ) { Sizzle.error( "unsupported lang: " + lang ); } lang = lang.replace( runescape, funescape ).toLowerCase(); return function( elem ) { var elemLang; do { - if ( (elemLang = documentIsHTML ? + if ( ( elemLang = documentIsHTML ? elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { elemLang = elemLang.toLowerCase(); return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); return false; }; - }), + } ), // Miscellaneous "target": function( elem ) { @@ -2001,7 +2170,9 @@ Expr = Sizzle.selectors = { }, "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); }, // Boolean properties @@ -2009,16 +2180,20 @@ Expr = Sizzle.selectors = { "disabled": createDisabledPseudo( true ), "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); }, "selected": function( elem ) { + // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions elem.parentNode.selectedIndex; } @@ -2027,6 +2202,7 @@ Expr = Sizzle.selectors = { // Contents "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), // but not by others (comment: 8; processing instruction: 7; etc.) @@ -2040,7 +2216,7 @@ Expr = Sizzle.selectors = { }, "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); + return !Expr.pseudos[ "empty" ]( elem ); }, // Element/input types @@ -2064,57 +2240,62 @@ Expr = Sizzle.selectors = { // Support: IE<8 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); }, // Position-in-collection - "first": createPositionalPseudo(function() { + "first": createPositionalPseudo( function() { return [ 0 ]; - }), + } ), - "last": createPositionalPseudo(function( matchIndexes, length ) { + "last": createPositionalPseudo( function( _matchIndexes, length ) { return [ length - 1 ]; - }), + } ), - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { return [ argument < 0 ? argument + length : argument ]; - }), + } ), - "even": createPositionalPseudo(function( matchIndexes, length ) { + "even": createPositionalPseudo( function( matchIndexes, length ) { var i = 0; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; - }), + } ), - "odd": createPositionalPseudo(function( matchIndexes, length ) { + "odd": createPositionalPseudo( function( matchIndexes, length ) { var i = 1; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; - }), + } ), - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; for ( ; --i >= 0; ) { matchIndexes.push( i ); } return matchIndexes; - }), + } ), - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; ++i < length; ) { matchIndexes.push( i ); } return matchIndexes; - }) + } ) } }; -Expr.pseudos["nth"] = Expr.pseudos["eq"]; +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; // Add button/input type pseudos for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { @@ -2145,37 +2326,39 @@ tokenize = Sizzle.tokenize = function( selector, parseOnly ) { while ( soFar ) { // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { if ( match ) { + // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; + soFar = soFar.slice( match[ 0 ].length ) || soFar; } - groups.push( (tokens = []) ); + groups.push( ( tokens = [] ) ); } matched = false; // Combinators - if ( (match = rcombinators.exec( soFar )) ) { + if ( ( match = rcombinators.exec( soFar ) ) ) { matched = match.shift(); - tokens.push({ + tokens.push( { value: matched, + // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); + type: match[ 0 ].replace( rtrim, " " ) + } ); soFar = soFar.slice( matched.length ); } // Filters for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { matched = match.shift(); - tokens.push({ + tokens.push( { value: matched, type: type, matches: match - }); + } ); soFar = soFar.slice( matched.length ); } } @@ -2192,6 +2375,7 @@ tokenize = Sizzle.tokenize = function( selector, parseOnly ) { soFar.length : soFar ? Sizzle.error( selector ) : + // Cache the tokens tokenCache( selector, groups ).slice( 0 ); }; @@ -2201,7 +2385,7 @@ function toSelector( tokens ) { len = tokens.length, selector = ""; for ( ; i < len; i++ ) { - selector += tokens[i].value; + selector += tokens[ i ].value; } return selector; } @@ -2214,9 +2398,10 @@ function addCombinator( matcher, combinator, base ) { doneName = done++; return combinator.first ? + // Check against closest ancestor/preceding element function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { + while ( ( elem = elem[ dir ] ) ) { if ( elem.nodeType === 1 || checkNonElements ) { return matcher( elem, context, xml ); } @@ -2231,7 +2416,7 @@ function addCombinator( matcher, combinator, base ) { // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching if ( xml ) { - while ( (elem = elem[ dir ]) ) { + while ( ( elem = elem[ dir ] ) ) { if ( elem.nodeType === 1 || checkNonElements ) { if ( matcher( elem, context, xml ) ) { return true; @@ -2239,27 +2424,29 @@ function addCombinator( matcher, combinator, base ) { } } } else { - while ( (elem = elem[ dir ]) ) { + while ( ( elem = elem[ dir ] ) ) { if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); if ( skip && skip === elem.nodeName.toLowerCase() ) { elem = elem[ dir ] || elem; - } else if ( (oldCache = uniqueCache[ key ]) && + } else if ( ( oldCache = uniqueCache[ key ] ) && oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); + return ( newCache[ 2 ] = oldCache[ 2 ] ); } else { + // Reuse newcache so results back-propagate to previous elements uniqueCache[ key ] = newCache; // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { return true; } } @@ -2275,20 +2462,20 @@ function elementMatcher( matchers ) { function( elem, context, xml ) { var i = matchers.length; while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { + if ( !matchers[ i ]( elem, context, xml ) ) { return false; } } return true; } : - matchers[0]; + matchers[ 0 ]; } function multipleContexts( selector, contexts, results ) { var i = 0, len = contexts.length; for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); + Sizzle( selector, contexts[ i ], results ); } return results; } @@ -2301,7 +2488,7 @@ function condense( unmatched, map, filter, context, xml ) { mapped = map != null; for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { + if ( ( elem = unmatched[ i ] ) ) { if ( !filter || filter( elem, context, xml ) ) { newUnmatched.push( elem ); if ( mapped ) { @@ -2321,14 +2508,18 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS if ( postFinder && !postFinder[ expando ] ) { postFinder = setMatcher( postFinder, postSelector ); } - return markFunction(function( seed, results, context, xml ) { + return markFunction( function( seed, results, context, xml ) { var temp, i, elem, preMap = [], postMap = [], preexisting = results.length, // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), // Prefilter to get matcher input, preserving a map for seed-results synchronization matcherIn = preFilter && ( seed || !selector ) ? @@ -2336,6 +2527,7 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS elems, matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, postFinder || ( seed ? preFilter : preexisting || postFilter ) ? @@ -2359,8 +2551,8 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS // Un-match failing elements by moving them back to matcherIn i = temp.length; while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); } } } @@ -2368,25 +2560,27 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS if ( seed ) { if ( postFinder || preFilter ) { if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts temp = []; i = matcherOut.length; while ( i-- ) { - if ( (elem = matcherOut[i]) ) { + if ( ( elem = matcherOut[ i ] ) ) { + // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); + temp.push( ( matcherIn[ i ] = elem ) ); } } - postFinder( null, (matcherOut = []), temp, xml ); + postFinder( null, ( matcherOut = [] ), temp, xml ); } // Move matched elements from seed to results to keep them synchronized i = matcherOut.length; while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { - seed[temp] = !(results[temp] = elem); + seed[ temp ] = !( results[ temp ] = elem ); } } } @@ -2404,14 +2598,14 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS push.apply( results, matcherOut ); } } - }); + } ); } function matcherFromTokens( tokens ) { var checkContext, matcher, j, len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], i = leadingRelative ? 1 : 0, // The foundational matcher ensures that elements are reachable from top-level context(s) @@ -2423,38 +2617,43 @@ function matcherFromTokens( tokens ) { }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? + ( checkContext = context ).nodeType ? matchContext( elem, context, xml ) : matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) checkContext = null; return ret; } ]; for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); // Return special upon seeing a positional matcher if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling j = ++i; for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { + if ( Expr.relative[ tokens[ j ].type ] ) { break; } } return setMatcher( i > 1 && elementMatcher( matchers ), i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) ).replace( rtrim, "$1" ), matcher, i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), j < len && toSelector( tokens ) ); } @@ -2475,28 +2674,40 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { unmatched = seed && [], setMatched = [], contextBackup = outermostContext, + // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), len = elems.length; if ( outermost ) { - outermostContext = context === document || context || outermost; + + // 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 + outermostContext = context == document || context || outermost; } // Add elements passing elementMatchers directly to results // Support: IE<9, Safari // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { if ( byElement && elem ) { j = 0; - if ( !context && elem.ownerDocument !== document ) { + + // 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 ( !context && elem.ownerDocument != document ) { setDocument( elem ); xml = !documentIsHTML; } - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context || document, xml) ) { + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { results.push( elem ); break; } @@ -2508,8 +2719,9 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { // Track unmatched elements for set filters if ( bySet ) { + // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { + if ( ( elem = !matcher && elem ) ) { matchedCount--; } @@ -2533,16 +2745,17 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { // numerically zero. if ( bySet && i !== matchedCount ) { j = 0; - while ( (matcher = setMatchers[j++]) ) { + while ( ( matcher = setMatchers[ j++ ] ) ) { matcher( unmatched, setMatched, context, xml ); } if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting if ( matchedCount > 0 ) { while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); } } } @@ -2583,13 +2796,14 @@ compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { cached = compilerCache[ selector + " " ]; if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element if ( !match ) { match = tokenize( selector ); } i = match.length; while ( i-- ) { - cached = matcherFromTokens( match[i] ); + cached = matcherFromTokens( match[ i ] ); if ( cached[ expando ] ) { setMatchers.push( cached ); } else { @@ -2598,7 +2812,10 @@ compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { } // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); // Save selector and tokenization cached.selector = selector; @@ -2618,7 +2835,7 @@ compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { select = Sizzle.select = function( selector, context, results, seed ) { var i, tokens, token, type, find, compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); results = results || []; @@ -2627,11 +2844,12 @@ select = Sizzle.select = function( selector, context, results, seed ) { if ( match.length === 1 ) { // Reduce context if the leading compound selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; if ( !context ) { return results; @@ -2644,20 +2862,22 @@ select = Sizzle.select = function( selector, context, results, seed ) { } // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; while ( i-- ) { - token = tokens[i]; + token = tokens[ i ]; // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { + if ( Expr.relative[ ( type = token.type ) ] ) { break; } - if ( (find = Expr.find[ type ]) ) { + if ( ( find = Expr.find[ type ] ) ) { + // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { // If seed is empty or no tokens remain, we can return early tokens.splice( i, 1 ); @@ -2688,7 +2908,7 @@ select = Sizzle.select = function( selector, context, results, seed ) { // One-time assignments // Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; // Support: Chrome 14-35+ // Always assume duplicates if they aren't passed to the comparison function @@ -2699,58 +2919,59 @@ setDocument(); // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) // Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( el ) { +support.sortDetached = assert( function( el ) { + // Should return 1, but returns 4 (following) - return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; -}); + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); // Support: IE<8 // Prevent attribute/property "interpolation" // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( el ) { +if ( !assert( function( el ) { el.innerHTML = ""; - return el.firstChild.getAttribute("href") === "#" ; -}) ) { + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { addHandle( "type|href|height|width", function( elem, name, isXML ) { if ( !isXML ) { return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); } - }); + } ); } // Support: IE<9 // Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( el ) { +if ( !support.attributes || !assert( function( el ) { el.innerHTML = ""; el.firstChild.setAttribute( "value", "" ); return el.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { return elem.defaultValue; } - }); + } ); } // Support: IE<9 // Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( el ) { - return el.getAttribute("disabled") == null; -}) ) { +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { addHandle( booleans, function( elem, name, isXML ) { var val; if ( !isXML ) { return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? + ( val = elem.getAttributeNode( name ) ) && val.specified ? val.value : - null; + null; } - }); + } ); } return Sizzle; -})( window ); +} )( window ); @@ -3119,7 +3340,7 @@ jQuery.each( { parents: function( elem ) { return dir( elem, "parentNode" ); }, - parentsUntil: function( elem, i, until ) { + parentsUntil: function( elem, _i, until ) { return dir( elem, "parentNode", until ); }, next: function( elem ) { @@ -3134,10 +3355,10 @@ jQuery.each( { prevAll: function( elem ) { return dir( elem, "previousSibling" ); }, - nextUntil: function( elem, i, until ) { + nextUntil: function( elem, _i, until ) { return dir( elem, "nextSibling", until ); }, - prevUntil: function( elem, i, until ) { + prevUntil: function( elem, _i, until ) { return dir( elem, "previousSibling", until ); }, siblings: function( elem ) { @@ -3147,18 +3368,24 @@ jQuery.each( { return siblings( elem.firstChild ); }, contents: function( elem ) { - if ( nodeName( elem, "iframe" ) ) { - return elem.contentDocument; - } + if ( elem.contentDocument != null && - // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only - // Treat the template element as a regular one in browsers that - // don't support it. - if ( nodeName( elem, "template" ) ) { - elem = elem.content || elem; - } + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { - return jQuery.merge( [], elem.childNodes ); + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { @@ -3490,7 +3717,7 @@ jQuery.extend( { var fns = arguments; return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { + jQuery.each( tuples, function( _i, tuple ) { // Map tuples (progress, done, fail) to arguments (done, fail, progress) var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; @@ -3943,7 +4170,7 @@ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { // ...except when executing function values } else { bulk = fn; - fn = function( elem, key, value ) { + fn = function( elem, _key, value ) { return bulk.call( jQuery( elem ), value ); }; } @@ -3978,7 +4205,7 @@ var rmsPrefix = /^-ms-/, rdashAlpha = /-([a-z])/g; // Used by camelCase as callback to replace() -function fcamelCase( all, letter ) { +function fcamelCase( _all, letter ) { return letter.toUpperCase(); } @@ -4467,6 +4694,26 @@ var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } var isHiddenWithinTree = function( elem, el ) { // isHiddenWithinTree might be called from jQuery#filter function; @@ -4481,32 +4728,11 @@ var isHiddenWithinTree = function( elem, el ) { // Support: Firefox <=43 - 45 // Disconnected elements can have computed display: none, so first confirm that elem is // in the document. - jQuery.contains( elem.ownerDocument, elem ) && + isAttached( elem ) && jQuery.css( elem, "display" ) === "none"; }; -var swap = function( elem, options, callback, args ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.apply( elem, args || [] ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - function adjustCSS( elem, prop, valueParts, tween ) { @@ -4523,7 +4749,8 @@ function adjustCSS( elem, prop, valueParts, tween ) { unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), // Starting value computation is required for potential unit mismatches - initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && rcssNum.exec( jQuery.css( elem, prop ) ); if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { @@ -4670,17 +4897,46 @@ jQuery.fn.extend( { } ); var rcheckableType = ( /^(?:checkbox|radio)$/i ); -var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); -// We have to close these tags to support XHTML (#13200) -var wrapMap = { +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; // Support: IE <=9 only - option: [ 1, "" ], + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { // XHTML parsers do not magically insert elements in the // same way that tag soup parsers do. So we cannot shorten @@ -4693,12 +4949,14 @@ var wrapMap = { _default: [ 0, "", "" ] }; -// Support: IE <=9 only -wrapMap.optgroup = wrapMap.option; - wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + function getAll( context, tag ) { @@ -4742,7 +5000,7 @@ function setGlobalEval( elems, refElements ) { var rhtml = /<|&#?\w+;/; function buildFragment( elems, context, scripts, selection, ignored ) { - var elem, tmp, tag, wrap, contains, j, + var elem, tmp, tag, wrap, attached, j, fragment = context.createDocumentFragment(), nodes = [], i = 0, @@ -4806,13 +5064,13 @@ function buildFragment( elems, context, scripts, selection, ignored ) { continue; } - contains = jQuery.contains( elem.ownerDocument, elem ); + attached = isAttached( elem ); // Append to fragment tmp = getAll( fragment.appendChild( elem ), "script" ); // Preserve script evaluation history - if ( contains ) { + if ( attached ) { setGlobalEval( tmp ); } @@ -4831,34 +5089,6 @@ function buildFragment( elems, context, scripts, selection, ignored ) { } -( function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Android <=4.1 only - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE <=11 only - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -} )(); -var documentElement = document.documentElement; - - - var rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, @@ -4872,8 +5102,19 @@ function returnFalse() { return false; } +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + // Support: IE <=9 only -// See #13393 for more info +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 function safeActiveElement() { try { return document.activeElement; @@ -4956,8 +5197,8 @@ jQuery.event = { special, handlers, type, namespaces, origType, elemData = dataPriv.get( elem ); - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { return; } @@ -4981,7 +5222,7 @@ jQuery.event = { // Init the element's event structure and main handler, if this is the first if ( !( events = elemData.events ) ) { - events = elemData.events = {}; + events = elemData.events = Object.create( null ); } if ( !( eventHandle = elemData.handle ) ) { eventHandle = elemData.handle = function( e ) { @@ -5139,12 +5380,15 @@ jQuery.event = { dispatch: function( nativeEvent ) { - // Make a writable jQuery.Event from the native event object - var event = jQuery.event.fix( nativeEvent ); - var i, j, ret, matched, handleObj, handlerQueue, args = new Array( arguments.length ), - handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event @@ -5173,9 +5417,10 @@ jQuery.event = { while ( ( handleObj = matched.handlers[ j++ ] ) && !event.isImmediatePropagationStopped() ) { - // Triggered event must either 1) have no namespace, or 2) have namespace(s) - // a subset or equal to those in the bound event (both can have no namespace). - if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { event.handleObj = handleObj; event.data = handleObj.data; @@ -5299,39 +5544,51 @@ jQuery.event = { // Prevent triggered image.load events from bubbling to window.load noBubble: true }, - focus: { - - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - this.focus(); - return false; - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, click: { - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { - this.click(); - return false; + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; }, - // For cross-browser consistency, don't fire native .click() on links + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack _default: function( event ) { - return nodeName( event.target, "a" ); + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); } }, @@ -5348,6 +5605,93 @@ jQuery.event = { } }; +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + jQuery.removeEvent = function( elem, type, handle ) { // This "if" is needed for plain objects @@ -5460,6 +5804,7 @@ jQuery.each( { shiftKey: true, view: true, "char": true, + code: true, charCode: true, key: true, keyCode: true, @@ -5506,6 +5851,33 @@ jQuery.each( { } }, jQuery.event.addProp ); +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + // Create mouseenter/leave events using mouseover/out and event-time checks // so that event delegation works in jQuery. // Do the same for pointerenter/pointerleave and pointerover/pointerout @@ -5591,13 +5963,6 @@ jQuery.fn.extend( { var - /* eslint-disable max-len */ - - // See https://github.com/eslint/eslint/issues/3229 - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, - - /* eslint-enable */ - // Support: IE <=10 - 11, Edge 12 - 13 only // In IE/Edge using regex groups here causes severe slowdowns. // See https://connect.microsoft.com/IE/feedback/details/1736512/ @@ -5634,7 +5999,7 @@ function restoreScript( elem ) { } function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + var i, l, type, pdataOld, udataOld, udataCur, events; if ( dest.nodeType !== 1 ) { return; @@ -5642,13 +6007,11 @@ function cloneCopyEvent( src, dest ) { // 1. Copy private data: events, handlers, etc. if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.access( src ); - pdataCur = dataPriv.set( dest, pdataOld ); + pdataOld = dataPriv.get( src ); events = pdataOld.events; if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; + dataPriv.remove( dest, "handle events" ); for ( type in events ) { for ( i = 0, l = events[ type ].length; i < l; i++ ) { @@ -5684,7 +6047,7 @@ function fixInput( src, dest ) { function domManip( collection, args, callback, ignored ) { // Flatten any nested arrays - args = concat.apply( [], args ); + args = flat( args ); var fragment, first, scripts, hasScripts, node, doc, i = 0, @@ -5756,11 +6119,13 @@ function domManip( collection, args, callback, ignored ) { if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); } } else { - DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); } } } @@ -5782,7 +6147,7 @@ function remove( elem, selector, keepData ) { } if ( node.parentNode ) { - if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + if ( keepData && isAttached( node ) ) { setGlobalEval( getAll( node, "script" ) ); } node.parentNode.removeChild( node ); @@ -5794,13 +6159,13 @@ function remove( elem, selector, keepData ) { jQuery.extend( { htmlPrefilter: function( html ) { - return html.replace( rxhtmlTag, "<$1>" ); + return html; }, clone: function( elem, dataAndEvents, deepDataAndEvents ) { var i, l, srcElements, destElements, clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); + inPage = isAttached( elem ); // Fix IE cloning issues if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && @@ -6056,6 +6421,27 @@ var getStyles = function( elem ) { return view.getComputedStyle( elem ); }; +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); @@ -6096,8 +6482,10 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); // Support: IE 9 only // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) div.style.position = "absolute"; - scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; documentElement.removeChild( container ); @@ -6111,7 +6499,7 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); } var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, - reliableMarginLeftVal, + reliableTrDimensionsVal, reliableMarginLeftVal, container = document.createElement( "div" ), div = document.createElement( "div" ); @@ -6146,6 +6534,35 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); scrollboxSize: function() { computeStyleTests(); return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; } } ); } )(); @@ -6168,7 +6585,7 @@ function curCSS( elem, name, computed ) { if ( computed ) { ret = computed.getPropertyValue( name ) || computed[ name ]; - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + if ( ret === "" && !isAttached( elem ) ) { ret = jQuery.style( elem, name ); } @@ -6224,30 +6641,13 @@ function addGetHookIf( conditionFn, hookFn ) { } -var +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; - // Swappable if display is none or starts with table - // except "table", "table-cell", or "table-caption" - // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rcustomProp = /^--/, - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }, - - cssPrefixes = [ "Webkit", "Moz", "ms" ], - emptyStyle = document.createElement( "div" ).style; - -// Return a css property mapped to a potentially vendor prefixed property +// Return a vendor-prefixed property or undefined function vendorPropName( name ) { - // Shortcut for names that are not vendor prefixed - if ( name in emptyStyle ) { - return name; - } - // Check for vendor prefixed names var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), i = cssPrefixes.length; @@ -6260,17 +6660,34 @@ function vendorPropName( name ) { } } -// Return a property mapped along what jQuery.cssProps suggests or to -// a vendor prefixed property. +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property function finalPropName( name ) { - var ret = jQuery.cssProps[ name ]; - if ( !ret ) { - ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; } - return ret; + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; } -function setPositiveNumber( elem, value, subtract ) { + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { // Any relative (+/-) values have already been // normalized at this point @@ -6341,7 +6758,10 @@ function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computed delta - extra - 0.5 - ) ); + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; } return delta; @@ -6351,9 +6771,16 @@ function getWidthOrHeight( elem, dimension, extra ) { // Start with computed style var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + val = curCSS( elem, dimension, styles ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - valueIsBorderBox = isBorderBox; + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); // Support: Firefox <=54 // Return a confounding non-pixel value or feign ignorance, as appropriate. @@ -6364,22 +6791,38 @@ function getWidthOrHeight( elem, dimension, extra ) { val = "auto"; } - // Check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = valueIsBorderBox && - ( support.boxSizingReliable() || val === elem.style[ dimension ] ); - // Fall back to offsetWidth/offsetHeight when value is "auto" - // This happens for inline elements with no explicit setting (gh-3571) - // Support: Android <=4.1 - 4.3 only - // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) - if ( val === "auto" || - !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || - val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || - // offsetWidth/offsetHeight provide border-box values - valueIsBorderBox = true; + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } } // Normalize "" and auto @@ -6425,6 +6868,13 @@ jQuery.extend( { "flexGrow": true, "flexShrink": true, "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, "lineHeight": true, "opacity": true, "order": true, @@ -6480,7 +6930,9 @@ jQuery.extend( { } // If a number was passed in, add the unit (except for certain CSS properties) - if ( type === "number" ) { + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); } @@ -6554,7 +7006,7 @@ jQuery.extend( { } } ); -jQuery.each( [ "height", "width" ], function( i, dimension ) { +jQuery.each( [ "height", "width" ], function( _i, dimension ) { jQuery.cssHooks[ dimension ] = { get: function( elem, computed, extra ) { if ( computed ) { @@ -6580,18 +7032,29 @@ jQuery.each( [ "height", "width" ], function( i, dimension ) { set: function( elem, value, extra ) { var matches, styles = getStyles( elem ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - subtract = extra && boxModelAdjustment( - elem, - dimension, - extra, - isBorderBox, - styles - ); + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; // Account for unreliable border-box dimensions by comparing offset* to computed and // faking a content-box to get border and padding (gh-3699) - if ( isBorderBox && support.scrollboxSize() === styles.position ) { + if ( isBorderBox && scrollboxSizeBuggy ) { subtract -= Math.ceil( elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - parseFloat( styles[ dimension ] ) - @@ -6759,9 +7222,9 @@ Tween.propHooks = { // Use .style if available and use plain properties where available. if ( jQuery.fx.step[ tween.prop ] ) { jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.nodeType === 1 && - ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || - jQuery.cssHooks[ tween.prop ] ) ) { + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); } else { tween.elem[ tween.prop ] = tween.now; @@ -7316,7 +7779,7 @@ jQuery.fn.extend( { clearQueue = type; type = undefined; } - if ( clearQueue && type !== false ) { + if ( clearQueue ) { this.queue( type || "fx", [] ); } @@ -7399,7 +7862,7 @@ jQuery.fn.extend( { } } ); -jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { var cssFn = jQuery.fn[ name ]; jQuery.fn[ name ] = function( speed, easing, callback ) { return speed == null || typeof speed === "boolean" ? @@ -7620,7 +8083,7 @@ boolHook = { } }; -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { var getter = attrHandle[ name ] || jQuery.find.attr; attrHandle[ name ] = function( elem, name, isXML ) { @@ -8244,7 +8707,9 @@ jQuery.extend( jQuery.event, { special.bindType || type; // jQuery handler - handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && dataPriv.get( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); @@ -8355,7 +8820,10 @@ if ( !support.focusin ) { jQuery.event.special[ fix ] = { setup: function() { - var doc = this.ownerDocument || this, + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, attaches = dataPriv.access( doc, fix ); if ( !attaches ) { @@ -8364,7 +8832,7 @@ if ( !support.focusin ) { dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); }, teardown: function() { - var doc = this.ownerDocument || this, + var doc = this.ownerDocument || this.document || this, attaches = dataPriv.access( doc, fix ) - 1; if ( !attaches ) { @@ -8380,7 +8848,7 @@ if ( !support.focusin ) { } var location = window.location; -var nonce = Date.now(); +var nonce = { guid: Date.now() }; var rquery = ( /\?/ ); @@ -8468,6 +8936,10 @@ jQuery.param = function( a, traditional ) { encodeURIComponent( value == null ? "" : value ); }; + if ( a == null ) { + return ""; + } + // If an array was passed in, assume that it is an array of form elements. if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { @@ -8508,7 +8980,7 @@ jQuery.fn.extend( { rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && ( this.checked || !rcheckableType.test( type ) ); } ) - .map( function( i, elem ) { + .map( function( _i, elem ) { var val = jQuery( this ).val(); if ( val == null ) { @@ -8970,12 +9442,14 @@ jQuery.extend( { if ( !responseHeaders ) { responseHeaders = {}; while ( ( match = rheaders.exec( responseHeadersString ) ) ) { - responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); } } - match = responseHeaders[ key.toLowerCase() ]; + match = responseHeaders[ key.toLowerCase() + " " ]; } - return match == null ? null : match; + return match == null ? null : match.join( ", " ); }, // Raw string @@ -9119,7 +9593,8 @@ jQuery.extend( { // Add or update anti-cache param if needed if ( s.cache === false ) { cacheURL = cacheURL.replace( rantiCache, "$1" ); - uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; } // Put hash and anti-cache on the URL that will be requested (gh-1732) @@ -9252,6 +9727,11 @@ jQuery.extend( { response = ajaxHandleResponses( s, jqXHR, responses ); } + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + // Convert no matter what (that way responseXXX fields are always set) response = ajaxConvert( s, response, jqXHR, isSuccess ); @@ -9342,7 +9822,7 @@ jQuery.extend( { } } ); -jQuery.each( [ "get", "post" ], function( i, method ) { +jQuery.each( [ "get", "post" ], function( _i, method ) { jQuery[ method ] = function( url, data, callback, type ) { // Shift arguments if data argument was omitted @@ -9363,8 +9843,17 @@ jQuery.each( [ "get", "post" ], function( i, method ) { }; } ); +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); -jQuery._evalUrl = function( url ) { + +jQuery._evalUrl = function( url, options, doc ) { return jQuery.ajax( { url: url, @@ -9374,7 +9863,16 @@ jQuery._evalUrl = function( url ) { cache: true, async: false, global: false, - "throws": true + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } } ); }; @@ -9657,24 +10155,21 @@ jQuery.ajaxPrefilter( "script", function( s ) { // Bind script tag hack transport jQuery.ajaxTransport( "script", function( s ) { - // This transport only deals with cross domain requests - if ( s.crossDomain ) { + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { var script, callback; return { send: function( _, complete ) { - script = jQuery( "