diff --git a/.env b/.env
index fe28319..954bc78 100644
--- a/.env
+++ b/.env
@@ -4,9 +4,14 @@ REDIS_PORT=6300
POSTGRES_PORT_5432_TCP_ADDR=radarsys-postgres
# POSTGRES_PORT_5432_TCP_PORT=5400
POSTGRES_PORT_5432_TCP_PORT=5432
-DB_NAME=radarsys
-DB_USER=docker
-DB_PASSWORD=docker
+#POSTGRES_HOST?? DONDE IRIA
+POSTGRES_USER=docker
+POSTGRES_PASSWORD=docker
+POSTGRES_DB=radarsys
+
+# DB_NAME=radarsys
+# DB_USER=docker
+# DB_PASSWORD=docker
PGDATA=/var/lib/postgresql/data
LC_ALL=C.UTF-8
TZ=America/Lima
diff --git a/apps/abs/migrations/0003_merge_0002_auto_20230117_0948_0002_initial.py b/apps/abs/migrations/0003_merge_0002_auto_20230117_0948_0002_initial.py
new file mode 100644
index 0000000..c65f3d7
--- /dev/null
+++ b/apps/abs/migrations/0003_merge_0002_auto_20230117_0948_0002_initial.py
@@ -0,0 +1,14 @@
+# Generated by Django 4.1.5 on 2023-01-31 16:15
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('abs', '0002_auto_20230117_0948'),
+ ('abs', '0002_initial'),
+ ]
+
+ operations = [
+ ]
diff --git a/apps/main/static/css/style.css b/apps/main/static/css/style.css
index 89feaa5..6bcc007 100644
--- a/apps/main/static/css/style.css
+++ b/apps/main/static/css/style.css
@@ -131,7 +131,7 @@ h3 {
}
#sidebar a {
- color: gray;
+ color: white;
padding: 0.1rem;
}
diff --git a/apps/main/views.py b/apps/main/views.py
index 47d0ec7..6d3ccf5 100644
--- a/apps/main/views.py
+++ b/apps/main/views.py
@@ -441,9 +441,10 @@ def campaign_new(request):
if form.is_valid():
campaign = form.save(commit=False)
campaign.author = request.user
+ campaign.save()
for exp in experiments:
campaign.experiments.add(exp)
- campaign.save()
+
return redirect('url_campaign', id_camp=campaign.id)
kwargs['form'] = form
diff --git a/docker-compose.yml b/docker-compose.yml
index 6d7b71d..f8b7817 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,28 +1,28 @@
version: '2'
services:
# Django app
- web:
- container_name: 'radarsys'
- build: .
- restart: always
- image: radarsys
- command: gunicorn radarsys.wsgi:application -w 2 -b :8000
- #command: python manage.py runserver 0.0.0.0:8030
- ports:
- - 8000:8000
- #ports:
- # - 8030:8030
- env_file: .env
+ # web:
+ # container_name: 'radarsys'
+ # build: .
+ # restart: always
+ # image: radarsys
+ # command: gunicorn radarsys.wsgi:application -w 2 -b :8000
+ # #command: python manage.py runserver 0.0.0.0:8030
+ # ports:
+ # - 8000:8000
+ # #ports:
+ # # - 8030:8030
+ # env_file: .env
- links:
- # - redis
- - postgres
- volumes:
- - './:/radarsys'
- - '${DOCKER_DATA}/static:/radarsys/static'
- depends_on:
- # - redis
- - postgres
+ # links:
+ # # - redis
+ # - postgres
+ # volumes:
+ # - './:/radarsys'
+ # - '${DOCKER_DATA}/static:/radarsys/static'
+ # depends_on:
+ # # - redis
+ # - postgres
# redis:
# container_name: 'radarsys-redis'
@@ -47,23 +47,27 @@ services:
volumes:
- ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
- pgdata:/var/lib/postgresql/data
- # ports:
- # - 5432:5432
+ ports:
+ - 5432:5432
+ environment:
+ - POSTGRES_PASSWORD=docker
+ - POSTGRES_USER=docker
+ - POSTGRES_DB=radarsys
env_file: .env
- #Web Server
- nginx:
- container_name: 'radarsys-nginx'
- restart: always
- build: ./nginx/
- ports:
- - '8030:8030'
- volumes_from:
- - web
- links:
- - web:web
- depends_on:
- - web
+ # #Web Server
+ # nginx:
+ # container_name: 'radarsys-nginx'
+ # restart: always
+ # build: ./nginx/
+ # ports:
+ # - '8030:8030'
+ # volumes_from:
+ # - web
+ # links:
+ # - web:web
+ # depends_on:
+ # - web
volumes:
pgdata:
diff --git a/postgres/Dockerfile b/postgres/Dockerfile
index eca8cc5..85c06d7 100644
--- a/postgres/Dockerfile
+++ b/postgres/Dockerfile
@@ -1,3 +1,5 @@
FROM postgres:14.6-alpine
+#FROM library/postgres
-RUN mkdir -p "$PGDATA" && chmod 700 "$PGDATA"
\ No newline at end of file
+RUN mkdir -p "$PGDATA" && chmod 700 "$PGDATA"
+#COPY ./init.sql /docker-entrypoint-initdb.d/
\ No newline at end of file
diff --git a/postgres/docker-entrypoint-initdb.d/create_db.sh b/postgres/docker-entrypoint-initdb.d/create_db.sh
index ff7fd3d..826c1c9 100755
--- a/postgres/docker-entrypoint-initdb.d/create_db.sh
+++ b/postgres/docker-entrypoint-initdb.d/create_db.sh
@@ -2,8 +2,8 @@
set -e
echo "Creating database & user"
-psql -v --username "postgres" --dbname "postgres" <<-EOSQL
- CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';
- CREATE DATABASE $DB_NAME;
- GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
+psql -v --username "docker" --dbname "radarsys" <<-EOSQL
+ CREATE USER docker WITH PASSWORD 'docker';
+ CREATE DATABASE radarsys;
+ GRANT ALL PRIVILEGES ON DATABASE radarsys TO docker;
EOSQL
diff --git a/postgres/init.sql b/postgres/init.sql
new file mode 100644
index 0000000..46d7de5
--- /dev/null
+++ b/postgres/init.sql
@@ -0,0 +1,3 @@
+CREATE USER docker WITH PASSWORD docker;
+CREATE DATABASE radarsys;
+GRANT ALL PRIVILEGES ON DATABASE radarsys TO docker;
\ No newline at end of file
diff --git a/static/admin/css/autocomplete.css b/static/admin/css/autocomplete.css
index 3ef95d1..69c94e7 100644
--- a/static/admin/css/autocomplete.css
+++ b/static/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/static/admin/css/base.css b/static/admin/css/base.css
index fd011a3..1ff93e2 100644
--- a/static/admin/css/base.css
+++ b/static/admin/css/base.css
@@ -4,24 +4,82 @@
@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);
+}
+
+html, body {
+ height: 100%;
+}
+
body {
margin: 0;
padding: 0;
- font-size: 14px;
+ font-size: 0.875rem;
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 +91,7 @@ a img {
}
a.section:link, a.section:visited {
- color: #fff;
+ color: var(--header-link-color);
text-decoration: none;
}
@@ -59,12 +117,12 @@ h1,h2,h3,h4,h5 {
h1 {
margin: 0 0 20px;
font-weight: 300;
- font-size: 20px;
- color: #666;
+ font-size: 1.25rem;
+ color: var(--body-quiet-color);
}
h2 {
- font-size: 16px;
+ font-size: 1rem;
margin: 1em 0 .5em 0;
}
@@ -74,27 +132,27 @@ h2.subhead {
}
h3 {
- font-size: 14px;
+ font-size: 0.875rem;
margin: .8em 0 .3em 0;
- color: #666;
+ color: var(--body-quiet-color);
font-weight: bold;
}
h4 {
- font-size: 12px;
+ font-size: 0.75rem;
margin: 1em 0 .8em 0;
padding-bottom: 3px;
}
h5 {
- font-size: 10px;
+ font-size: 0.625rem;
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;
}
@@ -104,7 +162,7 @@ li ul {
}
li, dt, dd {
- font-size: 13px;
+ font-size: 0.8125rem;
line-height: 20px;
}
@@ -124,13 +182,14 @@ form {
fieldset {
margin: 0;
+ min-width: 0;
padding: 0;
border: none;
- border-top: 1px solid #eee;
+ border-top: 1px solid var(--hairline-color);
}
blockquote {
- font-size: 11px;
+ font-size: 0.6875rem;
color: #777;
margin-left: 2px;
padding-left: 10px;
@@ -139,13 +198,14 @@ blockquote {
code, pre {
font-family: "Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace;
- color: #666;
- font-size: 12px;
+ color: var(--body-quiet-color);
+ font-size: 0.75rem;
+ overflow-x: auto;
}
pre.literal-block {
margin: 10px;
- background: #eee;
+ background: var(--darkened-bg);
padding: 6px 8px;
}
@@ -155,41 +215,28 @@ 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;
padding: 0;
- font-size: 1px;
line-height: 1px;
}
/* TEXT STYLES & MODIFIERS */
.small {
- font-size: 11px;
-}
-
-.tiny {
- font-size: 10px;
-}
-
-p.tiny {
- margin-top: -2px;
+ font-size: 0.6875rem;
}
.mini {
- font-size: 10px;
-}
-
-p.mini {
- margin-top: -3px;
+ font-size: 0.625rem;
}
.help, p.help, form p.help, div.help, form div.help, div.help li {
- font-size: 11px;
- color: #999;
+ font-size: 0.6875rem;
+ color: var(--body-quiet-color);
}
div.help ul {
@@ -205,54 +252,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 !important;
+}
+
/* TABLES */
table {
border-collapse: collapse;
- border-color: #ccc;
+ border-color: var(--border-color);
}
td, th {
- font-size: 13px;
+ font-size: 0.8125rem;
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 +290,37 @@ th {
thead th,
tfoot td {
- color: #666;
+ color: var(--body-quiet-color);
padding: 5px 10px;
- font-size: 11px;
- background: #fff;
+ font-size: 0.6875rem;
+ 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 +329,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 +356,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 {
@@ -371,13 +402,13 @@ table thead th.sorted .sortoptions a.sortremove:after {
top: -6px;
left: 3px;
font-weight: 200;
- font-size: 18px;
- color: #999;
+ font-size: 1.125rem;
+ 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,
@@ -412,7 +443,7 @@ input, textarea, select, .form-row p, form .button {
vertical-align: middle;
font-family: "Roboto", "Lucida Grande", Verdana, Arial, sans-serif;
font-weight: normal;
- font-size: 13px;
+ font-size: 0.8125rem;
}
.form-row div.help {
padding: 2px 3px;
@@ -424,16 +455,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 +482,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 +498,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 +509,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 +530,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 {
@@ -520,15 +554,15 @@ input[type=button][disabled].default {
margin: 0;
padding: 8px;
font-weight: 400;
- font-size: 13px;
+ font-size: 0.8125rem;
text-align: left;
- background: #79aec8;
- color: #fff;
+ background: var(--primary);
+ color: var(--header-link-color);
}
.module caption,
.inline-group h2 {
- font-size: 12px;
+ font-size: 0.75rem;
letter-spacing: 0.5px;
text-transform: uppercase;
}
@@ -547,48 +581,51 @@ ul.messagelist {
ul.messagelist li {
display: block;
font-weight: 400;
- font-size: 13px;
+ font-size: 0.8125rem;
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);
+ word-break: break-word;
}
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;
}
.errornote {
- font-size: 14px;
+ font-size: 0.875rem;
font-weight: 700;
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;
+ font-size: 0.8125rem;
display: block;
margin-bottom: 4px;
+ overflow-wrap: break-word;
}
ul.errorlist li:first-child {
@@ -612,7 +649,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,46 +657,32 @@ 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 {
- font-size: 12px;
+ font-size: 0.75rem;
padding: 5px 0 0 12px;
}
/* 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,18 +708,18 @@ 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;
}
/* OBJECT TOOLS */
.object-tools {
- font-size: 10px;
+ font-size: 0.625rem;
font-weight: bold;
padding-left: 0;
float: right;
@@ -704,14 +727,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 +742,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;
+ font-size: 0.6875rem;
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);
}
@@ -759,14 +774,21 @@ a.deletelink:focus, a.deletelink:hover {
/* OBJECT HISTORY */
-table#change-history {
+#change-history table {
width: 100%;
}
-table#change-history tbody th {
+#change-history table tbody th {
width: 16em;
}
+#change-history .paginator {
+ color: var(--body-quiet-color);
+ border-bottom: 1px solid var(--hairline-color);
+ background: var(--body-bg);
+ overflow: hidden;
+}
+
/* PAGE STRUCTURE */
#container {
@@ -774,6 +796,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 +873,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;
+#header a:link, #header a:visited, #logout-form button {
+ color: var(--header-link-color);
}
#header a:focus , #header a:hover {
@@ -855,51 +894,69 @@ table#change-history tbody th {
padding: 0;
margin: 0 20px 0 0;
font-weight: 300;
- font-size: 24px;
- color: #f5dd5d;
+ font-size: 1.5rem;
+ color: var(--header-branding-color);
}
-#branding h1, #branding h1 a:link, #branding h1 a:visited {
- color: #f5dd5d;
+#branding h1 a:link, #branding h1 a:visited {
+ color: var(--accent);
}
#branding h2 {
padding: 0 10px;
- font-size: 14px;
+ font-size: 0.875rem;
margin: -8px 0 8px 0;
font-weight: normal;
- color: #ffc;
+ color: var(--header-color);
}
#branding a:hover {
text-decoration: none;
}
+#logout-form {
+ display: inline;
+}
+
+#logout-form button {
+ background: none;
+ border: 0;
+ cursor: pointer;
+ font-family: "Roboto","Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif;
+}
+
#user-tools {
float: right;
- padding: 0;
margin: 0 0 0 20px;
+ text-align: right;
+}
+
+#user-tools, #logout-form button{
+ padding: 0;
font-weight: 300;
- font-size: 11px;
+ font-size: 0.6875rem;
letter-spacing: 0.5px;
text-transform: uppercase;
- text-align: right;
}
-#user-tools a {
+#user-tools a, #logout-form button {
border-bottom: 1px solid rgba(255, 255, 255, 0.25);
}
-#user-tools a:focus, #user-tools a:hover {
+#user-tools a:focus, #user-tools a:hover,
+#logout-form button:active, #logout-form button:hover {
text-decoration: none;
- border-bottom-color: #79aec8;
- color: #79aec8;
+ border-bottom: 0;
+}
+
+#logout-form button:active, #logout-form button:hover {
+ margin-bottom: 1px;
}
/* SIDEBAR */
#content-related {
- background: #f8f8f8;
+ background: var(--darkened-bg);
}
#content-related .module {
@@ -907,14 +964,13 @@ 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;
}
#content-related h4 {
- font-size: 13px;
+ font-size: 0.8125rem;
}
#content-related p {
@@ -937,22 +993,22 @@ table#change-history tbody th {
background: none;
padding: 16px;
margin-bottom: 16px;
- border-bottom: 1px solid #eaeaea;
- font-size: 18px;
- color: #333;
+ border-bottom: 1px solid var(--hairline-color);
+ font-size: 1.125rem;
+ 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 +1016,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 */
@@ -985,3 +1041,49 @@ table#change-history tbody th {
.popup #header {
padding: 10px 20px;
}
+
+/* PAGINATOR */
+
+.paginator {
+ font-size: 0.8125rem;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ line-height: 22px;
+ margin: 0;
+ border-top: 1px solid var(--hairline-color);
+ width: 100%;
+}
+
+.paginator a:link, .paginator a:visited {
+ padding: 2px 6px;
+ background: var(--button-bg);
+ text-decoration: none;
+ color: var(--button-fg);
+}
+
+.paginator a.showall {
+ border: none;
+ background: none;
+ color: var(--link-fg);
+}
+
+.paginator a.showall:focus, .paginator a.showall:hover {
+ background: none;
+ color: var(--link-hover-color);
+}
+
+.paginator .end {
+ margin-right: 6px;
+}
+
+.paginator .this-page {
+ padding: 2px 6px;
+ font-weight: bold;
+ font-size: 0.8125rem;
+ vertical-align: top;
+}
+
+.paginator a:focus, .paginator a:hover {
+ color: white;
+ background: var(--link-hover-color);
+}
diff --git a/static/admin/css/changelists.css b/static/admin/css/changelists.css
index 17690a3..68ba557 100644
--- a/static/admin/css/changelists.css
+++ b/static/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,76 +68,79 @@
}
#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;
+ font-size: 0.875rem;
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;
+ font-size: 0.8125rem;
+ 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: 0.8125rem;
+ 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;
}
+#changelist-search .help {
+ word-break: break-word;
+}
+
/* 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 {
- font-size: 14px;
+ font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.5px;
padding: 5px 15px;
@@ -139,22 +148,43 @@
border-bottom: none;
}
-#changelist-filter h3 {
+#changelist-filter h3,
+#changelist-filter details summary {
font-weight: 400;
- font-size: 14px;
padding: 0 15px;
margin-bottom: 10px;
}
+#changelist-filter details summary > * {
+ display: inline;
+}
+
+#changelist-filter details > summary {
+ list-style-type: none;
+}
+
+#changelist-filter details > summary::-webkit-details-marker {
+ display: none;
+}
+
+#changelist-filter details > summary::before {
+ content: '→';
+ font-weight: bold;
+ color: var(--link-hover-color);
+}
+
+#changelist-filter details[open] > summary::before {
+ content: '↓';
+}
+
#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 +195,30 @@
#changelist-filter a {
display: block;
- color: #999;
- text-overflow: ellipsis;
- overflow-x: hidden;
+ color: var(--body-quiet-color);
+ word-break: break-word;
}
#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: 0.8125rem;
+ padding-bottom: 10px;
+ border-bottom: 1px solid var(--hairline-color);
}
/* DATE DRILLDOWN */
@@ -204,64 +239,17 @@
}
.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;
-}
-
-/* PAGINATOR */
-
-.paginator {
- font-size: 13px;
- padding-top: 10px;
- padding-bottom: 10px;
- line-height: 22px;
- margin: 0;
- border-top: 1px solid #ddd;
-}
-
-.paginator a:link, .paginator a:visited {
- padding: 2px 6px;
- background: #79aec8;
- text-decoration: none;
- color: #fff;
-}
-
-.paginator a.showall {
- padding: 0;
- border: none;
- background: none;
- color: #5b80b2;
-}
-
-.paginator a.showall:focus, .paginator a.showall:hover {
- background: none;
- color: #036;
-}
-
-.paginator .end {
- margin-right: 6px;
-}
-
-.paginator .this-page {
- padding: 2px 6px;
- font-weight: bold;
- font-size: 13px;
- vertical-align: top;
-}
-
-.paginator a:focus, .paginator a:hover {
- color: white;
- background: #036;
+ color: var(--link-hover-color);
}
/* ACTIONS */
.filtered .actions {
- margin-right: 280px;
border-right: none;
}
@@ -271,31 +259,25 @@
}
#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;
-}
-
-#changelist .actions.selected {
- background: #fffccf;
- border-top: 1px solid #fffee8;
- border-bottom: 1px solid #edecd6;
+ color: var(--body-quiet-color);
+ width: 100%;
}
#changelist .actions span.all,
#changelist .actions span.action-counter,
#changelist .actions span.clear,
#changelist .actions span.question {
- font-size: 13px;
+ font-size: 0.8125rem;
margin: 0 0.5em;
- display: none;
}
#changelist .actions:last-child {
@@ -305,40 +287,39 @@
#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;
+ font-size: 0.875rem;
padding: 0 0 0 4px;
margin: 0;
margin-left: 10px;
}
#changelist .actions select:focus {
- border-color: #999;
+ border-color: var(--body-quiet-color);
}
#changelist .actions label {
display: inline-block;
vertical-align: middle;
- font-size: 13px;
+ font-size: 0.8125rem;
}
#changelist .actions .button {
- font-size: 13px;
- border: 1px solid #ccc;
+ font-size: 0.8125rem;
+ 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/static/admin/css/dark_mode.css b/static/admin/css/dark_mode.css
new file mode 100644
index 0000000..547717c
--- /dev/null
+++ b/static/admin/css/dark_mode.css
@@ -0,0 +1,33 @@
+@media (prefers-color-scheme: dark) {
+ :root {
+ --primary: #264b5d;
+ --primary-fg: #f7f7f7;
+
+ --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;
+ }
+ }
diff --git a/static/admin/css/dashboard.css b/static/admin/css/dashboard.css
index 1560c7b..91d6efd 100644
--- a/static/admin/css/dashboard.css
+++ b/static/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/static/admin/css/forms.css b/static/admin/css/forms.css
index 62a093f..e1873b3 100644
--- a/static/admin/css/forms.css
+++ b/static/admin/css/forms.css
@@ -5,8 +5,8 @@
.form-row {
overflow: hidden;
padding: 10px;
- font-size: 13px;
- border-bottom: 1px solid #eee;
+ font-size: 0.8125rem;
+ border-bottom: 1px solid var(--hairline-color);
}
.form-row img, .form-row input {
@@ -22,35 +22,34 @@ form .form-row p {
padding-left: 0;
}
-.hidden {
- display: none;
-}
-
/* FORM LABELS */
label {
font-weight: normal;
- color: #666;
- font-size: 13px;
+ color: var(--body-quiet-color);
+ font-size: 0.8125rem;
}
.required label, label.required {
font-weight: bold;
- color: #333;
+ color: var(--body-fg);
}
/* RADIO BUTTONS */
-form ul.radiolist li {
- list-style-type: none;
+form div.radiolist div {
+ padding-right: 7px;
}
-form ul.radiolist label {
- float: none;
- display: inline;
+form div.radiolist.inline div {
+ display: inline-block;
+}
+
+form div.radiolist label {
+ width: auto;
}
-form ul.radiolist input[type="radio"] {
+form div.radiolist input[type="radio"] {
margin: -2px 4px 0 0;
padding: 0;
}
@@ -88,6 +87,7 @@ form ul.inline li {
margin-top: 0;
margin-bottom: 0;
margin-left: 170px;
+ overflow-wrap: break-word;
}
.aligned ul label {
@@ -109,7 +109,7 @@ form .aligned ul {
padding-left: 10px;
}
-form .aligned ul.radiolist {
+form .aligned div.radiolist {
display: inline-block;
margin: 0;
padding: 0;
@@ -219,24 +219,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 */
@@ -248,10 +248,10 @@ fieldset.monospace textarea {
/* SUBMIT ROW */
.submit-row {
- padding: 12px 14px;
+ padding: 12px 14px 7px;
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;
@@ -264,11 +264,11 @@ body.popup .submit-row {
.submit-row input {
height: 35px;
line-height: 15px;
- margin: 0 0 0 5px;
+ margin: 0 0 5px 5px;
}
.submit-row input.default {
- margin: 0 0 0 8px;
+ margin: 0 0 5px 8px;
text-transform: uppercase;
}
@@ -283,35 +283,36 @@ 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;
+ margin-bottom: 5px;
+ 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 */
@@ -353,10 +354,6 @@ body.popup .submit-row {
width: 2.2em;
}
-.vTextField, .vUUIDField {
- width: 20em;
-}
-
.vIntegerField {
width: 5em;
}
@@ -369,6 +366,10 @@ body.popup .submit-row {
width: 5em;
}
+.vTextField, .vUUIDField {
+ width: 20em;
+}
+
/* INLINES */
.inline-group {
@@ -390,12 +391,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;
+ font-size: 0.8125rem;
+ background: var(--darkened-bg);
+ border-top: 1px solid var(--hairline-color);
+ border-bottom: 1px solid var(--hairline-color);
}
.inline-related h3 span.delete {
@@ -404,12 +405,12 @@ body.popup .submit-row {
.inline-related h3 span.delete label {
margin-left: 2px;
- font-size: 11px;
+ font-size: 0.6875rem;
}
.inline-related fieldset {
margin: 0;
- background: #fff;
+ background: var(--body-bg);
border: none;
width: 100%;
}
@@ -417,11 +418,11 @@ body.popup .submit-row {
.inline-related fieldset.module h3 {
margin: 0;
padding: 2px 5px 3px 5px;
- font-size: 11px;
+ font-size: 0.6875rem;
text-align: left;
font-weight: bold;
background: #bcd;
- color: #fff;
+ color: var(--body-bg);
}
.inline-group .tabular fieldset.module {
@@ -430,6 +431,7 @@ body.popup .submit-row {
.inline-related.tabular fieldset.module table {
width: 100%;
+ overflow-x: scroll;
}
.last-related fieldset {
@@ -457,9 +459,9 @@ body.popup .submit-row {
height: 1.1em;
padding: 2px 9px;
overflow: hidden;
- font-size: 9px;
+ font-size: 0.5625rem;
font-weight: bold;
- color: #666;
+ color: var(--body-quiet-color);
_width: 700px;
}
@@ -476,15 +478,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,
@@ -492,7 +494,7 @@ body.popup .submit-row {
.inline-group .tabular tr.add-row td a {
background: url(../img/icon-addlink.svg) 0 1px no-repeat;
padding-left: 16px;
- font-size: 12px;
+ font-size: 0.75rem;
}
.empty-form {
@@ -501,7 +503,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 +511,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/static/admin/css/login.css b/static/admin/css/login.css
index 2ec241c..389772f 100644
--- a/static/admin/css/login.css
+++ b/static/admin/css/login.css
@@ -1,7 +1,8 @@
/* LOGIN FORM */
-body.login {
- background: #f8f8f8;
+.login {
+ background: var(--darkened-bg);
+ height: auto;
}
.login #header {
@@ -11,11 +12,12 @@ body.login {
}
.login #header h1 {
- font-size: 18px;
+ font-size: 1.125rem;
+ margin: 0;
}
.login #header h1 a {
- color: #fff;
+ color: var(--header-link-color);
}
.login #content {
@@ -23,55 +25,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/static/admin/css/nav_sidebar.css b/static/admin/css/nav_sidebar.css
new file mode 100644
index 0000000..5fd2ff0
--- /dev/null
+++ b/static/admin/css/nav_sidebar.css
@@ -0,0 +1,139 @@
+.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: 1.25rem;
+ 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 {
+ margin-left: 0;
+}
+
+[dir="rtl"] .main.shifted > #nav-sidebar {
+ 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%;
+ }
+}
+
+#nav-filter {
+ width: 100%;
+ box-sizing: border-box;
+ padding: 2px 5px;
+ margin: 5px 0;
+ border: 1px solid var(--border-color);
+ background-color: var(--darkened-bg);
+ color: var(--body-fg);
+}
+
+#nav-filter:focus {
+ border-color: var(--body-quiet-color);
+}
+
+#nav-filter.no-results {
+ background: var(--message-error-bg);
+}
+
+#nav-sidebar table {
+ width: 100%;
+}
diff --git a/static/admin/css/responsive.css b/static/admin/css/responsive.css
index 5b0d1ec..9a4615d 100644
--- a/static/admin/css/responsive.css
+++ b/static/admin/css/responsive.css
@@ -14,11 +14,11 @@ input[type="submit"], button {
td, th {
padding: 10px;
- font-size: 14px;
+ font-size: 0.875rem;
}
.small {
- font-size: 12px;
+ font-size: 0.75rem;
}
/* Layout */
@@ -28,7 +28,7 @@ input[type="submit"], button {
}
#content {
- padding: 20px 30px 30px;
+ padding: 15px 20px 20px;
}
div.breadcrumbs {
@@ -45,7 +45,6 @@ input[type="submit"], button {
#branding h1 {
margin: 0 0 8px;
- font-size: 20px;
line-height: 1.2;
}
@@ -88,21 +87,19 @@ input[type="submit"], button {
}
td .changelink, td .addlink {
- font-size: 13px;
+ font-size: 0.8125rem;
}
/* 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 +107,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;
}
@@ -129,16 +130,12 @@ input[type="submit"], button {
padding: 15px 0;
}
- #changelist .actions.selected {
- border: none;
- }
-
#changelist .actions label {
display: flex;
}
#changelist .actions select {
- background: #fff;
+ background: var(--body-bg);
}
#changelist .actions .button {
@@ -150,24 +147,21 @@ input[type="submit"], button {
#changelist .actions span.clear,
#changelist .actions span.question,
#changelist .actions span.action-counter {
- font-size: 11px;
+ font-size: 0.6875rem;
margin: 0 10px 0 0;
}
#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 {
@@ -177,7 +171,7 @@ input[type="submit"], button {
/* Forms */
label {
- font-size: 14px;
+ font-size: 0.875rem;
}
.form-row input[type=text],
@@ -193,7 +187,7 @@ input[type="submit"], button {
margin: 0;
padding: 6px 8px;
min-height: 36px;
- font-size: 14px;
+ font-size: 0.875rem;
}
.form-row select {
@@ -214,11 +208,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 +220,6 @@ input[type="submit"], button {
padding-top: 6px;
}
- .aligned .add-another,
.aligned .related-lookup,
.aligned .datetimeshortcuts,
.aligned .related-lookup + strong {
@@ -234,10 +227,26 @@ input[type="submit"], button {
margin-left: 15px;
}
- form .aligned ul.radiolist {
+ form .aligned div.radiolist {
margin-left: 2px;
}
+ .submit-row {
+ padding: 8px 8px 3px 8px;
+ }
+
+ .submit-row a.deletelink {
+ padding: 10px 7px;
+ }
+
+ .submit-row input.default {
+ margin: 0 0 5px 5px;
+ }
+
+ .button, input[type=submit], input[type=button], .submit-row input, a.button {
+ padding: 7px;
+ }
+
/* Related widget */
.related-widget-wrapper {
@@ -354,6 +363,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 +379,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;
}
@@ -379,17 +404,21 @@ input[type="submit"], button {
}
.datetime span {
- font-size: 13px;
+ font-size: 0.8125rem;
}
.datetime .timezonewarning {
display: block;
- font-size: 11px;
- color: #999;
+ font-size: 0.6875rem;
+ 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 {
@@ -478,31 +507,22 @@ input[type="submit"], button {
#content-related .module h2 {
padding: 10px 15px;
- font-size: 16px;
+ font-size: 1rem;
}
/* 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 +538,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;
@@ -618,7 +633,7 @@ input[type="submit"], button {
.aligned p.file-upload {
margin-left: 0;
- font-size: 13px;
+ font-size: 0.8125rem;
}
span.clearable-file-input {
@@ -626,7 +641,7 @@ input[type="submit"], button {
}
span.clearable-file-input label {
- font-size: 13px;
+ font-size: 0.8125rem;
padding-bottom: 0;
}
@@ -646,12 +661,13 @@ input[type="submit"], button {
padding-left: 0;
}
- form .aligned ul.radiolist {
+ form .aligned div.radiolist {
+ margin-top: 5px;
margin-right: 15px;
margin-bottom: -3px;
}
- form .aligned ul.radiolist li + li {
+ form .aligned div.radiolist:not(.inline) div + div {
margin-top: 5px;
}
@@ -721,14 +737,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 +762,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 +804,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;
}
@@ -798,7 +823,7 @@ input[type="submit"], button {
/* Submit row */
.submit-row {
- padding: 10px 10px 0;
+ padding: 10px 10px 5px;
margin: 0 0 15px;
display: flex;
flex-direction: column;
@@ -873,9 +898,7 @@ input[type="submit"], button {
}
.login .form-row label {
- display: block;
margin: 0 0 5px;
- padding: 0;
line-height: 1.2;
}
@@ -883,7 +906,7 @@ input[type="submit"], button {
padding: 15px 0 0;
}
- .login br, .login .submit-row label {
+ .login br {
display: none;
}
@@ -895,7 +918,7 @@ input[type="submit"], button {
.errornote {
margin: 0 0 20px;
padding: 8px 12px;
- font-size: 13px;
+ font-size: 0.8125rem;
}
/* Calendar and clock */
@@ -942,7 +965,7 @@ input[type="submit"], button {
.calendar-shortcuts {
padding: 10px 0;
- font-size: 12px;
+ font-size: 0.75rem;
line-height: 12px;
}
@@ -951,7 +974,7 @@ input[type="submit"], button {
}
.timelist a {
- background: #fff;
+ background: var(--body-bg);
padding: 4px;
}
@@ -975,7 +998,7 @@ input[type="submit"], button {
/* History */
table#change-history tbody th, table#change-history tbody td {
- font-size: 13px;
+ font-size: 0.8125rem;
word-break: break-word;
}
@@ -986,7 +1009,7 @@ input[type="submit"], button {
/* Docs */
table.model tbody th, table.model tbody td {
- font-size: 13px;
+ font-size: 0.8125rem;
word-break: break-word;
}
}
diff --git a/static/admin/css/responsive_rtl.css b/static/admin/css/responsive_rtl.css
index f999cb1..66d3c2f 100644
--- a/static/admin/css/responsive_rtl.css
+++ b/static/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/static/admin/css/rtl.css b/static/admin/css/rtl.css
index b9e26bf..e0fadce 100644
--- a/static/admin/css/rtl.css
+++ b/static/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;
@@ -207,12 +175,24 @@ fieldset .fieldBox {
top: 0;
left: auto;
right: 10px;
+ background: url(../img/calendar-icons.svg) 0 -30px no-repeat;
+}
+
+.calendarbox .calendarnav-previous:focus,
+.calendarbox .calendarnav-previous:hover {
+ background-position: 0 -45px;
}
.calendarnav-next {
top: 0;
right: auto;
left: 10px;
+ background: url(../img/calendar-icons.svg) 0 0 no-repeat;
+}
+
+.calendarbox .calendarnav-next:focus,
+.calendarbox .calendarnav-next:hover {
+ background-position: 0 -15px;
}
.calendar caption, .calendarbox h2 {
@@ -257,13 +237,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/static/admin/css/vendor/select2/LICENSE-SELECT2.md b/static/admin/css/vendor/select2/LICENSE-SELECT2.md
index 86c7c29..8cb8a2b 100644
--- a/static/admin/css/vendor/select2/LICENSE-SELECT2.md
+++ b/static/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/static/admin/css/vendor/select2/select2.css b/static/admin/css/vendor/select2/select2.css
index 447b2b8..750b320 100644
--- a/static/admin/css/vendor/select2/select2.css
+++ b/static/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/static/admin/css/vendor/select2/select2.min.css b/static/admin/css/vendor/select2/select2.min.css
index 76de04d..7c18ad5 100644
--- a/static/admin/css/vendor/select2/select2.min.css
+++ b/static/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/static/admin/css/widgets.css b/static/admin/css/widgets.css
index d3bd67a..cd1d6b4 100644
--- a/static/admin/css/widgets.css
+++ b/static/admin/css/widgets.css
@@ -3,18 +3,21 @@
.selector {
width: 800px;
float: left;
+ display: flex;
}
.selector select {
width: 380px;
height: 17.2em;
+ flex: 1 0 auto;
}
.selector-available, .selector-chosen {
- float: left;
width: 380px;
text-align: center;
margin-bottom: 5px;
+ display: flex;
+ flex-direction: column;
}
.selector-chosen select {
@@ -22,27 +25,26 @@
}
.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;
- font-size: 10px;
+ color: var(--body-quiet-color);
+ font-size: 0.625rem;
margin: 0;
text-align: left;
}
@@ -64,12 +66,13 @@
}
.selector ul.selector-chooser {
- float: left;
+ align-self: center;
width: 22px;
- background-color: #eee;
+ background-color: var(--selected-bg);
border-radius: 10px;
- margin: 10em 5px 0 5px;
+ margin: 0 5px;
padding: 0;
+ transform: translateY(-17px);
}
.selector-chooser li {
@@ -91,7 +94,7 @@
text-indent: -3000px;
overflow: hidden;
cursor: default;
- opacity: 0.3;
+ opacity: 0.55;
}
.active.selector-add, .active.selector-remove {
@@ -126,14 +129,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 {
@@ -169,6 +172,7 @@ a.active.selector-clearall:focus, a.active.selector-clearall:hover {
.stacked {
float: left;
width: 490px;
+ display: block;
}
.stacked select {
@@ -194,6 +198,7 @@ a.active.selector-clearall:focus, a.active.selector-clearall:hover {
margin: 0 0 10px 40%;
background-color: #eee;
border-radius: 10px;
+ transform: none;
}
.stacked .selector-chooser li {
@@ -211,6 +216,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 +231,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,25 +266,24 @@ p.datetime {
line-height: 20px;
margin: 0;
padding: 0;
- color: #666;
+ color: var(--body-quiet-color);
font-weight: bold;
}
.datetime span {
white-space: nowrap;
font-weight: normal;
- font-size: 11px;
- color: #ccc;
+ font-size: 0.6875rem;
+ 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;
}
table p.datetime {
- font-size: 11px;
+ font-size: 0.6875rem;
margin-left: 0;
padding-left: 0;
}
@@ -303,8 +317,8 @@ table p.datetime {
}
.timezonewarning {
- font-size: 11px;
- color: #999;
+ font-size: 0.6875rem;
+ color: var(--body-quiet-color);
}
/* URL */
@@ -313,8 +327,8 @@ p.url {
line-height: 20px;
margin: 0;
padding: 0;
- color: #666;
- font-size: 11px;
+ color: var(--body-quiet-color);
+ font-size: 0.6875rem;
font-weight: bold;
}
@@ -328,8 +342,8 @@ p.file-upload {
line-height: 20px;
margin: 0;
padding: 0;
- color: #666;
- font-size: 11px;
+ color: var(--body-quiet-color);
+ font-size: 0.6875rem;
font-weight: bold;
}
@@ -346,8 +360,8 @@ p.file-upload {
}
span.clearable-file-input label {
- color: #333;
- font-size: 11px;
+ color: var(--body-fg);
+ font-size: 0.6875rem;
display: inline;
float: none;
}
@@ -356,11 +370,12 @@ span.clearable-file-input label {
.calendarbox, .clockbox {
margin: 5px auto;
- font-size: 12px;
+ font-size: 0.75rem;
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,38 +403,38 @@ span.clearable-file-input label {
margin: 0;
text-align: center;
border-top: none;
- background: #f5dd5d;
font-weight: 700;
- font-size: 12px;
+ font-size: 0.75rem;
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;
+ font-size: 0.75rem;
text-align: center;
- color: #666;
+ color: var(--body-quiet-color);
}
.calendar td {
font-weight: 400;
- font-size: 12px;
+ font-size: 0.75rem;
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,22 +446,22 @@ 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;
}
.calendarnav {
- font-size: 10px;
+ font-size: 0.625rem;
text-align: center;
color: #ccc;
margin: 0;
@@ -455,16 +470,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;
- font-size: 11px;
+ background: var(--body-bg);
+ color: var(--body-quiet-color);
+ font-size: 0.6875rem;
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 {
@@ -500,10 +515,10 @@ span.clearable-file-input label {
.calendar-cancel {
margin: 0;
padding: 4px 0;
- font-size: 12px;
+ font-size: 0.75rem;
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/static/admin/js/SelectBox.js b/static/admin/js/SelectBox.js
index 1a14959..ace6d9d 100644
--- a/static/admin/js/SelectBox.js
+++ b/static/admin/js/SelectBox.js
@@ -1,64 +1,50 @@
-(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
+ break; // Once the first token isn't found we're done
}
}
}
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/static/admin/js/SelectFilter2.js b/static/admin/js/SelectFilter2.js
index 4221778..194c2db 100644
--- a/static/admin/js/SelectFilter2.js
+++ b/static/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');
@@ -162,66 +153,50 @@ Requires jQuery, core.js, and SelectBox.js.
// Move selected from_box options to to_box
SelectBox.move(field_id + '_from', field_id + '_to');
- 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());
- }
-
// 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 +206,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/static/admin/js/actions.js b/static/admin/js/actions.js
index 524616f..20a5c14 100644
--- a/static/admin/js/actions.js
+++ b/static/admin/js/actions.js
@@ -1,153 +1,201 @@
/*global gettext, interpolate, ngettext*/
-(function($) {
- 'use strict';
- var lastChecked;
-
- $.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(
+'use strict';
+{
+ function show(selector) {
+ document.querySelectorAll(selector).forEach(function(el) {
+ el.classList.remove('hidden');
+ });
+ }
+
+ function hide(selector) {
+ document.querySelectorAll(selector).forEach(function(el) {
+ el.classList.add('hidden');
+ });
+ }
+
+ 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);
+ const acrossInputs = document.querySelectorAll(options.acrossInput);
+ acrossInputs.forEach(function(acrossInput) {
+ 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);
+ });
+ }
+
+ 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));
- $(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();
- }
- });
- $(options.allToggle).show().on('click', function() {
- checker($(this).prop("checked"));
- updateCounter();
+ }, 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",
+ allToggleId: "action-toggle",
+ selectedClass: "selected"
+ };
+
+ 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;
});
- $("a", options.acrossQuestions).on('click', function(event) {
- event.preventDefault();
- $(options.acrossInput).val(1);
- showClear();
+
+ document.addEventListener('keyup', (event) => {
+ shiftPressed = event.shiftKey;
});
- $("a", options.acrossClears).on('click', function(event) {
- event.preventDefault();
- $(options.allToggle).prop("checked", false);
- clearAcross();
- checker(0);
- updateCounter();
+
+ document.getElementById(options.allToggleId).addEventListener('click', function(event) {
+ checker(actionCheckboxes, options, this.checked);
+ updateCounter(actionCheckboxes, options);
});
- 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);
- }
+
+ document.querySelectorAll(options.acrossQuestions + " a").forEach(function(el) {
+ el.addEventListener('click', function(event) {
+ event.preventDefault();
+ const acrossInputs = document.querySelectorAll(options.acrossInput);
+ acrossInputs.forEach(function(acrossInput) {
+ acrossInput.value = 1;
});
- }
- $(target).parent().parent().toggleClass(options.selectedClass, target.checked);
- lastChecked = target;
- updateCounter();
+ showClear(options);
+ });
});
- $('form#changelist-form table#result_list tr').on('change', 'td:gt(0) :input', function() {
- list_editable_changed = true;
+
+ 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);
+ });
});
- $('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."));
+
+ function affectedCheckboxes(target, withModifier) {
+ const multiSelect = (lastChecked && withModifier && lastChecked !== target);
+ if (!multiSelect) {
+ return [target];
}
- });
- $('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;
+ 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;
}
});
- 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."));
+ });
+
+ document.querySelector('#changelist-form button[name=index]').addEventListener('click', function(event) {
+ 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();
+ }
+ }
+ });
+ }
};
- /* Setup plugin defaults */
- $.fn.actions.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",
- selectedClass: "selected"
- };
- $(document).ready(function() {
- var $actionsEls = $('tr input.action-select');
- if ($actionsEls.length > 0) {
- $actionsEls.actions();
+
+ // 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/static/admin/js/admin/DateTimeShortcuts.js b/static/admin/js/admin/DateTimeShortcuts.js
index 08b2785..176b0e3 100644
--- a/static/admin/js/admin/DateTimeShortcuts.js
+++ b/static/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: [],
@@ -20,29 +20,26 @@
dismissClockFunc: [],
dismissCalendarFunc: [],
calendarDivName1: 'calendarbox', // name of calendar
that gets toggled
- calendarDivName2: 'calendarin', // name of
that contains calendar
- calendarLinkName: 'calendarlink',// name of the link that is used to toggle
- clockDivName: 'clockbox', // name of clock
that gets toggled
- clockLinkName: 'clocklink', // name of the link that is used to toggle
+ calendarDivName2: 'calendarin', // name of
that contains calendar
+ calendarLinkName: 'calendarlink', // name of the link that is used to toggle
+ clockDivName: 'clockbox', // name of clock
that gets toggled
+ clockLinkName: 'clocklink', // name of the link that is used to toggle
shortCutsClass: 'datetimeshortcuts', // class of the clock and cal shortcuts
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,13 +388,7 @@
DateTimeShortcuts.calendars[num].drawNextMonth();
},
handleCalendarCallback: function(num) {
- var format = get_format('DATE_INPUT_FORMATS')[0];
- // the format needs to be escaped a little
- format = format.replace('\\', '\\\\')
- .replace('\r', '\\r')
- .replace('\n', '\\n')
- .replace('\t', '\\t')
- .replace("'", "\\'");
+ const format = get_format('DATE_INPUT_FORMATS')[0];
return function(y, m, d) {
DateTimeShortcuts.calendarInputs[num].value = new Date(y, m - 1, d).strftime(format);
DateTimeShortcuts.calendarInputs[num].focus();
@@ -410,7 +396,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 +406,4 @@
window.addEventListener('load', DateTimeShortcuts.init);
window.DateTimeShortcuts = DateTimeShortcuts;
-})();
+}
diff --git a/static/admin/js/admin/RelatedObjectLookups.js b/static/admin/js/admin/RelatedObjectLookups.js
index f4c57c4..752dcad 100644
--- a/static/admin/js/admin/RelatedObjectLookups.js
+++ b/static/admin/js/admin/RelatedObjectLookups.js
@@ -1,38 +1,48 @@
/*global SelectBox, interpolate*/
// Handles related-objects functionality: lookup link for raw_id_fields
// and Add Another links.
+'use strict';
+{
+ const $ = django.jQuery;
+ let popupIndex = 0;
+ const relatedWindows = [];
+
+ function dismissChildPopups() {
+ relatedWindows.forEach(function(win) {
+ if(!win.closed) {
+ win.dismissChildPopups();
+ win.close();
+ }
+ });
+ }
+
+ function setPopupIndex() {
+ if(document.getElementsByName("_popup").length > 0) {
+ const index = window.name.lastIndexOf("__") + 2;
+ popupIndex = parseInt(window.name.substring(index));
+ } else {
+ popupIndex = 0;
+ }
+ }
-(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 addPopupIndex(name) {
+ name = name + "__" + (popupIndex + 1);
+ return name;
}
- function windowname_to_id(text) {
- text = text.replace(/__dot__/g, '.');
- text = text.replace(/__dash__/g, '-');
- return text;
+ function removePopupIndex(name) {
+ name = name.replace(new RegExp("__" + (popupIndex + 1) + "$"), '');
+ return name;
}
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 = addPopupIndex(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');
+ relatedWindows.push(win);
win.focus();
return false;
}
@@ -42,13 +52,17 @@
}
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 = removePopupIndex(win.name);
+ const elem = document.getElementById(name);
+ if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) {
elem.value += ',' + chosenId;
} else {
document.getElementById(name).value = chosenId;
}
+ const index = relatedWindows.indexOf(win);
+ if (index > -1) {
+ relatedWindows.splice(index, 1);
+ }
win.close();
}
@@ -57,15 +71,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 {
@@ -73,15 +87,46 @@
}
}
+ function updateRelatedSelectsOptions(currentSelect, win, objId, newRepr, newId) {
+ // After create/edit a model from the options next to the current
+ // select (+ or :pencil:) update ForeignKey PK of the rest of selects
+ // in the page.
+
+ const path = win.location.pathname;
+ // Extract the model from the popup url '.../
/add/' or
+ // '...///change/' depending the action (add or change).
+ const modelName = path.split('/')[path.split('/').length - (objId ? 4 : 3)];
+ // Exclude autocomplete selects.
+ const selectsRelated = document.querySelectorAll(`[data-model-ref="${modelName}"] select:not(.admin-autocomplete)`);
+
+ selectsRelated.forEach(function(select) {
+ if (currentSelect === select) {
+ return;
+ }
+
+ let option = select.querySelector(`option[value="${objId}"]`);
+
+ if (!option) {
+ option = new Option(newRepr, newId);
+ select.options.add(option);
+ return;
+ }
+
+ option.textContent = newRepr;
+ option.value = newId;
+ });
+ }
+
function dismissAddRelatedObjectPopup(win, newId, newRepr) {
- var name = windowname_to_id(win.name);
- var elem = document.getElementById(name);
+ const name = removePopupIndex(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);
+ updateRelatedSelectsOptions(elem, win, null, newRepr, newId);
} 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,49 +135,58 @@
// 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);
}
+ const index = relatedWindows.indexOf(win);
+ if (index > -1) {
+ relatedWindows.splice(index, 1);
+ }
win.close();
}
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 = removePopupIndex(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;
this.value = newId;
}
- });
+ }).trigger('change');
+ updateRelatedSelectsOptions(selects[0], win, objId, newRepr, newId);
selects.next().find('.select2-selection__rendered').each(function() {
// The element can have a clear button as a child.
// Use the lastChild to modify only the displayed value.
this.lastChild.textContent = newRepr;
this.title = newRepr;
});
+ const index = relatedWindows.indexOf(win);
+ if (index > -1) {
+ relatedWindows.splice(index, 1);
+ }
win.close();
}
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 = removePopupIndex(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();
}
}).trigger('change');
+ const index = relatedWindows.indexOf(win);
+ if (index > -1) {
+ relatedWindows.splice(index, 1);
+ }
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;
@@ -140,20 +194,26 @@
window.dismissAddRelatedObjectPopup = dismissAddRelatedObjectPopup;
window.dismissChangeRelatedObjectPopup = dismissChangeRelatedObjectPopup;
window.dismissDeleteRelatedObjectPopup = dismissDeleteRelatedObjectPopup;
+ window.dismissChildPopups = dismissChildPopups;
// Kept for backward compatibility
window.showAddAnotherPopup = showRelatedObjectPopup;
window.dismissAddAnotherPopup = dismissAddRelatedObjectPopup;
+ window.addEventListener('unload', function(evt) {
+ window.dismissChildPopups();
+ });
+
$(document).ready(function() {
+ setPopupIndex();
$("a[data-popup-opener]").on('click', function(event) {
event.preventDefault();
opener.dismissRelatedLookupPopup(window, $(this).data("popup-opener"));
});
- $('body').on('click', '.related-widget-wrapper-link', function(e) {
+ $('body').on('click', '.related-widget-wrapper-link[data-popup="yes"]', 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 +221,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 +230,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/static/admin/js/autocomplete.js b/static/admin/js/autocomplete.js
index 65c0702..d3daeab 100644
--- a/static/admin/js/autocomplete.js
+++ b/static/admin/js/autocomplete.js
@@ -1,24 +1,22 @@
-(function($) {
- 'use strict';
- var init = function($element, options) {
- var settings = $.extend({
- ajax: {
- data: function(params) {
- return {
- term: params.term,
- page: params.page
- };
- }
- }
- }, options);
- $element.select2(settings);
- };
+'use strict';
+{
+ const $ = django.jQuery;
- $.fn.djangoAdminSelect2 = function(options) {
- var settings = $.extend({}, options);
+ $.fn.djangoAdminSelect2 = function() {
$.each(this, function(i, element) {
- var $element = $(element);
- init($element, settings);
+ $(element).select2({
+ ajax: {
+ data: (params) => {
+ return {
+ term: params.term,
+ page: params.page,
+ app_label: element.dataset.appLabel,
+ model_name: element.dataset.modelName,
+ field_name: element.dataset.fieldName
+ };
+ }
+ }
+ });
});
return this;
};
@@ -29,9 +27,7 @@
$('.admin-autocomplete').not('[name*=__prefix__]').djangoAdminSelect2();
});
- $(document).on('formset:added', (function() {
- return function(event, $newFormset) {
- return $newFormset.find('.admin-autocomplete').djangoAdminSelect2();
- };
- })(this));
-}(django.jQuery));
+ document.addEventListener('formset:added', (event) => {
+ $(event.target).find('.admin-autocomplete').djangoAdminSelect2();
+ });
+}
diff --git a/static/admin/js/calendar.js b/static/admin/js/calendar.js
index a4c047a..a62d10a 100644
--- a/static/admin/js/calendar.js
+++ b/static/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/static/admin/js/cancel.js b/static/admin/js/cancel.js
index 04ec812..3069c6f 100644
--- a/static/admin/js/cancel.js
+++ b/static/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/static/admin/js/change_form.js b/static/admin/js/change_form.js
index 4797383..96a4c62 100644
--- a/static/admin/js/change_form.js
+++ b/static/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/static/admin/js/collapse.js b/static/admin/js/collapse.js
index 3123878..c6c7b0f 100644
--- a/static/admin/js/collapse.js
+++ b/static/admin/js/collapse.js
@@ -1,52 +1,43 @@
/*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);
h2.appendChild(document.createTextNode(')'));
}
}
- // Add toggle to anchor tag
- var toggles = document.querySelectorAll('fieldset.collapse a.collapse-toggle');
- var toggleFunc = function(ev) {
- ev.preventDefault();
- var fieldset = closestElem(this, 'fieldset');
- if (fieldset.classList.contains('collapsed')) {
- // Show
- this.textContent = gettext('Hide');
- fieldset.classList.remove('collapsed');
- } else {
- // Hide
- this.textContent = gettext('Show');
- fieldset.classList.add('collapsed');
+ // Add toggle to hide/show anchor tag
+ const toggleFunc = function(ev) {
+ if (ev.target.matches('.collapse-toggle')) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ const fieldset = ev.target.closest('fieldset');
+ if (fieldset.classList.contains('collapsed')) {
+ // Show
+ ev.target.textContent = gettext('Hide');
+ fieldset.classList.remove('collapsed');
+ } else {
+ // Hide
+ ev.target.textContent = gettext('Show');
+ fieldset.classList.add('collapsed');
+ }
}
};
- for (i = 0; i < toggles.length; i++) {
- toggles[i].addEventListener('click', toggleFunc);
- }
+ document.querySelectorAll('fieldset.module').forEach(function(el) {
+ el.addEventListener('click', toggleFunc);
+ });
});
-})();
+}
diff --git a/static/admin/js/core.js b/static/admin/js/core.js
index 591394e..afdae28 100644
--- a/static/admin/js/core.js
+++ b/static/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]);
+// Core JavaScript helper functions
+'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)];
@@ -153,36 +130,35 @@ function findPosY(obj) {
return result;
};
-// ----------------------------------------------------------------------------
-// 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 object extensions
+ // ----------------------------------------------------------------------------
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":
- day = date[i];
- break;
- case "%m":
- month = date[i] - 1;
- break;
- case "%Y":
+ case "%d":
+ day = date[i];
+ break;
+ case "%m":
+ month = date[i] - 1;
+ break;
+ case "%Y":
+ year = date[i];
+ break;
+ case "%y":
+ // 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];
- break;
- case "%y":
- year = date[i];
- break;
+ } 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/static/admin/js/filters.js b/static/admin/js/filters.js
new file mode 100644
index 0000000..ba691ac
--- /dev/null
+++ b/static/admin/js/filters.js
@@ -0,0 +1,30 @@
+/**
+ * Persist changelist filters state (collapsed/expanded).
+ */
+'use strict';
+{
+ // Init filters.
+ let filters = JSON.parse(sessionStorage.getItem('django.admin.filtersState'));
+
+ if (!filters) {
+ filters = {};
+ }
+
+ Object.entries(filters).forEach(([key, value]) => {
+ const detailElement = document.querySelector(`[data-filter-title='${key}']`);
+
+ // Check if the filter is present, it could be from other view.
+ if (detailElement) {
+ value ? detailElement.setAttribute('open', '') : detailElement.removeAttribute('open');
+ }
+ });
+
+ // Save filter state when clicks.
+ const details = document.querySelectorAll('details');
+ details.forEach(detail => {
+ detail.addEventListener('toggle', event => {
+ filters[`${event.target.dataset.filterTitle}`] = detail.open;
+ sessionStorage.setItem('django.admin.filtersState', JSON.stringify(filters));
+ });
+ });
+}
diff --git a/static/admin/js/inlines.js b/static/admin/js/inlines.js
index 045ef1e..e9a1dfe 100644
--- a/static/admin/js/inlines.js
+++ b/static/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,102 +58,163 @@
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)
+ 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);
- 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();
+ 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);
+ }
+ row.get(0).dispatchEvent(new CustomEvent("formset:added", {
+ bubbles: true,
+ detail: {
+ formsetName: options.prefix
}
- // 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);
+ }));
+ };
+
+ /**
+ * 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.dispatchEvent(new CustomEvent("formset:removed", {
+ detail: {
+ formsetName: options.prefix
}
- $(document).trigger('formset:added', [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;
};
/* Setup plugin defaults */
$.fn.formset.defaults = {
- prefix: "form", // The form prefix for your django formset
- addText: "add another", // Text for the add link
- deleteText: "remove", // Text for the delete link
- addCssClass: "add-row", // CSS class applied to the add link
- deleteCssClass: "delete-row", // CSS class applied to the delete link
- emptyCssClass: "empty-row", // CSS class applied to the empty row
- formCssClass: "dynamic-form", // CSS class applied to each form in a formset
- added: null, // Function called each time a new form is added
- removed: null, // Function called each time a form is deleted
- addButton: null // Existing add button to use
+ prefix: "form", // The form prefix for your django formset
+ addText: "add another", // Text for the add link
+ deleteText: "remove", // Text for the delete link
+ addCssClass: "add-row", // CSS class applied to the add link
+ deleteCssClass: "delete-row", // CSS class applied to the delete link
+ emptyCssClass: "empty-row", // CSS class applied to the empty row
+ formCssClass: "dynamic-form", // CSS class applied to each form in a formset
+ added: null, // Function called each time a new form is added
+ removed: null, // Function called each time a form is deleted
+ addButton: null // Existing add button to use
};
// 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 +222,22 @@
}
};
- 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('-');
- SelectFilter.init(value.id, namearr[namearr.length - 1], false);
+ SelectFilter.init(value.id, this.dataset.fieldName, false);
});
$('.selectfilterstacked').each(function(index, value) {
- var namearr = value.name.split('-');
- SelectFilter.init(value.id, namearr[namearr.length - 1], true);
+ SelectFilter.init(value.id, this.dataset.fieldName, 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 +257,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 +270,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,28 +286,32 @@
}
};
- 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('-');
- SelectFilter.init(value.id, namearr[namearr.length - 1], false);
+ SelectFilter.init(value.id, this.dataset.fieldName, false);
});
$(".selectfilterstacked").each(function(index, value) {
- var namearr = value.name.split('-');
- SelectFilter.init(value.id, namearr[namearr.length - 1], true);
+ SelectFilter.init(value.id, this.dataset.fieldName, 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 = [];
$.each(dependency_list, function(i, field_name) {
- dependencies.push('#' + row.find('.form-row .field-' + field_name).find('input, select, textarea').attr('id'));
+ // Dependency in a fieldset.
+ let field_element = row.find('.form-row .field-' + field_name);
+ // Dependency without a fieldset.
+ if (!field_element.length) {
+ field_element = row.find('.form-row.field-' + field_name);
+ }
+ dependencies.push('#' + field_element.find('input, select, textarea').attr('id'));
});
if (dependencies.length) {
input.prepopulate(dependencies, input.attr('maxlength'));
@@ -280,19 +341,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/static/admin/js/jquery.init.js b/static/admin/js/jquery.init.js
index f3ac162..f40b27f 100644
--- a/static/admin/js/jquery.init.js
+++ b/static/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/static/admin/js/nav_sidebar.js b/static/admin/js/nav_sidebar.js
new file mode 100644
index 0000000..261a9d4
--- /dev/null
+++ b/static/admin/js/nav_sidebar.js
@@ -0,0 +1,102 @@
+'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;
+ }
+ }
+ function disableNavFilterTabbing() {
+ document.getElementById('nav-filter').tabIndex = -1;
+ }
+ function enableNavFilterTabbing() {
+ document.getElementById('nav-filter').tabIndex = 0;
+ }
+
+ const main = document.getElementById('main');
+ let navSidebarIsOpen = localStorage.getItem('django.admin.navSidebarIsOpen');
+ if (navSidebarIsOpen === null) {
+ navSidebarIsOpen = 'true';
+ }
+ if (navSidebarIsOpen === 'false') {
+ disableNavLinkTabbing();
+ disableNavFilterTabbing();
+ }
+ main.classList.toggle('shifted', navSidebarIsOpen === 'true');
+
+ toggleNavSidebar.addEventListener('click', function() {
+ if (navSidebarIsOpen === 'true') {
+ navSidebarIsOpen = 'false';
+ disableNavLinkTabbing();
+ disableNavFilterTabbing();
+ } else {
+ navSidebarIsOpen = 'true';
+ enableNavLinkTabbing();
+ enableNavFilterTabbing();
+ }
+ localStorage.setItem('django.admin.navSidebarIsOpen', navSidebarIsOpen);
+ main.classList.toggle('shifted');
+ });
+ }
+
+ function initSidebarQuickFilter() {
+ const options = [];
+ const navSidebar = document.getElementById('nav-sidebar');
+ if (!navSidebar) {
+ return;
+ }
+ navSidebar.querySelectorAll('th[scope=row] a').forEach((container) => {
+ options.push({title: container.innerHTML, node: container});
+ });
+
+ function checkValue(event) {
+ let filterValue = event.target.value;
+ if (filterValue) {
+ filterValue = filterValue.toLowerCase();
+ }
+ if (event.key === 'Escape') {
+ filterValue = '';
+ event.target.value = ''; // clear input
+ }
+ let matches = false;
+ for (const o of options) {
+ let displayValue = '';
+ if (filterValue) {
+ if (o.title.toLowerCase().indexOf(filterValue) === -1) {
+ displayValue = 'none';
+ } else {
+ matches = true;
+ }
+ }
+ // show/hide parent
+ o.node.parentNode.parentNode.style.display = displayValue;
+ }
+ if (!filterValue || matches) {
+ event.target.classList.remove('no-results');
+ } else {
+ event.target.classList.add('no-results');
+ }
+ sessionStorage.setItem('django.admin.navSidebarFilterValue', filterValue);
+ }
+
+ const nav = document.getElementById('nav-filter');
+ nav.addEventListener('change', checkValue, false);
+ nav.addEventListener('input', checkValue, false);
+ nav.addEventListener('keyup', checkValue, false);
+
+ const storedValue = sessionStorage.getItem('django.admin.navSidebarFilterValue');
+ if (storedValue) {
+ nav.value = storedValue;
+ checkValue({target: nav, key: ''});
+ }
+ }
+ window.initSidebarQuickFilter = initSidebarQuickFilter;
+ initSidebarQuickFilter();
+}
diff --git a/static/admin/js/popup_response.js b/static/admin/js/popup_response.js
index b4a07e7..2b1d3dd 100644
--- a/static/admin/js/popup_response.js
+++ b/static/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/static/admin/js/prepopulate.js b/static/admin/js/prepopulate.js
index bef45a3..89e95ab 100644
--- a/static/admin/js/prepopulate.js
+++ b/static/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/static/admin/js/prepopulate_init.js b/static/admin/js/prepopulate_init.js
index 184df92..a58841f 100644
--- a/static/admin/js/prepopulate_init.js
+++ b/static/admin/js/prepopulate_init.js
@@ -1,10 +1,15 @@
-(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');
+ $(
+ '.empty-form .form-row .field-' + field.name +
+ ', .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/static/admin/js/urlify.js b/static/admin/js/urlify.js
index 2d70dcd..61dedb2 100644
--- a/static/admin/js/urlify.js
+++ b/static/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
+ 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 (var k in Downcoder.map) {
- if (Downcoder.map.hasOwnProperty(k)) {
- Downcoder.chars.push(k);
- }
+ for (const lookup of ALL_DOWNCODE_MAPS) {
+ Object.assign(Downcoder.map, lookup);
}
- Downcoder.regex = new RegExp(Downcoder.chars.join('|'), 'g');
+ Downcoder.regex = new RegExp(Object.keys(Downcoder.map).join('|'), 'g');
}
};
@@ -160,36 +148,23 @@
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
// characters, whitespace, and dash; remove other characters.
s = XRegExp.replace(s, XRegExp('[^-_\\p{L}\\p{N}\\s]', 'g'), '');
} else {
- s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
+ s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
}
- s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
- 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
+ s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
+ 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;
}
window.URLify = URLify;
-})();
+}
diff --git a/static/admin/js/vendor/jquery/LICENSE.txt b/static/admin/js/vendor/jquery/LICENSE.txt
index d930e62..f642c3f 100644
--- a/static/admin/js/vendor/jquery/LICENSE.txt
+++ b/static/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 OpenJS Foundation and other contributors, https://openjsf.org/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/static/admin/js/vendor/jquery/jquery.js b/static/admin/js/vendor/jquery/jquery.js
index 9b5206b..fc6c299 100644
--- a/static/admin/js/vendor/jquery/jquery.js
+++ b/static/admin/js/vendor/jquery/jquery.js
@@ -1,15 +1,15 @@
/*!
- * jQuery JavaScript Library v3.3.1
+ * jQuery JavaScript Library v3.6.0
* https://jquery.com/
*
* Includes Sizzle.js
* https://sizzlejs.com/
*
- * Copyright JS Foundation and other contributors
+ * Copyright OpenJS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
- * Date: 2018-01-20T17:24Z
+ * Date: 2021-03-02T17:08Z
*/
( 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;
@@ -73,12 +76,16 @@ var support = {};
var isFunction = function isFunction( obj ) {
- // Support: Chrome <=57, Firefox <=52
- // In some browsers, typeof returns "function" for HTML elements
- // (i.e., `typeof document.createElement( "object" ) === "function"`).
- // We don't want to classify *any* DOM node as a function.
- return typeof obj === "function" && typeof obj.nodeType !== "number";
- };
+ // Support: Chrome <=57, Firefox <=52
+ // In some browsers, typeof returns "function" for HTML elements
+ // (i.e., `typeof document.createElement( "object" ) === "function"`).
+ // We don't want to classify *any* DOM node as a function.
+ // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5
+ // Plus for old WebKit, typeof returns "function" for HTML collections
+ // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756)
+ return typeof obj === "function" && typeof obj.nodeType !== "number" &&
+ typeof obj.item !== "function";
+ };
var isWindow = function isWindow( obj ) {
@@ -86,25 +93,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 +151,7 @@ function toType( obj ) {
var
- version = "3.3.1",
+ version = "3.6.0",
// Define a local copy of jQuery
jQuery = function( selector, context ) {
@@ -137,11 +159,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 +225,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,25 +288,28 @@ jQuery.extend = jQuery.fn.extend = function() {
// Extend the base object
for ( name in options ) {
- src = target[ name ];
copy = options[ name ];
+ // Prevent Object.prototype pollution
// Prevent never-ending loop
- if ( target === copy ) {
+ if ( name === "__proto__" || target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
( copyIsArray = Array.isArray( copy ) ) ) ) {
+ src = target[ name ];
- 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 );
@@ -329,9 +362,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 ) {
@@ -340,9 +370,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 ) {
@@ -366,13 +397,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 || [];
@@ -381,7 +405,7 @@ jQuery.extend( {
if ( isArrayLike( Object( arr ) ) ) {
jQuery.merge( ret,
typeof arr === "string" ?
- [ arr ] : arr
+ [ arr ] : arr
);
} else {
push.call( ret, arr );
@@ -459,7 +483,7 @@ jQuery.extend( {
}
// Flatten any nested arrays
- return concat.apply( [], ret );
+ return flat( ret );
},
// A global GUID counter for objects
@@ -476,9 +500,9 @@ if ( typeof Symbol === "function" ) {
// Populate the class2type map
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
-function( i, name ) {
- class2type[ "[object " + name + "]" ] = name.toLowerCase();
-} );
+ function( _i, name ) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+ } );
function isArrayLike( obj ) {
@@ -498,17 +522,16 @@ function isArrayLike( obj ) {
}
var Sizzle =
/*!
- * Sizzle CSS Selector Engine v2.3.3
+ * Sizzle CSS Selector Engine v2.3.6
* 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: 2021-02-16
*/
-(function( window ) {
-
+( function( window ) {
var i,
support,
Expr,
@@ -539,6 +562,7 @@ var i,
classCache = createCache(),
tokenCache = createCache(),
compilerCache = createCache(),
+ nonnativeSelectorCache = createCache(),
sortOrder = function( a, b ) {
if ( a === b ) {
hasDuplicate = true;
@@ -547,61 +571,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 + "$" ),
@@ -612,16 +646,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,
@@ -634,18 +671,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 );
},
@@ -661,7 +701,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
@@ -676,9 +717,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" }
);
@@ -686,18 +727,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
@@ -705,8 +748,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;
}
};
@@ -730,24 +774,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
@@ -766,7 +807,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 ) {
@@ -776,12 +817,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 ) );
@@ -791,50 +832,62 @@ function Sizzle( selector, context, results, seed ) {
// Take advantage of querySelectorAll
if ( support.qsa &&
- !compilerCache[ selector + " " ] &&
- (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
-
- if ( nodeType !== 1 ) {
- newContext = context;
- newSelector = selector;
+ !nonnativeSelectorCache[ selector + " " ] &&
+ ( !rbuggyQSA || !rbuggyQSA.test( 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" );
}
}
}
@@ -855,12 +908,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;
}
@@ -879,17 +934,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;
}
@@ -901,11 +958,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;
}
}
@@ -927,7 +984,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;
}
@@ -955,7 +1012,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;
};
}
@@ -998,7 +1055,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;
@@ -1020,21 +1077,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 ] );
}
}
- });
- });
+ } );
+ } );
}
/**
@@ -1055,10 +1112,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 && elem.namespaceURI,
+ docElem = elem && ( elem.ownerDocument || elem ).documentElement;
+
+ // Support: IE <=8
+ // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
+ // https://bugs.jquery.com/ticket/4833
+ return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
};
/**
@@ -1071,7 +1131,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;
}
@@ -1080,10 +1144,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 ) {
@@ -1095,25 +1163,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 );
@@ -1122,38 +1201,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 );
@@ -1161,7 +1240,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 ];
}
@@ -1169,8 +1248,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 ];
}
@@ -1183,7 +1262,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 );
@@ -1198,12 +1277,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 );
}
@@ -1215,7 +1295,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 );
}
@@ -1236,10 +1316,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,
@@ -1253,78 +1337,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, "*" );
@@ -1333,11 +1437,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
---------------------------------------------------------------------- */
@@ -1354,11 +1458,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;
}
@@ -1387,7 +1491,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
@@ -1395,13 +1503,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;
}
@@ -1414,6 +1533,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;
@@ -1429,8 +1549,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 ?
@@ -1444,26 +1570,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;
};
@@ -1475,16 +1607,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 ) ) ) {
@@ -1493,32 +1619,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 ) :
@@ -1528,13 +1668,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 ) {
@@ -1557,7 +1697,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 );
}
@@ -1585,17 +1725,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 );
@@ -1604,6 +1748,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;
@@ -1631,19 +1776,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)
@@ -1654,22 +1801,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;
@@ -1677,26 +1827,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)
@@ -1709,7 +1861,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;
};
@@ -1719,10 +1873,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 ) {
@@ -1738,6 +1898,8 @@ Expr = Sizzle.selectors = {
result += "";
+ /* eslint-disable max-len */
+
return operator === "=" ? result === check :
operator === "!=" ? result !== check :
operator === "^=" ? check && result.indexOf( check ) === 0 :
@@ -1746,10 +1908,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";
@@ -1761,7 +1925,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,
@@ -1775,7 +1939,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 ) {
@@ -1783,6 +1947,7 @@ Expr = Sizzle.selectors = {
return false;
}
}
+
// Reverse direction for :only-* (if we haven't yet done so)
start = dir = type === "only" && !start && "nextSibling";
}
@@ -1798,22 +1963,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 ) {
@@ -1823,16 +1988,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 ];
@@ -1842,9 +2009,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 :
@@ -1853,12 +2021,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 ];
}
@@ -1879,6 +2048,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
@@ -1898,15 +2068,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 );
};
@@ -1917,8 +2087,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
@@ -1927,39 +2099,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
@@ -1969,25 +2142,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 ) {
@@ -2000,7 +2174,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
@@ -2008,16 +2184,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;
}
@@ -2026,6 +2206,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.)
@@ -2039,7 +2220,7 @@ Expr = Sizzle.selectors = {
},
"parent": function( elem ) {
- return !Expr.pseudos["empty"]( elem );
+ return !Expr.pseudos[ "empty" ]( elem );
},
// Element/input types
@@ -2063,57 +2244,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 } ) {
@@ -2144,37 +2330,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 );
}
}
@@ -2191,6 +2379,7 @@ tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
soFar.length :
soFar ?
Sizzle.error( selector ) :
+
// Cache the tokens
tokenCache( selector, groups ).slice( 0 );
};
@@ -2200,7 +2389,7 @@ function toSelector( tokens ) {
len = tokens.length,
selector = "";
for ( ; i < len; i++ ) {
- selector += tokens[i].value;
+ selector += tokens[ i ].value;
}
return selector;
}
@@ -2213,9 +2402,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 );
}
@@ -2230,7 +2420,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;
@@ -2238,27 +2428,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;
}
}
@@ -2274,20 +2466,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;
}
@@ -2300,7 +2492,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 ) {
@@ -2320,14 +2512,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 ) ?
@@ -2335,6 +2531,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 ) ?
@@ -2358,8 +2555,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 );
}
}
}
@@ -2367,25 +2564,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 );
}
}
}
@@ -2403,14 +2602,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)
@@ -2422,38 +2621,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 )
);
}
@@ -2474,28 +2678,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;
}
@@ -2507,8 +2723,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--;
}
@@ -2532,16 +2749,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 );
}
}
}
@@ -2582,13 +2800,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 {
@@ -2597,7 +2816,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;
@@ -2617,7 +2839,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 || [];
@@ -2626,11 +2848,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;
@@ -2643,20 +2866,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 );
@@ -2687,7 +2912,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
@@ -2698,58 +2923,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 );
@@ -2802,9 +3028,9 @@ var rneedsContext = jQuery.expr.match.needsContext;
function nodeName( elem, name ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
-};
+}
var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
@@ -3118,7 +3344,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 ) {
@@ -3133,10 +3359,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 ) {
@@ -3146,18 +3372,24 @@ jQuery.each( {
return siblings( elem.firstChild );
},
contents: function( elem ) {
- if ( nodeName( elem, "iframe" ) ) {
- return elem.contentDocument;
- }
+ if ( elem.contentDocument != null &&
+
+ // Support: IE 11+
+ // elements with no `data` attribute has an object
+ // `contentDocument` with a `null` prototype.
+ getProto( 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 elem.contentDocument;
+ }
- return jQuery.merge( [], elem.childNodes );
+ // 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 ) {
@@ -3489,7 +3721,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 ] ];
@@ -3769,8 +4001,8 @@ jQuery.extend( {
resolveContexts = Array( i ),
resolveValues = slice.call( arguments ),
- // the master Deferred
- master = jQuery.Deferred(),
+ // the primary Deferred
+ primary = jQuery.Deferred(),
// subordinate callback factory
updateFunc = function( i ) {
@@ -3778,30 +4010,30 @@ jQuery.extend( {
resolveContexts[ i ] = this;
resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
if ( !( --remaining ) ) {
- master.resolveWith( resolveContexts, resolveValues );
+ primary.resolveWith( resolveContexts, resolveValues );
}
};
};
// Single- and empty arguments are adopted like Promise.resolve
if ( remaining <= 1 ) {
- adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
+ adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject,
!remaining );
// Use .then() to unwrap secondary thenables (cf. gh-3000)
- if ( master.state() === "pending" ||
+ if ( primary.state() === "pending" ||
isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
- return master.then();
+ return primary.then();
}
}
// Multiple arguments are aggregated like Promise.all array elements
while ( i-- ) {
- adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
+ adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject );
}
- return master.promise();
+ return primary.promise();
}
} );
@@ -3942,7 +4174,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 );
};
}
@@ -3952,8 +4184,8 @@ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
for ( ; i < len; i++ ) {
fn(
elems[ i ], key, raw ?
- value :
- value.call( elems[ i ], i, fn( elems[ i ], key ) )
+ value :
+ value.call( elems[ i ], i, fn( elems[ i ], key ) )
);
}
}
@@ -3977,7 +4209,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();
}
@@ -4466,6 +4698,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;
@@ -4480,32 +4732,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 ) {
@@ -4522,7 +4753,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 ) {
@@ -4669,17 +4901,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 tags with their contents when inserted outside of
+ // the select element.
+ div.innerHTML = " ";
+ 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
@@ -4692,12 +4953,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 ) {
@@ -4741,7 +5004,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,
@@ -4805,13 +5068,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 );
}
@@ -4830,38 +5093,7 @@ 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/,
- rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
+var rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
function returnTrue() {
return true;
@@ -4871,8 +5103,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;
@@ -4955,8 +5198,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;
}
@@ -4980,7 +5223,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 ) {
@@ -5138,12 +5381,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
@@ -5172,9 +5418,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;
@@ -5266,12 +5513,12 @@ jQuery.event = {
get: isFunction( hook ) ?
function() {
if ( this.originalEvent ) {
- return hook( this.originalEvent );
+ return hook( this.originalEvent );
}
} :
function() {
if ( this.originalEvent ) {
- return this.originalEvent[ name ];
+ return this.originalEvent[ name ];
}
},
@@ -5298,39 +5545,51 @@ jQuery.event = {
// Prevent triggered image.load events from bubbling to window.load
noBubble: true
},
- focus: {
+ click: {
- // 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;
+ // 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;
},
- delegateType: "focusout"
- },
- click: {
+ trigger: function( data ) {
- // 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;
+ // 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" );
}
},
@@ -5347,6 +5606,99 @@ 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();
+
+ // Support: Chrome 86+
+ // In Chrome, if an element having a focusout handler is blurred by
+ // clicking outside of it, it invokes the handler synchronously. If
+ // that handler calls `.remove()` on the element, the data is cleared,
+ // leaving `result` undefined. We need to guard against this.
+ return result && 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
@@ -5459,6 +5811,7 @@ jQuery.each( {
shiftKey: true,
view: true,
"char": true,
+ code: true,
charCode: true,
key: true,
keyCode: true,
@@ -5475,35 +5828,41 @@ jQuery.each( {
targetTouches: true,
toElement: true,
touches: true,
+ which: true
+}, jQuery.event.addProp );
- which: function( event ) {
- var button = event.button;
+jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
+ jQuery.event.special[ type ] = {
- // Add which for key events
- if ( event.which == null && rkeyEvent.test( event.type ) ) {
- return event.charCode != null ? event.charCode : event.keyCode;
- }
+ // Utilize native event if possible so blur/focus sequence is correct
+ setup: function() {
- // Add which for click: 1 === left; 2 === middle; 3 === right
- if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
- if ( button & 1 ) {
- return 1;
- }
+ // Claim the first handler
+ // dataPriv.set( this, "focus", ... )
+ // dataPriv.set( this, "blur", ... )
+ leverageNative( this, type, expectSync );
- if ( button & 2 ) {
- return 3;
- }
+ // Return false to allow normal processing in the caller
+ return false;
+ },
+ trigger: function() {
- if ( button & 4 ) {
- return 2;
- }
+ // Force setup before trigger
+ leverageNative( this, type );
- return 0;
- }
+ // Return non-false to allow normal event-path propagation
+ return true;
+ },
- return event.which;
- }
-}, jQuery.event.addProp );
+ // Suppress native focus or blur as it's already being fired
+ // in leverageNative.
+ _default: function() {
+ return true;
+ },
+
+ delegateType: delegateType
+ };
+} );
// Create mouseenter/leave events using mouseover/out and event-time checks
// so that event delegation works in jQuery.
@@ -5590,13 +5949,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/
@@ -5633,7 +5985,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;
@@ -5641,13 +5993,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++ ) {
@@ -5683,7 +6033,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,
@@ -5755,11 +6105,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 );
}
}
}
@@ -5781,7 +6133,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 );
@@ -5793,13 +6145,13 @@ function remove( elem, selector, keepData ) {
jQuery.extend( {
htmlPrefilter: function( html ) {
- return html.replace( rxhtmlTag, "<$1>$2>" );
+ 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 ) &&
@@ -6055,6 +6407,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" );
@@ -6095,8 +6468,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 );
@@ -6110,7 +6485,7 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
}
var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,
- reliableMarginLeftVal,
+ reliableTrDimensionsVal, reliableMarginLeftVal,
container = document.createElement( "div" ),
div = document.createElement( "div" );
@@ -6145,6 +6520,54 @@ 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!
+ //
+ // Support: Firefox 70+
+ // Only Firefox includes border widths
+ // in computed dimensions. (gh-4529)
+ 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;border-collapse:separate";
+ tr.style.cssText = "border:1px solid";
+
+ // Support: Chrome 86+
+ // Height set through cssText does not get applied.
+ // Computed height then comes back as 0.
+ tr.style.height = "1px";
+ trChild.style.height = "9px";
+
+ // Support: Android 8 Chrome 86+
+ // In our bodyBackground.html iframe,
+ // display for all div elements is set to "inline",
+ // which causes a problem only in Android 8 Chrome 86.
+ // Ensuring the div is display: block
+ // gets around this issue.
+ trChild.style.display = "block";
+
+ documentElement
+ .appendChild( table )
+ .appendChild( tr )
+ .appendChild( trChild );
+
+ trStyle = window.getComputedStyle( tr );
+ reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) +
+ parseInt( trStyle.borderTopWidth, 10 ) +
+ parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight;
+
+ documentElement.removeChild( table );
+ }
+ return reliableTrDimensionsVal;
}
} );
} )();
@@ -6167,7 +6590,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 );
}
@@ -6223,30 +6646,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;
@@ -6259,17 +6665,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
@@ -6340,7 +6763,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;
@@ -6350,9 +6776,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.
@@ -6363,22 +6796,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 ||
+
+ // 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" ) ||
+
+ // 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 ) {
- val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ];
+ isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
- // offsetWidth/offsetHeight provide border-box values
- valueIsBorderBox = true;
+ // 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
@@ -6424,6 +6873,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,
@@ -6479,7 +6935,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" );
}
@@ -6553,7 +7011,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 ) {
@@ -6569,28 +7027,39 @@ jQuery.each( [ "height", "width" ], function( i, dimension ) {
// Running getBoundingClientRect on a disconnected node
// in IE throws an error.
( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
- swap( elem, cssShow, function() {
- return getWidthOrHeight( elem, dimension, extra );
- } ) :
- getWidthOrHeight( elem, dimension, extra );
+ swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, dimension, extra );
+ } ) :
+ getWidthOrHeight( elem, dimension, extra );
}
},
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 ] ) -
@@ -6620,7 +7089,7 @@ jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
swap( elem, { marginLeft: 0 }, function() {
return elem.getBoundingClientRect().left;
} )
- ) + "px";
+ ) + "px";
}
}
);
@@ -6758,9 +7227,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;
@@ -7004,7 +7473,7 @@ function defaultPrefilter( elem, props, opts ) {
anim.done( function() {
- /* eslint-enable no-loop-func */
+ /* eslint-enable no-loop-func */
// The final step of a "hide" animation is actually hiding the element
if ( !hidden ) {
@@ -7124,7 +7593,7 @@ function Animation( elem, properties, options ) {
tweens: [],
createTween: function( prop, end ) {
var tween = jQuery.Tween( elem, animation.opts, prop, end,
- animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
animation.tweens.push( tween );
return tween;
},
@@ -7297,7 +7766,8 @@ jQuery.fn.extend( {
anim.stop( true );
}
};
- doAnimation.finish = doAnimation;
+
+ doAnimation.finish = doAnimation;
return empty || optall.queue === false ?
this.each( doAnimation ) :
@@ -7315,7 +7785,7 @@ jQuery.fn.extend( {
clearQueue = type;
type = undefined;
}
- if ( clearQueue && type !== false ) {
+ if ( clearQueue ) {
this.queue( type || "fx", [] );
}
@@ -7398,7 +7868,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" ?
@@ -7619,7 +8089,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 ) {
@@ -7937,8 +8407,8 @@ jQuery.fn.extend( {
if ( this.setAttribute ) {
this.setAttribute( "class",
className || value === false ?
- "" :
- dataPriv.get( this, "__className__" ) || ""
+ "" :
+ dataPriv.get( this, "__className__" ) || ""
);
}
}
@@ -7953,7 +8423,7 @@ jQuery.fn.extend( {
while ( ( elem = this[ i++ ] ) ) {
if ( elem.nodeType === 1 &&
( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
- return true;
+ return true;
}
}
@@ -8243,7 +8713,7 @@ 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 );
@@ -8354,7 +8824,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 ) {
@@ -8363,7 +8836,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 ) {
@@ -8379,7 +8852,7 @@ if ( !support.focusin ) {
}
var location = window.location;
-var nonce = Date.now();
+var nonce = { guid: Date.now() };
var rquery = ( /\?/ );
@@ -8387,7 +8860,7 @@ var rquery = ( /\?/ );
// Cross-browser xml parsing
jQuery.parseXML = function( data ) {
- var xml;
+ var xml, parserErrorElem;
if ( !data || typeof data !== "string" ) {
return null;
}
@@ -8396,12 +8869,17 @@ jQuery.parseXML = function( data ) {
// IE throws on parseFromString with invalid input.
try {
xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
- } catch ( e ) {
- xml = undefined;
- }
+ } catch ( e ) {}
- if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
- jQuery.error( "Invalid XML: " + data );
+ parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ];
+ if ( !xml || parserErrorElem ) {
+ jQuery.error( "Invalid XML: " + (
+ parserErrorElem ?
+ jQuery.map( parserErrorElem.childNodes, function( el ) {
+ return el.textContent;
+ } ).join( "\n" ) :
+ data
+ ) );
}
return xml;
};
@@ -8467,6 +8945,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 ) ) ) {
@@ -8498,16 +8980,14 @@ jQuery.fn.extend( {
// Can add propHook for "elements" to filter or add form elements
var elements = jQuery.prop( this, "elements" );
return elements ? jQuery.makeArray( elements ) : this;
- } )
- .filter( function() {
+ } ).filter( function() {
var type = this.type;
// Use .is( ":disabled" ) so that fieldset[disabled] works
return this.name && !jQuery( this ).is( ":disabled" ) &&
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 ) {
@@ -8560,7 +9040,8 @@ var
// Anchor tag for parsing the document origin
originAnchor = document.createElement( "a" );
- originAnchor.href = location.href;
+
+originAnchor.href = location.href;
// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {
@@ -8941,8 +9422,8 @@ jQuery.extend( {
// Context for global events is callbackContext if it is a DOM node or jQuery collection
globalEventContext = s.context &&
( callbackContext.nodeType || callbackContext.jquery ) ?
- jQuery( callbackContext ) :
- jQuery.event,
+ jQuery( callbackContext ) :
+ jQuery.event,
// Deferreds
deferred = jQuery.Deferred(),
@@ -8969,12 +9450,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
@@ -9118,7 +9601,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)
@@ -9251,6 +9735,13 @@ jQuery.extend( {
response = ajaxHandleResponses( s, jqXHR, responses );
}
+ // Use a noop converter for missing script but not if jsonp
+ if ( !isSuccess &&
+ jQuery.inArray( "script", s.dataTypes ) > -1 &&
+ jQuery.inArray( "json", s.dataTypes ) < 0 ) {
+ s.converters[ "text script" ] = function() {};
+ }
+
// Convert no matter what (that way responseXXX fields are always set)
response = ajaxConvert( s, response, jqXHR, isSuccess );
@@ -9341,7 +9832,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
@@ -9362,8 +9853,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,
@@ -9373,7 +9873,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 );
+ }
} );
};
@@ -9656,24 +10165,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( "