##// END OF EJS Templates
Se logró solucionar el problema del ID replicado al momento de crear un campaña con template experiment
Renato-TUF -
r367:9e304f85f976
parent child
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,14
1 # Generated by Django 4.1.5 on 2023-01-31 16:15
2
3 from django.db import migrations
4
5
6 class Migration(migrations.Migration):
7
8 dependencies = [
9 ('abs', '0002_auto_20230117_0948'),
10 ('abs', '0002_initial'),
11 ]
12
13 operations = [
14 ]
@@ -0,0 +1,3
1 CREATE USER docker WITH PASSWORD docker;
2 CREATE DATABASE radarsys;
3 GRANT ALL PRIVILEGES ON DATABASE radarsys TO docker; No newline at end of file
@@ -0,0 +1,33
1 @media (prefers-color-scheme: dark) {
2 :root {
3 --primary: #264b5d;
4 --primary-fg: #f7f7f7;
5
6 --body-fg: #eeeeee;
7 --body-bg: #121212;
8 --body-quiet-color: #e0e0e0;
9 --body-loud-color: #ffffff;
10
11 --breadcrumbs-link-fg: #e0e0e0;
12 --breadcrumbs-bg: var(--primary);
13
14 --link-fg: #81d4fa;
15 --link-hover-color: #4ac1f7;
16 --link-selected-fg: #6f94c6;
17
18 --hairline-color: #272727;
19 --border-color: #353535;
20
21 --error-fg: #e35f5f;
22 --message-success-bg: #006b1b;
23 --message-warning-bg: #583305;
24 --message-error-bg: #570808;
25
26 --darkened-bg: #212121;
27 --selected-bg: #1b1b1b;
28 --selected-row: #00363a;
29
30 --close-button-bg: #333333;
31 --close-button-hover-bg: #666666;
32 }
33 }
@@ -0,0 +1,139
1 .sticky {
2 position: sticky;
3 top: 0;
4 max-height: 100vh;
5 }
6
7 .toggle-nav-sidebar {
8 z-index: 20;
9 left: 0;
10 display: flex;
11 align-items: center;
12 justify-content: center;
13 flex: 0 0 23px;
14 width: 23px;
15 border: 0;
16 border-right: 1px solid var(--hairline-color);
17 background-color: var(--body-bg);
18 cursor: pointer;
19 font-size: 1.25rem;
20 color: var(--link-fg);
21 padding: 0;
22 }
23
24 [dir="rtl"] .toggle-nav-sidebar {
25 border-left: 1px solid var(--hairline-color);
26 border-right: 0;
27 }
28
29 .toggle-nav-sidebar:hover,
30 .toggle-nav-sidebar:focus {
31 background-color: var(--darkened-bg);
32 }
33
34 #nav-sidebar {
35 z-index: 15;
36 flex: 0 0 275px;
37 left: -276px;
38 margin-left: -276px;
39 border-top: 1px solid transparent;
40 border-right: 1px solid var(--hairline-color);
41 background-color: var(--body-bg);
42 overflow: auto;
43 }
44
45 [dir="rtl"] #nav-sidebar {
46 border-left: 1px solid var(--hairline-color);
47 border-right: 0;
48 left: 0;
49 margin-left: 0;
50 right: -276px;
51 margin-right: -276px;
52 }
53
54 .toggle-nav-sidebar::before {
55 content: '\00BB';
56 }
57
58 .main.shifted .toggle-nav-sidebar::before {
59 content: '\00AB';
60 }
61
62 .main.shifted > #nav-sidebar {
63 margin-left: 0;
64 }
65
66 [dir="rtl"] .main.shifted > #nav-sidebar {
67 margin-right: 0;
68 }
69
70 #nav-sidebar .module th {
71 width: 100%;
72 overflow-wrap: anywhere;
73 }
74
75 #nav-sidebar .module th,
76 #nav-sidebar .module caption {
77 padding-left: 16px;
78 }
79
80 #nav-sidebar .module td {
81 white-space: nowrap;
82 }
83
84 [dir="rtl"] #nav-sidebar .module th,
85 [dir="rtl"] #nav-sidebar .module caption {
86 padding-left: 8px;
87 padding-right: 16px;
88 }
89
90 #nav-sidebar .current-app .section:link,
91 #nav-sidebar .current-app .section:visited {
92 color: var(--header-color);
93 font-weight: bold;
94 }
95
96 #nav-sidebar .current-model {
97 background: var(--selected-row);
98 }
99
100 .main > #nav-sidebar + .content {
101 max-width: calc(100% - 23px);
102 }
103
104 .main.shifted > #nav-sidebar + .content {
105 max-width: calc(100% - 299px);
106 }
107
108 @media (max-width: 767px) {
109 #nav-sidebar, #toggle-nav-sidebar {
110 display: none;
111 }
112
113 .main > #nav-sidebar + .content,
114 .main.shifted > #nav-sidebar + .content {
115 max-width: 100%;
116 }
117 }
118
119 #nav-filter {
120 width: 100%;
121 box-sizing: border-box;
122 padding: 2px 5px;
123 margin: 5px 0;
124 border: 1px solid var(--border-color);
125 background-color: var(--darkened-bg);
126 color: var(--body-fg);
127 }
128
129 #nav-filter:focus {
130 border-color: var(--body-quiet-color);
131 }
132
133 #nav-filter.no-results {
134 background: var(--message-error-bg);
135 }
136
137 #nav-sidebar table {
138 width: 100%;
139 }
@@ -0,0 +1,30
1 /**
2 * Persist changelist filters state (collapsed/expanded).
3 */
4 'use strict';
5 {
6 // Init filters.
7 let filters = JSON.parse(sessionStorage.getItem('django.admin.filtersState'));
8
9 if (!filters) {
10 filters = {};
11 }
12
13 Object.entries(filters).forEach(([key, value]) => {
14 const detailElement = document.querySelector(`[data-filter-title='${key}']`);
15
16 // Check if the filter is present, it could be from other view.
17 if (detailElement) {
18 value ? detailElement.setAttribute('open', '') : detailElement.removeAttribute('open');
19 }
20 });
21
22 // Save filter state when clicks.
23 const details = document.querySelectorAll('details');
24 details.forEach(detail => {
25 detail.addEventListener('toggle', event => {
26 filters[`${event.target.dataset.filterTitle}`] = detail.open;
27 sessionStorage.setItem('django.admin.filtersState', JSON.stringify(filters));
28 });
29 });
30 }
@@ -0,0 +1,102
1 'use strict';
2 {
3 const toggleNavSidebar = document.getElementById('toggle-nav-sidebar');
4 if (toggleNavSidebar !== null) {
5 const navLinks = document.querySelectorAll('#nav-sidebar a');
6 function disableNavLinkTabbing() {
7 for (const navLink of navLinks) {
8 navLink.tabIndex = -1;
9 }
10 }
11 function enableNavLinkTabbing() {
12 for (const navLink of navLinks) {
13 navLink.tabIndex = 0;
14 }
15 }
16 function disableNavFilterTabbing() {
17 document.getElementById('nav-filter').tabIndex = -1;
18 }
19 function enableNavFilterTabbing() {
20 document.getElementById('nav-filter').tabIndex = 0;
21 }
22
23 const main = document.getElementById('main');
24 let navSidebarIsOpen = localStorage.getItem('django.admin.navSidebarIsOpen');
25 if (navSidebarIsOpen === null) {
26 navSidebarIsOpen = 'true';
27 }
28 if (navSidebarIsOpen === 'false') {
29 disableNavLinkTabbing();
30 disableNavFilterTabbing();
31 }
32 main.classList.toggle('shifted', navSidebarIsOpen === 'true');
33
34 toggleNavSidebar.addEventListener('click', function() {
35 if (navSidebarIsOpen === 'true') {
36 navSidebarIsOpen = 'false';
37 disableNavLinkTabbing();
38 disableNavFilterTabbing();
39 } else {
40 navSidebarIsOpen = 'true';
41 enableNavLinkTabbing();
42 enableNavFilterTabbing();
43 }
44 localStorage.setItem('django.admin.navSidebarIsOpen', navSidebarIsOpen);
45 main.classList.toggle('shifted');
46 });
47 }
48
49 function initSidebarQuickFilter() {
50 const options = [];
51 const navSidebar = document.getElementById('nav-sidebar');
52 if (!navSidebar) {
53 return;
54 }
55 navSidebar.querySelectorAll('th[scope=row] a').forEach((container) => {
56 options.push({title: container.innerHTML, node: container});
57 });
58
59 function checkValue(event) {
60 let filterValue = event.target.value;
61 if (filterValue) {
62 filterValue = filterValue.toLowerCase();
63 }
64 if (event.key === 'Escape') {
65 filterValue = '';
66 event.target.value = ''; // clear input
67 }
68 let matches = false;
69 for (const o of options) {
70 let displayValue = '';
71 if (filterValue) {
72 if (o.title.toLowerCase().indexOf(filterValue) === -1) {
73 displayValue = 'none';
74 } else {
75 matches = true;
76 }
77 }
78 // show/hide parent <TR>
79 o.node.parentNode.parentNode.style.display = displayValue;
80 }
81 if (!filterValue || matches) {
82 event.target.classList.remove('no-results');
83 } else {
84 event.target.classList.add('no-results');
85 }
86 sessionStorage.setItem('django.admin.navSidebarFilterValue', filterValue);
87 }
88
89 const nav = document.getElementById('nav-filter');
90 nav.addEventListener('change', checkValue, false);
91 nav.addEventListener('input', checkValue, false);
92 nav.addEventListener('keyup', checkValue, false);
93
94 const storedValue = sessionStorage.getItem('django.admin.navSidebarFilterValue');
95 if (storedValue) {
96 nav.value = storedValue;
97 checkValue({target: nav, key: ''});
98 }
99 }
100 window.initSidebarQuickFilter = initSidebarQuickFilter;
101 initSidebarQuickFilter();
102 }
@@ -0,0 +1,3
1 /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
3 !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/af",[],function(){return{errorLoading:function(){return"Die resultate kon nie gelaai word nie."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Verwyders asseblief "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Voer asseblief "+(e.minimum-e.input.length)+" of meer karakters"},loadingMore:function(){return"Meer resultate word gelaai…"},maximumSelected:function(e){var n="Kies asseblief net "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"Geen resultate gevind"},searching:function(){return"Besig…"},removeAllItems:function(){return"Verwyder alle items"}}}),e.define,e.require}(); No newline at end of file
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -4,9 +4,14 REDIS_PORT=6300
4 4 POSTGRES_PORT_5432_TCP_ADDR=radarsys-postgres
5 5 # POSTGRES_PORT_5432_TCP_PORT=5400
6 6 POSTGRES_PORT_5432_TCP_PORT=5432
7 DB_NAME=radarsys
8 DB_USER=docker
9 DB_PASSWORD=docker
7 #POSTGRES_HOST?? DONDE IRIA
8 POSTGRES_USER=docker
9 POSTGRES_PASSWORD=docker
10 POSTGRES_DB=radarsys
11
12 # DB_NAME=radarsys
13 # DB_USER=docker
14 # DB_PASSWORD=docker
10 15 PGDATA=/var/lib/postgresql/data
11 16 LC_ALL=C.UTF-8
12 17 TZ=America/Lima
@@ -131,7 +131,7 h3 {
131 131 }
132 132
133 133 #sidebar a {
134 color: gray;
134 color: white;
135 135 padding: 0.1rem;
136 136 }
137 137
@@ -441,9 +441,10 def campaign_new(request):
441 441 if form.is_valid():
442 442 campaign = form.save(commit=False)
443 443 campaign.author = request.user
444 campaign.save()
444 445 for exp in experiments:
445 446 campaign.experiments.add(exp)
446 campaign.save()
447
447 448 return redirect('url_campaign', id_camp=campaign.id)
448 449
449 450 kwargs['form'] = form
@@ -1,28 +1,28
1 1 version: '2'
2 2 services:
3 3 # Django app
4 web:
5 container_name: 'radarsys'
6 build: .
7 restart: always
8 image: radarsys
9 command: gunicorn radarsys.wsgi:application -w 2 -b :8000
10 #command: python manage.py runserver 0.0.0.0:8030
11 ports:
12 - 8000:8000
4 # web:
5 # container_name: 'radarsys'
6 # build: .
7 # restart: always
8 # image: radarsys
9 # command: gunicorn radarsys.wsgi:application -w 2 -b :8000
10 # #command: python manage.py runserver 0.0.0.0:8030
13 11 #ports:
14 # - 8030:8030
15 env_file: .env
12 # - 8000:8000
13 # #ports:
14 # # - 8030:8030
15 # env_file: .env
16 16
17 links:
18 # - redis
19 - postgres
20 volumes:
21 - './:/radarsys'
22 - '${DOCKER_DATA}/static:/radarsys/static'
23 depends_on:
24 # - redis
25 - postgres
17 # links:
18 # # - redis
19 # - postgres
20 # volumes:
21 # - './:/radarsys'
22 # - '${DOCKER_DATA}/static:/radarsys/static'
23 # depends_on:
24 # # - redis
25 # - postgres
26 26
27 27 # redis:
28 28 # container_name: 'radarsys-redis'
@@ -47,23 +47,27 services:
47 47 volumes:
48 48 - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
49 49 - pgdata:/var/lib/postgresql/data
50 # ports:
51 # - 5432:5432
50 ports:
51 - 5432:5432
52 environment:
53 - POSTGRES_PASSWORD=docker
54 - POSTGRES_USER=docker
55 - POSTGRES_DB=radarsys
52 56 env_file: .env
53 57
54 #Web Server
55 nginx:
56 container_name: 'radarsys-nginx'
57 restart: always
58 build: ./nginx/
59 ports:
60 - '8030:8030'
61 volumes_from:
62 - web
63 links:
64 - web:web
65 depends_on:
66 - web
58 # #Web Server
59 # nginx:
60 # container_name: 'radarsys-nginx'
61 # restart: always
62 # build: ./nginx/
63 # ports:
64 # - '8030:8030'
65 # volumes_from:
66 # - web
67 # links:
68 # - web:web
69 # depends_on:
70 # - web
67 71
68 72 volumes:
69 73 pgdata:
@@ -1,3 +1,5
1 1 FROM postgres:14.6-alpine
2 #FROM library/postgres
2 3
3 4 RUN mkdir -p "$PGDATA" && chmod 700 "$PGDATA"
5 #COPY ./init.sql /docker-entrypoint-initdb.d/ No newline at end of file
@@ -2,8 +2,8
2 2 set -e
3 3
4 4 echo "Creating database & user"
5 psql -v --username "postgres" --dbname "postgres" <<-EOSQL
6 CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';
7 CREATE DATABASE $DB_NAME;
8 GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
5 psql -v --username "docker" --dbname "radarsys" <<-EOSQL
6 CREATE USER docker WITH PASSWORD 'docker';
7 CREATE DATABASE radarsys;
8 GRANT ALL PRIVILEGES ON DATABASE radarsys TO docker;
9 9 EOSQL
@@ -14,7 +14,7 select.admin-autocomplete {
14 14
15 15 .select2-container--admin-autocomplete.select2-container--focus .select2-selection,
16 16 .select2-container--admin-autocomplete.select2-container--open .select2-selection {
17 border-color: #999;
17 border-color: var(--body-quiet-color);
18 18 min-height: 30px;
19 19 }
20 20
@@ -29,13 +29,13 select.admin-autocomplete {
29 29 }
30 30
31 31 .select2-container--admin-autocomplete .select2-selection--single {
32 background-color: #fff;
33 border: 1px solid #ccc;
32 background-color: var(--body-bg);
33 border: 1px solid var(--border-color);
34 34 border-radius: 4px;
35 35 }
36 36
37 37 .select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered {
38 color: #444;
38 color: var(--body-fg);
39 39 line-height: 30px;
40 40 }
41 41
@@ -46,7 +46,7 select.admin-autocomplete {
46 46 }
47 47
48 48 .select2-container--admin-autocomplete .select2-selection--single .select2-selection__placeholder {
49 color: #999;
49 color: var(--body-quiet-color);
50 50 }
51 51
52 52 .select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow {
@@ -80,7 +80,7 select.admin-autocomplete {
80 80 }
81 81
82 82 .select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single {
83 background-color: #eee;
83 background-color: var(--darkened-bg);
84 84 cursor: default;
85 85 }
86 86
@@ -94,8 +94,8 select.admin-autocomplete {
94 94 }
95 95
96 96 .select2-container--admin-autocomplete .select2-selection--multiple {
97 background-color: white;
98 border: 1px solid #ccc;
97 background-color: var(--body-bg);
98 border: 1px solid var(--border-color);
99 99 border-radius: 4px;
100 100 cursor: text;
101 101 }
@@ -104,8 +104,10 select.admin-autocomplete {
104 104 box-sizing: border-box;
105 105 list-style: none;
106 106 margin: 0;
107 padding: 0 5px;
107 padding: 0 10px 5px 5px;
108 108 width: 100%;
109 display: flex;
110 flex-wrap: wrap;
109 111 }
110 112
111 113 .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered li {
@@ -113,7 +115,7 select.admin-autocomplete {
113 115 }
114 116
115 117 .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__placeholder {
116 color: #999;
118 color: var(--body-quiet-color);
117 119 margin-top: 5px;
118 120 float: left;
119 121 }
@@ -123,11 +125,13 select.admin-autocomplete {
123 125 float: right;
124 126 font-weight: bold;
125 127 margin: 5px;
128 position: absolute;
129 right: 0;
126 130 }
127 131
128 132 .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice {
129 background-color: #e4e4e4;
130 border: 1px solid #ccc;
133 background-color: var(--darkened-bg);
134 border: 1px solid var(--border-color);
131 135 border-radius: 4px;
132 136 cursor: default;
133 137 float: left;
@@ -137,7 +141,7 select.admin-autocomplete {
137 141 }
138 142
139 143 .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove {
140 color: #999;
144 color: var(--body-quiet-color);
141 145 cursor: pointer;
142 146 display: inline-block;
143 147 font-weight: bold;
@@ -145,7 +149,7 select.admin-autocomplete {
145 149 }
146 150
147 151 .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove:hover {
148 color: #333;
152 color: var(--body-fg);
149 153 }
150 154
151 155 .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 {
163 167 }
164 168
165 169 .select2-container--admin-autocomplete.select2-container--focus .select2-selection--multiple {
166 border: solid #999 1px;
170 border: solid var(--body-quiet-color) 1px;
167 171 outline: 0;
168 172 }
169 173
170 174 .select2-container--admin-autocomplete.select2-container--disabled .select2-selection--multiple {
171 background-color: #eee;
175 background-color: var(--darkened-bg);
172 176 cursor: default;
173 177 }
174 178
@@ -186,12 +190,20 select.admin-autocomplete {
186 190 border-bottom-right-radius: 0;
187 191 }
188 192
193 .select2-container--admin-autocomplete .select2-search--dropdown {
194 background: var(--darkened-bg);
195 }
196
189 197 .select2-container--admin-autocomplete .select2-search--dropdown .select2-search__field {
190 border: 1px solid #ccc;
198 background: var(--body-bg);
199 color: var(--body-fg);
200 border: 1px solid var(--border-color);
201 border-radius: 4px;
191 202 }
192 203
193 204 .select2-container--admin-autocomplete .select2-search--inline .select2-search__field {
194 205 background: transparent;
206 color: var(--body-fg);
195 207 border: none;
196 208 outline: 0;
197 209 box-shadow: none;
@@ -201,6 +213,8 select.admin-autocomplete {
201 213 .select2-container--admin-autocomplete .select2-results > .select2-results__options {
202 214 max-height: 200px;
203 215 overflow-y: auto;
216 color: var(--body-fg);
217 background: var(--body-bg);
204 218 }
205 219
206 220 .select2-container--admin-autocomplete .select2-results__option[role=group] {
@@ -208,11 +222,12 select.admin-autocomplete {
208 222 }
209 223
210 224 .select2-container--admin-autocomplete .select2-results__option[aria-disabled=true] {
211 color: #999;
225 color: var(--body-quiet-color);
212 226 }
213 227
214 228 .select2-container--admin-autocomplete .select2-results__option[aria-selected=true] {
215 background-color: #ddd;
229 background-color: var(--selected-bg);
230 color: var(--body-fg);
216 231 }
217 232
218 233 .select2-container--admin-autocomplete .select2-results__option .select2-results__option {
@@ -249,8 +264,8 select.admin-autocomplete {
249 264 }
250 265
251 266 .select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] {
252 background-color: #79aec8;
253 color: white;
267 background-color: var(--primary);
268 color: var(--primary-fg);
254 269 }
255 270
256 271 .select2-container--admin-autocomplete .select2-results__group {
@@ -4,24 +4,82
4 4
5 5 @import url(fonts.css);
6 6
7 /* VARIABLE DEFINITIONS */
8 :root {
9 --primary: #79aec8;
10 --secondary: #417690;
11 --accent: #f5dd5d;
12 --primary-fg: #fff;
13
14 --body-fg: #333;
15 --body-bg: #fff;
16 --body-quiet-color: #666;
17 --body-loud-color: #000;
18
19 --header-color: #ffc;
20 --header-branding-color: var(--accent);
21 --header-bg: var(--secondary);
22 --header-link-color: var(--primary-fg);
23
24 --breadcrumbs-fg: #c4dce8;
25 --breadcrumbs-link-fg: var(--body-bg);
26 --breadcrumbs-bg: var(--primary);
27
28 --link-fg: #447e9b;
29 --link-hover-color: #036;
30 --link-selected-fg: #5b80b2;
31
32 --hairline-color: #e8e8e8;
33 --border-color: #ccc;
34
35 --error-fg: #ba2121;
36
37 --message-success-bg: #dfd;
38 --message-warning-bg: #ffc;
39 --message-error-bg: #ffefef;
40
41 --darkened-bg: #f8f8f8; /* A bit darker than --body-bg */
42 --selected-bg: #e4e4e4; /* E.g. selected table cells */
43 --selected-row: #ffc;
44
45 --button-fg: #fff;
46 --button-bg: var(--primary);
47 --button-hover-bg: #609ab6;
48 --default-button-bg: var(--secondary);
49 --default-button-hover-bg: #205067;
50 --close-button-bg: #888; /* Previously #bbb, contrast 1.92 */
51 --close-button-hover-bg: #747474;
52 --delete-button-bg: #ba2121;
53 --delete-button-hover-bg: #a41515;
54
55 --object-tools-fg: var(--button-fg);
56 --object-tools-bg: var(--close-button-bg);
57 --object-tools-hover-bg: var(--close-button-hover-bg);
58 }
59
60 html, body {
61 height: 100%;
62 }
63
7 64 body {
8 65 margin: 0;
9 66 padding: 0;
10 font-size: 14px;
67 font-size: 0.875rem;
11 68 font-family: "Roboto","Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif;
12 color: #333;
13 background: #fff;
69 color: var(--body-fg);
70 background: var(--body-bg);
14 71 }
15 72
16 73 /* LINKS */
17 74
18 75 a:link, a:visited {
19 color: #447e9b;
76 color: var(--link-fg);
20 77 text-decoration: none;
78 transition: color 0.15s, background 0.15s;
21 79 }
22 80
23 81 a:focus, a:hover {
24 color: #036;
82 color: var(--link-hover-color);
25 83 }
26 84
27 85 a:focus {
@@ -33,7 +91,7 a img {
33 91 }
34 92
35 93 a.section:link, a.section:visited {
36 color: #fff;
94 color: var(--header-link-color);
37 95 text-decoration: none;
38 96 }
39 97
@@ -59,12 +117,12 h1,h2,h3,h4,h5 {
59 117 h1 {
60 118 margin: 0 0 20px;
61 119 font-weight: 300;
62 font-size: 20px;
63 color: #666;
120 font-size: 1.25rem;
121 color: var(--body-quiet-color);
64 122 }
65 123
66 124 h2 {
67 font-size: 16px;
125 font-size: 1rem;
68 126 margin: 1em 0 .5em 0;
69 127 }
70 128
@@ -74,27 +132,27 h2.subhead {
74 132 }
75 133
76 134 h3 {
77 font-size: 14px;
135 font-size: 0.875rem;
78 136 margin: .8em 0 .3em 0;
79 color: #666;
137 color: var(--body-quiet-color);
80 138 font-weight: bold;
81 139 }
82 140
83 141 h4 {
84 font-size: 12px;
142 font-size: 0.75rem;
85 143 margin: 1em 0 .8em 0;
86 144 padding-bottom: 3px;
87 145 }
88 146
89 147 h5 {
90 font-size: 10px;
148 font-size: 0.625rem;
91 149 margin: 1.5em 0 .5em 0;
92 color: #666;
150 color: var(--body-quiet-color);
93 151 text-transform: uppercase;
94 152 letter-spacing: 1px;
95 153 }
96 154
97 ul li {
155 ul > li {
98 156 list-style-type: square;
99 157 padding: 1px 0;
100 158 }
@@ -104,7 +162,7 li ul {
104 162 }
105 163
106 164 li, dt, dd {
107 font-size: 13px;
165 font-size: 0.8125rem;
108 166 line-height: 20px;
109 167 }
110 168
@@ -124,13 +182,14 form {
124 182
125 183 fieldset {
126 184 margin: 0;
185 min-width: 0;
127 186 padding: 0;
128 187 border: none;
129 border-top: 1px solid #eee;
188 border-top: 1px solid var(--hairline-color);
130 189 }
131 190
132 191 blockquote {
133 font-size: 11px;
192 font-size: 0.6875rem;
134 193 color: #777;
135 194 margin-left: 2px;
136 195 padding-left: 10px;
@@ -139,13 +198,14 blockquote {
139 198
140 199 code, pre {
141 200 font-family: "Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace;
142 color: #666;
143 font-size: 12px;
201 color: var(--body-quiet-color);
202 font-size: 0.75rem;
203 overflow-x: auto;
144 204 }
145 205
146 206 pre.literal-block {
147 207 margin: 10px;
148 background: #eee;
208 background: var(--darkened-bg);
149 209 padding: 6px 8px;
150 210 }
151 211
@@ -155,41 +215,28 code strong {
155 215
156 216 hr {
157 217 clear: both;
158 color: #eee;
159 background-color: #eee;
218 color: var(--hairline-color);
219 background-color: var(--hairline-color);
160 220 height: 1px;
161 221 border: none;
162 222 margin: 0;
163 223 padding: 0;
164 font-size: 1px;
165 224 line-height: 1px;
166 225 }
167 226
168 227 /* TEXT STYLES & MODIFIERS */
169 228
170 229 .small {
171 font-size: 11px;
172 }
173
174 .tiny {
175 font-size: 10px;
176 }
177
178 p.tiny {
179 margin-top: -2px;
230 font-size: 0.6875rem;
180 231 }
181 232
182 233 .mini {
183 font-size: 10px;
184 }
185
186 p.mini {
187 margin-top: -3px;
234 font-size: 0.625rem;
188 235 }
189 236
190 237 .help, p.help, form p.help, div.help, form div.help, div.help li {
191 font-size: 11px;
192 color: #999;
238 font-size: 0.6875rem;
239 color: var(--body-quiet-color);
193 240 }
194 241
195 242 div.help ul {
@@ -205,54 +252,35 p img, h1 img, h2 img, h3 img, h4 img, td img {
205 252 }
206 253
207 254 .quiet, a.quiet:link, a.quiet:visited {
208 color: #999;
255 color: var(--body-quiet-color);
209 256 font-weight: normal;
210 257 }
211 258
212 .float-right {
213 float: right;
214 }
215
216 .float-left {
217 float: left;
218 }
219
220 259 .clear {
221 260 clear: both;
222 261 }
223 262
224 .align-left {
225 text-align: left;
226 }
227
228 .align-right {
229 text-align: right;
230 }
231
232 .example {
233 margin: 10px 0;
234 padding: 5px 10px;
235 background: #efefef;
236 }
237
238 263 .nowrap {
239 264 white-space: nowrap;
240 265 }
241 266
267 .hidden {
268 display: none !important;
269 }
270
242 271 /* TABLES */
243 272
244 273 table {
245 274 border-collapse: collapse;
246 border-color: #ccc;
275 border-color: var(--border-color);
247 276 }
248 277
249 278 td, th {
250 font-size: 13px;
279 font-size: 0.8125rem;
251 280 line-height: 16px;
252 border-bottom: 1px solid #eee;
281 border-bottom: 1px solid var(--hairline-color);
253 282 vertical-align: top;
254 283 padding: 8px;
255 font-family: "Roboto", "Lucida Grande", Verdana, Arial, sans-serif;
256 284 }
257 285
258 286 th {
@@ -262,34 +290,37 th {
262 290
263 291 thead th,
264 292 tfoot td {
265 color: #666;
293 color: var(--body-quiet-color);
266 294 padding: 5px 10px;
267 font-size: 11px;
268 background: #fff;
295 font-size: 0.6875rem;
296 background: var(--body-bg);
269 297 border: none;
270 border-top: 1px solid #eee;
271 border-bottom: 1px solid #eee;
298 border-top: 1px solid var(--hairline-color);
299 border-bottom: 1px solid var(--hairline-color);
272 300 }
273 301
274 302 tfoot td {
275 303 border-bottom: none;
276 border-top: 1px solid #eee;
304 border-top: 1px solid var(--hairline-color);
277 305 }
278 306
279 307 thead th.required {
280 color: #000;
308 color: var(--body-loud-color);
281 309 }
282 310
283 311 tr.alt {
284 background: #f6f6f6;
312 background: var(--darkened-bg);
285 313 }
286 314
287 .row1 {
288 background: #fff;
315 tr:nth-child(odd), .row-form-errors {
316 background: var(--body-bg);
289 317 }
290 318
291 .row2 {
292 background: #f9f9f9;
319 tr:nth-child(even),
320 tr:nth-child(even) .errorlist,
321 tr:nth-child(odd) + .row-form-errors,
322 tr:nth-child(odd) + .row-form-errors .errorlist {
323 background: var(--darkened-bg);
293 324 }
294 325
295 326 /* SORTABLE TABLES */
@@ -298,15 +329,15 thead th {
298 329 padding: 5px 10px;
299 330 line-height: normal;
300 331 text-transform: uppercase;
301 background: #f6f6f6;
332 background: var(--darkened-bg);
302 333 }
303 334
304 335 thead th a:link, thead th a:visited {
305 color: #666;
336 color: var(--body-quiet-color);
306 337 }
307 338
308 339 thead th.sorted {
309 background: #eee;
340 background: var(--selected-bg);
310 341 }
311 342
312 343 thead th.sorted .text {
@@ -325,7 +356,7 table thead th .text a {
325 356 }
326 357
327 358 table thead th .text a:focus, table thead th .text a:hover {
328 background: #eee;
359 background: var(--selected-bg);
329 360 }
330 361
331 362 thead th.sorted a.sortremove {
@@ -371,13 +402,13 table thead th.sorted .sortoptions a.sortremove:after {
371 402 top: -6px;
372 403 left: 3px;
373 404 font-weight: 200;
374 font-size: 18px;
375 color: #999;
405 font-size: 1.125rem;
406 color: var(--body-quiet-color);
376 407 }
377 408
378 409 table thead th.sorted .sortoptions a.sortremove:focus:after,
379 410 table thead th.sorted .sortoptions a.sortremove:hover:after {
380 color: #447e9b;
411 color: var(--link-fg);
381 412 }
382 413
383 414 table thead th.sorted .sortoptions a.sortremove:focus,
@@ -412,7 +443,7 input, textarea, select, .form-row p, form .button {
412 443 vertical-align: middle;
413 444 font-family: "Roboto", "Lucida Grande", Verdana, Arial, sans-serif;
414 445 font-weight: normal;
415 font-size: 13px;
446 font-size: 0.8125rem;
416 447 }
417 448 .form-row div.help {
418 449 padding: 2px 3px;
@@ -424,16 +455,18 textarea {
424 455
425 456 input[type=text], input[type=password], input[type=email], input[type=url],
426 457 input[type=number], input[type=tel], textarea, select, .vTextField {
427 border: 1px solid #ccc;
458 border: 1px solid var(--border-color);
428 459 border-radius: 4px;
429 460 padding: 5px 6px;
430 461 margin-top: 0;
462 color: var(--body-fg);
463 background-color: var(--body-bg);
431 464 }
432 465
433 466 input[type=text]:focus, input[type=password]:focus, input[type=email]:focus,
434 467 input[type=url]:focus, input[type=number]:focus, input[type=tel]:focus,
435 468 textarea:focus, select:focus, .vTextField:focus {
436 border-color: #999;
469 border-color: var(--body-quiet-color);
437 470 }
438 471
439 472 select {
@@ -449,12 +482,13 select[multiple] {
449 482 /* FORM BUTTONS */
450 483
451 484 .button, input[type=submit], input[type=button], .submit-row input, a.button {
452 background: #79aec8;
485 background: var(--button-bg);
453 486 padding: 10px 15px;
454 487 border: none;
455 488 border-radius: 4px;
456 color: #fff;
489 color: var(--button-fg);
457 490 cursor: pointer;
491 transition: background 0.15s;
458 492 }
459 493
460 494 a.button {
@@ -464,7 +498,7 a.button {
464 498 .button:active, input[type=submit]:active, input[type=button]:active,
465 499 .button:focus, input[type=submit]:focus, input[type=button]:focus,
466 500 .button:hover, input[type=submit]:hover, input[type=button]:hover {
467 background: #609ab6;
501 background: var(--button-hover-bg);
468 502 }
469 503
470 504 .button[disabled], input[type=submit][disabled], input[type=button][disabled] {
@@ -475,13 +509,13 a.button {
475 509 float: right;
476 510 border: none;
477 511 font-weight: 400;
478 background: #417690;
512 background: var(--default-button-bg);
479 513 }
480 514
481 515 .button.default:active, input[type=submit].default:active,
482 516 .button.default:focus, input[type=submit].default:focus,
483 517 .button.default:hover, input[type=submit].default:hover {
484 background: #205067;
518 background: var(--default-button-hover-bg);
485 519 }
486 520
487 521 .button[disabled].default,
@@ -496,7 +530,7 input[type=button][disabled].default {
496 530 .module {
497 531 border: none;
498 532 margin-bottom: 30px;
499 background: #fff;
533 background: var(--body-bg);
500 534 }
501 535
502 536 .module p, .module ul, .module h3, .module h4, .module dl, .module pre {
@@ -520,15 +554,15 input[type=button][disabled].default {
520 554 margin: 0;
521 555 padding: 8px;
522 556 font-weight: 400;
523 font-size: 13px;
557 font-size: 0.8125rem;
524 558 text-align: left;
525 background: #79aec8;
526 color: #fff;
559 background: var(--primary);
560 color: var(--header-link-color);
527 561 }
528 562
529 563 .module caption,
530 564 .inline-group h2 {
531 font-size: 12px;
565 font-size: 0.75rem;
532 566 letter-spacing: 0.5px;
533 567 text-transform: uppercase;
534 568 }
@@ -547,48 +581,51 ul.messagelist {
547 581 ul.messagelist li {
548 582 display: block;
549 583 font-weight: 400;
550 font-size: 13px;
584 font-size: 0.8125rem;
551 585 padding: 10px 10px 10px 65px;
552 586 margin: 0 0 10px 0;
553 background: #dfd url(../img/icon-yes.svg) 40px 12px no-repeat;
587 background: var(--message-success-bg) url(../img/icon-yes.svg) 40px 12px no-repeat;
554 588 background-size: 16px auto;
555 color: #333;
589 color: var(--body-fg);
590 word-break: break-word;
556 591 }
557 592
558 593 ul.messagelist li.warning {
559 background: #ffc url(../img/icon-alert.svg) 40px 14px no-repeat;
594 background: var(--message-warning-bg) url(../img/icon-alert.svg) 40px 14px no-repeat;
560 595 background-size: 14px auto;
561 596 }
562 597
563 598 ul.messagelist li.error {
564 background: #ffefef url(../img/icon-no.svg) 40px 12px no-repeat;
599 background: var(--message-error-bg) url(../img/icon-no.svg) 40px 12px no-repeat;
565 600 background-size: 16px auto;
566 601 }
567 602
568 603 .errornote {
569 font-size: 14px;
604 font-size: 0.875rem;
570 605 font-weight: 700;
571 606 display: block;
572 607 padding: 10px 12px;
573 608 margin: 0 0 10px 0;
574 color: #ba2121;
575 border: 1px solid #ba2121;
609 color: var(--error-fg);
610 border: 1px solid var(--error-fg);
576 611 border-radius: 4px;
577 background-color: #fff;
612 background-color: var(--body-bg);
578 613 background-position: 5px 12px;
614 overflow-wrap: break-word;
579 615 }
580 616
581 617 ul.errorlist {
582 618 margin: 0 0 4px;
583 619 padding: 0;
584 color: #ba2121;
585 background: #fff;
620 color: var(--error-fg);
621 background: var(--body-bg);
586 622 }
587 623
588 624 ul.errorlist li {
589 font-size: 13px;
625 font-size: 0.8125rem;
590 626 display: block;
591 627 margin-bottom: 4px;
628 overflow-wrap: break-word;
592 629 }
593 630
594 631 ul.errorlist li:first-child {
@@ -612,7 +649,7 td ul.errorlist li {
612 649 .form-row.errors {
613 650 margin: 0;
614 651 border: none;
615 border-bottom: 1px solid #eee;
652 border-bottom: 1px solid var(--hairline-color);
616 653 background: none;
617 654 }
618 655
@@ -620,46 +657,32 td ul.errorlist li {
620 657 padding-left: 0;
621 658 }
622 659
623 .errors input, .errors select, .errors textarea {
624 border: 1px solid #ba2121;
625 }
626
627 div.system-message {
628 background: #ffc;
629 margin: 10px;
630 padding: 6px 8px;
631 font-size: .8em;
632 }
633
634 div.system-message p.system-message-title {
635 padding: 4px 5px 4px 25px;
636 margin: 0;
637 color: #c11;
638 background: #ffefef url(../img/icon-no.svg) 5px 5px no-repeat;
660 .errors input, .errors select, .errors textarea,
661 td ul.errorlist + input, td ul.errorlist + select, td ul.errorlist + textarea {
662 border: 1px solid var(--error-fg);
639 663 }
640 664
641 665 .description {
642 font-size: 12px;
666 font-size: 0.75rem;
643 667 padding: 5px 0 0 12px;
644 668 }
645 669
646 670 /* BREADCRUMBS */
647 671
648 672 div.breadcrumbs {
649 background: #79aec8;
673 background: var(--breadcrumbs-bg);
650 674 padding: 10px 40px;
651 675 border: none;
652 font-size: 14px;
653 color: #c4dce8;
676 color: var(--breadcrumbs-fg);
654 677 text-align: left;
655 678 }
656 679
657 680 div.breadcrumbs a {
658 color: #fff;
681 color: var(--breadcrumbs-link-fg);
659 682 }
660 683
661 684 div.breadcrumbs a:focus, div.breadcrumbs a:hover {
662 color: #c4dce8;
685 color: var(--breadcrumbs-fg);
663 686 }
664 687
665 688 /* ACTION ICONS */
@@ -685,18 +708,18 div.breadcrumbs a:focus, div.breadcrumbs a:hover {
685 708 }
686 709
687 710 a.deletelink:link, a.deletelink:visited {
688 color: #CC3434;
711 color: #CC3434; /* XXX Probably unused? */
689 712 }
690 713
691 714 a.deletelink:focus, a.deletelink:hover {
692 color: #993333;
715 color: #993333; /* XXX Probably unused? */
693 716 text-decoration: none;
694 717 }
695 718
696 719 /* OBJECT TOOLS */
697 720
698 721 .object-tools {
699 font-size: 10px;
722 font-size: 0.625rem;
700 723 font-weight: bold;
701 724 padding-left: 0;
702 725 float: right;
@@ -704,14 +727,6 a.deletelink:focus, a.deletelink:hover {
704 727 margin-top: -48px;
705 728 }
706 729
707 .form-row .object-tools {
708 margin-top: 5px;
709 margin-bottom: 5px;
710 float: none;
711 height: 2em;
712 padding-left: 3.5em;
713 }
714
715 730 .object-tools li {
716 731 display: block;
717 732 float: left;
@@ -727,29 +742,29 a.deletelink:focus, a.deletelink:hover {
727 742 display: block;
728 743 float: left;
729 744 padding: 3px 12px;
730 background: #999;
745 background: var(--object-tools-bg);
746 color: var(--object-tools-fg);
731 747 font-weight: 400;
732 font-size: 11px;
748 font-size: 0.6875rem;
733 749 text-transform: uppercase;
734 750 letter-spacing: 0.5px;
735 color: #fff;
736 751 }
737 752
738 753 .object-tools a:focus, .object-tools a:hover {
739 background-color: #417690;
754 background-color: var(--object-tools-hover-bg);
740 755 }
741 756
742 757 .object-tools a:focus{
743 758 text-decoration: none;
744 759 }
745 760
746 .object-tools a.viewsitelink, .object-tools a.golink,.object-tools a.addlink {
761 .object-tools a.viewsitelink, .object-tools a.addlink {
747 762 background-repeat: no-repeat;
748 763 background-position: right 7px center;
749 764 padding-right: 26px;
750 765 }
751 766
752 .object-tools a.viewsitelink, .object-tools a.golink {
767 .object-tools a.viewsitelink {
753 768 background-image: url(../img/tooltag-arrowright.svg);
754 769 }
755 770
@@ -759,14 +774,21 a.deletelink:focus, a.deletelink:hover {
759 774
760 775 /* OBJECT HISTORY */
761 776
762 table#change-history {
777 #change-history table {
763 778 width: 100%;
764 779 }
765 780
766 table#change-history tbody th {
781 #change-history table tbody th {
767 782 width: 16em;
768 783 }
769 784
785 #change-history .paginator {
786 color: var(--body-quiet-color);
787 border-bottom: 1px solid var(--hairline-color);
788 background: var(--body-bg);
789 overflow: hidden;
790 }
791
770 792 /* PAGE STRUCTURE */
771 793
772 794 #container {
@@ -774,6 +796,23 table#change-history tbody th {
774 796 width: 100%;
775 797 min-width: 980px;
776 798 padding: 0;
799 display: flex;
800 flex-direction: column;
801 height: 100%;
802 }
803
804 #container > div {
805 flex-shrink: 0;
806 }
807
808 #container > .main {
809 display: flex;
810 flex: 1 0 auto;
811 }
812
813 .main > .content {
814 flex: 1 0;
815 max-width: 100%;
777 816 }
778 817
779 818 #content {
@@ -834,13 +873,13 table#change-history tbody th {
834 873 justify-content: space-between;
835 874 align-items: center;
836 875 padding: 10px 40px;
837 background: #417690;
838 color: #ffc;
876 background: var(--header-bg);
877 color: var(--header-color);
839 878 overflow: hidden;
840 879 }
841 880
842 #header a:link, #header a:visited {
843 color: #fff;
881 #header a:link, #header a:visited, #logout-form button {
882 color: var(--header-link-color);
844 883 }
845 884
846 885 #header a:focus , #header a:hover {
@@ -855,51 +894,69 table#change-history tbody th {
855 894 padding: 0;
856 895 margin: 0 20px 0 0;
857 896 font-weight: 300;
858 font-size: 24px;
859 color: #f5dd5d;
897 font-size: 1.5rem;
898 color: var(--header-branding-color);
860 899 }
861 900
862 #branding h1, #branding h1 a:link, #branding h1 a:visited {
863 color: #f5dd5d;
901 #branding h1 a:link, #branding h1 a:visited {
902 color: var(--accent);
864 903 }
865 904
866 905 #branding h2 {
867 906 padding: 0 10px;
868 font-size: 14px;
907 font-size: 0.875rem;
869 908 margin: -8px 0 8px 0;
870 909 font-weight: normal;
871 color: #ffc;
910 color: var(--header-color);
872 911 }
873 912
874 913 #branding a:hover {
875 914 text-decoration: none;
876 915 }
877 916
917 #logout-form {
918 display: inline;
919 }
920
921 #logout-form button {
922 background: none;
923 border: 0;
924 cursor: pointer;
925 font-family: "Roboto","Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif;
926 }
927
878 928 #user-tools {
879 929 float: right;
880 padding: 0;
881 930 margin: 0 0 0 20px;
931 text-align: right;
932 }
933
934 #user-tools, #logout-form button{
935 padding: 0;
882 936 font-weight: 300;
883 font-size: 11px;
937 font-size: 0.6875rem;
884 938 letter-spacing: 0.5px;
885 939 text-transform: uppercase;
886 text-align: right;
887 940 }
888 941
889 #user-tools a {
942 #user-tools a, #logout-form button {
890 943 border-bottom: 1px solid rgba(255, 255, 255, 0.25);
891 944 }
892 945
893 #user-tools a:focus, #user-tools a:hover {
946 #user-tools a:focus, #user-tools a:hover,
947 #logout-form button:active, #logout-form button:hover {
894 948 text-decoration: none;
895 border-bottom-color: #79aec8;
896 color: #79aec8;
949 border-bottom: 0;
950 }
951
952 #logout-form button:active, #logout-form button:hover {
953 margin-bottom: 1px;
897 954 }
898 955
899 956 /* SIDEBAR */
900 957
901 958 #content-related {
902 background: #f8f8f8;
959 background: var(--darkened-bg);
903 960 }
904 961
905 962 #content-related .module {
@@ -907,14 +964,13 table#change-history tbody th {
907 964 }
908 965
909 966 #content-related h3 {
910 font-size: 14px;
911 color: #666;
967 color: var(--body-quiet-color);
912 968 padding: 0 16px;
913 969 margin: 0 0 16px;
914 970 }
915 971
916 972 #content-related h4 {
917 font-size: 13px;
973 font-size: 0.8125rem;
918 974 }
919 975
920 976 #content-related p {
@@ -937,22 +993,22 table#change-history tbody th {
937 993 background: none;
938 994 padding: 16px;
939 995 margin-bottom: 16px;
940 border-bottom: 1px solid #eaeaea;
941 font-size: 18px;
942 color: #333;
996 border-bottom: 1px solid var(--hairline-color);
997 font-size: 1.125rem;
998 color: var(--body-fg);
943 999 }
944 1000
945 1001 .delete-confirmation form input[type="submit"] {
946 background: #ba2121;
1002 background: var(--delete-button-bg);
947 1003 border-radius: 4px;
948 1004 padding: 10px 15px;
949 color: #fff;
1005 color: var(--button-fg);
950 1006 }
951 1007
952 1008 .delete-confirmation form input[type="submit"]:active,
953 1009 .delete-confirmation form input[type="submit"]:focus,
954 1010 .delete-confirmation form input[type="submit"]:hover {
955 background: #a41515;
1011 background: var(--delete-button-hover-bg);
956 1012 }
957 1013
958 1014 .delete-confirmation form .cancel-link {
@@ -960,17 +1016,17 table#change-history tbody th {
960 1016 vertical-align: middle;
961 1017 height: 15px;
962 1018 line-height: 15px;
963 background: #ddd;
964 1019 border-radius: 4px;
965 1020 padding: 10px 15px;
966 color: #333;
1021 color: var(--button-fg);
1022 background: var(--close-button-bg);
967 1023 margin: 0 0 0 10px;
968 1024 }
969 1025
970 1026 .delete-confirmation form .cancel-link:active,
971 1027 .delete-confirmation form .cancel-link:focus,
972 1028 .delete-confirmation form .cancel-link:hover {
973 background: #ccc;
1029 background: var(--close-button-hover-bg);
974 1030 }
975 1031
976 1032 /* POPUP */
@@ -985,3 +1041,49 table#change-history tbody th {
985 1041 .popup #header {
986 1042 padding: 10px 20px;
987 1043 }
1044
1045 /* PAGINATOR */
1046
1047 .paginator {
1048 font-size: 0.8125rem;
1049 padding-top: 10px;
1050 padding-bottom: 10px;
1051 line-height: 22px;
1052 margin: 0;
1053 border-top: 1px solid var(--hairline-color);
1054 width: 100%;
1055 }
1056
1057 .paginator a:link, .paginator a:visited {
1058 padding: 2px 6px;
1059 background: var(--button-bg);
1060 text-decoration: none;
1061 color: var(--button-fg);
1062 }
1063
1064 .paginator a.showall {
1065 border: none;
1066 background: none;
1067 color: var(--link-fg);
1068 }
1069
1070 .paginator a.showall:focus, .paginator a.showall:hover {
1071 background: none;
1072 color: var(--link-hover-color);
1073 }
1074
1075 .paginator .end {
1076 margin-right: 6px;
1077 }
1078
1079 .paginator .this-page {
1080 padding: 2px 6px;
1081 font-weight: bold;
1082 font-size: 0.8125rem;
1083 vertical-align: top;
1084 }
1085
1086 .paginator a:focus, .paginator a:hover {
1087 color: white;
1088 background: var(--link-hover-color);
1089 }
@@ -1,8 +1,14
1 1 /* CHANGELISTS */
2 2
3 3 #changelist {
4 position: relative;
5 width: 100%;
4 display: flex;
5 align-items: flex-start;
6 justify-content: space-between;
7 }
8
9 #changelist .changelist-form-container {
10 flex: 1 1 auto;
11 min-width: 0;
6 12 }
7 13
8 14 #changelist table {
@@ -21,7 +27,6
21 27
22 28 .change-list .filtered .results, .change-list .filtered .paginator,
23 29 .filtered #toolbar, .filtered div.xfull {
24 margin-right: 280px;
25 30 width: auto;
26 31 }
27 32
@@ -31,16 +36,17
31 36
32 37 #changelist-form .results {
33 38 overflow-x: auto;
39 width: 100%;
34 40 }
35 41
36 42 #changelist .toplinks {
37 border-bottom: 1px solid #ddd;
43 border-bottom: 1px solid var(--hairline-color);
38 44 }
39 45
40 46 #changelist .paginator {
41 color: #666;
42 border-bottom: 1px solid #eee;
43 background: #fff;
47 color: var(--body-quiet-color);
48 border-bottom: 1px solid var(--hairline-color);
49 background: var(--body-bg);
44 50 overflow: hidden;
45 51 }
46 52
@@ -62,76 +68,79
62 68 }
63 69
64 70 #changelist table tfoot {
65 color: #666;
71 color: var(--body-quiet-color);
66 72 }
67 73
68 74 /* TOOLBAR */
69 75
70 #changelist #toolbar {
76 #toolbar {
71 77 padding: 8px 10px;
72 78 margin-bottom: 15px;
73 border-top: 1px solid #eee;
74 border-bottom: 1px solid #eee;
75 background: #f8f8f8;
76 color: #666;
79 border-top: 1px solid var(--hairline-color);
80 border-bottom: 1px solid var(--hairline-color);
81 background: var(--darkened-bg);
82 color: var(--body-quiet-color);
77 83 }
78 84
79 #changelist #toolbar form input {
85 #toolbar form input {
80 86 border-radius: 4px;
81 font-size: 14px;
87 font-size: 0.875rem;
82 88 padding: 5px;
83 color: #333;
89 color: var(--body-fg);
84 90 }
85 91
86 #changelist #toolbar form #searchbar {
92 #toolbar #searchbar {
87 93 height: 19px;
88 border: 1px solid #ccc;
94 border: 1px solid var(--border-color);
89 95 padding: 2px 5px;
90 96 margin: 0;
91 97 vertical-align: top;
92 font-size: 13px;
98 font-size: 0.8125rem;
99 max-width: 100%;
93 100 }
94 101
95 #changelist #toolbar form #searchbar:focus {
96 border-color: #999;
102 #toolbar #searchbar:focus {
103 border-color: var(--body-quiet-color);
97 104 }
98 105
99 #changelist #toolbar form input[type="submit"] {
100 border: 1px solid #ccc;
101 padding: 2px 10px;
106 #toolbar form input[type="submit"] {
107 border: 1px solid var(--border-color);
108 font-size: 0.8125rem;
109 padding: 4px 8px;
102 110 margin: 0;
103 111 vertical-align: middle;
104 background: #fff;
112 background: var(--body-bg);
105 113 box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
106 114 cursor: pointer;
107 color: #333;
115 color: var(--body-fg);
108 116 }
109 117
110 #changelist #toolbar form input[type="submit"]:focus,
111 #changelist #toolbar form input[type="submit"]:hover {
112 border-color: #999;
118 #toolbar form input[type="submit"]:focus,
119 #toolbar form input[type="submit"]:hover {
120 border-color: var(--body-quiet-color);
113 121 }
114 122
115 #changelist #changelist-search img {
123 #changelist-search img {
116 124 vertical-align: middle;
117 125 margin-right: 4px;
118 126 }
119 127
128 #changelist-search .help {
129 word-break: break-word;
130 }
131
120 132 /* FILTER COLUMN */
121 133
122 134 #changelist-filter {
123 position: absolute;
124 top: 0;
125 right: 0;
126 z-index: 1000;
127 width: 240px;
128 background: #f8f8f8;
135 flex: 0 0 240px;
136 order: 1;
137 background: var(--darkened-bg);
129 138 border-left: none;
130 margin: 0;
139 margin: 0 0 0 30px;
131 140 }
132 141
133 142 #changelist-filter h2 {
134 font-size: 14px;
143 font-size: 0.875rem;
135 144 text-transform: uppercase;
136 145 letter-spacing: 0.5px;
137 146 padding: 5px 15px;
@@ -139,22 +148,43
139 148 border-bottom: none;
140 149 }
141 150
142 #changelist-filter h3 {
151 #changelist-filter h3,
152 #changelist-filter details summary {
143 153 font-weight: 400;
144 font-size: 14px;
145 154 padding: 0 15px;
146 155 margin-bottom: 10px;
147 156 }
148 157
158 #changelist-filter details summary > * {
159 display: inline;
160 }
161
162 #changelist-filter details > summary {
163 list-style-type: none;
164 }
165
166 #changelist-filter details > summary::-webkit-details-marker {
167 display: none;
168 }
169
170 #changelist-filter details > summary::before {
171 content: '→';
172 font-weight: bold;
173 color: var(--link-hover-color);
174 }
175
176 #changelist-filter details[open] > summary::before {
177 content: '↓';
178 }
179
149 180 #changelist-filter ul {
150 181 margin: 5px 0;
151 182 padding: 0 15px 15px;
152 border-bottom: 1px solid #eaeaea;
183 border-bottom: 1px solid var(--hairline-color);
153 184 }
154 185
155 186 #changelist-filter ul:last-child {
156 187 border-bottom: none;
157 padding-bottom: none;
158 188 }
159 189
160 190 #changelist-filter li {
@@ -165,25 +195,30
165 195
166 196 #changelist-filter a {
167 197 display: block;
168 color: #999;
169 text-overflow: ellipsis;
170 overflow-x: hidden;
198 color: var(--body-quiet-color);
199 word-break: break-word;
171 200 }
172 201
173 202 #changelist-filter li.selected {
174 border-left: 5px solid #eaeaea;
203 border-left: 5px solid var(--hairline-color);
175 204 padding-left: 10px;
176 205 margin-left: -15px;
177 206 }
178 207
179 208 #changelist-filter li.selected a {
180 color: #5b80b2;
209 color: var(--link-selected-fg);
181 210 }
182 211
183 212 #changelist-filter a:focus, #changelist-filter a:hover,
184 213 #changelist-filter li.selected a:focus,
185 214 #changelist-filter li.selected a:hover {
186 color: #036;
215 color: var(--link-hover-color);
216 }
217
218 #changelist-filter #changelist-filter-clear a {
219 font-size: 0.8125rem;
220 padding-bottom: 10px;
221 border-bottom: 1px solid var(--hairline-color);
187 222 }
188 223
189 224 /* DATE DRILLDOWN */
@@ -204,64 +239,17
204 239 }
205 240
206 241 .change-list ul.toplinks .date-back a {
207 color: #999;
242 color: var(--body-quiet-color);
208 243 }
209 244
210 245 .change-list ul.toplinks .date-back a:focus,
211 246 .change-list ul.toplinks .date-back a:hover {
212 color: #036;
213 }
214
215 /* PAGINATOR */
216
217 .paginator {
218 font-size: 13px;
219 padding-top: 10px;
220 padding-bottom: 10px;
221 line-height: 22px;
222 margin: 0;
223 border-top: 1px solid #ddd;
224 }
225
226 .paginator a:link, .paginator a:visited {
227 padding: 2px 6px;
228 background: #79aec8;
229 text-decoration: none;
230 color: #fff;
231 }
232
233 .paginator a.showall {
234 padding: 0;
235 border: none;
236 background: none;
237 color: #5b80b2;
238 }
239
240 .paginator a.showall:focus, .paginator a.showall:hover {
241 background: none;
242 color: #036;
243 }
244
245 .paginator .end {
246 margin-right: 6px;
247 }
248
249 .paginator .this-page {
250 padding: 2px 6px;
251 font-weight: bold;
252 font-size: 13px;
253 vertical-align: top;
254 }
255
256 .paginator a:focus, .paginator a:hover {
257 color: white;
258 background: #036;
247 color: var(--link-hover-color);
259 248 }
260 249
261 250 /* ACTIONS */
262 251
263 252 .filtered .actions {
264 margin-right: 280px;
265 253 border-right: none;
266 254 }
267 255
@@ -271,31 +259,25
271 259 }
272 260
273 261 #changelist table tbody tr.selected {
274 background-color: #FFFFCC;
262 background-color: var(--selected-row);
275 263 }
276 264
277 265 #changelist .actions {
278 266 padding: 10px;
279 background: #fff;
267 background: var(--body-bg);
280 268 border-top: none;
281 269 border-bottom: none;
282 270 line-height: 24px;
283 color: #999;
284 }
285
286 #changelist .actions.selected {
287 background: #fffccf;
288 border-top: 1px solid #fffee8;
289 border-bottom: 1px solid #edecd6;
271 color: var(--body-quiet-color);
272 width: 100%;
290 273 }
291 274
292 275 #changelist .actions span.all,
293 276 #changelist .actions span.action-counter,
294 277 #changelist .actions span.clear,
295 278 #changelist .actions span.question {
296 font-size: 13px;
279 font-size: 0.8125rem;
297 280 margin: 0 0.5em;
298 display: none;
299 281 }
300 282
301 283 #changelist .actions:last-child {
@@ -305,40 +287,39
305 287 #changelist .actions select {
306 288 vertical-align: top;
307 289 height: 24px;
308 background: none;
309 color: #000;
310 border: 1px solid #ccc;
290 color: var(--body-fg);
291 border: 1px solid var(--border-color);
311 292 border-radius: 4px;
312 font-size: 14px;
293 font-size: 0.875rem;
313 294 padding: 0 0 0 4px;
314 295 margin: 0;
315 296 margin-left: 10px;
316 297 }
317 298
318 299 #changelist .actions select:focus {
319 border-color: #999;
300 border-color: var(--body-quiet-color);
320 301 }
321 302
322 303 #changelist .actions label {
323 304 display: inline-block;
324 305 vertical-align: middle;
325 font-size: 13px;
306 font-size: 0.8125rem;
326 307 }
327 308
328 309 #changelist .actions .button {
329 font-size: 13px;
330 border: 1px solid #ccc;
310 font-size: 0.8125rem;
311 border: 1px solid var(--border-color);
331 312 border-radius: 4px;
332 background: #fff;
313 background: var(--body-bg);
333 314 box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
334 315 cursor: pointer;
335 316 height: 24px;
336 317 line-height: 1;
337 318 padding: 4px 8px;
338 319 margin: 0;
339 color: #333;
320 color: var(--body-fg);
340 321 }
341 322
342 323 #changelist .actions .button:focus, #changelist .actions .button:hover {
343 border-color: #999;
324 border-color: var(--body-quiet-color);
344 325 }
@@ -23,5 +23,4 ul.actionlist li {
23 23 list-style-type: none;
24 24 overflow: hidden;
25 25 text-overflow: ellipsis;
26 -o-text-overflow: ellipsis;
27 26 }
@@ -5,8 +5,8
5 5 .form-row {
6 6 overflow: hidden;
7 7 padding: 10px;
8 font-size: 13px;
9 border-bottom: 1px solid #eee;
8 font-size: 0.8125rem;
9 border-bottom: 1px solid var(--hairline-color);
10 10 }
11 11
12 12 .form-row img, .form-row input {
@@ -22,35 +22,34 form .form-row p {
22 22 padding-left: 0;
23 23 }
24 24
25 .hidden {
26 display: none;
27 }
28
29 25 /* FORM LABELS */
30 26
31 27 label {
32 28 font-weight: normal;
33 color: #666;
34 font-size: 13px;
29 color: var(--body-quiet-color);
30 font-size: 0.8125rem;
35 31 }
36 32
37 33 .required label, label.required {
38 34 font-weight: bold;
39 color: #333;
35 color: var(--body-fg);
40 36 }
41 37
42 38 /* RADIO BUTTONS */
43 39
44 form ul.radiolist li {
45 list-style-type: none;
40 form div.radiolist div {
41 padding-right: 7px;
46 42 }
47 43
48 form ul.radiolist label {
49 float: none;
50 display: inline;
44 form div.radiolist.inline div {
45 display: inline-block;
46 }
47
48 form div.radiolist label {
49 width: auto;
51 50 }
52 51
53 form ul.radiolist input[type="radio"] {
52 form div.radiolist input[type="radio"] {
54 53 margin: -2px 4px 0 0;
55 54 padding: 0;
56 55 }
@@ -88,6 +87,7 form ul.inline li {
88 87 margin-top: 0;
89 88 margin-bottom: 0;
90 89 margin-left: 170px;
90 overflow-wrap: break-word;
91 91 }
92 92
93 93 .aligned ul label {
@@ -109,7 +109,7 form .aligned ul {
109 109 padding-left: 10px;
110 110 }
111 111
112 form .aligned ul.radiolist {
112 form .aligned div.radiolist {
113 113 display: inline-block;
114 114 margin: 0;
115 115 padding: 0;
@@ -219,24 +219,24 fieldset.collapsed h2, fieldset.collapsed {
219 219 }
220 220
221 221 fieldset.collapsed {
222 border: 1px solid #eee;
222 border: 1px solid var(--hairline-color);
223 223 border-radius: 4px;
224 224 overflow: hidden;
225 225 }
226 226
227 227 fieldset.collapsed h2 {
228 background: #f8f8f8;
229 color: #666;
228 background: var(--darkened-bg);
229 color: var(--body-quiet-color);
230 230 }
231 231
232 232 fieldset .collapse-toggle {
233 color: #fff;
233 color: var(--header-link-color);
234 234 }
235 235
236 236 fieldset.collapsed .collapse-toggle {
237 237 background: transparent;
238 238 display: inline;
239 color: #447e9b;
239 color: var(--link-fg);
240 240 }
241 241
242 242 /* MONOSPACE TEXTAREAS */
@@ -248,10 +248,10 fieldset.monospace textarea {
248 248 /* SUBMIT ROW */
249 249
250 250 .submit-row {
251 padding: 12px 14px;
251 padding: 12px 14px 7px;
252 252 margin: 0 0 20px;
253 background: #f8f8f8;
254 border: 1px solid #eee;
253 background: var(--darkened-bg);
254 border: 1px solid var(--hairline-color);
255 255 border-radius: 4px;
256 256 text-align: right;
257 257 overflow: hidden;
@@ -264,11 +264,11 body.popup .submit-row {
264 264 .submit-row input {
265 265 height: 35px;
266 266 line-height: 15px;
267 margin: 0 0 0 5px;
267 margin: 0 0 5px 5px;
268 268 }
269 269
270 270 .submit-row input.default {
271 margin: 0 0 0 8px;
271 margin: 0 0 5px 8px;
272 272 text-transform: uppercase;
273 273 }
274 274
@@ -283,35 +283,36 body.popup .submit-row {
283 283
284 284 .submit-row a.deletelink {
285 285 display: block;
286 background: #ba2121;
286 background: var(--delete-button-bg);
287 287 border-radius: 4px;
288 288 padding: 10px 15px;
289 289 height: 15px;
290 290 line-height: 15px;
291 color: #fff;
291 margin-bottom: 5px;
292 color: var(--button-fg);
292 293 }
293 294
294 295 .submit-row a.closelink {
295 296 display: inline-block;
296 background: #bbbbbb;
297 background: var(--close-button-bg);
297 298 border-radius: 4px;
298 299 padding: 10px 15px;
299 300 height: 15px;
300 301 line-height: 15px;
301 302 margin: 0 0 0 5px;
302 color: #fff;
303 color: var(--button-fg);
303 304 }
304 305
305 306 .submit-row a.deletelink:focus,
306 307 .submit-row a.deletelink:hover,
307 308 .submit-row a.deletelink:active {
308 background: #a41515;
309 background: var(--delete-button-hover-bg);
309 310 }
310 311
311 312 .submit-row a.closelink:focus,
312 313 .submit-row a.closelink:hover,
313 314 .submit-row a.closelink:active {
314 background: #aaaaaa;
315 background: var(--close-button-hover-bg);
315 316 }
316 317
317 318 /* CUSTOM FORM FIELDS */
@@ -353,10 +354,6 body.popup .submit-row {
353 354 width: 2.2em;
354 355 }
355 356
356 .vTextField, .vUUIDField {
357 width: 20em;
358 }
359
360 357 .vIntegerField {
361 358 width: 5em;
362 359 }
@@ -369,6 +366,10 body.popup .submit-row {
369 366 width: 5em;
370 367 }
371 368
369 .vTextField, .vUUIDField {
370 width: 20em;
371 }
372
372 373 /* INLINES */
373 374
374 375 .inline-group {
@@ -390,12 +391,12 body.popup .submit-row {
390 391
391 392 .inline-related h3 {
392 393 margin: 0;
393 color: #666;
394 color: var(--body-quiet-color);
394 395 padding: 5px;
395 font-size: 13px;
396 background: #f8f8f8;
397 border-top: 1px solid #eee;
398 border-bottom: 1px solid #eee;
396 font-size: 0.8125rem;
397 background: var(--darkened-bg);
398 border-top: 1px solid var(--hairline-color);
399 border-bottom: 1px solid var(--hairline-color);
399 400 }
400 401
401 402 .inline-related h3 span.delete {
@@ -404,12 +405,12 body.popup .submit-row {
404 405
405 406 .inline-related h3 span.delete label {
406 407 margin-left: 2px;
407 font-size: 11px;
408 font-size: 0.6875rem;
408 409 }
409 410
410 411 .inline-related fieldset {
411 412 margin: 0;
412 background: #fff;
413 background: var(--body-bg);
413 414 border: none;
414 415 width: 100%;
415 416 }
@@ -417,11 +418,11 body.popup .submit-row {
417 418 .inline-related fieldset.module h3 {
418 419 margin: 0;
419 420 padding: 2px 5px 3px 5px;
420 font-size: 11px;
421 font-size: 0.6875rem;
421 422 text-align: left;
422 423 font-weight: bold;
423 424 background: #bcd;
424 color: #fff;
425 color: var(--body-bg);
425 426 }
426 427
427 428 .inline-group .tabular fieldset.module {
@@ -430,6 +431,7 body.popup .submit-row {
430 431
431 432 .inline-related.tabular fieldset.module table {
432 433 width: 100%;
434 overflow-x: scroll;
433 435 }
434 436
435 437 .last-related fieldset {
@@ -457,9 +459,9 body.popup .submit-row {
457 459 height: 1.1em;
458 460 padding: 2px 9px;
459 461 overflow: hidden;
460 font-size: 9px;
462 font-size: 0.5625rem;
461 463 font-weight: bold;
462 color: #666;
464 color: var(--body-quiet-color);
463 465 _width: 700px;
464 466 }
465 467
@@ -476,15 +478,15 body.popup .submit-row {
476 478
477 479 .inline-group div.add-row,
478 480 .inline-group .tabular tr.add-row td {
479 color: #666;
480 background: #f8f8f8;
481 color: var(--body-quiet-color);
482 background: var(--darkened-bg);
481 483 padding: 8px 10px;
482 border-bottom: 1px solid #eee;
484 border-bottom: 1px solid var(--hairline-color);
483 485 }
484 486
485 487 .inline-group .tabular tr.add-row td {
486 488 padding: 8px 10px;
487 border-bottom: 1px solid #eee;
489 border-bottom: 1px solid var(--hairline-color);
488 490 }
489 491
490 492 .inline-group ul.tools a.add,
@@ -492,7 +494,7 body.popup .submit-row {
492 494 .inline-group .tabular tr.add-row td a {
493 495 background: url(../img/icon-addlink.svg) 0 1px no-repeat;
494 496 padding-left: 16px;
495 font-size: 12px;
497 font-size: 0.75rem;
496 498 }
497 499
498 500 .empty-form {
@@ -501,7 +503,7 body.popup .submit-row {
501 503
502 504 /* RELATED FIELD ADD ONE / LOOKUP */
503 505
504 .add-another, .related-lookup {
506 .related-lookup {
505 507 margin-left: 5px;
506 508 display: inline-block;
507 509 vertical-align: middle;
@@ -509,12 +511,6 body.popup .submit-row {
509 511 background-size: 14px;
510 512 }
511 513
512 .add-another {
513 width: 16px;
514 height: 16px;
515 background-image: url(../img/icon-addlink.svg);
516 }
517
518 514 .related-lookup {
519 515 width: 16px;
520 516 height: 16px;
@@ -1,7 +1,8
1 1 /* LOGIN FORM */
2 2
3 body.login {
4 background: #f8f8f8;
3 .login {
4 background: var(--darkened-bg);
5 height: auto;
5 6 }
6 7
7 8 .login #header {
@@ -11,11 +12,12 body.login {
11 12 }
12 13
13 14 .login #header h1 {
14 font-size: 18px;
15 font-size: 1.125rem;
16 margin: 0;
15 17 }
16 18
17 19 .login #header h1 a {
18 color: #fff;
20 color: var(--header-link-color);
19 21 }
20 22
21 23 .login #content {
@@ -23,55 +25,35 body.login {
23 25 }
24 26
25 27 .login #container {
26 background: #fff;
27 border: 1px solid #eaeaea;
28 background: var(--body-bg);
29 border: 1px solid var(--hairline-color);
28 30 border-radius: 4px;
29 31 overflow: hidden;
30 32 width: 28em;
31 33 min-width: 300px;
32 34 margin: 100px auto;
33 }
34
35 .login #content-main {
36 width: 100%;
35 height: auto;
37 36 }
38 37
39 38 .login .form-row {
40 39 padding: 4px 0;
41 float: left;
42 width: 100%;
43 border-bottom: none;
44 40 }
45 41
46 42 .login .form-row label {
47 padding-right: 0.5em;
43 display: block;
48 44 line-height: 2em;
49 font-size: 1em;
50 clear: both;
51 color: #333;
52 45 }
53 46
54 47 .login .form-row #id_username, .login .form-row #id_password {
55 clear: both;
56 48 padding: 8px;
57 49 width: 100%;
58 -webkit-box-sizing: border-box;
59 -moz-box-sizing: border-box;
60 50 box-sizing: border-box;
61 51 }
62 52
63 .login span.help {
64 font-size: 10px;
65 display: block;
66 }
67
68 53 .login .submit-row {
69 clear: both;
70 padding: 1em 0 0 9.4em;
54 padding: 1em 0 0 0;
71 55 margin: 0;
72 border: none;
73 background: none;
74 text-align: left;
56 text-align: center;
75 57 }
76 58
77 59 .login .password-reset-link {
@@ -14,11 +14,11 input[type="submit"], button {
14 14
15 15 td, th {
16 16 padding: 10px;
17 font-size: 14px;
17 font-size: 0.875rem;
18 18 }
19 19
20 20 .small {
21 font-size: 12px;
21 font-size: 0.75rem;
22 22 }
23 23
24 24 /* Layout */
@@ -28,7 +28,7 input[type="submit"], button {
28 28 }
29 29
30 30 #content {
31 padding: 20px 30px 30px;
31 padding: 15px 20px 20px;
32 32 }
33 33
34 34 div.breadcrumbs {
@@ -45,7 +45,6 input[type="submit"], button {
45 45
46 46 #branding h1 {
47 47 margin: 0 0 8px;
48 font-size: 20px;
49 48 line-height: 1.2;
50 49 }
51 50
@@ -88,21 +87,19 input[type="submit"], button {
88 87 }
89 88
90 89 td .changelink, td .addlink {
91 font-size: 13px;
90 font-size: 0.8125rem;
92 91 }
93 92
94 93 /* Changelist */
95 94
96 #changelist #toolbar {
95 #toolbar {
97 96 border: none;
98 97 padding: 15px;
99 98 }
100 99
101 100 #changelist-search > div {
102 display: -webkit-flex;
103 101 display: flex;
104 -webkit-flex-wrap: wrap;
105 flex-wrap: wrap;
102 flex-wrap: nowrap;
106 103 max-width: 480px;
107 104 }
108 105
@@ -110,16 +107,20 input[type="submit"], button {
110 107 line-height: 22px;
111 108 }
112 109
113 #changelist #toolbar form #searchbar {
114 -webkit-flex: 1 0 auto;
110 #toolbar form #searchbar {
115 111 flex: 1 0 auto;
116 112 width: 0;
117 113 height: 22px;
118 114 margin: 0 10px 0 6px;
119 115 }
120 116
117 #toolbar form input[type=submit] {
118 flex: 0 1 auto;
119 }
120
121 121 #changelist-search .quiet {
122 width: 100%;
122 width: 0;
123 flex: 1 0 auto;
123 124 margin: 5px 0 0 25px;
124 125 }
125 126
@@ -129,16 +130,12 input[type="submit"], button {
129 130 padding: 15px 0;
130 131 }
131 132
132 #changelist .actions.selected {
133 border: none;
134 }
135
136 133 #changelist .actions label {
137 134 display: flex;
138 135 }
139 136
140 137 #changelist .actions select {
141 background: #fff;
138 background: var(--body-bg);
142 139 }
143 140
144 141 #changelist .actions .button {
@@ -150,24 +147,21 input[type="submit"], button {
150 147 #changelist .actions span.clear,
151 148 #changelist .actions span.question,
152 149 #changelist .actions span.action-counter {
153 font-size: 11px;
150 font-size: 0.6875rem;
154 151 margin: 0 10px 0 0;
155 152 }
156 153
157 154 #changelist-filter {
158 width: 200px;
155 flex-basis: 200px;
159 156 }
160 157
161 158 .change-list .filtered .results,
162 159 .change-list .filtered .paginator,
163 160 .filtered #toolbar,
164 161 .filtered .actions,
165 .filtered div.xfull {
166 margin-right: 230px;
167 }
168 162
169 163 #changelist .paginator {
170 border-top-color: #eee;
164 border-top-color: var(--hairline-color); /* XXX Is this used at all? */
171 165 }
172 166
173 167 #changelist .results + .paginator {
@@ -177,7 +171,7 input[type="submit"], button {
177 171 /* Forms */
178 172
179 173 label {
180 font-size: 14px;
174 font-size: 0.875rem;
181 175 }
182 176
183 177 .form-row input[type=text],
@@ -193,7 +187,7 input[type="submit"], button {
193 187 margin: 0;
194 188 padding: 6px 8px;
195 189 min-height: 36px;
196 font-size: 14px;
190 font-size: 0.875rem;
197 191 }
198 192
199 193 .form-row select {
@@ -214,11 +208,11 input[type="submit"], button {
214 208 fieldset .fieldBox + .fieldBox {
215 209 margin-top: 10px;
216 210 padding-top: 10px;
217 border-top: 1px solid #eee;
211 border-top: 1px solid var(--hairline-color);
218 212 }
219 213
220 214 textarea {
221 max-width: 518px;
215 max-width: 100%;
222 216 max-height: 120px;
223 217 }
224 218
@@ -226,7 +220,6 input[type="submit"], button {
226 220 padding-top: 6px;
227 221 }
228 222
229 .aligned .add-another,
230 223 .aligned .related-lookup,
231 224 .aligned .datetimeshortcuts,
232 225 .aligned .related-lookup + strong {
@@ -234,10 +227,26 input[type="submit"], button {
234 227 margin-left: 15px;
235 228 }
236 229
237 form .aligned ul.radiolist {
230 form .aligned div.radiolist {
238 231 margin-left: 2px;
239 232 }
240 233
234 .submit-row {
235 padding: 8px 8px 3px 8px;
236 }
237
238 .submit-row a.deletelink {
239 padding: 10px 7px;
240 }
241
242 .submit-row input.default {
243 margin: 0 0 5px 5px;
244 }
245
246 .button, input[type=submit], input[type=button], .submit-row input, a.button {
247 padding: 7px;
248 }
249
241 250 /* Related widget */
242 251
243 252 .related-widget-wrapper {
@@ -354,6 +363,14 input[type="submit"], button {
354 363 }
355 364
356 365 .stacked .active.selector-add {
366 background-position: 0 -40px;
367 }
368
369 .active.selector-add:focus, .active.selector-add:hover {
370 background-position: 0 -140px;
371 }
372
373 .stacked .active.selector-add:focus, .stacked .active.selector-add:hover {
357 374 background-position: 0 -60px;
358 375 }
359 376
@@ -362,6 +379,14 input[type="submit"], button {
362 379 }
363 380
364 381 .stacked .active.selector-remove {
382 background-position: 0 0;
383 }
384
385 .active.selector-remove:focus, .active.selector-remove:hover {
386 background-position: 0 -100px;
387 }
388
389 .stacked .active.selector-remove:focus, .stacked .active.selector-remove:hover {
365 390 background-position: 0 -20px;
366 391 }
367 392
@@ -379,17 +404,21 input[type="submit"], button {
379 404 }
380 405
381 406 .datetime span {
382 font-size: 13px;
407 font-size: 0.8125rem;
383 408 }
384 409
385 410 .datetime .timezonewarning {
386 411 display: block;
387 font-size: 11px;
388 color: #999;
412 font-size: 0.6875rem;
413 color: var(--body-quiet-color);
389 414 }
390 415
391 416 .datetimeshortcuts {
392 color: #ccc;
417 color: var(--border-color); /* XXX Redundant, .datetime span also sets #ccc */
418 }
419
420 .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField {
421 width: 75%;
393 422 }
394 423
395 424 .inline-group {
@@ -478,31 +507,22 input[type="submit"], button {
478 507
479 508 #content-related .module h2 {
480 509 padding: 10px 15px;
481 font-size: 16px;
510 font-size: 1rem;
482 511 }
483 512
484 513 /* Changelist */
485 514
486 515 #changelist {
487 display: flex;
516 align-items: stretch;
488 517 flex-direction: column;
489 518 }
490 519
491 #changelist #toolbar {
492 order: 1;
520 #toolbar {
493 521 padding: 10px;
494 522 }
495 523
496 #changelist .xfull {
497 order: 2;
498 }
499
500 #changelist-form {
501 order: 3;
502 }
503
504 524 #changelist-filter {
505 order: 4;
525 margin-left: 0;
506 526 }
507 527
508 528 #changelist .actions label {
@@ -518,11 +538,6 input[type="submit"], button {
518 538 flex: 1 0 100%;
519 539 }
520 540
521 .change-list .filtered .results, .change-list .filtered .paginator,
522 .filtered #toolbar, .filtered .actions, .filtered div.xfull {
523 margin-right: 0;
524 }
525
526 541 #changelist-filter {
527 542 position: static;
528 543 width: auto;
@@ -618,7 +633,7 input[type="submit"], button {
618 633
619 634 .aligned p.file-upload {
620 635 margin-left: 0;
621 font-size: 13px;
636 font-size: 0.8125rem;
622 637 }
623 638
624 639 span.clearable-file-input {
@@ -626,7 +641,7 input[type="submit"], button {
626 641 }
627 642
628 643 span.clearable-file-input label {
629 font-size: 13px;
644 font-size: 0.8125rem;
630 645 padding-bottom: 0;
631 646 }
632 647
@@ -646,12 +661,13 input[type="submit"], button {
646 661 padding-left: 0;
647 662 }
648 663
649 form .aligned ul.radiolist {
664 form .aligned div.radiolist {
665 margin-top: 5px;
650 666 margin-right: 15px;
651 667 margin-bottom: -3px;
652 668 }
653 669
654 form .aligned ul.radiolist li + li {
670 form .aligned div.radiolist:not(.inline) div + div {
655 671 margin-top: 5px;
656 672 }
657 673
@@ -721,14 +737,22 input[type="submit"], button {
721 737 background-position: 0 0;
722 738 }
723 739
740 .active.selector-remove:focus, .active.selector-remove:hover {
741 background-position: 0 -20px;
742 }
743
724 744 .selector-add {
725 745 background-position: 0 -40px;
726 746 }
727 747
748 .active.selector-add:focus, .active.selector-add:hover {
749 background-position: 0 -60px;
750 }
751
728 752 /* Inlines */
729 753
730 754 .inline-group[data-inline-type="stacked"] .inline-related {
731 border: 2px solid #eee;
755 border: 1px solid var(--hairline-color);
732 756 border-radius: 4px;
733 757 margin-top: 15px;
734 758 overflow: auto;
@@ -738,18 +762,19 input[type="submit"], button {
738 762 box-sizing: border-box;
739 763 }
740 764
741 .inline-group[data-inline-type="stacked"] .inline-related + .inline-related {
742 margin-top: 30px;
743 }
744
745 765 .inline-group[data-inline-type="stacked"] .inline-related .module {
746 766 padding: 0 10px;
747 767 }
748 768
749 .inline-group[data-inline-type="stacked"] .inline-related .module .form-row:last-child {
769 .inline-group[data-inline-type="stacked"] .inline-related .module .form-row {
770 border-top: 1px solid var(--hairline-color);
750 771 border-bottom: none;
751 772 }
752 773
774 .inline-group[data-inline-type="stacked"] .inline-related .module .form-row:first-child {
775 border-top: none;
776 }
777
753 778 .inline-group[data-inline-type="stacked"] .inline-related h3 {
754 779 padding: 10px;
755 780 border-top-width: 0;
@@ -779,7 +804,7 input[type="submit"], button {
779 804
780 805 .inline-group[data-inline-type="stacked"] div.add-row {
781 806 margin-top: 15px;
782 border: 1px solid #eee;
807 border: 1px solid var(--hairline-color);
783 808 border-radius: 4px;
784 809 }
785 810
@@ -798,7 +823,7 input[type="submit"], button {
798 823 /* Submit row */
799 824
800 825 .submit-row {
801 padding: 10px 10px 0;
826 padding: 10px 10px 5px;
802 827 margin: 0 0 15px;
803 828 display: flex;
804 829 flex-direction: column;
@@ -873,9 +898,7 input[type="submit"], button {
873 898 }
874 899
875 900 .login .form-row label {
876 display: block;
877 901 margin: 0 0 5px;
878 padding: 0;
879 902 line-height: 1.2;
880 903 }
881 904
@@ -883,7 +906,7 input[type="submit"], button {
883 906 padding: 15px 0 0;
884 907 }
885 908
886 .login br, .login .submit-row label {
909 .login br {
887 910 display: none;
888 911 }
889 912
@@ -895,7 +918,7 input[type="submit"], button {
895 918 .errornote {
896 919 margin: 0 0 20px;
897 920 padding: 8px 12px;
898 font-size: 13px;
921 font-size: 0.8125rem;
899 922 }
900 923
901 924 /* Calendar and clock */
@@ -942,7 +965,7 input[type="submit"], button {
942 965
943 966 .calendar-shortcuts {
944 967 padding: 10px 0;
945 font-size: 12px;
968 font-size: 0.75rem;
946 969 line-height: 12px;
947 970 }
948 971
@@ -951,7 +974,7 input[type="submit"], button {
951 974 }
952 975
953 976 .timelist a {
954 background: #fff;
977 background: var(--body-bg);
955 978 padding: 4px;
956 979 }
957 980
@@ -975,7 +998,7 input[type="submit"], button {
975 998 /* History */
976 999
977 1000 table#change-history tbody th, table#change-history tbody td {
978 font-size: 13px;
1001 font-size: 0.8125rem;
979 1002 word-break: break-word;
980 1003 }
981 1004
@@ -986,7 +1009,7 input[type="submit"], button {
986 1009 /* Docs */
987 1010
988 1011 table.model tbody th, table.model tbody td {
989 font-size: 13px;
1012 font-size: 0.8125rem;
990 1013 word-break: break-word;
991 1014 }
992 1015 }
@@ -23,9 +23,9
23 23 [dir="rtl"] .change-list .filtered .paginator,
24 24 [dir="rtl"] .filtered #toolbar,
25 25 [dir="rtl"] .filtered div.xfull,
26 [dir="rtl"] .filtered .actions {
27 margin-right: 0;
28 margin-left: 230px;
26 [dir="rtl"] .filtered .actions,
27 [dir="rtl"] #changelist-filter {
28 margin-left: 0;
29 29 }
30 30
31 31 [dir="rtl"] .inline-group ul.tools a.add,
@@ -63,15 +63,6
63 63 /* MOBILE */
64 64
65 65 @media (max-width: 767px) {
66 [dir="rtl"] .change-list .filtered .results,
67 [dir="rtl"] .change-list .filtered .paginator,
68 [dir="rtl"] .filtered #toolbar,
69 [dir="rtl"] .filtered div.xfull,
70 [dir="rtl"] .filtered .actions {
71 margin-left: 0;
72 }
73
74 [dir="rtl"] .aligned .add-another,
75 66 [dir="rtl"] .aligned .related-lookup,
76 67 [dir="rtl"] .aligned .datetimeshortcuts {
77 68 margin-left: 0;
@@ -81,4 +72,9
81 72 [dir="rtl"] .aligned ul {
82 73 margin-right: 0;
83 74 }
75
76 [dir="rtl"] #changelist-filter {
77 margin-left: 0;
78 margin-right: 0;
79 }
84 80 }
@@ -1,25 +1,3
1 body {
2 direction: rtl;
3 }
4
5 /* LOGIN */
6
7 .login .form-row {
8 float: right;
9 }
10
11 .login .form-row label {
12 float: right;
13 padding-left: 0.5em;
14 padding-right: 0;
15 text-align: left;
16 }
17
18 .login .submit-row {
19 clear: both;
20 padding: 1em 9.4em 0 0;
21 }
22
23 1 /* GLOBAL */
24 2
25 3 th {
@@ -109,31 +87,21 thead th.sorted .text {
109 87 }
110 88
111 89 #changelist-filter {
112 right: auto;
113 left: 0;
114 90 border-left: none;
115 91 border-right: none;
116 }
117
118 .change-list .filtered .results, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull {
119 margin-right: 0;
120 margin-left: 280px;
92 margin-left: 0;
93 margin-right: 30px;
121 94 }
122 95
123 96 #changelist-filter li.selected {
124 97 border-left: none;
125 98 padding-left: 10px;
126 99 margin-left: 0;
127 border-right: 5px solid #eaeaea;
100 border-right: 5px solid var(--hairline-color);
128 101 padding-right: 10px;
129 102 margin-right: -15px;
130 103 }
131 104
132 .filtered .actions {
133 margin-left: 280px;
134 margin-right: 0;
135 }
136
137 105 #changelist table tbody td:first-child, #changelist table tbody th:first-child {
138 106 border-right: none;
139 107 border-left: none;
@@ -207,12 +175,24 fieldset .fieldBox {
207 175 top: 0;
208 176 left: auto;
209 177 right: 10px;
178 background: url(../img/calendar-icons.svg) 0 -30px no-repeat;
179 }
180
181 .calendarbox .calendarnav-previous:focus,
182 .calendarbox .calendarnav-previous:hover {
183 background-position: 0 -45px;
210 184 }
211 185
212 186 .calendarnav-next {
213 187 top: 0;
214 188 right: auto;
215 189 left: 10px;
190 background: url(../img/calendar-icons.svg) 0 0 no-repeat;
191 }
192
193 .calendarbox .calendarnav-next:focus,
194 .calendarbox .calendarnav-next:hover {
195 background-position: 0 -15px;
216 196 }
217 197
218 198 .calendar caption, .calendarbox h2 {
@@ -257,13 +237,3 form .form-row p.datetime {
257 237 margin-left: inherit;
258 238 margin-right: 2px;
259 239 }
260
261 /* IE7 specific bug fixes */
262
263 div.colM {
264 position: relative;
265 }
266
267 .submit-row input {
268 float: left;
269 }
@@ -1,6 +1,6
1 1 The MIT License (MIT)
2 2
3 Copyright (c) 2012-2015 Kevin Brown, Igor Vaynberg, and Select2 contributors
3 Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors
4 4
5 5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 6 of this software and associated documentation files (the "Software"), to deal
@@ -118,12 +118,14
118 118 .select2-hidden-accessible {
119 119 border: 0 !important;
120 120 clip: rect(0 0 0 0) !important;
121 -webkit-clip-path: inset(50%) !important;
122 clip-path: inset(50%) !important;
121 123 height: 1px !important;
122 margin: -1px !important;
123 124 overflow: hidden !important;
124 125 padding: 0 !important;
125 126 position: absolute !important;
126 width: 1px !important; }
127 width: 1px !important;
128 white-space: nowrap !important; }
127 129
128 130 .select2-container--default .select2-selection--single {
129 131 background-color: #fff;
@@ -186,16 +188,13
186 188 width: 100%; }
187 189 .select2-container--default .select2-selection--multiple .select2-selection__rendered li {
188 190 list-style: none; }
189 .select2-container--default .select2-selection--multiple .select2-selection__placeholder {
190 color: #999;
191 margin-top: 5px;
192 float: left; }
193 191 .select2-container--default .select2-selection--multiple .select2-selection__clear {
194 192 cursor: pointer;
195 193 float: right;
196 194 font-weight: bold;
197 195 margin-top: 5px;
198 margin-right: 10px; }
196 margin-right: 10px;
197 padding: 1px; }
199 198 .select2-container--default .select2-selection--multiple .select2-selection__choice {
200 199 background-color: #e4e4e4;
201 200 border: 1px solid #aaa;
@@ -214,7 +213,7
214 213 .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
215 214 color: #333; }
216 215
217 .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 {
216 .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
218 217 float: right; }
219 218
220 219 .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
@@ -420,9 +419,7
420 419 color: #555; }
421 420
422 421 .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
423 float: right; }
424
425 .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
422 float: right;
426 423 margin-left: 5px;
427 424 margin-right: auto; }
428 425
@@ -1,1 +1,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}
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;-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}
@@ -3,18 +3,21
3 3 .selector {
4 4 width: 800px;
5 5 float: left;
6 display: flex;
6 7 }
7 8
8 9 .selector select {
9 10 width: 380px;
10 11 height: 17.2em;
12 flex: 1 0 auto;
11 13 }
12 14
13 15 .selector-available, .selector-chosen {
14 float: left;
15 16 width: 380px;
16 17 text-align: center;
17 18 margin-bottom: 5px;
19 display: flex;
20 flex-direction: column;
18 21 }
19 22
20 23 .selector-chosen select {
@@ -22,27 +25,26
22 25 }
23 26
24 27 .selector-available h2, .selector-chosen h2 {
25 border: 1px solid #ccc;
28 border: 1px solid var(--border-color);
26 29 border-radius: 4px 4px 0 0;
27 30 }
28 31
29 32 .selector-chosen h2 {
30 background: #79aec8;
31 color: #fff;
33 background: var(--primary);
34 color: var(--header-link-color);
32 35 }
33 36
34 37 .selector .selector-available h2 {
35 background: #f8f8f8;
36 color: #666;
38 background: var(--darkened-bg);
39 color: var(--body-quiet-color);
37 40 }
38 41
39 42 .selector .selector-filter {
40 background: white;
41 border: 1px solid #ccc;
43 border: 1px solid var(--border-color);
42 44 border-width: 0 1px;
43 45 padding: 8px;
44 color: #999;
45 font-size: 10px;
46 color: var(--body-quiet-color);
47 font-size: 0.625rem;
46 48 margin: 0;
47 49 text-align: left;
48 50 }
@@ -64,12 +66,13
64 66 }
65 67
66 68 .selector ul.selector-chooser {
67 float: left;
69 align-self: center;
68 70 width: 22px;
69 background-color: #eee;
71 background-color: var(--selected-bg);
70 72 border-radius: 10px;
71 margin: 10em 5px 0 5px;
73 margin: 0 5px;
72 74 padding: 0;
75 transform: translateY(-17px);
73 76 }
74 77
75 78 .selector-chooser li {
@@ -91,7 +94,7
91 94 text-indent: -3000px;
92 95 overflow: hidden;
93 96 cursor: default;
94 opacity: 0.3;
97 opacity: 0.55;
95 98 }
96 99
97 100 .active.selector-add, .active.selector-remove {
@@ -126,14 +129,14 a.selector-chooseall, a.selector-clearall {
126 129 overflow: hidden;
127 130 font-weight: bold;
128 131 line-height: 16px;
129 color: #666;
132 color: var(--body-quiet-color);
130 133 text-decoration: none;
131 opacity: 0.3;
134 opacity: 0.55;
132 135 }
133 136
134 137 a.active.selector-chooseall:focus, a.active.selector-clearall:focus,
135 138 a.active.selector-chooseall:hover, a.active.selector-clearall:hover {
136 color: #447e9b;
139 color: var(--link-fg);
137 140 }
138 141
139 142 a.active.selector-chooseall, a.active.selector-clearall {
@@ -169,6 +172,7 a.active.selector-clearall:focus, a.active.selector-clearall:hover {
169 172 .stacked {
170 173 float: left;
171 174 width: 490px;
175 display: block;
172 176 }
173 177
174 178 .stacked select {
@@ -194,6 +198,7 a.active.selector-clearall:focus, a.active.selector-clearall:hover {
194 198 margin: 0 0 10px 40%;
195 199 background-color: #eee;
196 200 border-radius: 10px;
201 transform: none;
197 202 }
198 203
199 204 .stacked .selector-chooser li {
@@ -211,6 +216,11 a.active.selector-clearall:focus, a.active.selector-clearall:hover {
211 216 }
212 217
213 218 .stacked .active.selector-add {
219 background-position: 0 -32px;
220 cursor: pointer;
221 }
222
223 .stacked .active.selector-add:focus, .stacked .active.selector-add:hover {
214 224 background-position: 0 -48px;
215 225 cursor: pointer;
216 226 }
@@ -221,6 +231,11 a.active.selector-clearall:focus, a.active.selector-clearall:hover {
221 231 }
222 232
223 233 .stacked .active.selector-remove {
234 background-position: 0 0px;
235 cursor: pointer;
236 }
237
238 .stacked .active.selector-remove:focus, .stacked .active.selector-remove:hover {
224 239 background-position: 0 -16px;
225 240 cursor: pointer;
226 241 }
@@ -251,25 +266,24 p.datetime {
251 266 line-height: 20px;
252 267 margin: 0;
253 268 padding: 0;
254 color: #666;
269 color: var(--body-quiet-color);
255 270 font-weight: bold;
256 271 }
257 272
258 273 .datetime span {
259 274 white-space: nowrap;
260 275 font-weight: normal;
261 font-size: 11px;
262 color: #ccc;
276 font-size: 0.6875rem;
277 color: var(--body-quiet-color);
263 278 }
264 279
265 280 .datetime input, .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField {
266 min-width: 0;
267 281 margin-left: 5px;
268 282 margin-bottom: 4px;
269 283 }
270 284
271 285 table p.datetime {
272 font-size: 11px;
286 font-size: 0.6875rem;
273 287 margin-left: 0;
274 288 padding-left: 0;
275 289 }
@@ -303,8 +317,8 table p.datetime {
303 317 }
304 318
305 319 .timezonewarning {
306 font-size: 11px;
307 color: #999;
320 font-size: 0.6875rem;
321 color: var(--body-quiet-color);
308 322 }
309 323
310 324 /* URL */
@@ -313,8 +327,8 p.url {
313 327 line-height: 20px;
314 328 margin: 0;
315 329 padding: 0;
316 color: #666;
317 font-size: 11px;
330 color: var(--body-quiet-color);
331 font-size: 0.6875rem;
318 332 font-weight: bold;
319 333 }
320 334
@@ -328,8 +342,8 p.file-upload {
328 342 line-height: 20px;
329 343 margin: 0;
330 344 padding: 0;
331 color: #666;
332 font-size: 11px;
345 color: var(--body-quiet-color);
346 font-size: 0.6875rem;
333 347 font-weight: bold;
334 348 }
335 349
@@ -346,8 +360,8 p.file-upload {
346 360 }
347 361
348 362 span.clearable-file-input label {
349 color: #333;
350 font-size: 11px;
363 color: var(--body-fg);
364 font-size: 0.6875rem;
351 365 display: inline;
352 366 float: none;
353 367 }
@@ -356,11 +370,12 span.clearable-file-input label {
356 370
357 371 .calendarbox, .clockbox {
358 372 margin: 5px auto;
359 font-size: 12px;
373 font-size: 0.75rem;
360 374 width: 19em;
361 375 text-align: center;
362 background: white;
363 border: 1px solid #ddd;
376 background: var(--body-bg);
377 color: var(--body-fg);
378 border: 1px solid var(--hairline-color);
364 379 border-radius: 4px;
365 380 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
366 381 overflow: hidden;
@@ -388,38 +403,38 span.clearable-file-input label {
388 403 margin: 0;
389 404 text-align: center;
390 405 border-top: none;
391 background: #f5dd5d;
392 406 font-weight: 700;
393 font-size: 12px;
407 font-size: 0.75rem;
394 408 color: #333;
409 background: var(--accent);
395 410 }
396 411
397 412 .calendar th {
398 413 padding: 8px 5px;
399 background: #f8f8f8;
400 border-bottom: 1px solid #ddd;
414 background: var(--darkened-bg);
415 border-bottom: 1px solid var(--border-color);
401 416 font-weight: 400;
402 font-size: 12px;
417 font-size: 0.75rem;
403 418 text-align: center;
404 color: #666;
419 color: var(--body-quiet-color);
405 420 }
406 421
407 422 .calendar td {
408 423 font-weight: 400;
409 font-size: 12px;
424 font-size: 0.75rem;
410 425 text-align: center;
411 426 padding: 0;
412 border-top: 1px solid #eee;
427 border-top: 1px solid var(--hairline-color);
413 428 border-bottom: none;
414 429 }
415 430
416 431 .calendar td.selected a {
417 background: #79aec8;
418 color: #fff;
432 background: var(--primary);
433 color: var(--button-fg);
419 434 }
420 435
421 436 .calendar td.nonday {
422 background: #f8f8f8;
437 background: var(--darkened-bg);
423 438 }
424 439
425 440 .calendar td.today a {
@@ -431,22 +446,22 span.clearable-file-input label {
431 446 font-weight: 400;
432 447 padding: 6px;
433 448 text-decoration: none;
434 color: #444;
449 color: var(--body-quiet-color);
435 450 }
436 451
437 452 .calendar td a:focus, .timelist a:focus,
438 453 .calendar td a:hover, .timelist a:hover {
439 background: #79aec8;
454 background: var(--primary);
440 455 color: white;
441 456 }
442 457
443 458 .calendar td a:active, .timelist a:active {
444 background: #417690;
459 background: var(--header-bg);
445 460 color: white;
446 461 }
447 462
448 463 .calendarnav {
449 font-size: 10px;
464 font-size: 0.625rem;
450 465 text-align: center;
451 466 color: #ccc;
452 467 margin: 0;
@@ -455,16 +470,16 span.clearable-file-input label {
455 470
456 471 .calendarnav a:link, #calendarnav a:visited,
457 472 #calendarnav a:focus, #calendarnav a:hover {
458 color: #999;
473 color: var(--body-quiet-color);
459 474 }
460 475
461 476 .calendar-shortcuts {
462 background: white;
463 font-size: 11px;
477 background: var(--body-bg);
478 color: var(--body-quiet-color);
479 font-size: 0.6875rem;
464 480 line-height: 11px;
465 border-top: 1px solid #eee;
481 border-top: 1px solid var(--hairline-color);
466 482 padding: 8px 0;
467 color: #ccc;
468 483 }
469 484
470 485 .calendarbox .calendarnav-previous, .calendarbox .calendarnav-next {
@@ -500,10 +515,10 span.clearable-file-input label {
500 515 .calendar-cancel {
501 516 margin: 0;
502 517 padding: 4px 0;
503 font-size: 12px;
518 font-size: 0.75rem;
504 519 background: #eee;
505 border-top: 1px solid #ddd;
506 color: #333;
520 border-top: 1px solid var(--border-color);
521 color: var(--body-fg);
507 522 }
508 523
509 524 .calendar-cancel:focus, .calendar-cancel:hover {
@@ -1,52 +1,39
1 (function($) {
2 1 'use strict';
3 var SelectBox = {
2 {
3 const SelectBox = {
4 4 cache: {},
5 5 init: function(id) {
6 var box = document.getElementById(id);
7 var node;
6 const box = document.getElementById(id);
8 7 SelectBox.cache[id] = [];
9 var cache = SelectBox.cache[id];
10 var boxOptions = box.options;
11 var boxOptionsLength = boxOptions.length;
12 for (var i = 0, j = boxOptionsLength; i < j; i++) {
13 node = boxOptions[i];
8 const cache = SelectBox.cache[id];
9 for (const node of box.options) {
14 10 cache.push({value: node.value, text: node.text, displayed: 1});
15 11 }
16 12 },
17 13 redisplay: function(id) {
18 14 // Repopulate HTML select box from cache
19 var box = document.getElementById(id);
20 var node;
21 $(box).empty(); // clear all options
22 var new_options = box.outerHTML.slice(0, -9); // grab just the opening tag
23 var cache = SelectBox.cache[id];
24 for (var i = 0, j = cache.length; i < j; i++) {
25 node = cache[i];
15 const box = document.getElementById(id);
16 const scroll_value_from_top = box.scrollTop;
17 box.innerHTML = '';
18 for (const node of SelectBox.cache[id]) {
26 19 if (node.displayed) {
27 var new_option = new Option(node.text, node.value, false, false);
20 const new_option = new Option(node.text, node.value, false, false);
28 21 // Shows a tooltip when hovering over the option
29 new_option.setAttribute("title", node.text);
30 new_options += new_option.outerHTML;
22 new_option.title = node.text;
23 box.appendChild(new_option);
31 24 }
32 25 }
33 new_options += '</select>';
34 box.outerHTML = new_options;
26 box.scrollTop = scroll_value_from_top;
35 27 },
36 28 filter: function(id, text) {
37 29 // Redisplay the HTML select box, displaying only the choices containing ALL
38 30 // the words in text. (It's an AND search.)
39 var tokens = text.toLowerCase().split(/\s+/);
40 var node, token;
41 var cache = SelectBox.cache[id];
42 for (var i = 0, j = cache.length; i < j; i++) {
43 node = cache[i];
31 const tokens = text.toLowerCase().split(/\s+/);
32 for (const node of SelectBox.cache[id]) {
44 33 node.displayed = 1;
45 var node_text = node.text.toLowerCase();
46 var numTokens = tokens.length;
47 for (var k = 0; k < numTokens; k++) {
48 token = tokens[k];
49 if (node_text.indexOf(token) === -1) {
34 const node_text = node.text.toLowerCase();
35 for (const token of tokens) {
36 if (!node_text.includes(token)) {
50 37 node.displayed = 0;
51 38 break; // Once the first token isn't found we're done
52 39 }
@@ -55,10 +42,9
55 42 SelectBox.redisplay(id);
56 43 },
57 44 delete_from_cache: function(id, value) {
58 var node, delete_index = null;
59 var cache = SelectBox.cache[id];
60 for (var i = 0, j = cache.length; i < j; i++) {
61 node = cache[i];
45 let delete_index = null;
46 const cache = SelectBox.cache[id];
47 for (const [i, node] of cache.entries()) {
62 48 if (node.value === value) {
63 49 delete_index = i;
64 50 break;
@@ -71,10 +57,7
71 57 },
72 58 cache_contains: function(id, value) {
73 59 // Check if an item is contained in the cache
74 var node;
75 var cache = SelectBox.cache[id];
76 for (var i = 0, j = cache.length; i < j; i++) {
77 node = cache[i];
60 for (const node of SelectBox.cache[id]) {
78 61 if (node.value === value) {
79 62 return true;
80 63 }
@@ -82,13 +65,9
82 65 return false;
83 66 },
84 67 move: function(from, to) {
85 var from_box = document.getElementById(from);
86 var option;
87 var boxOptions = from_box.options;
88 var boxOptionsLength = boxOptions.length;
89 for (var i = 0, j = boxOptionsLength; i < j; i++) {
90 option = boxOptions[i];
91 var option_value = option.value;
68 const from_box = document.getElementById(from);
69 for (const option of from_box.options) {
70 const option_value = option.value;
92 71 if (option.selected && SelectBox.cache_contains(from, option_value)) {
93 72 SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1});
94 73 SelectBox.delete_from_cache(from, option_value);
@@ -98,13 +77,9
98 77 SelectBox.redisplay(to);
99 78 },
100 79 move_all: function(from, to) {
101 var from_box = document.getElementById(from);
102 var option;
103 var boxOptions = from_box.options;
104 var boxOptionsLength = boxOptions.length;
105 for (var i = 0, j = boxOptionsLength; i < j; i++) {
106 option = boxOptions[i];
107 var option_value = option.value;
80 const from_box = document.getElementById(from);
81 for (const option of from_box.options) {
82 const option_value = option.value;
108 83 if (SelectBox.cache_contains(from, option_value)) {
109 84 SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1});
110 85 SelectBox.delete_from_cache(from, option_value);
@@ -117,28 +92,21
117 92 SelectBox.cache[id].sort(function(a, b) {
118 93 a = a.text.toLowerCase();
119 94 b = b.text.toLowerCase();
120 try {
121 95 if (a > b) {
122 96 return 1;
123 97 }
124 98 if (a < b) {
125 99 return -1;
126 100 }
127 }
128 catch (e) {
129 // silently fail on IE 'unknown' exception
130 }
131 101 return 0;
132 102 } );
133 103 },
134 104 select_all: function(id) {
135 var box = document.getElementById(id);
136 var boxOptions = box.options;
137 var boxOptionsLength = boxOptions.length;
138 for (var i = 0; i < boxOptionsLength; i++) {
139 boxOptions[i].selected = 'selected';
105 const box = document.getElementById(id);
106 for (const option of box.options) {
107 option.selected = true;
140 108 }
141 109 }
142 110 };
143 111 window.SelectBox = SelectBox;
144 })(django.jQuery);
112 }
@@ -2,49 +2,40
2 2 /*
3 3 SelectFilter2 - Turns a multiple-select box into a filter interface.
4 4
5 Requires jQuery, core.js, and SelectBox.js.
5 Requires core.js and SelectBox.js.
6 6 */
7 (function($) {
8 7 'use strict';
9 function findForm(node) {
10 // returns the node of the form containing the given node
11 if (node.tagName.toLowerCase() !== 'form') {
12 return findForm(node.parentNode);
13 }
14 return node;
15 }
16
8 {
17 9 window.SelectFilter = {
18 10 init: function(field_id, field_name, is_stacked) {
19 11 if (field_id.match(/__prefix__/)) {
20 12 // Don't initialize on empty forms.
21 13 return;
22 14 }
23 var from_box = document.getElementById(field_id);
15 const from_box = document.getElementById(field_id);
24 16 from_box.id += '_from'; // change its ID
25 17 from_box.className = 'filtered';
26 18
27 var ps = from_box.parentNode.getElementsByTagName('p');
28 for (var i = 0; i < ps.length; i++) {
29 if (ps[i].className.indexOf("info") !== -1) {
19 for (const p of from_box.parentNode.getElementsByTagName('p')) {
20 if (p.classList.contains("info")) {
30 21 // Remove <p class="info">, because it just gets in the way.
31 from_box.parentNode.removeChild(ps[i]);
32 } else if (ps[i].className.indexOf("help") !== -1) {
22 from_box.parentNode.removeChild(p);
23 } else if (p.classList.contains("help")) {
33 24 // Move help text up to the top so it isn't below the select
34 25 // boxes or wrapped off on the side to the right of the add
35 26 // button:
36 from_box.parentNode.insertBefore(ps[i], from_box.parentNode.firstChild);
27 from_box.parentNode.insertBefore(p, from_box.parentNode.firstChild);
37 28 }
38 29 }
39 30
40 31 // <div class="selector"> or <div class="selector stacked">
41 var selector_div = quickElement('div', from_box.parentNode);
32 const selector_div = quickElement('div', from_box.parentNode);
42 33 selector_div.className = is_stacked ? 'selector stacked' : 'selector';
43 34
44 35 // <div class="selector-available">
45 var selector_available = quickElement('div', selector_div);
36 const selector_available = quickElement('div', selector_div);
46 37 selector_available.className = 'selector-available';
47 var title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name]));
38 const title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name]));
48 39 quickElement(
49 40 'span', title_available, '',
50 41 'class', 'help help-tooltip help-icon',
@@ -58,10 +49,10 Requires jQuery, core.js, and SelectBox.js.
58 49 )
59 50 );
60 51
61 var filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter');
52 const filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter');
62 53 filter_p.className = 'selector-filter';
63 54
64 var search_filter_label = quickElement('label', filter_p, '', 'for', field_id + '_input');
55 const search_filter_label = quickElement('label', filter_p, '', 'for', field_id + '_input');
65 56
66 57 quickElement(
67 58 'span', search_filter_label, '',
@@ -71,25 +62,25 Requires jQuery, core.js, and SelectBox.js.
71 62
72 63 filter_p.appendChild(document.createTextNode(' '));
73 64
74 var filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter"));
65 const filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter"));
75 66 filter_input.id = field_id + '_input';
76 67
77 68 selector_available.appendChild(from_box);
78 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');
69 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');
79 70 choose_all.className = 'selector-chooseall';
80 71
81 72 // <ul class="selector-chooser">
82 var selector_chooser = quickElement('ul', selector_div);
73 const selector_chooser = quickElement('ul', selector_div);
83 74 selector_chooser.className = 'selector-chooser';
84 var add_link = quickElement('a', quickElement('li', selector_chooser), gettext('Choose'), 'title', gettext('Choose'), 'href', '#', 'id', field_id + '_add_link');
75 const add_link = quickElement('a', quickElement('li', selector_chooser), gettext('Choose'), 'title', gettext('Choose'), 'href', '#', 'id', field_id + '_add_link');
85 76 add_link.className = 'selector-add';
86 var remove_link = quickElement('a', quickElement('li', selector_chooser), gettext('Remove'), 'title', gettext('Remove'), 'href', '#', 'id', field_id + '_remove_link');
77 const remove_link = quickElement('a', quickElement('li', selector_chooser), gettext('Remove'), 'title', gettext('Remove'), 'href', '#', 'id', field_id + '_remove_link');
87 78 remove_link.className = 'selector-remove';
88 79
89 80 // <div class="selector-chosen">
90 var selector_chosen = quickElement('div', selector_div);
81 const selector_chosen = quickElement('div', selector_div);
91 82 selector_chosen.className = 'selector-chosen';
92 var title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name]));
83 const title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name]));
93 84 quickElement(
94 85 'span', title_chosen, '',
95 86 'class', 'help help-tooltip help-icon',
@@ -103,16 +94,16 Requires jQuery, core.js, and SelectBox.js.
103 94 )
104 95 );
105 96
106 var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name'));
97 const to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', '', 'size', from_box.size, 'name', from_box.name);
107 98 to_box.className = 'filtered';
108 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');
99 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');
109 100 clear_all.className = 'selector-clearall';
110 101
111 from_box.setAttribute('name', from_box.getAttribute('name') + '_old');
102 from_box.name = from_box.name + '_old';
112 103
113 104 // Set up the JavaScript event handlers for the select box filter interface
114 var move_selection = function(e, elem, move_func, from, to) {
115 if (elem.className.indexOf('active') !== -1) {
105 const move_selection = function(e, elem, move_func, from, to) {
106 if (elem.classList.contains('active')) {
116 107 move_func(from, to);
117 108 SelectFilter.refresh_icons(field_id);
118 109 }
@@ -154,7 +145,7 Requires jQuery, core.js, and SelectBox.js.
154 145 SelectFilter.refresh_icons(field_id);
155 146 }
156 147 });
157 findForm(from_box).addEventListener('submit', function() {
148 from_box.closest('form').addEventListener('submit', function() {
158 149 SelectBox.select_all(field_id + '_to');
159 150 });
160 151 SelectBox.init(field_id + '_from');
@@ -162,66 +153,50 Requires jQuery, core.js, and SelectBox.js.
162 153 // Move selected from_box options to to_box
163 154 SelectBox.move(field_id + '_from', field_id + '_to');
164 155
165 if (!is_stacked) {
166 // In horizontal mode, give the same height to the two boxes.
167 var j_from_box = $('#' + field_id + '_from');
168 var j_to_box = $('#' + field_id + '_to');
169 j_to_box.height($(filter_p).outerHeight() + j_from_box.outerHeight());
170 }
171
172 156 // Initial icon refresh
173 157 SelectFilter.refresh_icons(field_id);
174 158 },
175 159 any_selected: function(field) {
176 var any_selected = false;
177 try {
178 160 // Temporarily add the required attribute and check validity.
179 // This is much faster in WebKit browsers than the fallback.
180 field.attr('required', 'required');
181 any_selected = field.is(':valid');
182 field.removeAttr('required');
183 } catch (e) {
184 // Browsers that don't support :valid (IE < 10)
185 any_selected = field.find('option:selected').length > 0;
186 }
161 field.required = true;
162 const any_selected = field.checkValidity();
163 field.required = false;
187 164 return any_selected;
188 165 },
189 166 refresh_icons: function(field_id) {
190 var from = $('#' + field_id + '_from');
191 var to = $('#' + field_id + '_to');
167 const from = document.getElementById(field_id + '_from');
168 const to = document.getElementById(field_id + '_to');
192 169 // Active if at least one item is selected
193 $('#' + field_id + '_add_link').toggleClass('active', SelectFilter.any_selected(from));
194 $('#' + field_id + '_remove_link').toggleClass('active', SelectFilter.any_selected(to));
170 document.getElementById(field_id + '_add_link').classList.toggle('active', SelectFilter.any_selected(from));
171 document.getElementById(field_id + '_remove_link').classList.toggle('active', SelectFilter.any_selected(to));
195 172 // Active if the corresponding box isn't empty
196 $('#' + field_id + '_add_all_link').toggleClass('active', from.find('option').length > 0);
197 $('#' + field_id + '_remove_all_link').toggleClass('active', to.find('option').length > 0);
173 document.getElementById(field_id + '_add_all_link').classList.toggle('active', from.querySelector('option'));
174 document.getElementById(field_id + '_remove_all_link').classList.toggle('active', to.querySelector('option'));
198 175 },
199 176 filter_key_press: function(event, field_id) {
200 var from = document.getElementById(field_id + '_from');
177 const from = document.getElementById(field_id + '_from');
201 178 // don't submit form if user pressed Enter
202 179 if ((event.which && event.which === 13) || (event.keyCode && event.keyCode === 13)) {
203 180 from.selectedIndex = 0;
204 181 SelectBox.move(field_id + '_from', field_id + '_to');
205 182 from.selectedIndex = 0;
206 183 event.preventDefault();
207 return false;
208 184 }
209 185 },
210 186 filter_key_up: function(event, field_id) {
211 var from = document.getElementById(field_id + '_from');
212 var temp = from.selectedIndex;
187 const from = document.getElementById(field_id + '_from');
188 const temp = from.selectedIndex;
213 189 SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value);
214 190 from.selectedIndex = temp;
215 return true;
216 191 },
217 192 filter_key_down: function(event, field_id) {
218 var from = document.getElementById(field_id + '_from');
193 const from = document.getElementById(field_id + '_from');
219 194 // right arrow -- move across
220 195 if ((event.which && event.which === 39) || (event.keyCode && event.keyCode === 39)) {
221 var old_index = from.selectedIndex;
196 const old_index = from.selectedIndex;
222 197 SelectBox.move(field_id + '_from', field_id + '_to');
223 198 from.selectedIndex = (old_index === from.length) ? from.length - 1 : old_index;
224 return false;
199 return;
225 200 }
226 201 // down arrow -- wrap around
227 202 if ((event.which && event.which === 40) || (event.keyCode && event.keyCode === 40)) {
@@ -231,16 +206,13 Requires jQuery, core.js, and SelectBox.js.
231 206 if ((event.which && event.which === 38) || (event.keyCode && event.keyCode === 38)) {
232 207 from.selectedIndex = (from.selectedIndex === 0) ? from.length - 1 : from.selectedIndex - 1;
233 208 }
234 return true;
235 209 }
236 210 };
237 211
238 212 window.addEventListener('load', function(e) {
239 $('select.selectfilter, select.selectfilterstacked').each(function() {
240 var $el = $(this),
241 data = $el.data();
242 SelectFilter.init($el.attr('id'), data.fieldName, parseInt(data.isStacked, 10));
213 document.querySelectorAll('select.selectfilter, select.selectfilterstacked').forEach(function(el) {
214 const data = el.dataset;
215 SelectFilter.init(el.id, data.fieldName, parseInt(data.isStacked, 10));
243 216 });
244 217 });
245
246 })(django.jQuery);
218 }
@@ -1,153 +1,201
1 1 /*global gettext, interpolate, ngettext*/
2 (function($) {
3 2 'use strict';
4 var lastChecked;
5
6 $.fn.actions = function(opts) {
7 var options = $.extend({}, $.fn.actions.defaults, opts);
8 var actionCheckboxes = $(this);
9 var list_editable_changed = false;
10 var showQuestion = function() {
11 $(options.acrossClears).hide();
12 $(options.acrossQuestions).show();
13 $(options.allContainer).hide();
14 },
15 showClear = function() {
16 $(options.acrossClears).show();
17 $(options.acrossQuestions).hide();
18 $(options.actionContainer).toggleClass(options.selectedClass);
19 $(options.allContainer).show();
20 $(options.counterContainer).hide();
21 },
22 reset = function() {
23 $(options.acrossClears).hide();
24 $(options.acrossQuestions).hide();
25 $(options.allContainer).hide();
26 $(options.counterContainer).show();
27 },
28 clearAcross = function() {
29 reset();
30 $(options.acrossInput).val(0);
31 $(options.actionContainer).removeClass(options.selectedClass);
32 },
33 checker = function(checked) {
3 {
4 function show(selector) {
5 document.querySelectorAll(selector).forEach(function(el) {
6 el.classList.remove('hidden');
7 });
8 }
9
10 function hide(selector) {
11 document.querySelectorAll(selector).forEach(function(el) {
12 el.classList.add('hidden');
13 });
14 }
15
16 function showQuestion(options) {
17 hide(options.acrossClears);
18 show(options.acrossQuestions);
19 hide(options.allContainer);
20 }
21
22 function showClear(options) {
23 show(options.acrossClears);
24 hide(options.acrossQuestions);
25 document.querySelector(options.actionContainer).classList.remove(options.selectedClass);
26 show(options.allContainer);
27 hide(options.counterContainer);
28 }
29
30 function reset(options) {
31 hide(options.acrossClears);
32 hide(options.acrossQuestions);
33 hide(options.allContainer);
34 show(options.counterContainer);
35 }
36
37 function clearAcross(options) {
38 reset(options);
39 const acrossInputs = document.querySelectorAll(options.acrossInput);
40 acrossInputs.forEach(function(acrossInput) {
41 acrossInput.value = 0;
42 });
43 document.querySelector(options.actionContainer).classList.remove(options.selectedClass);
44 }
45
46 function checker(actionCheckboxes, options, checked) {
34 47 if (checked) {
35 showQuestion();
48 showQuestion(options);
36 49 } else {
37 reset();
50 reset(options);
51 }
52 actionCheckboxes.forEach(function(el) {
53 el.checked = checked;
54 el.closest('tr').classList.toggle(options.selectedClass, checked);
55 });
38 56 }
39 $(actionCheckboxes).prop("checked", checked)
40 .parent().parent().toggleClass(options.selectedClass, checked);
41 },
42 updateCounter = function() {
43 var sel = $(actionCheckboxes).filter(":checked").length;
57
58 function updateCounter(actionCheckboxes, options) {
59 const sel = Array.from(actionCheckboxes).filter(function(el) {
60 return el.checked;
61 }).length;
62 const counter = document.querySelector(options.counterContainer);
44 63 // data-actions-icnt is defined in the generated HTML
45 64 // and contains the total amount of objects in the queryset
46 var actions_icnt = $('.action-counter').data('actionsIcnt');
47 $(options.counterContainer).html(interpolate(
65 const actions_icnt = Number(counter.dataset.actionsIcnt);
66 counter.textContent = interpolate(
48 67 ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), {
49 68 sel: sel,
50 69 cnt: actions_icnt
51 }, true));
52 $(options.allToggle).prop("checked", function() {
53 var value;
54 if (sel === actionCheckboxes.length) {
55 value = true;
56 showQuestion();
70 }, true);
71 const allToggle = document.getElementById(options.allToggleId);
72 allToggle.checked = sel === actionCheckboxes.length;
73 if (allToggle.checked) {
74 showQuestion(options);
57 75 } else {
58 value = false;
59 clearAcross();
76 clearAcross(options);
60 77 }
61 return value;
62 });
63 };
64 // Show counter by default
65 $(options.counterContainer).show();
66 // Check state of checkboxes and reinit state if needed
67 $(this).filter(":checked").each(function(i) {
68 $(this).parent().parent().toggleClass(options.selectedClass);
69 updateCounter();
70 if ($(options.acrossInput).val() === 1) {
71 showClear();
72 78 }
79
80 const defaults = {
81 actionContainer: "div.actions",
82 counterContainer: "span.action-counter",
83 allContainer: "div.actions span.all",
84 acrossInput: "div.actions input.select-across",
85 acrossQuestions: "div.actions span.question",
86 acrossClears: "div.actions span.clear",
87 allToggleId: "action-toggle",
88 selectedClass: "selected"
89 };
90
91 window.Actions = function(actionCheckboxes, options) {
92 options = Object.assign({}, defaults, options);
93 let list_editable_changed = false;
94 let lastChecked = null;
95 let shiftPressed = false;
96
97 document.addEventListener('keydown', (event) => {
98 shiftPressed = event.shiftKey;
73 99 });
74 $(options.allToggle).show().on('click', function() {
75 checker($(this).prop("checked"));
76 updateCounter();
100
101 document.addEventListener('keyup', (event) => {
102 shiftPressed = event.shiftKey;
103 });
104
105 document.getElementById(options.allToggleId).addEventListener('click', function(event) {
106 checker(actionCheckboxes, options, this.checked);
107 updateCounter(actionCheckboxes, options);
77 108 });
78 $("a", options.acrossQuestions).on('click', function(event) {
109
110 document.querySelectorAll(options.acrossQuestions + " a").forEach(function(el) {
111 el.addEventListener('click', function(event) {
79 112 event.preventDefault();
80 $(options.acrossInput).val(1);
81 showClear();
113 const acrossInputs = document.querySelectorAll(options.acrossInput);
114 acrossInputs.forEach(function(acrossInput) {
115 acrossInput.value = 1;
82 116 });
83 $("a", options.acrossClears).on('click', function(event) {
117 showClear(options);
118 });
119 });
120
121 document.querySelectorAll(options.acrossClears + " a").forEach(function(el) {
122 el.addEventListener('click', function(event) {
84 123 event.preventDefault();
85 $(options.allToggle).prop("checked", false);
86 clearAcross();
87 checker(0);
88 updateCounter();
89 });
90 lastChecked = null;
91 $(actionCheckboxes).on('click', function(event) {
92 if (!event) { event = window.event; }
93 var target = event.target ? event.target : event.srcElement;
94 if (lastChecked && $.data(lastChecked) !== $.data(target) && event.shiftKey === true) {
95 var inrange = false;
96 $(lastChecked).prop("checked", target.checked)
97 .parent().parent().toggleClass(options.selectedClass, target.checked);
98 $(actionCheckboxes).each(function() {
99 if ($.data(this) === $.data(lastChecked) || $.data(this) === $.data(target)) {
100 inrange = (inrange) ? false : true;
101 }
102 if (inrange) {
103 $(this).prop("checked", target.checked)
104 .parent().parent().toggleClass(options.selectedClass, target.checked);
105 }
106 });
107 }
108 $(target).parent().parent().toggleClass(options.selectedClass, target.checked);
109 lastChecked = target;
110 updateCounter();
124 document.getElementById(options.allToggleId).checked = false;
125 clearAcross(options);
126 checker(actionCheckboxes, options, false);
127 updateCounter(actionCheckboxes, options);
128 });
111 129 });
112 $('form#changelist-form table#result_list tr').on('change', 'td:gt(0) :input', function() {
130
131 function affectedCheckboxes(target, withModifier) {
132 const multiSelect = (lastChecked && withModifier && lastChecked !== target);
133 if (!multiSelect) {
134 return [target];
135 }
136 const checkboxes = Array.from(actionCheckboxes);
137 const targetIndex = checkboxes.findIndex(el => el === target);
138 const lastCheckedIndex = checkboxes.findIndex(el => el === lastChecked);
139 const startIndex = Math.min(targetIndex, lastCheckedIndex);
140 const endIndex = Math.max(targetIndex, lastCheckedIndex);
141 const filtered = checkboxes.filter((el, index) => (startIndex <= index) && (index <= endIndex));
142 return filtered;
143 };
144
145 Array.from(document.getElementById('result_list').tBodies).forEach(function(el) {
146 el.addEventListener('change', function(event) {
147 const target = event.target;
148 if (target.classList.contains('action-select')) {
149 const checkboxes = affectedCheckboxes(target, shiftPressed);
150 checker(checkboxes, options, target.checked);
151 updateCounter(actionCheckboxes, options);
152 lastChecked = target;
153 } else {
113 154 list_editable_changed = true;
155 }
114 156 });
115 $('form#changelist-form button[name="index"]').on('click', function(event) {
157 });
158
159 document.querySelector('#changelist-form button[name=index]').addEventListener('click', function(event) {
116 160 if (list_editable_changed) {
117 return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
161 const confirmed = confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
162 if (!confirmed) {
163 event.preventDefault();
118 164 }
119 });
120 $('form#changelist-form input[name="_save"]').on('click', function(event) {
121 var action_changed = false;
122 $('select option:selected', options.actionContainer).each(function() {
123 if ($(this).val()) {
124 action_changed = true;
125 165 }
126 166 });
127 if (action_changed) {
128 if (list_editable_changed) {
129 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."));
130 } else {
131 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."));
167
168 const el = document.querySelector('#changelist-form input[name=_save]');
169 // The button does not exist if no fields are editable.
170 if (el) {
171 el.addEventListener('click', function(event) {
172 if (document.querySelector('[name=action]').value) {
173 const text = list_editable_changed
174 ? 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.")
175 : 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.");
176 if (!confirm(text)) {
177 event.preventDefault();
132 178 }
133 179 }
134 180 });
181 }
135 182 };
136 /* Setup plugin defaults */
137 $.fn.actions.defaults = {
138 actionContainer: "div.actions",
139 counterContainer: "span.action-counter",
140 allContainer: "div.actions span.all",
141 acrossInput: "div.actions input.select-across",
142 acrossQuestions: "div.actions span.question",
143 acrossClears: "div.actions span.clear",
144 allToggle: "#action-toggle",
145 selectedClass: "selected"
146 };
147 $(document).ready(function() {
148 var $actionsEls = $('tr input.action-select');
149 if ($actionsEls.length > 0) {
150 $actionsEls.actions();
183
184 // Call function fn when the DOM is loaded and ready. If it is already
185 // loaded, call the function now.
186 // http://youmightnotneedjquery.com/#ready
187 function ready(fn) {
188 if (document.readyState !== 'loading') {
189 fn();
190 } else {
191 document.addEventListener('DOMContentLoaded', fn);
192 }
193 }
194
195 ready(function() {
196 const actionsEls = document.querySelectorAll('tr input.action-select');
197 if (actionsEls.length > 0) {
198 Actions(actionsEls);
151 199 }
152 200 });
153 })(django.jQuery);
201 }
@@ -1,10 +1,10
1 /*global Calendar, findPosX, findPosY, getStyle, get_format, gettext, gettext_noop, interpolate, ngettext, quickElement*/
1 /*global Calendar, findPosX, findPosY, get_format, gettext, gettext_noop, interpolate, ngettext, quickElement*/
2 2 // Inserts shortcut buttons after all of the following:
3 3 // <input type="text" class="vDateField">
4 4 // <input type="text" class="vTimeField">
5 (function() {
6 5 'use strict';
7 var DateTimeShortcuts = {
6 {
7 const DateTimeShortcuts = {
8 8 calendars: [],
9 9 calendarInputs: [],
10 10 clockInputs: [],
@@ -28,21 +28,18
28 28 timezoneWarningClass: 'timezonewarning', // class of the warning for timezone mismatch
29 29 timezoneOffset: 0,
30 30 init: function() {
31 var body = document.getElementsByTagName('body')[0];
32 var serverOffset = body.getAttribute('data-admin-utc-offset');
31 const serverOffset = document.body.dataset.adminUtcOffset;
33 32 if (serverOffset) {
34 var localOffset = new Date().getTimezoneOffset() * -60;
33 const localOffset = new Date().getTimezoneOffset() * -60;
35 34 DateTimeShortcuts.timezoneOffset = localOffset - serverOffset;
36 35 }
37 36
38 var inputs = document.getElementsByTagName('input');
39 for (var i = 0; i < inputs.length; i++) {
40 var inp = inputs[i];
41 if (inp.getAttribute('type') === 'text' && inp.className.match(/vTimeField/)) {
37 for (const inp of document.getElementsByTagName('input')) {
38 if (inp.type === 'text' && inp.classList.contains('vTimeField')) {
42 39 DateTimeShortcuts.addClock(inp);
43 40 DateTimeShortcuts.addTimezoneWarning(inp);
44 41 }
45 else if (inp.getAttribute('type') === 'text' && inp.className.match(/vDateField/)) {
42 else if (inp.type === 'text' && inp.classList.contains('vDateField')) {
46 43 DateTimeShortcuts.addCalendar(inp);
47 44 DateTimeShortcuts.addTimezoneWarning(inp);
48 45 }
@@ -50,11 +47,10
50 47 },
51 48 // Return the current time while accounting for the server timezone.
52 49 now: function() {
53 var body = document.getElementsByTagName('body')[0];
54 var serverOffset = body.getAttribute('data-admin-utc-offset');
50 const serverOffset = document.body.dataset.adminUtcOffset;
55 51 if (serverOffset) {
56 var localNow = new Date();
57 var localOffset = localNow.getTimezoneOffset() * -60;
52 const localNow = new Date();
53 const localOffset = localNow.getTimezoneOffset() * -60;
58 54 localNow.setTime(localNow.getTime() + 1000 * (serverOffset - localOffset));
59 55 return localNow;
60 56 } else {
@@ -63,8 +59,8
63 59 },
64 60 // Add a warning when the time zone in the browser and backend do not match.
65 61 addTimezoneWarning: function(inp) {
66 var warningClass = DateTimeShortcuts.timezoneWarningClass;
67 var timezoneOffset = DateTimeShortcuts.timezoneOffset / 3600;
62 const warningClass = DateTimeShortcuts.timezoneWarningClass;
63 let timezoneOffset = DateTimeShortcuts.timezoneOffset / 3600;
68 64
69 65 // Only warn if there is a time zone mismatch.
70 66 if (!timezoneOffset) {
@@ -76,7 +72,7
76 72 return;
77 73 }
78 74
79 var message;
75 let message;
80 76 if (timezoneOffset > 0) {
81 77 message = ngettext(
82 78 'Note: You are %s hour ahead of server time.',
@@ -94,7 +90,7
94 90 }
95 91 message = interpolate(message, [timezoneOffset]);
96 92
97 var warning = document.createElement('span');
93 const warning = document.createElement('span');
98 94 warning.className = warningClass;
99 95 warning.textContent = message;
100 96 inp.parentNode.appendChild(document.createElement('br'));
@@ -102,23 +98,23
102 98 },
103 99 // Add clock widget to a given field
104 100 addClock: function(inp) {
105 var num = DateTimeShortcuts.clockInputs.length;
101 const num = DateTimeShortcuts.clockInputs.length;
106 102 DateTimeShortcuts.clockInputs[num] = inp;
107 103 DateTimeShortcuts.dismissClockFunc[num] = function() { DateTimeShortcuts.dismissClock(num); return true; };
108 104
109 105 // Shortcut links (clock icon and "Now" link)
110 var shortcuts_span = document.createElement('span');
106 const shortcuts_span = document.createElement('span');
111 107 shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
112 108 inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
113 var now_link = document.createElement('a');
114 now_link.setAttribute('href', "#");
109 const now_link = document.createElement('a');
110 now_link.href = "#";
115 111 now_link.textContent = gettext('Now');
116 112 now_link.addEventListener('click', function(e) {
117 113 e.preventDefault();
118 114 DateTimeShortcuts.handleClockQuicklink(num, -1);
119 115 });
120 var clock_link = document.createElement('a');
121 clock_link.setAttribute('href', '#');
116 const clock_link = document.createElement('a');
117 clock_link.href = '#';
122 118 clock_link.id = DateTimeShortcuts.clockLinkName + num;
123 119 clock_link.addEventListener('click', function(e) {
124 120 e.preventDefault();
@@ -152,32 +148,32
152 148 // <p class="calendar-cancel"><a href="#">Cancel</a></p>
153 149 // </div>
154 150
155 var clock_box = document.createElement('div');
151 const clock_box = document.createElement('div');
156 152 clock_box.style.display = 'none';
157 153 clock_box.style.position = 'absolute';
158 154 clock_box.className = 'clockbox module';
159 clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
155 clock_box.id = DateTimeShortcuts.clockDivName + num;
160 156 document.body.appendChild(clock_box);
161 157 clock_box.addEventListener('click', function(e) { e.stopPropagation(); });
162 158
163 159 quickElement('h2', clock_box, gettext('Choose a time'));
164 var time_list = quickElement('ul', clock_box);
160 const time_list = quickElement('ul', clock_box);
165 161 time_list.className = 'timelist';
166 162 // The list of choices can be overridden in JavaScript like this:
167 163 // DateTimeShortcuts.clockHours.name = [['3 a.m.', 3]];
168 164 // where name is the name attribute of the <input>.
169 var name = typeof DateTimeShortcuts.clockHours[inp.name] === 'undefined' ? 'default_' : inp.name;
165 const name = typeof DateTimeShortcuts.clockHours[inp.name] === 'undefined' ? 'default_' : inp.name;
170 166 DateTimeShortcuts.clockHours[name].forEach(function(element) {
171 var time_link = quickElement('a', quickElement('li', time_list), gettext(element[0]), 'href', '#');
167 const time_link = quickElement('a', quickElement('li', time_list), gettext(element[0]), 'href', '#');
172 168 time_link.addEventListener('click', function(e) {
173 169 e.preventDefault();
174 170 DateTimeShortcuts.handleClockQuicklink(num, element[1]);
175 171 });
176 172 });
177 173
178 var cancel_p = quickElement('p', clock_box);
174 const cancel_p = quickElement('p', clock_box);
179 175 cancel_p.className = 'calendar-cancel';
180 var cancel_link = quickElement('a', cancel_p, gettext('Cancel'), 'href', '#');
176 const cancel_link = quickElement('a', cancel_p, gettext('Cancel'), 'href', '#');
181 177 cancel_link.addEventListener('click', function(e) {
182 178 e.preventDefault();
183 179 DateTimeShortcuts.dismissClock(num);
@@ -192,19 +188,17
192 188 });
193 189 },
194 190 openClock: function(num) {
195 var clock_box = document.getElementById(DateTimeShortcuts.clockDivName + num);
196 var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName + num);
191 const clock_box = document.getElementById(DateTimeShortcuts.clockDivName + num);
192 const clock_link = document.getElementById(DateTimeShortcuts.clockLinkName + num);
197 193
198 194 // Recalculate the clockbox position
199 195 // is it left-to-right or right-to-left layout ?
200 if (getStyle(document.body, 'direction') !== 'rtl') {
196 if (window.getComputedStyle(document.body).direction !== 'rtl') {
201 197 clock_box.style.left = findPosX(clock_link) + 17 + 'px';
202 198 }
203 199 else {
204 200 // since style's width is in em, it'd be tough to calculate
205 201 // px value of it. let's use an estimated px for now
206 // TODO: IE returns wrong value for findPosX when in rtl mode
207 // (it returns as it was left aligned), needs to be fixed.
208 202 clock_box.style.left = findPosX(clock_link) - 110 + 'px';
209 203 }
210 204 clock_box.style.top = Math.max(0, findPosY(clock_link) - 30) + 'px';
@@ -218,7 +212,7
218 212 document.removeEventListener('click', DateTimeShortcuts.dismissClockFunc[num]);
219 213 },
220 214 handleClockQuicklink: function(num, val) {
221 var d;
215 let d;
222 216 if (val === -1) {
223 217 d = DateTimeShortcuts.now();
224 218 }
@@ -231,24 +225,24
231 225 },
232 226 // Add calendar widget to a given field.
233 227 addCalendar: function(inp) {
234 var num = DateTimeShortcuts.calendars.length;
228 const num = DateTimeShortcuts.calendars.length;
235 229
236 230 DateTimeShortcuts.calendarInputs[num] = inp;
237 231 DateTimeShortcuts.dismissCalendarFunc[num] = function() { DateTimeShortcuts.dismissCalendar(num); return true; };
238 232
239 233 // Shortcut links (calendar icon and "Today" link)
240 var shortcuts_span = document.createElement('span');
234 const shortcuts_span = document.createElement('span');
241 235 shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
242 236 inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
243 var today_link = document.createElement('a');
244 today_link.setAttribute('href', '#');
237 const today_link = document.createElement('a');
238 today_link.href = '#';
245 239 today_link.appendChild(document.createTextNode(gettext('Today')));
246 240 today_link.addEventListener('click', function(e) {
247 241 e.preventDefault();
248 242 DateTimeShortcuts.handleCalendarQuickLink(num, 0);
249 243 });
250 var cal_link = document.createElement('a');
251 cal_link.setAttribute('href', '#');
244 const cal_link = document.createElement('a');
245 cal_link.href = '#';
252 246 cal_link.id = DateTimeShortcuts.calendarLinkName + num;
253 247 cal_link.addEventListener('click', function(e) {
254 248 e.preventDefault();
@@ -283,24 +277,24
283 277 // </div>
284 278 // <p class="calendar-cancel"><a href="#">Cancel</a></p>
285 279 // </div>
286 var cal_box = document.createElement('div');
280 const cal_box = document.createElement('div');
287 281 cal_box.style.display = 'none';
288 282 cal_box.style.position = 'absolute';
289 283 cal_box.className = 'calendarbox module';
290 cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
284 cal_box.id = DateTimeShortcuts.calendarDivName1 + num;
291 285 document.body.appendChild(cal_box);
292 286 cal_box.addEventListener('click', function(e) { e.stopPropagation(); });
293 287
294 288 // next-prev links
295 var cal_nav = quickElement('div', cal_box);
296 var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', '#');
289 const cal_nav = quickElement('div', cal_box);
290 const cal_nav_prev = quickElement('a', cal_nav, '<', 'href', '#');
297 291 cal_nav_prev.className = 'calendarnav-previous';
298 292 cal_nav_prev.addEventListener('click', function(e) {
299 293 e.preventDefault();
300 294 DateTimeShortcuts.drawPrev(num);
301 295 });
302 296
303 var cal_nav_next = quickElement('a', cal_nav, '>', 'href', '#');
297 const cal_nav_next = quickElement('a', cal_nav, '>', 'href', '#');
304 298 cal_nav_next.className = 'calendarnav-next';
305 299 cal_nav_next.addEventListener('click', function(e) {
306 300 e.preventDefault();
@@ -308,15 +302,15
308 302 });
309 303
310 304 // main box
311 var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
305 const cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
312 306 cal_main.className = 'calendar';
313 307 DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num));
314 308 DateTimeShortcuts.calendars[num].drawCurrent();
315 309
316 310 // calendar shortcuts
317 var shortcuts = quickElement('div', cal_box);
311 const shortcuts = quickElement('div', cal_box);
318 312 shortcuts.className = 'calendar-shortcuts';
319 var day_link = quickElement('a', shortcuts, gettext('Yesterday'), 'href', '#');
313 let day_link = quickElement('a', shortcuts, gettext('Yesterday'), 'href', '#');
320 314 day_link.addEventListener('click', function(e) {
321 315 e.preventDefault();
322 316 DateTimeShortcuts.handleCalendarQuickLink(num, -1);
@@ -335,9 +329,9
335 329 });
336 330
337 331 // cancel bar
338 var cancel_p = quickElement('p', cal_box);
332 const cancel_p = quickElement('p', cal_box);
339 333 cancel_p.className = 'calendar-cancel';
340 var cancel_link = quickElement('a', cancel_p, gettext('Cancel'), 'href', '#');
334 const cancel_link = quickElement('a', cancel_p, gettext('Cancel'), 'href', '#');
341 335 cancel_link.addEventListener('click', function(e) {
342 336 e.preventDefault();
343 337 DateTimeShortcuts.dismissCalendar(num);
@@ -351,18 +345,18
351 345 });
352 346 },
353 347 openCalendar: function(num) {
354 var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1 + num);
355 var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName + num);
356 var inp = DateTimeShortcuts.calendarInputs[num];
348 const cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1 + num);
349 const cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName + num);
350 const inp = DateTimeShortcuts.calendarInputs[num];
357 351
358 352 // Determine if the current value in the input has a valid date.
359 353 // If so, draw the calendar with that date's year and month.
360 354 if (inp.value) {
361 var format = get_format('DATE_INPUT_FORMATS')[0];
362 var selected = inp.value.strptime(format);
363 var year = selected.getUTCFullYear();
364 var month = selected.getUTCMonth() + 1;
365 var re = /\d{4}/;
355 const format = get_format('DATE_INPUT_FORMATS')[0];
356 const selected = inp.value.strptime(format);
357 const year = selected.getUTCFullYear();
358 const month = selected.getUTCMonth() + 1;
359 const re = /\d{4}/;
366 360 if (re.test(year.toString()) && month >= 1 && month <= 12) {
367 361 DateTimeShortcuts.calendars[num].drawDate(month, year, selected);
368 362 }
@@ -370,14 +364,12
370 364
371 365 // Recalculate the clockbox position
372 366 // is it left-to-right or right-to-left layout ?
373 if (getStyle(document.body, 'direction') !== 'rtl') {
367 if (window.getComputedStyle(document.body).direction !== 'rtl') {
374 368 cal_box.style.left = findPosX(cal_link) + 17 + 'px';
375 369 }
376 370 else {
377 371 // since style's width is in em, it'd be tough to calculate
378 372 // px value of it. let's use an estimated px for now
379 // TODO: IE returns wrong value for findPosX when in rtl mode
380 // (it returns as it was left aligned), needs to be fixed.
381 373 cal_box.style.left = findPosX(cal_link) - 180 + 'px';
382 374 }
383 375 cal_box.style.top = Math.max(0, findPosY(cal_link) - 75) + 'px';
@@ -396,13 +388,7
396 388 DateTimeShortcuts.calendars[num].drawNextMonth();
397 389 },
398 390 handleCalendarCallback: function(num) {
399 var format = get_format('DATE_INPUT_FORMATS')[0];
400 // the format needs to be escaped a little
401 format = format.replace('\\', '\\\\')
402 .replace('\r', '\\r')
403 .replace('\n', '\\n')
404 .replace('\t', '\\t')
405 .replace("'", "\\'");
391 const format = get_format('DATE_INPUT_FORMATS')[0];
406 392 return function(y, m, d) {
407 393 DateTimeShortcuts.calendarInputs[num].value = new Date(y, m - 1, d).strftime(format);
408 394 DateTimeShortcuts.calendarInputs[num].focus();
@@ -410,7 +396,7
410 396 };
411 397 },
412 398 handleCalendarQuickLink: function(num, offset) {
413 var d = DateTimeShortcuts.now();
399 const d = DateTimeShortcuts.now();
414 400 d.setDate(d.getDate() + offset);
415 401 DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]);
416 402 DateTimeShortcuts.calendarInputs[num].focus();
@@ -420,4 +406,4
420 406
421 407 window.addEventListener('load', DateTimeShortcuts.init);
422 408 window.DateTimeShortcuts = DateTimeShortcuts;
423 })();
409 }
@@ -1,38 +1,48
1 1 /*global SelectBox, interpolate*/
2 2 // Handles related-objects functionality: lookup link for raw_id_fields
3 3 // and Add Another links.
4
5 (function($) {
6 4 'use strict';
5 {
6 const $ = django.jQuery;
7 let popupIndex = 0;
8 const relatedWindows = [];
9
10 function dismissChildPopups() {
11 relatedWindows.forEach(function(win) {
12 if(!win.closed) {
13 win.dismissChildPopups();
14 win.close();
15 }
16 });
17 }
18
19 function setPopupIndex() {
20 if(document.getElementsByName("_popup").length > 0) {
21 const index = window.name.lastIndexOf("__") + 2;
22 popupIndex = parseInt(window.name.substring(index));
23 } else {
24 popupIndex = 0;
25 }
26 }
7 27
8 // IE doesn't accept periods or dashes in the window name, but the element IDs
9 // we use to generate popup window names may contain them, therefore we map them
10 // to allowed characters in a reversible way so that we can locate the correct
11 // element when the popup window is dismissed.
12 function id_to_windowname(text) {
13 text = text.replace(/\./g, '__dot__');
14 text = text.replace(/\-/g, '__dash__');
15 return text;
28 function addPopupIndex(name) {
29 name = name + "__" + (popupIndex + 1);
30 return name;
16 31 }
17 32
18 function windowname_to_id(text) {
19 text = text.replace(/__dot__/g, '.');
20 text = text.replace(/__dash__/g, '-');
21 return text;
33 function removePopupIndex(name) {
34 name = name.replace(new RegExp("__" + (popupIndex + 1) + "$"), '');
35 return name;
22 36 }
23 37
24 38 function showAdminPopup(triggeringLink, name_regexp, add_popup) {
25 var name = triggeringLink.id.replace(name_regexp, '');
26 name = id_to_windowname(name);
27 var href = triggeringLink.href;
39 const name = addPopupIndex(triggeringLink.id.replace(name_regexp, ''));
40 const href = new URL(triggeringLink.href);
28 41 if (add_popup) {
29 if (href.indexOf('?') === -1) {
30 href += '?_popup=1';
31 } else {
32 href += '&_popup=1';
33 }
42 href.searchParams.set('_popup', 1);
34 43 }
35 var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
44 const win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
45 relatedWindows.push(win);
36 46 win.focus();
37 47 return false;
38 48 }
@@ -42,13 +52,17
42 52 }
43 53
44 54 function dismissRelatedLookupPopup(win, chosenId) {
45 var name = windowname_to_id(win.name);
46 var elem = document.getElementById(name);
47 if (elem.className.indexOf('vManyToManyRawIdAdminField') !== -1 && elem.value) {
55 const name = removePopupIndex(win.name);
56 const elem = document.getElementById(name);
57 if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) {
48 58 elem.value += ',' + chosenId;
49 59 } else {
50 60 document.getElementById(name).value = chosenId;
51 61 }
62 const index = relatedWindows.indexOf(win);
63 if (index > -1) {
64 relatedWindows.splice(index, 1);
65 }
52 66 win.close();
53 67 }
54 68
@@ -57,15 +71,15
57 71 }
58 72
59 73 function updateRelatedObjectLinks(triggeringLink) {
60 var $this = $(triggeringLink);
61 var siblings = $this.nextAll('.view-related, .change-related, .delete-related');
74 const $this = $(triggeringLink);
75 const siblings = $this.nextAll('.view-related, .change-related, .delete-related');
62 76 if (!siblings.length) {
63 77 return;
64 78 }
65 var value = $this.val();
79 const value = $this.val();
66 80 if (value) {
67 81 siblings.each(function() {
68 var elm = $(this);
82 const elm = $(this);
69 83 elm.attr('href', elm.attr('data-href-template').replace('__fk__', value));
70 84 });
71 85 } else {
@@ -73,15 +87,46
73 87 }
74 88 }
75 89
90 function updateRelatedSelectsOptions(currentSelect, win, objId, newRepr, newId) {
91 // After create/edit a model from the options next to the current
92 // select (+ or :pencil:) update ForeignKey PK of the rest of selects
93 // in the page.
94
95 const path = win.location.pathname;
96 // Extract the model from the popup url '.../<model>/add/' or
97 // '.../<model>/<id>/change/' depending the action (add or change).
98 const modelName = path.split('/')[path.split('/').length - (objId ? 4 : 3)];
99 // Exclude autocomplete selects.
100 const selectsRelated = document.querySelectorAll(`[data-model-ref="${modelName}"] select:not(.admin-autocomplete)`);
101
102 selectsRelated.forEach(function(select) {
103 if (currentSelect === select) {
104 return;
105 }
106
107 let option = select.querySelector(`option[value="${objId}"]`);
108
109 if (!option) {
110 option = new Option(newRepr, newId);
111 select.options.add(option);
112 return;
113 }
114
115 option.textContent = newRepr;
116 option.value = newId;
117 });
118 }
119
76 120 function dismissAddRelatedObjectPopup(win, newId, newRepr) {
77 var name = windowname_to_id(win.name);
78 var elem = document.getElementById(name);
121 const name = removePopupIndex(win.name);
122 const elem = document.getElementById(name);
79 123 if (elem) {
80 var elemName = elem.nodeName.toUpperCase();
124 const elemName = elem.nodeName.toUpperCase();
81 125 if (elemName === 'SELECT') {
82 126 elem.options[elem.options.length] = new Option(newRepr, newId, true, true);
127 updateRelatedSelectsOptions(elem, win, null, newRepr, newId);
83 128 } else if (elemName === 'INPUT') {
84 if (elem.className.indexOf('vManyToManyRawIdAdminField') !== -1 && elem.value) {
129 if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) {
85 130 elem.value += ',' + newId;
86 131 } else {
87 132 elem.value = newId;
@@ -90,49 +135,58
90 135 // Trigger a change event to update related links if required.
91 136 $(elem).trigger('change');
92 137 } else {
93 var toId = name + "_to";
94 var o = new Option(newRepr, newId);
138 const toId = name + "_to";
139 const o = new Option(newRepr, newId);
95 140 SelectBox.add_to_cache(toId, o);
96 141 SelectBox.redisplay(toId);
97 142 }
143 const index = relatedWindows.indexOf(win);
144 if (index > -1) {
145 relatedWindows.splice(index, 1);
146 }
98 147 win.close();
99 148 }
100 149
101 150 function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) {
102 var id = windowname_to_id(win.name).replace(/^edit_/, '');
103 var selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
104 var selects = $(selectsSelector);
151 const id = removePopupIndex(win.name.replace(/^edit_/, ''));
152 const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
153 const selects = $(selectsSelector);
105 154 selects.find('option').each(function() {
106 155 if (this.value === objId) {
107 156 this.textContent = newRepr;
108 157 this.value = newId;
109 158 }
110 });
159 }).trigger('change');
160 updateRelatedSelectsOptions(selects[0], win, objId, newRepr, newId);
111 161 selects.next().find('.select2-selection__rendered').each(function() {
112 162 // The element can have a clear button as a child.
113 163 // Use the lastChild to modify only the displayed value.
114 164 this.lastChild.textContent = newRepr;
115 165 this.title = newRepr;
116 166 });
167 const index = relatedWindows.indexOf(win);
168 if (index > -1) {
169 relatedWindows.splice(index, 1);
170 }
117 171 win.close();
118 172 }
119 173
120 174 function dismissDeleteRelatedObjectPopup(win, objId) {
121 var id = windowname_to_id(win.name).replace(/^delete_/, '');
122 var selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
123 var selects = $(selectsSelector);
175 const id = removePopupIndex(win.name.replace(/^delete_/, ''));
176 const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
177 const selects = $(selectsSelector);
124 178 selects.find('option').each(function() {
125 179 if (this.value === objId) {
126 180 $(this).remove();
127 181 }
128 182 }).trigger('change');
183 const index = relatedWindows.indexOf(win);
184 if (index > -1) {
185 relatedWindows.splice(index, 1);
186 }
129 187 win.close();
130 188 }
131 189
132 // Global for testing purposes
133 window.id_to_windowname = id_to_windowname;
134 window.windowname_to_id = windowname_to_id;
135
136 190 window.showRelatedObjectLookupPopup = showRelatedObjectLookupPopup;
137 191 window.dismissRelatedLookupPopup = dismissRelatedLookupPopup;
138 192 window.showRelatedObjectPopup = showRelatedObjectPopup;
@@ -140,20 +194,26
140 194 window.dismissAddRelatedObjectPopup = dismissAddRelatedObjectPopup;
141 195 window.dismissChangeRelatedObjectPopup = dismissChangeRelatedObjectPopup;
142 196 window.dismissDeleteRelatedObjectPopup = dismissDeleteRelatedObjectPopup;
197 window.dismissChildPopups = dismissChildPopups;
143 198
144 199 // Kept for backward compatibility
145 200 window.showAddAnotherPopup = showRelatedObjectPopup;
146 201 window.dismissAddAnotherPopup = dismissAddRelatedObjectPopup;
147 202
203 window.addEventListener('unload', function(evt) {
204 window.dismissChildPopups();
205 });
206
148 207 $(document).ready(function() {
208 setPopupIndex();
149 209 $("a[data-popup-opener]").on('click', function(event) {
150 210 event.preventDefault();
151 211 opener.dismissRelatedLookupPopup(window, $(this).data("popup-opener"));
152 212 });
153 $('body').on('click', '.related-widget-wrapper-link', function(e) {
213 $('body').on('click', '.related-widget-wrapper-link[data-popup="yes"]', function(e) {
154 214 e.preventDefault();
155 215 if (this.href) {
156 var event = $.Event('django:show-related', {href: this.href});
216 const event = $.Event('django:show-related', {href: this.href});
157 217 $(this).trigger(event);
158 218 if (!event.isDefaultPrevented()) {
159 219 showRelatedObjectPopup(this);
@@ -161,7 +221,7
161 221 }
162 222 });
163 223 $('body').on('change', '.related-widget-wrapper select', function(e) {
164 var event = $.Event('django:update-related');
224 const event = $.Event('django:update-related');
165 225 $(this).trigger(event);
166 226 if (!event.isDefaultPrevented()) {
167 227 updateRelatedObjectLinks(this);
@@ -170,12 +230,11
170 230 $('.related-widget-wrapper select').trigger('change');
171 231 $('body').on('click', '.related-lookup', function(e) {
172 232 e.preventDefault();
173 var event = $.Event('django:lookup-related');
233 const event = $.Event('django:lookup-related');
174 234 $(this).trigger(event);
175 235 if (!event.isDefaultPrevented()) {
176 236 showRelatedObjectLookupPopup(this);
177 237 }
178 238 });
179 239 });
180
181 })(django.jQuery);
240 }
@@ -1,24 +1,22
1 (function($) {
2 1 'use strict';
3 var init = function($element, options) {
4 var settings = $.extend({
2 {
3 const $ = django.jQuery;
4
5 $.fn.djangoAdminSelect2 = function() {
6 $.each(this, function(i, element) {
7 $(element).select2({
5 8 ajax: {
6 data: function(params) {
9 data: (params) => {
7 10 return {
8 11 term: params.term,
9 page: params.page
12 page: params.page,
13 app_label: element.dataset.appLabel,
14 model_name: element.dataset.modelName,
15 field_name: element.dataset.fieldName
10 16 };
11 17 }
12 18 }
13 }, options);
14 $element.select2(settings);
15 };
16
17 $.fn.djangoAdminSelect2 = function(options) {
18 var settings = $.extend({}, options);
19 $.each(this, function(i, element) {
20 var $element = $(element);
21 init($element, settings);
19 });
22 20 });
23 21 return this;
24 22 };
@@ -29,9 +27,7
29 27 $('.admin-autocomplete').not('[name*=__prefix__]').djangoAdminSelect2();
30 28 });
31 29
32 $(document).on('formset:added', (function() {
33 return function(event, $newFormset) {
34 return $newFormset.find('.admin-autocomplete').djangoAdminSelect2();
35 };
36 })(this));
37 }(django.jQuery));
30 document.addEventListener('formset:added', (event) => {
31 $(event.target).find('.admin-autocomplete').djangoAdminSelect2();
32 });
33 }
@@ -3,11 +3,10
3 3 calendar.js - Calendar functions by Adrian Holovaty
4 4 depends on core.js for utility functions like removeChildren or quickElement
5 5 */
6
7 (function() {
8 6 'use strict';
7 {
9 8 // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions
10 var CalendarNamespace = {
9 const CalendarNamespace = {
11 10 monthsOfYear: [
12 11 gettext('January'),
13 12 gettext('February'),
@@ -22,6 +21,20 depends on core.js for utility functions like removeChildren or quickElement
22 21 gettext('November'),
23 22 gettext('December')
24 23 ],
24 monthsOfYearAbbrev: [
25 pgettext('abbrev. month January', 'Jan'),
26 pgettext('abbrev. month February', 'Feb'),
27 pgettext('abbrev. month March', 'Mar'),
28 pgettext('abbrev. month April', 'Apr'),
29 pgettext('abbrev. month May', 'May'),
30 pgettext('abbrev. month June', 'Jun'),
31 pgettext('abbrev. month July', 'Jul'),
32 pgettext('abbrev. month August', 'Aug'),
33 pgettext('abbrev. month September', 'Sep'),
34 pgettext('abbrev. month October', 'Oct'),
35 pgettext('abbrev. month November', 'Nov'),
36 pgettext('abbrev. month December', 'Dec')
37 ],
25 38 daysOfWeek: [
26 39 pgettext('one letter Sunday', 'S'),
27 40 pgettext('one letter Monday', 'M'),
@@ -36,7 +49,7 depends on core.js for utility functions like removeChildren or quickElement
36 49 return (((year % 4) === 0) && ((year % 100) !== 0 ) || ((year % 400) === 0));
37 50 },
38 51 getDaysInMonth: function(month, year) {
39 var days;
52 let days;
40 53 if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) {
41 54 days = 31;
42 55 }
@@ -52,11 +65,11 depends on core.js for utility functions like removeChildren or quickElement
52 65 return days;
53 66 },
54 67 draw: function(month, year, div_id, callback, selected) { // month = 1-12, year = 1-9999
55 var today = new Date();
56 var todayDay = today.getDate();
57 var todayMonth = today.getMonth() + 1;
58 var todayYear = today.getFullYear();
59 var todayClass = '';
68 const today = new Date();
69 const todayDay = today.getDate();
70 const todayMonth = today.getMonth() + 1;
71 const todayYear = today.getFullYear();
72 let todayClass = '';
60 73
61 74 // Use UTC functions here because the date field does not contain time
62 75 // 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
69 82 //
70 83 // The day variable above will be 1 instead of 2 in, say, US Pacific time
71 84 // zone.
72 var isSelectedMonth = false;
85 let isSelectedMonth = false;
73 86 if (typeof selected !== 'undefined') {
74 87 isSelectedMonth = (selected.getUTCFullYear() === year && (selected.getUTCMonth() + 1) === month);
75 88 }
76 89
77 90 month = parseInt(month);
78 91 year = parseInt(year);
79 var calDiv = document.getElementById(div_id);
92 const calDiv = document.getElementById(div_id);
80 93 removeChildren(calDiv);
81 var calTable = document.createElement('table');
94 const calTable = document.createElement('table');
82 95 quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month - 1] + ' ' + year);
83 var tableBody = quickElement('tbody', calTable);
96 const tableBody = quickElement('tbody', calTable);
84 97
85 98 // Draw days-of-week header
86 var tableRow = quickElement('tr', tableBody);
87 for (var i = 0; i < 7; i++) {
99 let tableRow = quickElement('tr', tableBody);
100 for (let i = 0; i < 7; i++) {
88 101 quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]);
89 102 }
90 103
91 var startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay();
92 var days = CalendarNamespace.getDaysInMonth(month, year);
104 const startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay();
105 const days = CalendarNamespace.getDaysInMonth(month, year);
93 106
94 var nonDayCell;
107 let nonDayCell;
95 108
96 109 // Draw blanks before first of month
97 110 tableRow = quickElement('tr', tableBody);
98 for (i = 0; i < startingPos; i++) {
111 for (let i = 0; i < startingPos; i++) {
99 112 nonDayCell = quickElement('td', tableRow, ' ');
100 113 nonDayCell.className = "nonday";
101 114 }
@@ -109,8 +122,8 depends on core.js for utility functions like removeChildren or quickElement
109 122 }
110 123
111 124 // Draw days of month
112 var currentDay = 1;
113 for (i = startingPos; currentDay <= days; i++) {
125 let currentDay = 1;
126 for (let i = startingPos; currentDay <= days; i++) {
114 127 if (i % 7 === 0 && currentDay !== 1) {
115 128 tableRow = quickElement('tr', tableBody);
116 129 }
@@ -128,8 +141,8 depends on core.js for utility functions like removeChildren or quickElement
128 141 todayClass += "selected";
129 142 }
130 143
131 var cell = quickElement('td', tableRow, '', 'class', todayClass);
132 var link = quickElement('a', cell, currentDay, 'href', '#');
144 const cell = quickElement('td', tableRow, '', 'class', todayClass);
145 const link = quickElement('a', cell, currentDay, 'href', '#');
133 146 link.addEventListener('click', calendarMonth(year, month));
134 147 currentDay++;
135 148 }
@@ -205,4 +218,4 depends on core.js for utility functions like removeChildren or quickElement
205 218 };
206 219 window.Calendar = Calendar;
207 220 window.CalendarNamespace = CalendarNamespace;
208 })();
221 }
@@ -1,13 +1,29
1 (function($) {
2 1 'use strict';
3 $(function() {
4 $('.cancel-link').on('click', function(e) {
5 e.preventDefault();
6 if (window.location.search.indexOf('&_popup=1') === -1) {
7 window.history.back(); // Go back if not a popup.
2 {
3 // Call function fn when the DOM is loaded and ready. If it is already
4 // loaded, call the function now.
5 // http://youmightnotneedjquery.com/#ready
6 function ready(fn) {
7 if (document.readyState !== 'loading') {
8 fn();
8 9 } else {
9 window.close(); // Otherwise, close the popup.
10 document.addEventListener('DOMContentLoaded', fn);
10 11 }
12 }
13
14 ready(function() {
15 function handleClick(event) {
16 event.preventDefault();
17 const params = new URLSearchParams(window.location.search);
18 if (params.has('_popup')) {
19 window.close(); // Close the popup.
20 } else {
21 window.history.back(); // Otherwise, go back.
22 }
23 }
24
25 document.querySelectorAll('.cancel-link').forEach(function(el) {
26 el.addEventListener('click', handleClick);
11 27 });
12 28 });
13 })(django.jQuery);
29 }
@@ -1,20 +1,16
1 /*global showAddAnotherPopup, showRelatedObjectLookupPopup showRelatedObjectPopup updateRelatedObjectLinks*/
2
3 (function($) {
4 1 'use strict';
5 $(document).ready(function() {
6 var modelName = $('#django-admin-form-add-constants').data('modelName');
7 $('body').on('click', '.add-another', function(e) {
8 e.preventDefault();
9 var event = $.Event('django:add-another-related');
10 $(this).trigger(event);
11 if (!event.isDefaultPrevented()) {
12 showAddAnotherPopup(this);
13 }
14 });
15
2 {
3 const inputTags = ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA'];
4 const modelName = document.getElementById('django-admin-form-add-constants').dataset.modelName;
16 5 if (modelName) {
17 $('form#' + modelName + '_form :input:visible:enabled:first').focus();
6 const form = document.getElementById(modelName + '_form');
7 for (const element of form.elements) {
8 // HTMLElement.offsetParent returns null when the element is not
9 // rendered.
10 if (inputTags.includes(element.tagName) && !element.disabled && element.offsetParent) {
11 element.focus();
12 break;
13 }
14 }
15 }
18 16 }
19 });
20 })(django.jQuery);
@@ -1,52 +1,43
1 1 /*global gettext*/
2 (function() {
3 2 'use strict';
4 var closestElem = function(elem, tagName) {
5 if (elem.nodeName === tagName.toUpperCase()) {
6 return elem;
7 }
8 if (elem.parentNode.nodeName === 'BODY') {
9 return null;
10 }
11 return elem.parentNode && closestElem(elem.parentNode, tagName);
12 };
13
3 {
14 4 window.addEventListener('load', function() {
15 5 // Add anchor tag for Show/Hide link
16 var fieldsets = document.querySelectorAll('fieldset.collapse');
17 for (var i = 0; i < fieldsets.length; i++) {
18 var elem = fieldsets[i];
6 const fieldsets = document.querySelectorAll('fieldset.collapse');
7 for (const [i, elem] of fieldsets.entries()) {
19 8 // Don't hide if fields in this fieldset have errors
20 if (elem.querySelectorAll('div.errors').length === 0) {
9 if (elem.querySelectorAll('div.errors, ul.errorlist').length === 0) {
21 10 elem.classList.add('collapsed');
22 var h2 = elem.querySelector('h2');
23 var link = document.createElement('a');
24 link.setAttribute('id', 'fieldsetcollapser' + i);
25 link.setAttribute('class', 'collapse-toggle');
26 link.setAttribute('href', '#');
11 const h2 = elem.querySelector('h2');
12 const link = document.createElement('a');
13 link.id = 'fieldsetcollapser' + i;
14 link.className = 'collapse-toggle';
15 link.href = '#';
27 16 link.textContent = gettext('Show');
28 17 h2.appendChild(document.createTextNode(' ('));
29 18 h2.appendChild(link);
30 19 h2.appendChild(document.createTextNode(')'));
31 20 }
32 21 }
33 // Add toggle to anchor tag
34 var toggles = document.querySelectorAll('fieldset.collapse a.collapse-toggle');
35 var toggleFunc = function(ev) {
22 // Add toggle to hide/show anchor tag
23 const toggleFunc = function(ev) {
24 if (ev.target.matches('.collapse-toggle')) {
36 25 ev.preventDefault();
37 var fieldset = closestElem(this, 'fieldset');
26 ev.stopPropagation();
27 const fieldset = ev.target.closest('fieldset');
38 28 if (fieldset.classList.contains('collapsed')) {
39 29 // Show
40 this.textContent = gettext('Hide');
30 ev.target.textContent = gettext('Hide');
41 31 fieldset.classList.remove('collapsed');
42 32 } else {
43 33 // Hide
44 this.textContent = gettext('Show');
34 ev.target.textContent = gettext('Show');
45 35 fieldset.classList.add('collapsed');
46 36 }
47 };
48 for (i = 0; i < toggles.length; i++) {
49 toggles[i].addEventListener('click', toggleFunc);
50 37 }
38 };
39 document.querySelectorAll('fieldset.module').forEach(function(el) {
40 el.addEventListener('click', toggleFunc);
41 });
51 42 });
52 })();
43 }
@@ -1,19 +1,15
1 // Core javascript helper functions
2
3 // basic browser identification & version
4 var isOpera = (navigator.userAgent.indexOf("Opera") >= 0) && parseFloat(navigator.appVersion);
5 var isIE = ((document.all) && (!isOpera)) && parseFloat(navigator.appVersion.split("MSIE ")[1].split(";")[0]);
1 // Core JavaScript helper functions
2 'use strict';
6 3
7 4 // quickElement(tagType, parentReference [, textInChildNode, attribute, attributeValue ...]);
8 5 function quickElement() {
9 'use strict';
10 var obj = document.createElement(arguments[0]);
6 const obj = document.createElement(arguments[0]);
11 7 if (arguments[2]) {
12 var textNode = document.createTextNode(arguments[2]);
8 const textNode = document.createTextNode(arguments[2]);
13 9 obj.appendChild(textNode);
14 10 }
15 var len = arguments.length;
16 for (var i = 3; i < len; i += 2) {
11 const len = arguments.length;
12 for (let i = 3; i < len; i += 2) {
17 13 obj.setAttribute(arguments[i], arguments[i + 1]);
18 14 }
19 15 arguments[1].appendChild(obj);
@@ -22,7 +18,6 function quickElement() {
22 18
23 19 // "a" is reference to an object
24 20 function removeChildren(a) {
25 'use strict';
26 21 while (a.hasChildNodes()) {
27 22 a.removeChild(a.lastChild);
28 23 }
@@ -33,16 +28,11 function removeChildren(a) {
33 28 // See https://www.quirksmode.org/js/findpos.html
34 29 // ----------------------------------------------------------------------------
35 30 function findPosX(obj) {
36 'use strict';
37 var curleft = 0;
31 let curleft = 0;
38 32 if (obj.offsetParent) {
39 33 while (obj.offsetParent) {
40 curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft);
41 obj = obj.offsetParent;
42 }
43 // IE offsetParent does not include the top-level
44 if (isIE && obj.parentElement) {
45 34 curleft += obj.offsetLeft - obj.scrollLeft;
35 obj = obj.offsetParent;
46 36 }
47 37 } else if (obj.x) {
48 38 curleft += obj.x;
@@ -51,16 +41,11 function findPosX(obj) {
51 41 }
52 42
53 43 function findPosY(obj) {
54 'use strict';
55 var curtop = 0;
44 let curtop = 0;
56 45 if (obj.offsetParent) {
57 46 while (obj.offsetParent) {
58 curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop);
59 obj = obj.offsetParent;
60 }
61 // IE offsetParent does not include the top-level
62 if (isIE && obj.parentElement) {
63 47 curtop += obj.offsetTop - obj.scrollTop;
48 obj = obj.offsetParent;
64 49 }
65 50 } else if (obj.y) {
66 51 curtop += obj.y;
@@ -71,16 +56,9 function findPosY(obj) {
71 56 //-----------------------------------------------------------------------------
72 57 // Date object extensions
73 58 // ----------------------------------------------------------------------------
74 (function() {
75 'use strict';
59 {
76 60 Date.prototype.getTwelveHours = function() {
77 var hours = this.getHours();
78 if (hours === 0) {
79 return 12;
80 }
81 else {
82 return hours <= 12 ? hours : hours - 12;
83 }
61 return this.getHours() % 12 || 12;
84 62 };
85 63
86 64 Date.prototype.getTwoDigitMonth = function() {
@@ -107,12 +85,10 function findPosY(obj) {
107 85 return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds();
108 86 };
109 87
110 Date.prototype.getHourMinute = function() {
111 return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute();
112 };
113
114 Date.prototype.getHourMinuteSecond = function() {
115 return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond();
88 Date.prototype.getAbbrevMonthName = function() {
89 return typeof window.CalendarNamespace === "undefined"
90 ? this.getTwoDigitMonth()
91 : window.CalendarNamespace.monthsOfYearAbbrev[this.getMonth()];
116 92 };
117 93
118 94 Date.prototype.getFullMonthName = function() {
@@ -122,7 +98,8 function findPosY(obj) {
122 98 };
123 99
124 100 Date.prototype.strftime = function(format) {
125 var fields = {
101 const fields = {
102 b: this.getAbbrevMonthName(),
126 103 B: this.getFullMonthName(),
127 104 c: this.toString(),
128 105 d: this.getTwoDigitDate(),
@@ -139,7 +116,7 function findPosY(obj) {
139 116 Y: '' + this.getFullYear(),
140 117 '%': '%'
141 118 };
142 var result = '', i = 0;
119 let result = '', i = 0;
143 120 while (i < format.length) {
144 121 if (format.charAt(i) === '%') {
145 122 result = result + fields[format.charAt(i + 1)];
@@ -156,19 +133,11 function findPosY(obj) {
156 133 // ----------------------------------------------------------------------------
157 134 // String object extensions
158 135 // ----------------------------------------------------------------------------
159 String.prototype.pad_left = function(pad_length, pad_string) {
160 var new_string = this;
161 for (var i = 0; new_string.length < pad_length; i++) {
162 new_string = pad_string + new_string;
163 }
164 return new_string;
165 };
166
167 136 String.prototype.strptime = function(format) {
168 var split_format = format.split(/[.\-/]/);
169 var date = this.split(/[.\-/]/);
170 var i = 0;
171 var day, month, year;
137 const split_format = format.split(/[.\-/]/);
138 const date = this.split(/[.\-/]/);
139 let i = 0;
140 let day, month, year;
172 141 while (i < split_format.length) {
173 142 switch (split_format[i]) {
174 143 case "%d":
@@ -181,7 +150,14 function findPosY(obj) {
181 150 year = date[i];
182 151 break;
183 152 case "%y":
153 // A %y value in the range of [00, 68] is in the current
154 // century, while [69, 99] is in the previous century,
155 // according to the Open Group Specification.
156 if (parseInt(date[i], 10) >= 69) {
184 157 year = date[i];
158 } else {
159 year = (new Date(Date.UTC(date[i], 0))).getUTCFullYear() + 100;
160 }
185 161 break;
186 162 }
187 163 ++i;
@@ -191,22 +167,4 function findPosY(obj) {
191 167 // date extraction.
192 168 return new Date(Date.UTC(year, month, day));
193 169 };
194
195 })();
196 // ----------------------------------------------------------------------------
197 // Get the computed style for and element
198 // ----------------------------------------------------------------------------
199 function getStyle(oElm, strCssRule) {
200 'use strict';
201 var strValue = "";
202 if(document.defaultView && document.defaultView.getComputedStyle) {
203 strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
204 }
205 else if(oElm.currentStyle) {
206 strCssRule = strCssRule.replace(/\-(\w)/g, function(strMatch, p1) {
207 return p1.toUpperCase();
208 });
209 strValue = oElm.currentStyle[strCssRule];
210 }
211 return strValue;
212 170 }
@@ -15,15 +15,16
15 15 * Licensed under the New BSD License
16 16 * See: https://opensource.org/licenses/bsd-license.php
17 17 */
18 (function($) {
19 18 'use strict';
19 {
20 const $ = django.jQuery;
20 21 $.fn.formset = function(opts) {
21 var options = $.extend({}, $.fn.formset.defaults, opts);
22 var $this = $(this);
23 var $parent = $this.parent();
24 var updateElementIndex = function(el, prefix, ndx) {
25 var id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))");
26 var replacement = prefix + "-" + ndx;
22 const options = $.extend({}, $.fn.formset.defaults, opts);
23 const $this = $(this);
24 const $parent = $this.parent();
25 const updateElementIndex = function(el, prefix, ndx) {
26 const id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))");
27 const replacement = prefix + "-" + ndx;
27 28 if ($(el).prop("for")) {
28 29 $(el).prop("for", $(el).prop("for").replace(id_regex, replacement));
29 30 }
@@ -34,22 +35,21
34 35 el.name = el.name.replace(id_regex, replacement);
35 36 }
36 37 };
37 var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off");
38 var nextIndex = parseInt(totalForms.val(), 10);
39 var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off");
40 // only show the add button if we are allowed to add more items,
41 // note that max_num = None translates to a blank string.
42 var showAddButton = maxForms.val() === '' || (maxForms.val() - totalForms.val()) > 0;
43 $this.each(function(i) {
44 $(this).not("." + options.emptyCssClass).addClass(options.formCssClass);
45 });
46 if ($this.length && showAddButton) {
47 var addButton = options.addButton;
38 const totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off");
39 let nextIndex = parseInt(totalForms.val(), 10);
40 const maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off");
41 const minForms = $("#id_" + options.prefix + "-MIN_NUM_FORMS").prop("autocomplete", "off");
42 let addButton;
43
44 /**
45 * The "Add another MyModel" button below the inline forms.
46 */
47 const addInlineAddButton = function() {
48 48 if (addButton === null) {
49 49 if ($this.prop("tagName") === "TR") {
50 50 // If forms are laid out as table rows, insert the
51 51 // "add" button in a new table row:
52 var numCols = this.eq(-1).children().length;
52 const numCols = $this.eq(-1).children().length;
53 53 $parent.append('<tr class="' + options.addCssClass + '"><td colspan="' + numCols + '"><a href="#">' + options.addText + "</a></tr>");
54 54 addButton = $parent.find("tr:last a");
55 55 } else {
@@ -58,13 +58,49
58 58 addButton = $this.filter(":last").next().find("a");
59 59 }
60 60 }
61 addButton.on('click', function(e) {
61 addButton.on('click', addInlineClickHandler);
62 };
63
64 const addInlineClickHandler = function(e) {
62 65 e.preventDefault();
63 var template = $("#" + options.prefix + "-empty");
64 var row = template.clone(true);
66 const template = $("#" + options.prefix + "-empty");
67 const row = template.clone(true);
65 68 row.removeClass(options.emptyCssClass)
66 69 .addClass(options.formCssClass)
67 70 .attr("id", options.prefix + "-" + nextIndex);
71 addInlineDeleteButton(row);
72 row.find("*").each(function() {
73 updateElementIndex(this, options.prefix, totalForms.val());
74 });
75 // Insert the new form when it has been fully edited.
76 row.insertBefore($(template));
77 // Update number of total forms.
78 $(totalForms).val(parseInt(totalForms.val(), 10) + 1);
79 nextIndex += 1;
80 // Hide the add button if there's a limit and it's been reached.
81 if ((maxForms.val() !== '') && (maxForms.val() - totalForms.val()) <= 0) {
82 addButton.parent().hide();
83 }
84 // Show the remove buttons if there are more than min_num.
85 toggleDeleteButtonVisibility(row.closest('.inline-group'));
86
87 // Pass the new form to the post-add callback, if provided.
88 if (options.added) {
89 options.added(row);
90 }
91 row.get(0).dispatchEvent(new CustomEvent("formset:added", {
92 bubbles: true,
93 detail: {
94 formsetName: options.prefix
95 }
96 }));
97 };
98
99 /**
100 * The "X" button that is part of every unsaved inline.
101 * (When saved, it is replaced with a "Delete" checkbox.)
102 */
103 const addInlineDeleteButton = function(row) {
68 104 if (row.is("tr")) {
69 105 // If the forms are laid out in table rows, insert
70 106 // the remove button into the last table cell:
@@ -78,54 +114,84
78 114 // last child element of the form's container:
79 115 row.children(":first").append('<span><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></span>");
80 116 }
81 row.find("*").each(function() {
82 updateElementIndex(this, options.prefix, totalForms.val());
83 });
84 // Insert the new form when it has been fully edited
85 row.insertBefore($(template));
86 // Update number of total forms
87 $(totalForms).val(parseInt(totalForms.val(), 10) + 1);
88 nextIndex += 1;
89 // Hide add button in case we've hit the max, except we want to add infinitely
90 if ((maxForms.val() !== '') && (maxForms.val() - totalForms.val()) <= 0) {
91 addButton.parent().hide();
92 }
93 // The delete button of each row triggers a bunch of other things
94 row.find("a." + options.deleteCssClass).on('click', function(e1) {
117 // Add delete handler for each row.
118 row.find("a." + options.deleteCssClass).on('click', inlineDeleteHandler.bind(this));
119 };
120
121 const inlineDeleteHandler = function(e1) {
95 122 e1.preventDefault();
96 // Remove the parent form containing this button:
123 const deleteButton = $(e1.target);
124 const row = deleteButton.closest('.' + options.formCssClass);
125 const inlineGroup = row.closest('.inline-group');
126 // Remove the parent form containing this button,
127 // and also remove the relevant row with non-field errors:
128 const prevRow = row.prev();
129 if (prevRow.length && prevRow.hasClass('row-form-errors')) {
130 prevRow.remove();
131 }
97 132 row.remove();
98 133 nextIndex -= 1;
99 // If a post-delete callback was provided, call it with the deleted form:
134 // Pass the deleted form to the post-delete callback, if provided.
100 135 if (options.removed) {
101 136 options.removed(row);
102 137 }
103 $(document).trigger('formset:removed', [row, options.prefix]);
138 document.dispatchEvent(new CustomEvent("formset:removed", {
139 detail: {
140 formsetName: options.prefix
141 }
142 }));
104 143 // Update the TOTAL_FORMS form count.
105 var forms = $("." + options.formCssClass);
144 const forms = $("." + options.formCssClass);
106 145 $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
107 // Show add button again once we drop below max
146 // Show add button again once below maximum number.
108 147 if ((maxForms.val() === '') || (maxForms.val() - forms.length) > 0) {
109 148 addButton.parent().show();
110 149 }
111 // Also, update names and ids for all remaining form controls
112 // so they remain in sequence:
113 var i, formCount;
114 var updateElementCallback = function() {
150 // Hide the remove buttons if at min_num.
151 toggleDeleteButtonVisibility(inlineGroup);
152 // Also, update names and ids for all remaining form controls so
153 // they remain in sequence:
154 let i, formCount;
155 const updateElementCallback = function() {
115 156 updateElementIndex(this, options.prefix, i);
116 157 };
117 158 for (i = 0, formCount = forms.length; i < formCount; i++) {
118 159 updateElementIndex($(forms).get(i), options.prefix, i);
119 160 $(forms.get(i)).find("*").each(updateElementCallback);
120 161 }
121 });
122 // If a post-add callback was supplied, call it with the added form:
123 if (options.added) {
124 options.added(row);
162 };
163
164 const toggleDeleteButtonVisibility = function(inlineGroup) {
165 if ((minForms.val() !== '') && (minForms.val() - totalForms.val()) >= 0) {
166 inlineGroup.find('.inline-deletelink').hide();
167 } else {
168 inlineGroup.find('.inline-deletelink').show();
125 169 }
126 $(document).trigger('formset:added', [row, options.prefix]);
170 };
171
172 $this.each(function(i) {
173 $(this).not("." + options.emptyCssClass).addClass(options.formCssClass);
174 });
175
176 // Create the delete buttons for all unsaved inlines:
177 $this.filter('.' + options.formCssClass + ':not(.has_original):not(.' + options.emptyCssClass + ')').each(function() {
178 addInlineDeleteButton($(this));
127 179 });
180 toggleDeleteButtonVisibility($this);
181
182 // Create the add button, initially hidden.
183 addButton = options.addButton;
184 addInlineAddButton();
185
186 // Show the add button if allowed to add more items.
187 // Note that max_num = None translates to a blank string.
188 const showAddButton = maxForms.val() === '' || (maxForms.val() - totalForms.val()) > 0;
189 if ($this.length && showAddButton) {
190 addButton.parent().show();
191 } else {
192 addButton.parent().hide();
128 193 }
194
129 195 return this;
130 196 };
131 197
@@ -146,14 +212,9
146 212
147 213 // Tabular inlines ---------------------------------------------------------
148 214 $.fn.tabularFormset = function(selector, options) {
149 var $rows = $(this);
150 var alternatingRows = function(row) {
151 $(selector).not(".add-row").removeClass("row1 row2")
152 .filter(":even").addClass("row1").end()
153 .filter(":odd").addClass("row2");
154 };
215 const $rows = $(this);
155 216
156 var reinitDateTimeShortCuts = function() {
217 const reinitDateTimeShortCuts = function() {
157 218 // Reinitialize the calendar and clock widgets by force
158 219 if (typeof DateTimeShortcuts !== "undefined") {
159 220 $(".datetimeshortcuts").remove();
@@ -161,24 +222,22
161 222 }
162 223 };
163 224
164 var updateSelectFilter = function() {
225 const updateSelectFilter = function() {
165 226 // If any SelectFilter widgets are a part of the new form,
166 227 // instantiate a new SelectFilter instance for it.
167 228 if (typeof SelectFilter !== 'undefined') {
168 229 $('.selectfilter').each(function(index, value) {
169 var namearr = value.name.split('-');
170 SelectFilter.init(value.id, namearr[namearr.length - 1], false);
230 SelectFilter.init(value.id, this.dataset.fieldName, false);
171 231 });
172 232 $('.selectfilterstacked').each(function(index, value) {
173 var namearr = value.name.split('-');
174 SelectFilter.init(value.id, namearr[namearr.length - 1], true);
233 SelectFilter.init(value.id, this.dataset.fieldName, true);
175 234 });
176 235 }
177 236 };
178 237
179 var initPrepopulatedFields = function(row) {
238 const initPrepopulatedFields = function(row) {
180 239 row.find('.prepopulated_field').each(function() {
181 var field = $(this),
240 const field = $(this),
182 241 input = field.find('input, select, textarea'),
183 242 dependency_list = input.data('dependency_list') || [],
184 243 dependencies = [];
@@ -198,12 +257,10
198 257 deleteCssClass: "inline-deletelink",
199 258 deleteText: options.deleteText,
200 259 emptyCssClass: "empty-form",
201 removed: alternatingRows,
202 260 added: function(row) {
203 261 initPrepopulatedFields(row);
204 262 reinitDateTimeShortCuts();
205 263 updateSelectFilter();
206 alternatingRows(row);
207 264 },
208 265 addButton: options.addButton
209 266 });
@@ -213,15 +270,15
213 270
214 271 // Stacked inlines ---------------------------------------------------------
215 272 $.fn.stackedFormset = function(selector, options) {
216 var $rows = $(this);
217 var updateInlineLabel = function(row) {
273 const $rows = $(this);
274 const updateInlineLabel = function(row) {
218 275 $(selector).find(".inline_label").each(function(i) {
219 var count = i + 1;
276 const count = i + 1;
220 277 $(this).html($(this).html().replace(/(#\d+)/g, "#" + count));
221 278 });
222 279 };
223 280
224 var reinitDateTimeShortCuts = function() {
281 const reinitDateTimeShortCuts = function() {
225 282 // Reinitialize the calendar and clock widgets by force, yuck.
226 283 if (typeof DateTimeShortcuts !== "undefined") {
227 284 $(".datetimeshortcuts").remove();
@@ -229,28 +286,32
229 286 }
230 287 };
231 288
232 var updateSelectFilter = function() {
289 const updateSelectFilter = function() {
233 290 // If any SelectFilter widgets were added, instantiate a new instance.
234 291 if (typeof SelectFilter !== "undefined") {
235 292 $(".selectfilter").each(function(index, value) {
236 var namearr = value.name.split('-');
237 SelectFilter.init(value.id, namearr[namearr.length - 1], false);
293 SelectFilter.init(value.id, this.dataset.fieldName, false);
238 294 });
239 295 $(".selectfilterstacked").each(function(index, value) {
240 var namearr = value.name.split('-');
241 SelectFilter.init(value.id, namearr[namearr.length - 1], true);
296 SelectFilter.init(value.id, this.dataset.fieldName, true);
242 297 });
243 298 }
244 299 };
245 300
246 var initPrepopulatedFields = function(row) {
301 const initPrepopulatedFields = function(row) {
247 302 row.find('.prepopulated_field').each(function() {
248 var field = $(this),
303 const field = $(this),
249 304 input = field.find('input, select, textarea'),
250 305 dependency_list = input.data('dependency_list') || [],
251 306 dependencies = [];
252 307 $.each(dependency_list, function(i, field_name) {
253 dependencies.push('#' + row.find('.form-row .field-' + field_name).find('input, select, textarea').attr('id'));
308 // Dependency in a fieldset.
309 let field_element = row.find('.form-row .field-' + field_name);
310 // Dependency without a fieldset.
311 if (!field_element.length) {
312 field_element = row.find('.form-row.field-' + field_name);
313 }
314 dependencies.push('#' + field_element.find('input, select, textarea').attr('id'));
254 315 });
255 316 if (dependencies.length) {
256 317 input.prepopulate(dependencies, input.attr('maxlength'));
@@ -280,19 +341,19
280 341
281 342 $(document).ready(function() {
282 343 $(".js-inline-admin-formset").each(function() {
283 var data = $(this).data(),
284 inlineOptions = data.inlineFormset,
285 selector;
344 const data = $(this).data(),
345 inlineOptions = data.inlineFormset;
346 let selector;
286 347 switch(data.inlineType) {
287 348 case "stacked":
288 349 selector = inlineOptions.name + "-group .inline-related";
289 350 $(selector).stackedFormset(selector, inlineOptions.options);
290 351 break;
291 352 case "tabular":
292 selector = inlineOptions.name + "-group .tabular.inline-related tbody:first > tr";
353 selector = inlineOptions.name + "-group .tabular.inline-related tbody:first > tr.form-row";
293 354 $(selector).tabularFormset(selector, inlineOptions.options);
294 355 break;
295 356 }
296 357 });
297 358 });
298 })(django.jQuery);
359 }
@@ -1,8 +1,8
1 /*global django:true, jQuery:false*/
1 /*global jQuery:false*/
2 'use strict';
2 3 /* Puts the included jQuery into our own namespace using noConflict and passing
3 4 * it 'true'. This ensures that the included jQuery doesn't pollute the global
4 5 * namespace (i.e. this preserves pre-existing values for both window.$ and
5 6 * window.jQuery).
6 7 */
7 var django = django || {};
8 django.jQuery = jQuery.noConflict(true);
8 window.django = {jQuery: jQuery.noConflict(true)};
@@ -1,7 +1,7
1 1 /*global opener */
2 (function() {
3 2 'use strict';
4 var initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
3 {
4 const initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
5 5 switch(initData.action) {
6 6 case 'change':
7 7 opener.dismissChangeRelatedObjectPopup(window, initData.value, initData.obj, initData.new_value);
@@ -13,4 +13,4
13 13 opener.dismissAddRelatedObjectPopup(window, initData.value, initData.obj);
14 14 break;
15 15 }
16 })();
16 }
@@ -1,6 +1,7
1 1 /*global URLify*/
2 (function($) {
3 2 'use strict';
3 {
4 const $ = django.jQuery;
4 5 $.fn.prepopulate = function(dependencies, maxLength, allowUnicode) {
5 6 /*
6 7 Depends on urlify.js
@@ -11,15 +12,15
11 12 allowUnicode - Unicode support of the URLify'd string
12 13 */
13 14 return this.each(function() {
14 var prepopulatedField = $(this);
15 const prepopulatedField = $(this);
15 16
16 var populate = function() {
17 const populate = function() {
17 18 // Bail if the field's value has been changed by the user
18 19 if (prepopulatedField.data('_changed')) {
19 20 return;
20 21 }
21 22
22 var values = [];
23 const values = [];
23 24 $.each(dependencies, function(i, field) {
24 25 field = $(field);
25 26 if (field.val().length > 0) {
@@ -39,4 +40,4
39 40 }
40 41 });
41 42 };
42 })(django.jQuery);
43 }
@@ -1,10 +1,15
1 (function($) {
2 1 'use strict';
3 var fields = $('#django-admin-prepopulated-fields-constants').data('prepopulatedFields');
2 {
3 const $ = django.jQuery;
4 const fields = $('#django-admin-prepopulated-fields-constants').data('prepopulatedFields');
4 5 $.each(fields, function(index, field) {
5 $('.empty-form .form-row .field-' + field.name + ', .empty-form.form-row .field-' + field.name).addClass('prepopulated_field');
6 $(
7 '.empty-form .form-row .field-' + field.name +
8 ', .empty-form.form-row .field-' + field.name +
9 ', .empty-form .form-row.field-' + field.name
10 ).addClass('prepopulated_field');
6 11 $(field.id).data('dependency_list', field.dependency_list).prepopulate(
7 12 field.dependency_ids, field.maxLength, field.allowUnicode
8 13 );
9 14 });
10 })(django.jQuery);
15 }
@@ -1,8 +1,7
1 1 /*global XRegExp*/
2 (function() {
3 2 'use strict';
4
5 var LATIN_MAP = {
3 {
4 const LATIN_MAP = {
6 5 'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE',
7 6 'Ç': 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I',
8 7 'Î': 'I', 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O',
@@ -14,10 +13,10
14 13 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u',
15 14 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
16 15 };
17 var LATIN_SYMBOLS_MAP = {
16 const LATIN_SYMBOLS_MAP = {
18 17 '©': '(c)'
19 18 };
20 var GREEK_MAP = {
19 const GREEK_MAP = {
21 20 'α': 'a', 'β': 'b', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'h',
22 21 'θ': '8', 'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': '3',
23 22 'ο': 'o', 'π': 'p', 'ρ': 'r', 'σ': 's', 'τ': 't', 'υ': 'y', 'φ': 'f',
@@ -29,15 +28,15
29 28 'Φ': 'F', 'Χ': 'X', 'Ψ': 'PS', 'Ω': 'W', 'Ά': 'A', 'Έ': 'E', 'Ί': 'I',
30 29 'Ό': 'O', 'Ύ': 'Y', 'Ή': 'H', 'Ώ': 'W', 'Ϊ': 'I', 'Ϋ': 'Y'
31 30 };
32 var TURKISH_MAP = {
31 const TURKISH_MAP = {
33 32 'ş': 's', 'Ş': 'S', 'ı': 'i', 'İ': 'I', 'ç': 'c', 'Ç': 'C', 'ü': 'u',
34 33 'Ü': 'U', 'ö': 'o', 'Ö': 'O', 'ğ': 'g', 'Ğ': 'G'
35 34 };
36 var ROMANIAN_MAP = {
35 const ROMANIAN_MAP = {
37 36 'ă': 'a', 'î': 'i', 'ș': 's', 'ț': 't', 'â': 'a',
38 37 'Ă': 'A', 'Î': 'I', 'Ș': 'S', 'Ț': 'T', 'Â': 'A'
39 38 };
40 var RUSSIAN_MAP = {
39 const RUSSIAN_MAP = {
41 40 'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo',
42 41 'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm',
43 42 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u',
@@ -49,16 +48,16
49 48 'Ф': 'F', 'Х': 'H', 'Ц': 'C', 'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Sh', 'Ъ': '',
50 49 'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu', 'Я': 'Ya'
51 50 };
52 var UKRAINIAN_MAP = {
51 const UKRAINIAN_MAP = {
53 52 'Є': 'Ye', 'І': 'I', 'Ї': 'Yi', 'Ґ': 'G', 'є': 'ye', 'і': 'i',
54 53 'ї': 'yi', 'ґ': 'g'
55 54 };
56 var CZECH_MAP = {
55 const CZECH_MAP = {
57 56 'č': 'c', 'ď': 'd', 'ě': 'e', 'ň': 'n', 'ř': 'r', 'š': 's', 'ť': 't',
58 57 'ů': 'u', 'ž': 'z', 'Č': 'C', 'Ď': 'D', 'Ě': 'E', 'Ň': 'N', 'Ř': 'R',
59 58 'Š': 'S', 'Ť': 'T', 'Ů': 'U', 'Ž': 'Z'
60 59 };
61 var SLOVAK_MAP = {
60 const SLOVAK_MAP = {
62 61 'á': 'a', 'ä': 'a', 'č': 'c', 'ď': 'd', 'é': 'e', 'í': 'i', 'ľ': 'l',
63 62 'ĺ': 'l', 'ň': 'n', 'ó': 'o', 'ô': 'o', 'ŕ': 'r', 'š': 's', 'ť': 't',
64 63 'ú': 'u', 'ý': 'y', 'ž': 'z',
@@ -66,40 +65,40
66 65 'Ĺ': 'L', 'Ň': 'N', 'Ó': 'O', 'Ô': 'O', 'Ŕ': 'R', 'Š': 'S', 'Ť': 'T',
67 66 'Ú': 'U', 'Ý': 'Y', 'Ž': 'Z'
68 67 };
69 var POLISH_MAP = {
68 const POLISH_MAP = {
70 69 'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's',
71 70 'ź': 'z', 'ż': 'z',
72 71 'Ą': 'A', 'Ć': 'C', 'Ę': 'E', 'Ł': 'L', 'Ń': 'N', 'Ó': 'O', 'Ś': 'S',
73 72 'Ź': 'Z', 'Ż': 'Z'
74 73 };
75 var LATVIAN_MAP = {
74 const LATVIAN_MAP = {
76 75 'ā': 'a', 'č': 'c', 'ē': 'e', 'ģ': 'g', 'ī': 'i', 'ķ': 'k', 'ļ': 'l',
77 76 'ņ': 'n', 'š': 's', 'ū': 'u', 'ž': 'z',
78 77 'Ā': 'A', 'Č': 'C', 'Ē': 'E', 'Ģ': 'G', 'Ī': 'I', 'Ķ': 'K', 'Ļ': 'L',
79 78 'Ņ': 'N', 'Š': 'S', 'Ū': 'U', 'Ž': 'Z'
80 79 };
81 var ARABIC_MAP = {
80 const ARABIC_MAP = {
82 81 'أ': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'g', 'ح': 'h', 'خ': 'kh', 'د': 'd',
83 82 'ذ': 'th', 'ر': 'r', 'ز': 'z', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': 't',
84 83 'ظ': 'th', 'ع': 'aa', 'غ': 'gh', 'ف': 'f', 'ق': 'k', 'ك': 'k', 'ل': 'l', 'م': 'm',
85 84 'ن': 'n', 'ه': 'h', 'و': 'o', 'ي': 'y'
86 85 };
87 var LITHUANIAN_MAP = {
86 const LITHUANIAN_MAP = {
88 87 'ą': 'a', 'č': 'c', 'ę': 'e', 'ė': 'e', 'į': 'i', 'š': 's', 'ų': 'u',
89 88 'ū': 'u', 'ž': 'z',
90 89 'Ą': 'A', 'Č': 'C', 'Ę': 'E', 'Ė': 'E', 'Į': 'I', 'Š': 'S', 'Ų': 'U',
91 90 'Ū': 'U', 'Ž': 'Z'
92 91 };
93 var SERBIAN_MAP = {
92 const SERBIAN_MAP = {
94 93 'ђ': 'dj', 'ј': 'j', 'љ': 'lj', 'њ': 'nj', 'ћ': 'c', 'џ': 'dz',
95 94 'đ': 'dj', 'Ђ': 'Dj', 'Ј': 'j', 'Љ': 'Lj', 'Њ': 'Nj', 'Ћ': 'C',
96 95 'Џ': 'Dz', 'Đ': 'Dj'
97 96 };
98 var AZERBAIJANI_MAP = {
97 const AZERBAIJANI_MAP = {
99 98 'ç': 'c', 'ə': 'e', 'ğ': 'g', 'ı': 'i', 'ö': 'o', 'ş': 's', 'ü': 'u',
100 99 'Ç': 'C', 'Ə': 'E', 'Ğ': 'G', 'İ': 'I', 'Ö': 'O', 'Ş': 'S', 'Ü': 'U'
101 100 };
102 var GEORGIAN_MAP = {
101 const GEORGIAN_MAP = {
103 102 'ა': 'a', 'ბ': 'b', 'გ': 'g', 'დ': 'd', 'ე': 'e', 'ვ': 'v', 'ზ': 'z',
104 103 'თ': 't', 'ი': 'i', 'კ': 'k', 'ლ': 'l', 'მ': 'm', 'ნ': 'n', 'ო': 'o',
105 104 'პ': 'p', 'ჟ': 'j', 'რ': 'r', 'ს': 's', 'ტ': 't', 'უ': 'u', 'ფ': 'f',
@@ -107,7 +106,7
107 106 'წ': 'w', 'ჭ': 'ch', 'ხ': 'x', 'ჯ': 'j', 'ჰ': 'h'
108 107 };
109 108
110 var ALL_DOWNCODE_MAPS = [
109 const ALL_DOWNCODE_MAPS = [
111 110 LATIN_MAP,
112 111 LATIN_SYMBOLS_MAP,
113 112 GREEK_MAP,
@@ -126,27 +125,16
126 125 GEORGIAN_MAP
127 126 ];
128 127
129 var Downcoder = {
128 const Downcoder = {
130 129 'Initialize': function() {
131 130 if (Downcoder.map) { // already made
132 131 return;
133 132 }
134 133 Downcoder.map = {};
135 Downcoder.chars = [];
136 for (var i = 0; i < ALL_DOWNCODE_MAPS.length; i++) {
137 var lookup = ALL_DOWNCODE_MAPS[i];
138 for (var c in lookup) {
139 if (lookup.hasOwnProperty(c)) {
140 Downcoder.map[c] = lookup[c];
141 }
142 }
143 }
144 for (var k in Downcoder.map) {
145 if (Downcoder.map.hasOwnProperty(k)) {
146 Downcoder.chars.push(k);
134 for (const lookup of ALL_DOWNCODE_MAPS) {
135 Object.assign(Downcoder.map, lookup);
147 136 }
148 }
149 Downcoder.regex = new RegExp(Downcoder.chars.join('|'), 'g');
137 Downcoder.regex = new RegExp(Object.keys(Downcoder.map).join('|'), 'g');
150 138 }
151 139 };
152 140
@@ -160,23 +148,10
160 148
161 149 function URLify(s, num_chars, allowUnicode) {
162 150 // changes, e.g., "Petty theft" to "petty-theft"
163 // remove all these words from the string before urlifying
164 151 if (!allowUnicode) {
165 152 s = downcode(s);
166 153 }
167 var hasUnicodeChars = /[^\u0000-\u007f]/.test(s);
168 // Remove English words only if the string contains ASCII (English)
169 // characters.
170 if (!hasUnicodeChars) {
171 var removeList = [
172 "a", "an", "as", "at", "before", "but", "by", "for", "from",
173 "is", "in", "into", "like", "of", "off", "on", "onto", "per",
174 "since", "than", "the", "this", "that", "to", "up", "via",
175 "with"
176 ];
177 var r = new RegExp('\\b(' + removeList.join('|') + ')\\b', 'gi');
178 s = s.replace(r, '');
179 }
154 s = s.toLowerCase(); // convert to lowercase
180 155 // if downcode doesn't hit, the char will be stripped here
181 156 if (allowUnicode) {
182 157 // Keep Unicode letters including both lowercase and uppercase
@@ -189,7 +164,7
189 164 s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
190 165 s = s.substring(0, num_chars); // trim to first num_chars chars
191 166 s = s.replace(/-+$/g, ''); // trim any trailing hyphens
192 return s.toLowerCase(); // convert to lowercase
167 return s;
193 168 }
194 169 window.URLify = URLify;
195 })();
170 }
@@ -1,10 +1,4
1 Copyright jQuery Foundation and other contributors, https://jquery.org/
2
3 This software consists of voluntary contributions made by many
4 individuals. For exact contribution history, see the revision history
5 available at https://github.com/jquery/jquery
6
7 ====
1 Copyright OpenJS Foundation and other contributors, https://openjsf.org/
8 2
9 3 Permission is hereby granted, free of charge, to any person obtaining
10 4 a copy of this software and associated documentation files (the
This diff has been collapsed as it changes many lines, (1369 lines changed) Show them Hide them
@@ -1,15 +1,15
1 1 /*!
2 * jQuery JavaScript Library v3.3.1
2 * jQuery JavaScript Library v3.6.0
3 3 * https://jquery.com/
4 4 *
5 5 * Includes Sizzle.js
6 6 * https://sizzlejs.com/
7 7 *
8 * Copyright JS Foundation and other contributors
8 * Copyright OpenJS Foundation and other contributors
9 9 * Released under the MIT license
10 10 * https://jquery.org/license
11 11 *
12 * Date: 2018-01-20T17:24Z
12 * Date: 2021-03-02T17:08Z
13 13 */
14 14 ( function( global, factory ) {
15 15
@@ -47,13 +47,16
47 47
48 48 var arr = [];
49 49
50 var document = window.document;
51
52 50 var getProto = Object.getPrototypeOf;
53 51
54 52 var slice = arr.slice;
55 53
56 var concat = arr.concat;
54 var flat = arr.flat ? function( array ) {
55 return arr.flat.call( array );
56 } : function( array ) {
57 return arr.concat.apply( [], array );
58 };
59
57 60
58 61 var push = arr.push;
59 62
@@ -77,7 +80,11 var isFunction = function isFunction( obj ) {
77 80 // In some browsers, typeof returns "function" for HTML <object> elements
78 81 // (i.e., `typeof document.createElement( "object" ) === "function"`).
79 82 // We don't want to classify *any* DOM node as a function.
80 return typeof obj === "function" && typeof obj.nodeType !== "number";
83 // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5
84 // Plus for old WebKit, typeof returns "function" for HTML collections
85 // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756)
86 return typeof obj === "function" && typeof obj.nodeType !== "number" &&
87 typeof obj.item !== "function";
81 88 };
82 89
83 90
@@ -86,25 +93,40 var isWindow = function isWindow( obj ) {
86 93 };
87 94
88 95
96 var document = window.document;
97
89 98
90 99
91 100 var preservedScriptAttributes = {
92 101 type: true,
93 102 src: true,
103 nonce: true,
94 104 noModule: true
95 105 };
96 106
97 function DOMEval( code, doc, node ) {
107 function DOMEval( code, node, doc ) {
98 108 doc = doc || document;
99 109
100 var i,
110 var i, val,
101 111 script = doc.createElement( "script" );
102 112
103 113 script.text = code;
104 114 if ( node ) {
105 115 for ( i in preservedScriptAttributes ) {
106 if ( node[ i ] ) {
107 script[ i ] = node[ i ];
116
117 // Support: Firefox 64+, Edge 18+
118 // Some browsers don't support the "nonce" property on scripts.
119 // On the other hand, just using `getAttribute` is not enough as
120 // the `nonce` attribute is reset to an empty string whenever it
121 // becomes browsing-context connected.
122 // See https://github.com/whatwg/html/issues/2369
123 // See https://html.spec.whatwg.org/#nonce-attributes
124 // The `node.getAttribute` check was added for the sake of
125 // `jQuery.globalEval` so that it can fake a nonce-containing node
126 // via an object.
127 val = node[ i ] || node.getAttribute && node.getAttribute( i );
128 if ( val ) {
129 script.setAttribute( i, val );
108 130 }
109 131 }
110 132 }
@@ -129,7 +151,7 function toType( obj ) {
129 151
130 152
131 153 var
132 version = "3.3.1",
154 version = "3.6.0",
133 155
134 156 // Define a local copy of jQuery
135 157 jQuery = function( selector, context ) {
@@ -137,11 +159,7 var
137 159 // The jQuery object is actually just the init constructor 'enhanced'
138 160 // Need init if jQuery is called (just allow error to be thrown if not included)
139 161 return new jQuery.fn.init( selector, context );
140 },
141
142 // Support: Android <=4.0 only
143 // Make sure we trim BOM and NBSP
144 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
162 };
145 163
146 164 jQuery.fn = jQuery.prototype = {
147 165
@@ -207,6 +225,18 jQuery.fn = jQuery.prototype = {
207 225 return this.eq( -1 );
208 226 },
209 227
228 even: function() {
229 return this.pushStack( jQuery.grep( this, function( _elem, i ) {
230 return ( i + 1 ) % 2;
231 } ) );
232 },
233
234 odd: function() {
235 return this.pushStack( jQuery.grep( this, function( _elem, i ) {
236 return i % 2;
237 } ) );
238 },
239
210 240 eq: function( i ) {
211 241 var len = this.length,
212 242 j = +i + ( i < 0 ? len : 0 );
@@ -258,25 +288,28 jQuery.extend = jQuery.fn.extend = function() {
258 288
259 289 // Extend the base object
260 290 for ( name in options ) {
261 src = target[ name ];
262 291 copy = options[ name ];
263 292
293 // Prevent Object.prototype pollution
264 294 // Prevent never-ending loop
265 if ( target === copy ) {
295 if ( name === "__proto__" || target === copy ) {
266 296 continue;
267 297 }
268 298
269 299 // Recurse if we're merging plain objects or arrays
270 300 if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
271 301 ( copyIsArray = Array.isArray( copy ) ) ) ) {
302 src = target[ name ];
272 303
273 if ( copyIsArray ) {
274 copyIsArray = false;
275 clone = src && Array.isArray( src ) ? src : [];
276
304 // Ensure proper type for the source value
305 if ( copyIsArray && !Array.isArray( src ) ) {
306 clone = [];
307 } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
308 clone = {};
277 309 } else {
278 clone = src && jQuery.isPlainObject( src ) ? src : {};
310 clone = src;
279 311 }
312 copyIsArray = false;
280 313
281 314 // Never move original objects, clone them
282 315 target[ name ] = jQuery.extend( deep, clone, copy );
@@ -329,9 +362,6 jQuery.extend( {
329 362 },
330 363
331 364 isEmptyObject: function( obj ) {
332
333 /* eslint-disable no-unused-vars */
334 // See https://github.com/eslint/eslint/issues/6125
335 365 var name;
336 366
337 367 for ( name in obj ) {
@@ -340,9 +370,10 jQuery.extend( {
340 370 return true;
341 371 },
342 372
343 // Evaluates a script in a global context
344 globalEval: function( code ) {
345 DOMEval( code );
373 // Evaluates a script in a provided context; falls back to the global one
374 // if not specified.
375 globalEval: function( code, options, doc ) {
376 DOMEval( code, { nonce: options && options.nonce }, doc );
346 377 },
347 378
348 379 each: function( obj, callback ) {
@@ -366,13 +397,6 jQuery.extend( {
366 397 return obj;
367 398 },
368 399
369 // Support: Android <=4.0 only
370 trim: function( text ) {
371 return text == null ?
372 "" :
373 ( text + "" ).replace( rtrim, "" );
374 },
375
376 400 // results is for internal usage only
377 401 makeArray: function( arr, results ) {
378 402 var ret = results || [];
@@ -459,7 +483,7 jQuery.extend( {
459 483 }
460 484
461 485 // Flatten any nested arrays
462 return concat.apply( [], ret );
486 return flat( ret );
463 487 },
464 488
465 489 // A global GUID counter for objects
@@ -476,7 +500,7 if ( typeof Symbol === "function" ) {
476 500
477 501 // Populate the class2type map
478 502 jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
479 function( i, name ) {
503 function( _i, name ) {
480 504 class2type[ "[object " + name + "]" ] = name.toLowerCase();
481 505 } );
482 506
@@ -498,17 +522,16 function isArrayLike( obj ) {
498 522 }
499 523 var Sizzle =
500 524 /*!
501 * Sizzle CSS Selector Engine v2.3.3
525 * Sizzle CSS Selector Engine v2.3.6
502 526 * https://sizzlejs.com/
503 527 *
504 * Copyright jQuery Foundation and other contributors
528 * Copyright JS Foundation and other contributors
505 529 * Released under the MIT license
506 * http://jquery.org/license
530 * https://js.foundation/
507 531 *
508 * Date: 2016-08-08
532 * Date: 2021-02-16
509 533 */
510 534 ( function( window ) {
511
512 535 var i,
513 536 support,
514 537 Expr,
@@ -539,6 +562,7 var i,
539 562 classCache = createCache(),
540 563 tokenCache = createCache(),
541 564 compilerCache = createCache(),
565 nonnativeSelectorCache = createCache(),
542 566 sortOrder = function( a, b ) {
543 567 if ( a === b ) {
544 568 hasDuplicate = true;
@@ -550,9 +574,10 var i,
550 574 hasOwn = ( {} ).hasOwnProperty,
551 575 arr = [],
552 576 pop = arr.pop,
553 push_native = arr.push,
577 pushNative = arr.push,
554 578 push = arr.push,
555 579 slice = arr.slice,
580
556 581 // Use a stripped-down indexOf as it's faster than native
557 582 // https://jsperf.com/thor-indexof-vs-for/5
558 583 indexOf = function( list, elem ) {
@@ -566,42 +591,51 var i,
566 591 return -1;
567 592 },
568 593
569 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
594 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" +
595 "ismap|loop|multiple|open|readonly|required|scoped",
570 596
571 597 // Regular expressions
572 598
573 599 // http://www.w3.org/TR/css3-selectors/#whitespace
574 600 whitespace = "[\\x20\\t\\r\\n\\f]",
575 601
576 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
577 identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
602 // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
603 identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
604 "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",
578 605
579 606 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
580 607 attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
608
581 609 // Operator (capture 2)
582 610 "*([*^$|!~]?=)" + whitespace +
583 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
584 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
585 "*\\]",
611
612 // "Attribute values must be CSS identifiers [capture 5]
613 // or strings [capture 3 or capture 4]"
614 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" +
615 whitespace + "*\\]",
586 616
587 617 pseudos = ":(" + identifier + ")(?:\\((" +
618
588 619 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
589 620 // 1. quoted (capture 3; capture 4 or capture 5)
590 621 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
622
591 623 // 2. simple (capture 6)
592 624 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
625
593 626 // 3. anything else (capture 2)
594 627 ".*" +
595 628 ")\\)|)",
596 629
597 630 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
598 631 rwhitespace = new RegExp( whitespace + "+", "g" ),
599 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
632 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" +
633 whitespace + "+$", "g" ),
600 634
601 635 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
602 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
603
604 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
636 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace +
637 "*" ),
638 rdescend = new RegExp( whitespace + "|>" ),
605 639
606 640 rpseudo = new RegExp( pseudos ),
607 641 ridentifier = new RegExp( "^" + identifier + "$" ),
@@ -612,16 +646,19 var i,
612 646 "TAG": new RegExp( "^(" + identifier + "|[*])" ),
613 647 "ATTR": new RegExp( "^" + attributes ),
614 648 "PSEUDO": new RegExp( "^" + pseudos ),
615 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
616 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
617 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
649 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" +
650 whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" +
651 whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
618 652 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
653
619 654 // For use in libraries implementing .is()
620 655 // We use this for POS matching in `select`
621 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
622 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
656 "needsContext": new RegExp( "^" + whitespace +
657 "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
658 "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
623 659 },
624 660
661 rhtml = /HTML$/i,
625 662 rinputs = /^(?:input|select|textarea|button)$/i,
626 663 rheader = /^h\d$/i,
627 664
@@ -634,18 +671,21 var i,
634 671
635 672 // CSS escapes
636 673 // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
637 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
638 funescape = function( _, escaped, escapedWhitespace ) {
639 var high = "0x" + escaped - 0x10000;
640 // NaN means non-codepoint
641 // Support: Firefox<24
642 // Workaround erroneous numeric interpretation of +"0x"
643 return high !== high || escapedWhitespace ?
644 escaped :
674 runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ),
675 funescape = function( escape, nonHex ) {
676 var high = "0x" + escape.slice( 1 ) - 0x10000;
677
678 return nonHex ?
679
680 // Strip the backslash prefix from a non-hex escape sequence
681 nonHex :
682
683 // Replace a hexadecimal escape sequence with the encoded Unicode code point
684 // Support: IE <=11+
685 // For values outside the Basic Multilingual Plane (BMP), manually construct a
686 // surrogate pair
645 687 high < 0 ?
646 // BMP codepoint
647 688 String.fromCharCode( high + 0x10000 ) :
648 // Supplemental Plane codepoint (surrogate pair)
649 689 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
650 690 },
651 691
@@ -661,7 +701,8 var i,
661 701 }
662 702
663 703 // Control characters and (dependent upon position) numbers get escaped as code points
664 return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
704 return ch.slice( 0, -1 ) + "\\" +
705 ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
665 706 }
666 707
667 708 // Other potentially-special ASCII characters get backslash-escaped
@@ -676,9 +717,9 var i,
676 717 setDocument();
677 718 },
678 719
679 disabledAncestor = addCombinator(
720 inDisabledFieldset = addCombinator(
680 721 function( elem ) {
681 return elem.disabled === true && ("form" in elem || "label" in elem);
722 return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset";
682 723 },
683 724 { dir: "parentNode", next: "legend" }
684 725 );
@@ -689,15 +730,17 try {
689 730 ( arr = slice.call( preferredDoc.childNodes ) ),
690 731 preferredDoc.childNodes
691 732 );
733
692 734 // Support: Android<4.0
693 735 // Detect silently failing push.apply
736 // eslint-disable-next-line no-unused-expressions
694 737 arr[ preferredDoc.childNodes.length ].nodeType;
695 738 } catch ( e ) {
696 739 push = { apply: arr.length ?
697 740
698 741 // Leverage slice if possible
699 742 function( target, els ) {
700 push_native.apply( target, slice.call(els) );
743 pushNative.apply( target, slice.call( els ) );
701 744 } :
702 745
703 746 // Support: IE<9
@@ -705,6 +748,7 try {
705 748 function( target, els ) {
706 749 var j = target.length,
707 750 i = 0;
751
708 752 // Can't trust NodeList.length
709 753 while ( ( target[ j++ ] = els[ i++ ] ) ) {}
710 754 target.length = j - 1;
@@ -730,10 +774,7 function Sizzle( selector, context, results, seed ) {
730 774
731 775 // Try to shortcut find operations (as opposed to filters) in HTML documents
732 776 if ( !seed ) {
733
734 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
735 777 setDocument( context );
736 }
737 778 context = context || document;
738 779
739 780 if ( documentIsHTML ) {
@@ -791,18 +832,33 function Sizzle( selector, context, results, seed ) {
791 832
792 833 // Take advantage of querySelectorAll
793 834 if ( support.qsa &&
794 !compilerCache[ selector + " " ] &&
795 (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
835 !nonnativeSelectorCache[ selector + " " ] &&
836 ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) &&
837
838 // Support: IE 8 only
839 // Exclude object elements
840 ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) {
796 841
797 if ( nodeType !== 1 ) {
798 newContext = context;
799 842 newSelector = selector;
843 newContext = context;
800 844
801 // qSA looks outside Element context, which is not what we want
802 // Thanks to Andrew Dupont for this workaround technique
803 // Support: IE <=8
804 // Exclude object elements
805 } else if ( context.nodeName.toLowerCase() !== "object" ) {
845 // qSA considers elements outside a scoping root when evaluating child or
846 // descendant combinators, which is not what we want.
847 // In such cases, we work around the behavior by prefixing every selector in the
848 // list with an ID selector referencing the scope context.
849 // The technique has to be used as well when a leading combinator is used
850 // as such selectors are not recognized by querySelectorAll.
851 // Thanks to Andrew Dupont for this technique.
852 if ( nodeType === 1 &&
853 ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) {
854
855 // Expand context for sibling selectors
856 newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
857 context;
858
859 // We can use :scope instead of the ID hack if the browser
860 // supports it & if we're not changing the context.
861 if ( newContext !== context || !support.scope ) {
806 862
807 863 // Capture the context ID, setting it first if necessary
808 864 if ( ( nid = context.getAttribute( "id" ) ) ) {
@@ -810,27 +866,25 function Sizzle( selector, context, results, seed ) {
810 866 } else {
811 867 context.setAttribute( "id", ( nid = expando ) );
812 868 }
869 }
813 870
814 871 // Prefix every selector in the list
815 872 groups = tokenize( selector );
816 873 i = groups.length;
817 874 while ( i-- ) {
818 groups[i] = "#" + nid + " " + toSelector( groups[i] );
875 groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
876 toSelector( groups[ i ] );
819 877 }
820 878 newSelector = groups.join( "," );
821
822 // Expand context for sibling selectors
823 newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
824 context;
825 879 }
826 880
827 if ( newSelector ) {
828 881 try {
829 882 push.apply( results,
830 883 newContext.querySelectorAll( newSelector )
831 884 );
832 885 return results;
833 886 } catch ( qsaError ) {
887 nonnativeSelectorCache( selector, true );
834 888 } finally {
835 889 if ( nid === expando ) {
836 890 context.removeAttribute( "id" );
@@ -839,7 +893,6 function Sizzle( selector, context, results, seed ) {
839 893 }
840 894 }
841 895 }
842 }
843 896
844 897 // All others
845 898 return select( selector.replace( rtrim, "$1" ), context, results, seed );
@@ -855,8 +908,10 function createCache() {
855 908 var keys = [];
856 909
857 910 function cache( key, value ) {
911
858 912 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
859 913 if ( keys.push( key + " " ) > Expr.cacheLength ) {
914
860 915 // Only keep the most recent entries
861 916 delete cache[ keys.shift() ];
862 917 }
@@ -886,10 +941,12 function assert( fn ) {
886 941 } catch ( e ) {
887 942 return false;
888 943 } finally {
944
889 945 // Remove from its parent by default
890 946 if ( el.parentNode ) {
891 947 el.parentNode.removeChild( el );
892 948 }
949
893 950 // release memory in IE
894 951 el = null;
895 952 }
@@ -998,7 +1055,7 function createDisabledPseudo( disabled ) {
998 1055 // Where there is no isDisabled, check manually
999 1056 /* jshint -W018 */
1000 1057 elem.isDisabled !== !disabled &&
1001 disabledAncestor( elem ) === disabled;
1058 inDisabledFieldset( elem ) === disabled;
1002 1059 }
1003 1060
1004 1061 return elem.disabled === disabled;
@@ -1055,10 +1112,13 support = Sizzle.support = {};
1055 1112 * @returns {Boolean} True iff elem is a non-HTML XML node
1056 1113 */
1057 1114 isXML = Sizzle.isXML = function( elem ) {
1058 // documentElement is verified for cases where it doesn't yet exist
1059 // (such as loading iframes in IE - #4833)
1060 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1061 return documentElement ? documentElement.nodeName !== "HTML" : false;
1115 var namespace = elem && elem.namespaceURI,
1116 docElem = elem && ( elem.ownerDocument || elem ).documentElement;
1117
1118 // Support: IE <=8
1119 // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
1120 // https://bugs.jquery.com/ticket/4833
1121 return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
1062 1122 };
1063 1123
1064 1124 /**
@@ -1071,7 +1131,11 setDocument = Sizzle.setDocument = function( node ) {
1071 1131 doc = node ? node.ownerDocument || node : preferredDoc;
1072 1132
1073 1133 // Return early if doc is invalid or already selected
1074 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1134 // Support: IE 11+, Edge 17 - 18+
1135 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1136 // two documents; shallow comparisons work.
1137 // eslint-disable-next-line eqeqeq
1138 if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {
1075 1139 return document;
1076 1140 }
1077 1141
@@ -1080,9 +1144,13 setDocument = Sizzle.setDocument = function( node ) {
1080 1144 docElem = document.documentElement;
1081 1145 documentIsHTML = !isXML( document );
1082 1146
1083 // Support: IE 9-11, Edge
1147 // Support: IE 9 - 11+, Edge 12 - 18+
1084 1148 // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
1085 if ( preferredDoc !== document &&
1149 // Support: IE 11+, Edge 17 - 18+
1150 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1151 // two documents; shallow comparisons work.
1152 // eslint-disable-next-line eqeqeq
1153 if ( preferredDoc != document &&
1086 1154 ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {
1087 1155
1088 1156 // Support: IE 11, Edge
@@ -1095,6 +1163,17 setDocument = Sizzle.setDocument = function( node ) {
1095 1163 }
1096 1164 }
1097 1165
1166 // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only,
1167 // Safari 4 - 5 only, Opera <=11.6 - 12.x only
1168 // IE/Edge & older browsers don't support the :scope pseudo-class.
1169 // Support: Safari 6.0 only
1170 // Safari 6.0 supports :scope but it's an alias of :root there.
1171 support.scope = assert( function( el ) {
1172 docElem.appendChild( el ).appendChild( document.createElement( "div" ) );
1173 return typeof el.querySelectorAll !== "undefined" &&
1174 !el.querySelectorAll( ":scope fieldset div" ).length;
1175 } );
1176
1098 1177 /* Attributes
1099 1178 ---------------------------------------------------------------------- */
1100 1179
@@ -1198,6 +1277,7 setDocument = Sizzle.setDocument = function( node ) {
1198 1277 var elem,
1199 1278 tmp = [],
1200 1279 i = 0,
1280
1201 1281 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
1202 1282 results = context.getElementsByTagName( tag );
1203 1283
@@ -1237,9 +1317,13 setDocument = Sizzle.setDocument = function( node ) {
1237 1317 rbuggyQSA = [];
1238 1318
1239 1319 if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) {
1320
1240 1321 // Build QSA regex
1241 1322 // Regex strategy adopted from Diego Perini
1242 1323 assert( function( el ) {
1324
1325 var input;
1326
1243 1327 // Select is set to empty string on purpose
1244 1328 // This is to test IE's treatment of not explicitly
1245 1329 // setting a boolean content attribute,
@@ -1268,6 +1352,19 setDocument = Sizzle.setDocument = function( node ) {
1268 1352 rbuggyQSA.push( "~=" );
1269 1353 }
1270 1354
1355 // Support: IE 11+, Edge 15 - 18+
1356 // IE 11/Edge don't find elements on a `[name='']` query in some cases.
1357 // Adding a temporary attribute to the document before the selection works
1358 // around the issue.
1359 // Interestingly, IE 10 & older don't seem to have the issue.
1360 input = document.createElement( "input" );
1361 input.setAttribute( "name", "" );
1362 el.appendChild( input );
1363 if ( !el.querySelectorAll( "[name='']" ).length ) {
1364 rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" +
1365 whitespace + "*(?:''|\"\")" );
1366 }
1367
1271 1368 // Webkit/Opera - :checked should return selected option elements
1272 1369 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1273 1370 // IE8 throws error here and will not see later tests
@@ -1281,6 +1378,11 setDocument = Sizzle.setDocument = function( node ) {
1281 1378 if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
1282 1379 rbuggyQSA.push( ".#.+[+~]" );
1283 1380 }
1381
1382 // Support: Firefox <=3.6 - 5 only
1383 // Old Firefox doesn't throw on a badly-escaped identifier.
1384 el.querySelectorAll( "\\\f" );
1385 rbuggyQSA.push( "[\\r\\n\\f]" );
1284 1386 } );
1285 1387
1286 1388 assert( function( el ) {
@@ -1312,6 +1414,7 setDocument = Sizzle.setDocument = function( node ) {
1312 1414 rbuggyQSA.push( ":enabled", ":disabled" );
1313 1415 }
1314 1416
1417 // Support: Opera 10 - 11 only
1315 1418 // Opera 10-11 does not throw on post-comma invalid pseudos
1316 1419 el.querySelectorAll( "*,:x" );
1317 1420 rbuggyQSA.push( ",.*:" );
@@ -1325,6 +1428,7 setDocument = Sizzle.setDocument = function( node ) {
1325 1428 docElem.msMatchesSelector ) ) ) ) {
1326 1429
1327 1430 assert( function( el ) {
1431
1328 1432 // Check to see if it's possible to do matchesSelector
1329 1433 // on a disconnected node (IE 9)
1330 1434 support.disconnectedMatch = matches.call( el, "*" );
@@ -1387,7 +1491,11 setDocument = Sizzle.setDocument = function( node ) {
1387 1491 }
1388 1492
1389 1493 // Calculate position if both inputs belong to the same document
1390 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1494 // Support: IE 11+, Edge 17 - 18+
1495 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1496 // two documents; shallow comparisons work.
1497 // eslint-disable-next-line eqeqeq
1498 compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ?
1391 1499 a.compareDocumentPosition( b ) :
1392 1500
1393 1501 // Otherwise we know they are disconnected
@@ -1398,10 +1506,21 setDocument = Sizzle.setDocument = function( node ) {
1398 1506 ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) {
1399 1507
1400 1508 // Choose the first element that is related to our preferred document
1401 if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1509 // Support: IE 11+, Edge 17 - 18+
1510 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1511 // two documents; shallow comparisons work.
1512 // eslint-disable-next-line eqeqeq
1513 if ( a == document || a.ownerDocument == preferredDoc &&
1514 contains( preferredDoc, a ) ) {
1402 1515 return -1;
1403 1516 }
1404 if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1517
1518 // Support: IE 11+, Edge 17 - 18+
1519 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1520 // two documents; shallow comparisons work.
1521 // eslint-disable-next-line eqeqeq
1522 if ( b == document || b.ownerDocument == preferredDoc &&
1523 contains( preferredDoc, b ) ) {
1405 1524 return 1;
1406 1525 }
1407 1526
@@ -1414,6 +1533,7 setDocument = Sizzle.setDocument = function( node ) {
1414 1533 return compare & 4 ? -1 : 1;
1415 1534 } :
1416 1535 function( a, b ) {
1536
1417 1537 // Exit early if the nodes are identical
1418 1538 if ( a === b ) {
1419 1539 hasDuplicate = true;
@@ -1429,8 +1549,14 setDocument = Sizzle.setDocument = function( node ) {
1429 1549
1430 1550 // Parentless nodes are either documents or disconnected
1431 1551 if ( !aup || !bup ) {
1432 return a === document ? -1 :
1433 b === document ? 1 :
1552
1553 // Support: IE 11+, Edge 17 - 18+
1554 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1555 // two documents; shallow comparisons work.
1556 /* eslint-disable eqeqeq */
1557 return a == document ? -1 :
1558 b == document ? 1 :
1559 /* eslint-enable eqeqeq */
1434 1560 aup ? -1 :
1435 1561 bup ? 1 :
1436 1562 sortInput ?
@@ -1458,12 +1584,18 setDocument = Sizzle.setDocument = function( node ) {
1458 1584 }
1459 1585
1460 1586 return i ?
1587
1461 1588 // Do a sibling check if the nodes have a common ancestor
1462 1589 siblingCheck( ap[ i ], bp[ i ] ) :
1463 1590
1464 1591 // Otherwise nodes in our document sort first
1465 ap[i] === preferredDoc ? -1 :
1466 bp[i] === preferredDoc ? 1 :
1592 // Support: IE 11+, Edge 17 - 18+
1593 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1594 // two documents; shallow comparisons work.
1595 /* eslint-disable eqeqeq */
1596 ap[ i ] == preferredDoc ? -1 :
1597 bp[ i ] == preferredDoc ? 1 :
1598 /* eslint-enable eqeqeq */
1467 1599 0;
1468 1600 };
1469 1601
@@ -1475,16 +1607,10 Sizzle.matches = function( expr, elements ) {
1475 1607 };
1476 1608
1477 1609 Sizzle.matchesSelector = function( elem, expr ) {
1478 // Set document vars if needed
1479 if ( ( elem.ownerDocument || elem ) !== document ) {
1480 1610 setDocument( elem );
1481 }
1482
1483 // Make sure that attribute selectors are quoted
1484 expr = expr.replace( rattributeQuotes, "='$1']" );
1485 1611
1486 1612 if ( support.matchesSelector && documentIsHTML &&
1487 !compilerCache[ expr + " " ] &&
1613 !nonnativeSelectorCache[ expr + " " ] &&
1488 1614 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1489 1615 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1490 1616
@@ -1493,32 +1619,46 Sizzle.matchesSelector = function( elem, expr ) {
1493 1619
1494 1620 // IE 9's matchesSelector returns false on disconnected nodes
1495 1621 if ( ret || support.disconnectedMatch ||
1622
1496 1623 // As well, disconnected nodes are said to be in a document
1497 1624 // fragment in IE 9
1498 1625 elem.document && elem.document.nodeType !== 11 ) {
1499 1626 return ret;
1500 1627 }
1501 } catch (e) {}
1628 } catch ( e ) {
1629 nonnativeSelectorCache( expr, true );
1630 }
1502 1631 }
1503 1632
1504 1633 return Sizzle( expr, document, null, [ elem ] ).length > 0;
1505 1634 };
1506 1635
1507 1636 Sizzle.contains = function( context, elem ) {
1637
1508 1638 // Set document vars if needed
1509 if ( ( context.ownerDocument || context ) !== document ) {
1639 // Support: IE 11+, Edge 17 - 18+
1640 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1641 // two documents; shallow comparisons work.
1642 // eslint-disable-next-line eqeqeq
1643 if ( ( context.ownerDocument || context ) != document ) {
1510 1644 setDocument( context );
1511 1645 }
1512 1646 return contains( context, elem );
1513 1647 };
1514 1648
1515 1649 Sizzle.attr = function( elem, name ) {
1650
1516 1651 // Set document vars if needed
1517 if ( ( elem.ownerDocument || elem ) !== document ) {
1652 // Support: IE 11+, Edge 17 - 18+
1653 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1654 // two documents; shallow comparisons work.
1655 // eslint-disable-next-line eqeqeq
1656 if ( ( elem.ownerDocument || elem ) != document ) {
1518 1657 setDocument( elem );
1519 1658 }
1520 1659
1521 1660 var fn = Expr.attrHandle[ name.toLowerCase() ],
1661
1522 1662 // Don't get fooled by Object.prototype properties (jQuery #13807)
1523 1663 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1524 1664 fn( elem, name, !documentIsHTML ) :
@@ -1585,17 +1725,21 getText = Sizzle.getText = function( elem ) {
1585 1725 nodeType = elem.nodeType;
1586 1726
1587 1727 if ( !nodeType ) {
1728
1588 1729 // If no nodeType, this is expected to be an array
1589 1730 while ( ( node = elem[ i++ ] ) ) {
1731
1590 1732 // Do not traverse comment nodes
1591 1733 ret += getText( node );
1592 1734 }
1593 1735 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1736
1594 1737 // Use textContent for elements
1595 1738 // innerText usage removed for consistency of new lines (jQuery #11153)
1596 1739 if ( typeof elem.textContent === "string" ) {
1597 1740 return elem.textContent;
1598 1741 } else {
1742
1599 1743 // Traverse its children
1600 1744 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1601 1745 ret += getText( elem );
@@ -1604,6 +1748,7 getText = Sizzle.getText = function( elem ) {
1604 1748 } else if ( nodeType === 3 || nodeType === 4 ) {
1605 1749 return elem.nodeValue;
1606 1750 }
1751
1607 1752 // Do not include comment or processing instruction nodes
1608 1753
1609 1754 return ret;
@@ -1634,7 +1779,8 Expr = Sizzle.selectors = {
1634 1779 match[ 1 ] = match[ 1 ].replace( runescape, funescape );
1635 1780
1636 1781 // Move the given value to match[3] whether quoted or unquoted
1637 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
1782 match[ 3 ] = ( match[ 3 ] || match[ 4 ] ||
1783 match[ 5 ] || "" ).replace( runescape, funescape );
1638 1784
1639 1785 if ( match[ 2 ] === "~=" ) {
1640 1786 match[ 3 ] = " " + match[ 3 ] + " ";
@@ -1644,6 +1790,7 Expr = Sizzle.selectors = {
1644 1790 },
1645 1791
1646 1792 "CHILD": function( match ) {
1793
1647 1794 /* matches from matchExpr["CHILD"]
1648 1795 1 type (only|nth|...)
1649 1796 2 what (child|of-type)
@@ -1657,6 +1804,7 Expr = Sizzle.selectors = {
1657 1804 match[ 1 ] = match[ 1 ].toLowerCase();
1658 1805
1659 1806 if ( match[ 1 ].slice( 0, 3 ) === "nth" ) {
1807
1660 1808 // nth-* requires argument
1661 1809 if ( !match[ 3 ] ) {
1662 1810 Sizzle.error( match[ 0 ] );
@@ -1664,7 +1812,9 Expr = Sizzle.selectors = {
1664 1812
1665 1813 // numeric x and y parameters for Expr.filter.CHILD
1666 1814 // remember that false/true cast respectively to 0/1
1667 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1815 match[ 4 ] = +( match[ 4 ] ?
1816 match[ 5 ] + ( match[ 6 ] || 1 ) :
1817 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) );
1668 1818 match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" );
1669 1819
1670 1820 // other types prohibit arguments
@@ -1689,8 +1839,10 Expr = Sizzle.selectors = {
1689 1839
1690 1840 // Strip excess characters from unquoted arguments
1691 1841 } else if ( unquoted && rpseudo.test( unquoted ) &&
1842
1692 1843 // Get excess from tokenize (recursively)
1693 1844 ( excess = tokenize( unquoted, true ) ) &&
1845
1694 1846 // advance to the next closing parenthesis
1695 1847 ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) {
1696 1848
@@ -1709,7 +1861,9 Expr = Sizzle.selectors = {
1709 1861 "TAG": function( nodeNameSelector ) {
1710 1862 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1711 1863 return nodeNameSelector === "*" ?
1712 function() { return true; } :
1864 function() {
1865 return true;
1866 } :
1713 1867 function( elem ) {
1714 1868 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1715 1869 };
@@ -1719,9 +1873,15 Expr = Sizzle.selectors = {
1719 1873 var pattern = classCache[ className + " " ];
1720 1874
1721 1875 return pattern ||
1722 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1723 classCache( className, function( elem ) {
1724 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
1876 ( pattern = new RegExp( "(^|" + whitespace +
1877 ")" + className + "(" + whitespace + "|$)" ) ) && classCache(
1878 className, function( elem ) {
1879 return pattern.test(
1880 typeof elem.className === "string" && elem.className ||
1881 typeof elem.getAttribute !== "undefined" &&
1882 elem.getAttribute( "class" ) ||
1883 ""
1884 );
1725 1885 } );
1726 1886 },
1727 1887
@@ -1738,6 +1898,8 Expr = Sizzle.selectors = {
1738 1898
1739 1899 result += "";
1740 1900
1901 /* eslint-disable max-len */
1902
1741 1903 return operator === "=" ? result === check :
1742 1904 operator === "!=" ? result !== check :
1743 1905 operator === "^=" ? check && result.indexOf( check ) === 0 :
@@ -1746,10 +1908,12 Expr = Sizzle.selectors = {
1746 1908 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
1747 1909 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1748 1910 false;
1911 /* eslint-enable max-len */
1912
1749 1913 };
1750 1914 },
1751 1915
1752 "CHILD": function( type, what, argument, first, last ) {
1916 "CHILD": function( type, what, _argument, first, last ) {
1753 1917 var simple = type.slice( 0, 3 ) !== "nth",
1754 1918 forward = type.slice( -4 ) !== "last",
1755 1919 ofType = what === "of-type";
@@ -1761,7 +1925,7 Expr = Sizzle.selectors = {
1761 1925 return !!elem.parentNode;
1762 1926 } :
1763 1927
1764 function( elem, context, xml ) {
1928 function( elem, _context, xml ) {
1765 1929 var cache, uniqueCache, outerCache, node, nodeIndex, start,
1766 1930 dir = simple !== forward ? "nextSibling" : "previousSibling",
1767 1931 parent = elem.parentNode,
@@ -1783,6 +1947,7 Expr = Sizzle.selectors = {
1783 1947 return false;
1784 1948 }
1785 1949 }
1950
1786 1951 // Reverse direction for :only-* (if we haven't yet done so)
1787 1952 start = dir = type === "only" && !start && "nextSibling";
1788 1953 }
@@ -1823,8 +1988,10 Expr = Sizzle.selectors = {
1823 1988 }
1824 1989
1825 1990 } else {
1991
1826 1992 // Use previously-cached element index if available
1827 1993 if ( useCache ) {
1994
1828 1995 // ...in a gzip-friendly way
1829 1996 node = elem;
1830 1997 outerCache = node[ expando ] || ( node[ expando ] = {} );
@@ -1842,6 +2009,7 Expr = Sizzle.selectors = {
1842 2009 // xml :nth-child(...)
1843 2010 // or :nth-last-child(...) or :nth(-last)?-of-type(...)
1844 2011 if ( diff === false ) {
2012
1845 2013 // Use the same loop as above to seek `elem` from the start
1846 2014 while ( ( node = ++nodeIndex && node && node[ dir ] ||
1847 2015 ( diff = nodeIndex = 0 ) || start.pop() ) ) {
@@ -1853,7 +2021,8 Expr = Sizzle.selectors = {
1853 2021
1854 2022 // Cache the index of each encountered element
1855 2023 if ( useCache ) {
1856 outerCache = node[ expando ] || (node[ expando ] = {});
2024 outerCache = node[ expando ] ||
2025 ( node[ expando ] = {} );
1857 2026
1858 2027 // Support: IE <9 only
1859 2028 // Defend against cloned attroperties (jQuery gh-1709)
@@ -1879,6 +2048,7 Expr = Sizzle.selectors = {
1879 2048 },
1880 2049
1881 2050 "PSEUDO": function( pseudo, argument ) {
2051
1882 2052 // pseudo-class names are case-insensitive
1883 2053 // http://www.w3.org/TR/selectors/#pseudo-classes
1884 2054 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
@@ -1917,8 +2087,10 Expr = Sizzle.selectors = {
1917 2087 },
1918 2088
1919 2089 pseudos: {
2090
1920 2091 // Potentially complex pseudos
1921 2092 "not": markFunction( function( selector ) {
2093
1922 2094 // Trim the selector passed to compile
1923 2095 // to avoid treating leading and trailing
1924 2096 // spaces as combinators
@@ -1927,7 +2099,7 Expr = Sizzle.selectors = {
1927 2099 matcher = compile( selector.replace( rtrim, "$1" ) );
1928 2100
1929 2101 return matcher[ expando ] ?
1930 markFunction(function( seed, matches, context, xml ) {
2102 markFunction( function( seed, matches, _context, xml ) {
1931 2103 var elem,
1932 2104 unmatched = matcher( seed, null, xml, [] ),
1933 2105 i = seed.length;
@@ -1939,9 +2111,10 Expr = Sizzle.selectors = {
1939 2111 }
1940 2112 }
1941 2113 } ) :
1942 function( elem, context, xml ) {
2114 function( elem, _context, xml ) {
1943 2115 input[ 0 ] = elem;
1944 2116 matcher( input, null, xml, results );
2117
1945 2118 // Don't keep the element (issue #299)
1946 2119 input[ 0 ] = null;
1947 2120 return !results.pop();
@@ -1957,7 +2130,7 Expr = Sizzle.selectors = {
1957 2130 "contains": markFunction( function( text ) {
1958 2131 text = text.replace( runescape, funescape );
1959 2132 return function( elem ) {
1960 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
2133 return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;
1961 2134 };
1962 2135 } ),
1963 2136
@@ -1969,6 +2142,7 Expr = Sizzle.selectors = {
1969 2142 // The identifier C does not have to be a valid language name."
1970 2143 // http://www.w3.org/TR/selectors/#lang-pseudo
1971 2144 "lang": markFunction( function( lang ) {
2145
1972 2146 // lang value must be a valid identifier
1973 2147 if ( !ridentifier.test( lang || "" ) ) {
1974 2148 Sizzle.error( "unsupported lang: " + lang );
@@ -2000,7 +2174,9 Expr = Sizzle.selectors = {
2000 2174 },
2001 2175
2002 2176 "focus": function( elem ) {
2003 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
2177 return elem === document.activeElement &&
2178 ( !document.hasFocus || document.hasFocus() ) &&
2179 !!( elem.type || elem.href || ~elem.tabIndex );
2004 2180 },
2005 2181
2006 2182 // Boolean properties
@@ -2008,16 +2184,20 Expr = Sizzle.selectors = {
2008 2184 "disabled": createDisabledPseudo( true ),
2009 2185
2010 2186 "checked": function( elem ) {
2187
2011 2188 // In CSS3, :checked should return both checked and selected elements
2012 2189 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
2013 2190 var nodeName = elem.nodeName.toLowerCase();
2014 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
2191 return ( nodeName === "input" && !!elem.checked ) ||
2192 ( nodeName === "option" && !!elem.selected );
2015 2193 },
2016 2194
2017 2195 "selected": function( elem ) {
2196
2018 2197 // Accessing this property makes selected-by-default
2019 2198 // options in Safari work properly
2020 2199 if ( elem.parentNode ) {
2200 // eslint-disable-next-line no-unused-expressions
2021 2201 elem.parentNode.selectedIndex;
2022 2202 }
2023 2203
@@ -2026,6 +2206,7 Expr = Sizzle.selectors = {
2026 2206
2027 2207 // Contents
2028 2208 "empty": function( elem ) {
2209
2029 2210 // http://www.w3.org/TR/selectors/#empty-pseudo
2030 2211 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
2031 2212 // but not by others (comment: 8; processing instruction: 7; etc.)
@@ -2063,7 +2244,8 Expr = Sizzle.selectors = {
2063 2244
2064 2245 // Support: IE<8
2065 2246 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
2066 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
2247 ( ( attr = elem.getAttribute( "type" ) ) == null ||
2248 attr.toLowerCase() === "text" );
2067 2249 },
2068 2250
2069 2251 // Position-in-collection
@@ -2071,11 +2253,11 Expr = Sizzle.selectors = {
2071 2253 return [ 0 ];
2072 2254 } ),
2073 2255
2074 "last": createPositionalPseudo(function( matchIndexes, length ) {
2256 "last": createPositionalPseudo( function( _matchIndexes, length ) {
2075 2257 return [ length - 1 ];
2076 2258 } ),
2077 2259
2078 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
2260 "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) {
2079 2261 return [ argument < 0 ? argument + length : argument ];
2080 2262 } ),
2081 2263
@@ -2096,7 +2278,11 Expr = Sizzle.selectors = {
2096 2278 } ),
2097 2279
2098 2280 "lt": createPositionalPseudo( function( matchIndexes, length, argument ) {
2099 var i = argument < 0 ? argument + length : argument;
2281 var i = argument < 0 ?
2282 argument + length :
2283 argument > length ?
2284 length :
2285 argument;
2100 2286 for ( ; --i >= 0; ) {
2101 2287 matchIndexes.push( i );
2102 2288 }
@@ -2146,6 +2332,7 tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2146 2332 // Comma and first run
2147 2333 if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
2148 2334 if ( match ) {
2335
2149 2336 // Don't consume trailing commas as valid
2150 2337 soFar = soFar.slice( match[ 0 ].length ) || soFar;
2151 2338 }
@@ -2159,6 +2346,7 tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2159 2346 matched = match.shift();
2160 2347 tokens.push( {
2161 2348 value: matched,
2349
2162 2350 // Cast descendant combinators to space
2163 2351 type: match[ 0 ].replace( rtrim, " " )
2164 2352 } );
@@ -2191,6 +2379,7 tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2191 2379 soFar.length :
2192 2380 soFar ?
2193 2381 Sizzle.error( selector ) :
2382
2194 2383 // Cache the tokens
2195 2384 tokenCache( selector, groups ).slice( 0 );
2196 2385 };
@@ -2213,6 +2402,7 function addCombinator( matcher, combinator, base ) {
2213 2402 doneName = done++;
2214 2403
2215 2404 return combinator.first ?
2405
2216 2406 // Check against closest ancestor/preceding element
2217 2407 function( elem, context, xml ) {
2218 2408 while ( ( elem = elem[ dir ] ) ) {
@@ -2244,7 +2434,8 function addCombinator( matcher, combinator, base ) {
2244 2434
2245 2435 // Support: IE <9 only
2246 2436 // Defend against cloned attroperties (jQuery gh-1709)
2247 uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
2437 uniqueCache = outerCache[ elem.uniqueID ] ||
2438 ( outerCache[ elem.uniqueID ] = {} );
2248 2439
2249 2440 if ( skip && skip === elem.nodeName.toLowerCase() ) {
2250 2441 elem = elem[ dir ] || elem;
@@ -2254,6 +2445,7 function addCombinator( matcher, combinator, base ) {
2254 2445 // Assign to newCache so results back-propagate to previous elements
2255 2446 return ( newCache[ 2 ] = oldCache[ 2 ] );
2256 2447 } else {
2448
2257 2449 // Reuse newcache so results back-propagate to previous elements
2258 2450 uniqueCache[ key ] = newCache;
2259 2451
@@ -2327,7 +2519,11 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS
2327 2519 preexisting = results.length,
2328 2520
2329 2521 // Get initial elements from seed or context
2330 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2522 elems = seed || multipleContexts(
2523 selector || "*",
2524 context.nodeType ? [ context ] : context,
2525 []
2526 ),
2331 2527
2332 2528 // Prefilter to get matcher input, preserving a map for seed-results synchronization
2333 2529 matcherIn = preFilter && ( seed || !selector ) ?
@@ -2335,6 +2531,7 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS
2335 2531 elems,
2336 2532
2337 2533 matcherOut = matcher ?
2534
2338 2535 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2339 2536 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2340 2537
@@ -2367,11 +2564,13 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS
2367 2564 if ( seed ) {
2368 2565 if ( postFinder || preFilter ) {
2369 2566 if ( postFinder ) {
2567
2370 2568 // Get the final matcherOut by condensing this intermediate into postFinder contexts
2371 2569 temp = [];
2372 2570 i = matcherOut.length;
2373 2571 while ( i-- ) {
2374 2572 if ( ( elem = matcherOut[ i ] ) ) {
2573
2375 2574 // Restore matcherIn since elem is not yet a final match
2376 2575 temp.push( ( matcherIn[ i ] = elem ) );
2377 2576 }
@@ -2425,6 +2624,7 function matcherFromTokens( tokens ) {
2425 2624 ( checkContext = context ).nodeType ?
2426 2625 matchContext( elem, context, xml ) :
2427 2626 matchAnyContext( elem, context, xml ) );
2627
2428 2628 // Avoid hanging onto element (issue #299)
2429 2629 checkContext = null;
2430 2630 return ret;
@@ -2438,6 +2638,7 function matcherFromTokens( tokens ) {
2438 2638
2439 2639 // Return special upon seeing a positional matcher
2440 2640 if ( matcher[ expando ] ) {
2641
2441 2642 // Find the next relative operator (if any) for proper handling
2442 2643 j = ++i;
2443 2644 for ( ; j < len; j++ ) {
@@ -2448,8 +2649,11 function matcherFromTokens( tokens ) {
2448 2649 return setMatcher(
2449 2650 i > 1 && elementMatcher( matchers ),
2450 2651 i > 1 && toSelector(
2652
2451 2653 // If the preceding token was a descendant combinator, insert an implicit any-element `*`
2452 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2654 tokens
2655 .slice( 0, i - 1 )
2656 .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
2453 2657 ).replace( rtrim, "$1" ),
2454 2658 matcher,
2455 2659 i < j && matcherFromTokens( tokens.slice( i, j ) ),
@@ -2474,14 +2678,21 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2474 2678 unmatched = seed && [],
2475 2679 setMatched = [],
2476 2680 contextBackup = outermostContext,
2681
2477 2682 // We must always have either seed elements or outermost context
2478 2683 elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ),
2684
2479 2685 // Use integer dirruns iff this is the outermost matcher
2480 2686 dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),
2481 2687 len = elems.length;
2482 2688
2483 2689 if ( outermost ) {
2484 outermostContext = context === document || context || outermost;
2690
2691 // Support: IE 11+, Edge 17 - 18+
2692 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2693 // two documents; shallow comparisons work.
2694 // eslint-disable-next-line eqeqeq
2695 outermostContext = context == document || context || outermost;
2485 2696 }
2486 2697
2487 2698 // Add elements passing elementMatchers directly to results
@@ -2490,7 +2701,12 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2490 2701 for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {
2491 2702 if ( byElement && elem ) {
2492 2703 j = 0;
2493 if ( !context && elem.ownerDocument !== document ) {
2704
2705 // Support: IE 11+, Edge 17 - 18+
2706 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2707 // two documents; shallow comparisons work.
2708 // eslint-disable-next-line eqeqeq
2709 if ( !context && elem.ownerDocument != document ) {
2494 2710 setDocument( elem );
2495 2711 xml = !documentIsHTML;
2496 2712 }
@@ -2507,6 +2723,7 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2507 2723
2508 2724 // Track unmatched elements for set filters
2509 2725 if ( bySet ) {
2726
2510 2727 // They will have gone through all possible matchers
2511 2728 if ( ( elem = !matcher && elem ) ) {
2512 2729 matchedCount--;
@@ -2537,6 +2754,7 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2537 2754 }
2538 2755
2539 2756 if ( seed ) {
2757
2540 2758 // Reintegrate element matches to eliminate the need for sorting
2541 2759 if ( matchedCount > 0 ) {
2542 2760 while ( i-- ) {
@@ -2582,6 +2800,7 compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2582 2800 cached = compilerCache[ selector + " " ];
2583 2801
2584 2802 if ( !cached ) {
2803
2585 2804 // Generate a function of recursive functions that can be used to check each element
2586 2805 if ( !match ) {
2587 2806 match = tokenize( selector );
@@ -2597,7 +2816,10 compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2597 2816 }
2598 2817
2599 2818 // Cache the compiled function
2600 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2819 cached = compilerCache(
2820 selector,
2821 matcherFromGroupMatchers( elementMatchers, setMatchers )
2822 );
2601 2823
2602 2824 // Save selector and tokenization
2603 2825 cached.selector = selector;
@@ -2630,7 +2852,8 select = Sizzle.select = function( selector, context, results, seed ) {
2630 2852 if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
2631 2853 context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
2632 2854
2633 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2855 context = ( Expr.find[ "ID" ]( token.matches[ 0 ]
2856 .replace( runescape, funescape ), context ) || [] )[ 0 ];
2634 2857 if ( !context ) {
2635 2858 return results;
2636 2859
@@ -2652,10 +2875,12 select = Sizzle.select = function( selector, context, results, seed ) {
2652 2875 break;
2653 2876 }
2654 2877 if ( ( find = Expr.find[ type ] ) ) {
2878
2655 2879 // Search, expanding context for leading sibling combinators
2656 2880 if ( ( seed = find(
2657 2881 token.matches[ 0 ].replace( runescape, funescape ),
2658 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2882 rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) ||
2883 context
2659 2884 ) ) ) {
2660 2885
2661 2886 // If seed is empty or no tokens remain, we can return early
@@ -2699,6 +2924,7 setDocument();
2699 2924 // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2700 2925 // Detached nodes confoundingly follow *each other*
2701 2926 support.sortDetached = assert( function( el ) {
2927
2702 2928 // Should return 1, but returns 4 (following)
2703 2929 return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1;
2704 2930 } );
@@ -2724,7 +2950,7 if ( !support.attributes || !assert(function( el ) {
2724 2950 el.firstChild.setAttribute( "value", "" );
2725 2951 return el.firstChild.getAttribute( "value" ) === "";
2726 2952 } ) ) {
2727 addHandle( "value", function( elem, name, isXML ) {
2953 addHandle( "value", function( elem, _name, isXML ) {
2728 2954 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2729 2955 return elem.defaultValue;
2730 2956 }
@@ -2804,7 +3030,7 function nodeName( elem, name ) {
2804 3030
2805 3031 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
2806 3032
2807 };
3033 }
2808 3034 var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
2809 3035
2810 3036
@@ -3118,7 +3344,7 jQuery.each( {
3118 3344 parents: function( elem ) {
3119 3345 return dir( elem, "parentNode" );
3120 3346 },
3121 parentsUntil: function( elem, i, until ) {
3347 parentsUntil: function( elem, _i, until ) {
3122 3348 return dir( elem, "parentNode", until );
3123 3349 },
3124 3350 next: function( elem ) {
@@ -3133,10 +3359,10 jQuery.each( {
3133 3359 prevAll: function( elem ) {
3134 3360 return dir( elem, "previousSibling" );
3135 3361 },
3136 nextUntil: function( elem, i, until ) {
3362 nextUntil: function( elem, _i, until ) {
3137 3363 return dir( elem, "nextSibling", until );
3138 3364 },
3139 prevUntil: function( elem, i, until ) {
3365 prevUntil: function( elem, _i, until ) {
3140 3366 return dir( elem, "previousSibling", until );
3141 3367 },
3142 3368 siblings: function( elem ) {
@@ -3146,7 +3372,13 jQuery.each( {
3146 3372 return siblings( elem.firstChild );
3147 3373 },
3148 3374 contents: function( elem ) {
3149 if ( nodeName( elem, "iframe" ) ) {
3375 if ( elem.contentDocument != null &&
3376
3377 // Support: IE 11+
3378 // <object> elements with no `data` attribute has an object
3379 // `contentDocument` with a `null` prototype.
3380 getProto( elem.contentDocument ) ) {
3381
3150 3382 return elem.contentDocument;
3151 3383 }
3152 3384
@@ -3489,7 +3721,7 jQuery.extend( {
3489 3721 var fns = arguments;
3490 3722
3491 3723 return jQuery.Deferred( function( newDefer ) {
3492 jQuery.each( tuples, function( i, tuple ) {
3724 jQuery.each( tuples, function( _i, tuple ) {
3493 3725
3494 3726 // Map tuples (progress, done, fail) to arguments (done, fail, progress)
3495 3727 var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
@@ -3769,8 +4001,8 jQuery.extend( {
3769 4001 resolveContexts = Array( i ),
3770 4002 resolveValues = slice.call( arguments ),
3771 4003
3772 // the master Deferred
3773 master = jQuery.Deferred(),
4004 // the primary Deferred
4005 primary = jQuery.Deferred(),
3774 4006
3775 4007 // subordinate callback factory
3776 4008 updateFunc = function( i ) {
@@ -3778,30 +4010,30 jQuery.extend( {
3778 4010 resolveContexts[ i ] = this;
3779 4011 resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3780 4012 if ( !( --remaining ) ) {
3781 master.resolveWith( resolveContexts, resolveValues );
4013 primary.resolveWith( resolveContexts, resolveValues );
3782 4014 }
3783 4015 };
3784 4016 };
3785 4017
3786 4018 // Single- and empty arguments are adopted like Promise.resolve
3787 4019 if ( remaining <= 1 ) {
3788 adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
4020 adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject,
3789 4021 !remaining );
3790 4022
3791 4023 // Use .then() to unwrap secondary thenables (cf. gh-3000)
3792 if ( master.state() === "pending" ||
4024 if ( primary.state() === "pending" ||
3793 4025 isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
3794 4026
3795 return master.then();
4027 return primary.then();
3796 4028 }
3797 4029 }
3798 4030
3799 4031 // Multiple arguments are aggregated like Promise.all array elements
3800 4032 while ( i-- ) {
3801 adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
4033 adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject );
3802 4034 }
3803 4035
3804 return master.promise();
4036 return primary.promise();
3805 4037 }
3806 4038 } );
3807 4039
@@ -3942,7 +4174,7 var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
3942 4174 // ...except when executing function values
3943 4175 } else {
3944 4176 bulk = fn;
3945 fn = function( elem, key, value ) {
4177 fn = function( elem, _key, value ) {
3946 4178 return bulk.call( jQuery( elem ), value );
3947 4179 };
3948 4180 }
@@ -3977,7 +4209,7 var rmsPrefix = /^-ms-/,
3977 4209 rdashAlpha = /-([a-z])/g;
3978 4210
3979 4211 // Used by camelCase as callback to replace()
3980 function fcamelCase( all, letter ) {
4212 function fcamelCase( _all, letter ) {
3981 4213 return letter.toUpperCase();
3982 4214 }
3983 4215
@@ -4466,6 +4698,26 var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
4466 4698
4467 4699 var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4468 4700
4701 var documentElement = document.documentElement;
4702
4703
4704
4705 var isAttached = function( elem ) {
4706 return jQuery.contains( elem.ownerDocument, elem );
4707 },
4708 composed = { composed: true };
4709
4710 // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
4711 // Check attachment across shadow DOM boundaries when possible (gh-3504)
4712 // Support: iOS 10.0-10.2 only
4713 // Early iOS 10 versions support `attachShadow` but not `getRootNode`,
4714 // leading to errors. We need to check for `getRootNode`.
4715 if ( documentElement.getRootNode ) {
4716 isAttached = function( elem ) {
4717 return jQuery.contains( elem.ownerDocument, elem ) ||
4718 elem.getRootNode( composed ) === elem.ownerDocument;
4719 };
4720 }
4469 4721 var isHiddenWithinTree = function( elem, el ) {
4470 4722
4471 4723 // isHiddenWithinTree might be called from jQuery#filter function;
@@ -4480,32 +4732,11 var isHiddenWithinTree = function( elem, el ) {
4480 4732 // Support: Firefox <=43 - 45
4481 4733 // Disconnected elements can have computed display: none, so first confirm that elem is
4482 4734 // in the document.
4483 jQuery.contains( elem.ownerDocument, elem ) &&
4735 isAttached( elem ) &&
4484 4736
4485 4737 jQuery.css( elem, "display" ) === "none";
4486 4738 };
4487 4739
4488 var swap = function( elem, options, callback, args ) {
4489 var ret, name,
4490 old = {};
4491
4492 // Remember the old values, and insert the new ones
4493 for ( name in options ) {
4494 old[ name ] = elem.style[ name ];
4495 elem.style[ name ] = options[ name ];
4496 }
4497
4498 ret = callback.apply( elem, args || [] );
4499
4500 // Revert the old values
4501 for ( name in options ) {
4502 elem.style[ name ] = old[ name ];
4503 }
4504
4505 return ret;
4506 };
4507
4508
4509 4740
4510 4741
4511 4742 function adjustCSS( elem, prop, valueParts, tween ) {
@@ -4522,7 +4753,8 function adjustCSS( elem, prop, valueParts, tween ) {
4522 4753 unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
4523 4754
4524 4755 // Starting value computation is required for potential unit mismatches
4525 initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
4756 initialInUnit = elem.nodeType &&
4757 ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
4526 4758 rcssNum.exec( jQuery.css( elem, prop ) );
4527 4759
4528 4760 if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
@@ -4669,17 +4901,46 jQuery.fn.extend( {
4669 4901 } );
4670 4902 var rcheckableType = ( /^(?:checkbox|radio)$/i );
4671 4903
4672 var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
4904 var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i );
4673 4905
4674 4906 var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
4675 4907
4676 4908
4677 4909
4678 // We have to close these tags to support XHTML (#13200)
4679 var wrapMap = {
4910 ( function() {
4911 var fragment = document.createDocumentFragment(),
4912 div = fragment.appendChild( document.createElement( "div" ) ),
4913 input = document.createElement( "input" );
4914
4915 // Support: Android 4.0 - 4.3 only
4916 // Check state lost if the name is set (#11217)
4917 // Support: Windows Web Apps (WWA)
4918 // `name` and `type` must use .setAttribute for WWA (#14901)
4919 input.setAttribute( "type", "radio" );
4920 input.setAttribute( "checked", "checked" );
4921 input.setAttribute( "name", "t" );
4922
4923 div.appendChild( input );
4924
4925 // Support: Android <=4.1 only
4926 // Older WebKit doesn't clone checked state correctly in fragments
4927 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4928
4929 // Support: IE <=11 only
4930 // Make sure textarea (and checkbox) defaultValue is properly cloned
4931 div.innerHTML = "<textarea>x</textarea>";
4932 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4680 4933
4681 4934 // Support: IE <=9 only
4682 option: [ 1, "<select multiple='multiple'>", "</select>" ],
4935 // IE <=9 replaces <option> tags with their contents when inserted outside of
4936 // the select element.
4937 div.innerHTML = "<option></option>";
4938 support.option = !!div.lastChild;
4939 } )();
4940
4941
4942 // We have to close these tags to support XHTML (#13200)
4943 var wrapMap = {
4683 4944
4684 4945 // XHTML parsers do not magically insert elements in the
4685 4946 // same way that tag soup parsers do. So we cannot shorten
@@ -4692,12 +4953,14 var wrapMap = {
4692 4953 _default: [ 0, "", "" ]
4693 4954 };
4694 4955
4695 // Support: IE <=9 only
4696 wrapMap.optgroup = wrapMap.option;
4697
4698 4956 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4699 4957 wrapMap.th = wrapMap.td;
4700 4958
4959 // Support: IE <=9 only
4960 if ( !support.option ) {
4961 wrapMap.optgroup = wrapMap.option = [ 1, "<select multiple='multiple'>", "</select>" ];
4962 }
4963
4701 4964
4702 4965 function getAll( context, tag ) {
4703 4966
@@ -4741,7 +5004,7 function setGlobalEval( elems, refElements ) {
4741 5004 var rhtml = /<|&#?\w+;/;
4742 5005
4743 5006 function buildFragment( elems, context, scripts, selection, ignored ) {
4744 var elem, tmp, tag, wrap, contains, j,
5007 var elem, tmp, tag, wrap, attached, j,
4745 5008 fragment = context.createDocumentFragment(),
4746 5009 nodes = [],
4747 5010 i = 0,
@@ -4805,13 +5068,13 function buildFragment( elems, context, scripts, selection, ignored ) {
4805 5068 continue;
4806 5069 }
4807 5070
4808 contains = jQuery.contains( elem.ownerDocument, elem );
5071 attached = isAttached( elem );
4809 5072
4810 5073 // Append to fragment
4811 5074 tmp = getAll( fragment.appendChild( elem ), "script" );
4812 5075
4813 5076 // Preserve script evaluation history
4814 if ( contains ) {
5077 if ( attached ) {
4815 5078 setGlobalEval( tmp );
4816 5079 }
4817 5080
@@ -4830,38 +5093,7 function buildFragment( elems, context, scripts, selection, ignored ) {
4830 5093 }
4831 5094
4832 5095
4833 ( function() {
4834 var fragment = document.createDocumentFragment(),
4835 div = fragment.appendChild( document.createElement( "div" ) ),
4836 input = document.createElement( "input" );
4837
4838 // Support: Android 4.0 - 4.3 only
4839 // Check state lost if the name is set (#11217)
4840 // Support: Windows Web Apps (WWA)
4841 // `name` and `type` must use .setAttribute for WWA (#14901)
4842 input.setAttribute( "type", "radio" );
4843 input.setAttribute( "checked", "checked" );
4844 input.setAttribute( "name", "t" );
4845
4846 div.appendChild( input );
4847
4848 // Support: Android <=4.1 only
4849 // Older WebKit doesn't clone checked state correctly in fragments
4850 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4851
4852 // Support: IE <=11 only
4853 // Make sure textarea (and checkbox) defaultValue is properly cloned
4854 div.innerHTML = "<textarea>x</textarea>";
4855 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4856 } )();
4857 var documentElement = document.documentElement;
4858
4859
4860
4861 var
4862 rkeyEvent = /^key/,
4863 rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
4864 rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
5096 var rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
4865 5097
4866 5098 function returnTrue() {
4867 5099 return true;
@@ -4871,8 +5103,19 function returnFalse() {
4871 5103 return false;
4872 5104 }
4873 5105
5106 // Support: IE <=9 - 11+
5107 // focus() and blur() are asynchronous, except when they are no-op.
5108 // So expect focus to be synchronous when the element is already active,
5109 // and blur to be synchronous when the element is not already active.
5110 // (focus and blur are always synchronous in other supported browsers,
5111 // this just defines when we can count on it).
5112 function expectSync( elem, type ) {
5113 return ( elem === safeActiveElement() ) === ( type === "focus" );
5114 }
5115
4874 5116 // Support: IE <=9 only
4875 // See #13393 for more info
5117 // Accessing document.activeElement can throw unexpectedly
5118 // https://bugs.jquery.com/ticket/13393
4876 5119 function safeActiveElement() {
4877 5120 try {
4878 5121 return document.activeElement;
@@ -4955,8 +5198,8 jQuery.event = {
4955 5198 special, handlers, type, namespaces, origType,
4956 5199 elemData = dataPriv.get( elem );
4957 5200
4958 // Don't attach events to noData or text/comment nodes (but allow plain objects)
4959 if ( !elemData ) {
5201 // Only attach events to objects that accept data
5202 if ( !acceptData( elem ) ) {
4960 5203 return;
4961 5204 }
4962 5205
@@ -4980,7 +5223,7 jQuery.event = {
4980 5223
4981 5224 // Init the element's event structure and main handler, if this is the first
4982 5225 if ( !( events = elemData.events ) ) {
4983 events = elemData.events = {};
5226 events = elemData.events = Object.create( null );
4984 5227 }
4985 5228 if ( !( eventHandle = elemData.handle ) ) {
4986 5229 eventHandle = elemData.handle = function( e ) {
@@ -5138,12 +5381,15 jQuery.event = {
5138 5381
5139 5382 dispatch: function( nativeEvent ) {
5140 5383
5141 // Make a writable jQuery.Event from the native event object
5142 var event = jQuery.event.fix( nativeEvent );
5143
5144 5384 var i, j, ret, matched, handleObj, handlerQueue,
5145 5385 args = new Array( arguments.length ),
5146 handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
5386
5387 // Make a writable jQuery.Event from the native event object
5388 event = jQuery.event.fix( nativeEvent ),
5389
5390 handlers = (
5391 dataPriv.get( this, "events" ) || Object.create( null )
5392 )[ event.type ] || [],
5147 5393 special = jQuery.event.special[ event.type ] || {};
5148 5394
5149 5395 // Use the fix-ed jQuery.Event rather than the (read-only) native event
@@ -5172,9 +5418,10 jQuery.event = {
5172 5418 while ( ( handleObj = matched.handlers[ j++ ] ) &&
5173 5419 !event.isImmediatePropagationStopped() ) {
5174 5420
5175 // Triggered event must either 1) have no namespace, or 2) have namespace(s)
5176 // a subset or equal to those in the bound event (both can have no namespace).
5177 if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
5421 // If the event is namespaced, then each handler is only invoked if it is
5422 // specially universal or its namespaces are a superset of the event's.
5423 if ( !event.rnamespace || handleObj.namespace === false ||
5424 event.rnamespace.test( handleObj.namespace ) ) {
5178 5425
5179 5426 event.handleObj = handleObj;
5180 5427 event.data = handleObj.data;
@@ -5298,39 +5545,51 jQuery.event = {
5298 5545 // Prevent triggered image.load events from bubbling to window.load
5299 5546 noBubble: true
5300 5547 },
5301 focus: {
5548 click: {
5302 5549
5303 // Fire native event if possible so blur/focus sequence is correct
5304 trigger: function() {
5305 if ( this !== safeActiveElement() && this.focus ) {
5306 this.focus();
5307 return false;
5550 // Utilize native event to ensure correct state for checkable inputs
5551 setup: function( data ) {
5552
5553 // For mutual compressibility with _default, replace `this` access with a local var.
5554 // `|| data` is dead code meant only to preserve the variable through minification.
5555 var el = this || data;
5556
5557 // Claim the first handler
5558 if ( rcheckableType.test( el.type ) &&
5559 el.click && nodeName( el, "input" ) ) {
5560
5561 // dataPriv.set( el, "click", ... )
5562 leverageNative( el, "click", returnTrue );
5308 5563 }
5309 },
5310 delegateType: "focusin"
5311 },
5312 blur: {
5313 trigger: function() {
5314 if ( this === safeActiveElement() && this.blur ) {
5315 this.blur();
5564
5565 // Return false to allow normal processing in the caller
5316 5566 return false;
5317 }
5318 5567 },
5319 delegateType: "focusout"
5320 },
5321 click: {
5568 trigger: function( data ) {
5322 5569
5323 // For checkbox, fire native event so checked state will be right
5324 trigger: function() {
5325 if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) {
5326 this.click();
5327 return false;
5570 // For mutual compressibility with _default, replace `this` access with a local var.
5571 // `|| data` is dead code meant only to preserve the variable through minification.
5572 var el = this || data;
5573
5574 // Force setup before triggering a click
5575 if ( rcheckableType.test( el.type ) &&
5576 el.click && nodeName( el, "input" ) ) {
5577
5578 leverageNative( el, "click" );
5328 5579 }
5580
5581 // Return non-false to allow normal event-path propagation
5582 return true;
5329 5583 },
5330 5584
5331 // For cross-browser consistency, don't fire native .click() on links
5585 // For cross-browser consistency, suppress native .click() on links
5586 // Also prevent it if we're currently inside a leveraged native-event stack
5332 5587 _default: function( event ) {
5333 return nodeName( event.target, "a" );
5588 var target = event.target;
5589 return rcheckableType.test( target.type ) &&
5590 target.click && nodeName( target, "input" ) &&
5591 dataPriv.get( target, "click" ) ||
5592 nodeName( target, "a" );
5334 5593 }
5335 5594 },
5336 5595
@@ -5347,6 +5606,99 jQuery.event = {
5347 5606 }
5348 5607 };
5349 5608
5609 // Ensure the presence of an event listener that handles manually-triggered
5610 // synthetic events by interrupting progress until reinvoked in response to
5611 // *native* events that it fires directly, ensuring that state changes have
5612 // already occurred before other listeners are invoked.
5613 function leverageNative( el, type, expectSync ) {
5614
5615 // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add
5616 if ( !expectSync ) {
5617 if ( dataPriv.get( el, type ) === undefined ) {
5618 jQuery.event.add( el, type, returnTrue );
5619 }
5620 return;
5621 }
5622
5623 // Register the controller as a special universal handler for all event namespaces
5624 dataPriv.set( el, type, false );
5625 jQuery.event.add( el, type, {
5626 namespace: false,
5627 handler: function( event ) {
5628 var notAsync, result,
5629 saved = dataPriv.get( this, type );
5630
5631 if ( ( event.isTrigger & 1 ) && this[ type ] ) {
5632
5633 // Interrupt processing of the outer synthetic .trigger()ed event
5634 // Saved data should be false in such cases, but might be a leftover capture object
5635 // from an async native handler (gh-4350)
5636 if ( !saved.length ) {
5637
5638 // Store arguments for use when handling the inner native event
5639 // There will always be at least one argument (an event object), so this array
5640 // will not be confused with a leftover capture object.
5641 saved = slice.call( arguments );
5642 dataPriv.set( this, type, saved );
5643
5644 // Trigger the native event and capture its result
5645 // Support: IE <=9 - 11+
5646 // focus() and blur() are asynchronous
5647 notAsync = expectSync( this, type );
5648 this[ type ]();
5649 result = dataPriv.get( this, type );
5650 if ( saved !== result || notAsync ) {
5651 dataPriv.set( this, type, false );
5652 } else {
5653 result = {};
5654 }
5655 if ( saved !== result ) {
5656
5657 // Cancel the outer synthetic event
5658 event.stopImmediatePropagation();
5659 event.preventDefault();
5660
5661 // Support: Chrome 86+
5662 // In Chrome, if an element having a focusout handler is blurred by
5663 // clicking outside of it, it invokes the handler synchronously. If
5664 // that handler calls `.remove()` on the element, the data is cleared,
5665 // leaving `result` undefined. We need to guard against this.
5666 return result && result.value;
5667 }
5668
5669 // If this is an inner synthetic event for an event with a bubbling surrogate
5670 // (focus or blur), assume that the surrogate already propagated from triggering the
5671 // native event and prevent that from happening again here.
5672 // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
5673 // bubbling surrogate propagates *after* the non-bubbling base), but that seems
5674 // less bad than duplication.
5675 } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
5676 event.stopPropagation();
5677 }
5678
5679 // If this is a native event triggered above, everything is now in order
5680 // Fire an inner synthetic event with the original arguments
5681 } else if ( saved.length ) {
5682
5683 // ...and capture the result
5684 dataPriv.set( this, type, {
5685 value: jQuery.event.trigger(
5686
5687 // Support: IE <=9 - 11+
5688 // Extend with the prototype to reset the above stopImmediatePropagation()
5689 jQuery.extend( saved[ 0 ], jQuery.Event.prototype ),
5690 saved.slice( 1 ),
5691 this
5692 )
5693 } );
5694
5695 // Abort handling of the native event
5696 event.stopImmediatePropagation();
5697 }
5698 }
5699 } );
5700 }
5701
5350 5702 jQuery.removeEvent = function( elem, type, handle ) {
5351 5703
5352 5704 // This "if" is needed for plain objects
@@ -5459,6 +5811,7 jQuery.each( {
5459 5811 shiftKey: true,
5460 5812 view: true,
5461 5813 "char": true,
5814 code: true,
5462 5815 charCode: true,
5463 5816 key: true,
5464 5817 keyCode: true,
@@ -5475,35 +5828,41 jQuery.each( {
5475 5828 targetTouches: true,
5476 5829 toElement: true,
5477 5830 touches: true,
5831 which: true
5832 }, jQuery.event.addProp );
5478 5833
5479 which: function( event ) {
5480 var button = event.button;
5834 jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
5835 jQuery.event.special[ type ] = {
5481 5836
5482 // Add which for key events
5483 if ( event.which == null && rkeyEvent.test( event.type ) ) {
5484 return event.charCode != null ? event.charCode : event.keyCode;
5485 }
5837 // Utilize native event if possible so blur/focus sequence is correct
5838 setup: function() {
5486 5839
5487 // Add which for click: 1 === left; 2 === middle; 3 === right
5488 if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
5489 if ( button & 1 ) {
5490 return 1;
5491 }
5840 // Claim the first handler
5841 // dataPriv.set( this, "focus", ... )
5842 // dataPriv.set( this, "blur", ... )
5843 leverageNative( this, type, expectSync );
5492 5844
5493 if ( button & 2 ) {
5494 return 3;
5495 }
5845 // Return false to allow normal processing in the caller
5846 return false;
5847 },
5848 trigger: function() {
5496 5849
5497 if ( button & 4 ) {
5498 return 2;
5499 }
5850 // Force setup before trigger
5851 leverageNative( this, type );
5500 5852
5501 return 0;
5502 }
5853 // Return non-false to allow normal event-path propagation
5854 return true;
5855 },
5503 5856
5504 return event.which;
5505 }
5506 }, jQuery.event.addProp );
5857 // Suppress native focus or blur as it's already being fired
5858 // in leverageNative.
5859 _default: function() {
5860 return true;
5861 },
5862
5863 delegateType: delegateType
5864 };
5865 } );
5507 5866
5508 5867 // Create mouseenter/leave events using mouseover/out and event-time checks
5509 5868 // so that event delegation works in jQuery.
@@ -5590,13 +5949,6 jQuery.fn.extend( {
5590 5949
5591 5950 var
5592 5951
5593 /* eslint-disable max-len */
5594
5595 // See https://github.com/eslint/eslint/issues/3229
5596 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
5597
5598 /* eslint-enable */
5599
5600 5952 // Support: IE <=10 - 11, Edge 12 - 13 only
5601 5953 // In IE/Edge using regex groups here causes severe slowdowns.
5602 5954 // See https://connect.microsoft.com/IE/feedback/details/1736512/
@@ -5633,7 +5985,7 function restoreScript( elem ) {
5633 5985 }
5634 5986
5635 5987 function cloneCopyEvent( src, dest ) {
5636 var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
5988 var i, l, type, pdataOld, udataOld, udataCur, events;
5637 5989
5638 5990 if ( dest.nodeType !== 1 ) {
5639 5991 return;
@@ -5641,13 +5993,11 function cloneCopyEvent( src, dest ) {
5641 5993
5642 5994 // 1. Copy private data: events, handlers, etc.
5643 5995 if ( dataPriv.hasData( src ) ) {
5644 pdataOld = dataPriv.access( src );
5645 pdataCur = dataPriv.set( dest, pdataOld );
5996 pdataOld = dataPriv.get( src );
5646 5997 events = pdataOld.events;
5647 5998
5648 5999 if ( events ) {
5649 delete pdataCur.handle;
5650 pdataCur.events = {};
6000 dataPriv.remove( dest, "handle events" );
5651 6001
5652 6002 for ( type in events ) {
5653 6003 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
@@ -5683,7 +6033,7 function fixInput( src, dest ) {
5683 6033 function domManip( collection, args, callback, ignored ) {
5684 6034
5685 6035 // Flatten any nested arrays
5686 args = concat.apply( [], args );
6036 args = flat( args );
5687 6037
5688 6038 var fragment, first, scripts, hasScripts, node, doc,
5689 6039 i = 0,
@@ -5755,11 +6105,13 function domManip( collection, args, callback, ignored ) {
5755 6105 if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) {
5756 6106
5757 6107 // Optional AJAX dependency, but won't run scripts if not present
5758 if ( jQuery._evalUrl ) {
5759 jQuery._evalUrl( node.src );
6108 if ( jQuery._evalUrl && !node.noModule ) {
6109 jQuery._evalUrl( node.src, {
6110 nonce: node.nonce || node.getAttribute( "nonce" )
6111 }, doc );
5760 6112 }
5761 6113 } else {
5762 DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node );
6114 DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );
5763 6115 }
5764 6116 }
5765 6117 }
@@ -5781,7 +6133,7 function remove( elem, selector, keepData ) {
5781 6133 }
5782 6134
5783 6135 if ( node.parentNode ) {
5784 if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
6136 if ( keepData && isAttached( node ) ) {
5785 6137 setGlobalEval( getAll( node, "script" ) );
5786 6138 }
5787 6139 node.parentNode.removeChild( node );
@@ -5793,13 +6145,13 function remove( elem, selector, keepData ) {
5793 6145
5794 6146 jQuery.extend( {
5795 6147 htmlPrefilter: function( html ) {
5796 return html.replace( rxhtmlTag, "<$1></$2>" );
6148 return html;
5797 6149 },
5798 6150
5799 6151 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5800 6152 var i, l, srcElements, destElements,
5801 6153 clone = elem.cloneNode( true ),
5802 inPage = jQuery.contains( elem.ownerDocument, elem );
6154 inPage = isAttached( elem );
5803 6155
5804 6156 // Fix IE cloning issues
5805 6157 if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
@@ -6055,6 +6407,27 var getStyles = function( elem ) {
6055 6407 return view.getComputedStyle( elem );
6056 6408 };
6057 6409
6410 var swap = function( elem, options, callback ) {
6411 var ret, name,
6412 old = {};
6413
6414 // Remember the old values, and insert the new ones
6415 for ( name in options ) {
6416 old[ name ] = elem.style[ name ];
6417 elem.style[ name ] = options[ name ];
6418 }
6419
6420 ret = callback.call( elem );
6421
6422 // Revert the old values
6423 for ( name in options ) {
6424 elem.style[ name ] = old[ name ];
6425 }
6426
6427 return ret;
6428 };
6429
6430
6058 6431 var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
6059 6432
6060 6433
@@ -6095,8 +6468,10 var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
6095 6468
6096 6469 // Support: IE 9 only
6097 6470 // Detect overflow:scroll screwiness (gh-3699)
6471 // Support: Chrome <=64
6472 // Don't get tricked when zoom affects offsetWidth (gh-4029)
6098 6473 div.style.position = "absolute";
6099 scrollboxSizeVal = div.offsetWidth === 36 || "absolute";
6474 scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;
6100 6475
6101 6476 documentElement.removeChild( container );
6102 6477
@@ -6110,7 +6485,7 var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
6110 6485 }
6111 6486
6112 6487 var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,
6113 reliableMarginLeftVal,
6488 reliableTrDimensionsVal, reliableMarginLeftVal,
6114 6489 container = document.createElement( "div" ),
6115 6490 div = document.createElement( "div" );
6116 6491
@@ -6145,6 +6520,54 var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
6145 6520 scrollboxSize: function() {
6146 6521 computeStyleTests();
6147 6522 return scrollboxSizeVal;
6523 },
6524
6525 // Support: IE 9 - 11+, Edge 15 - 18+
6526 // IE/Edge misreport `getComputedStyle` of table rows with width/height
6527 // set in CSS while `offset*` properties report correct values.
6528 // Behavior in IE 9 is more subtle than in newer versions & it passes
6529 // some versions of this test; make sure not to make it pass there!
6530 //
6531 // Support: Firefox 70+
6532 // Only Firefox includes border widths
6533 // in computed dimensions. (gh-4529)
6534 reliableTrDimensions: function() {
6535 var table, tr, trChild, trStyle;
6536 if ( reliableTrDimensionsVal == null ) {
6537 table = document.createElement( "table" );
6538 tr = document.createElement( "tr" );
6539 trChild = document.createElement( "div" );
6540
6541 table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate";
6542 tr.style.cssText = "border:1px solid";
6543
6544 // Support: Chrome 86+
6545 // Height set through cssText does not get applied.
6546 // Computed height then comes back as 0.
6547 tr.style.height = "1px";
6548 trChild.style.height = "9px";
6549
6550 // Support: Android 8 Chrome 86+
6551 // In our bodyBackground.html iframe,
6552 // display for all div elements is set to "inline",
6553 // which causes a problem only in Android 8 Chrome 86.
6554 // Ensuring the div is display: block
6555 // gets around this issue.
6556 trChild.style.display = "block";
6557
6558 documentElement
6559 .appendChild( table )
6560 .appendChild( tr )
6561 .appendChild( trChild );
6562
6563 trStyle = window.getComputedStyle( tr );
6564 reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) +
6565 parseInt( trStyle.borderTopWidth, 10 ) +
6566 parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight;
6567
6568 documentElement.removeChild( table );
6569 }
6570 return reliableTrDimensionsVal;
6148 6571 }
6149 6572 } );
6150 6573 } )();
@@ -6167,7 +6590,7 function curCSS( elem, name, computed ) {
6167 6590 if ( computed ) {
6168 6591 ret = computed.getPropertyValue( name ) || computed[ name ];
6169 6592
6170 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6593 if ( ret === "" && !isAttached( elem ) ) {
6171 6594 ret = jQuery.style( elem, name );
6172 6595 }
6173 6596
@@ -6223,30 +6646,13 function addGetHookIf( conditionFn, hookFn ) {
6223 6646 }
6224 6647
6225 6648
6226 var
6227
6228 // Swappable if display is none or starts with table
6229 // except "table", "table-cell", or "table-caption"
6230 // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6231 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6232 rcustomProp = /^--/,
6233 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6234 cssNormalTransform = {
6235 letterSpacing: "0",
6236 fontWeight: "400"
6237 },
6238
6239 cssPrefixes = [ "Webkit", "Moz", "ms" ],
6240 emptyStyle = document.createElement( "div" ).style;
6649 var cssPrefixes = [ "Webkit", "Moz", "ms" ],
6650 emptyStyle = document.createElement( "div" ).style,
6651 vendorProps = {};
6241 6652
6242 // Return a css property mapped to a potentially vendor prefixed property
6653 // Return a vendor-prefixed property or undefined
6243 6654 function vendorPropName( name ) {
6244 6655
6245 // Shortcut for names that are not vendor prefixed
6246 if ( name in emptyStyle ) {
6247 return name;
6248 }
6249
6250 6656 // Check for vendor prefixed names
6251 6657 var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
6252 6658 i = cssPrefixes.length;
@@ -6259,17 +6665,34 function vendorPropName( name ) {
6259 6665 }
6260 6666 }
6261 6667
6262 // Return a property mapped along what jQuery.cssProps suggests or to
6263 // a vendor prefixed property.
6668 // Return a potentially-mapped jQuery.cssProps or vendor prefixed property
6264 6669 function finalPropName( name ) {
6265 var ret = jQuery.cssProps[ name ];
6266 if ( !ret ) {
6267 ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;
6670 var final = jQuery.cssProps[ name ] || vendorProps[ name ];
6671
6672 if ( final ) {
6673 return final;
6268 6674 }
6269 return ret;
6675 if ( name in emptyStyle ) {
6676 return name;
6677 }
6678 return vendorProps[ name ] = vendorPropName( name ) || name;
6270 6679 }
6271 6680
6272 function setPositiveNumber( elem, value, subtract ) {
6681
6682 var
6683
6684 // Swappable if display is none or starts with table
6685 // except "table", "table-cell", or "table-caption"
6686 // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6687 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6688 rcustomProp = /^--/,
6689 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6690 cssNormalTransform = {
6691 letterSpacing: "0",
6692 fontWeight: "400"
6693 };
6694
6695 function setPositiveNumber( _elem, value, subtract ) {
6273 6696
6274 6697 // Any relative (+/-) values have already been
6275 6698 // normalized at this point
@@ -6340,7 +6763,10 function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computed
6340 6763 delta -
6341 6764 extra -
6342 6765 0.5
6343 ) );
6766
6767 // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter
6768 // Use an explicit zero to avoid NaN (gh-3964)
6769 ) ) || 0;
6344 6770 }
6345 6771
6346 6772 return delta;
@@ -6350,9 +6776,16 function getWidthOrHeight( elem, dimension, extra ) {
6350 6776
6351 6777 // Start with computed style
6352 6778 var styles = getStyles( elem ),
6779
6780 // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).
6781 // Fake content-box until we know it's needed to know the true value.
6782 boxSizingNeeded = !support.boxSizingReliable() || extra,
6783 isBorderBox = boxSizingNeeded &&
6784 jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6785 valueIsBorderBox = isBorderBox,
6786
6353 6787 val = curCSS( elem, dimension, styles ),
6354 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6355 valueIsBorderBox = isBorderBox;
6788 offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );
6356 6789
6357 6790 // Support: Firefox <=54
6358 6791 // Return a confounding non-pixel value or feign ignorance, as appropriate.
@@ -6363,22 +6796,38 function getWidthOrHeight( elem, dimension, extra ) {
6363 6796 val = "auto";
6364 6797 }
6365 6798
6366 // Check for style in case a browser which returns unreliable values
6367 // for getComputedStyle silently falls back to the reliable elem.style
6368 valueIsBorderBox = valueIsBorderBox &&
6369 ( support.boxSizingReliable() || val === elem.style[ dimension ] );
6799
6800 // Support: IE 9 - 11 only
6801 // Use offsetWidth/offsetHeight for when box sizing is unreliable.
6802 // In those cases, the computed value can be trusted to be border-box.
6803 if ( ( !support.boxSizingReliable() && isBorderBox ||
6804
6805 // Support: IE 10 - 11+, Edge 15 - 18+
6806 // IE/Edge misreport `getComputedStyle` of table rows with width/height
6807 // set in CSS while `offset*` properties report correct values.
6808 // Interestingly, in some cases IE 9 doesn't suffer from this issue.
6809 !support.reliableTrDimensions() && nodeName( elem, "tr" ) ||
6370 6810
6371 6811 // Fall back to offsetWidth/offsetHeight when value is "auto"
6372 6812 // This happens for inline elements with no explicit setting (gh-3571)
6813 val === "auto" ||
6814
6373 6815 // Support: Android <=4.1 - 4.3 only
6374 6816 // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
6375 if ( val === "auto" ||
6376 !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) {
6817 !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) &&
6377 6818
6378 val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ];
6819 // Make sure the element is visible & connected
6820 elem.getClientRects().length ) {
6379 6821
6380 // offsetWidth/offsetHeight provide border-box values
6381 valueIsBorderBox = true;
6822 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
6823
6824 // Where available, offsetWidth/offsetHeight approximate border box dimensions.
6825 // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the
6826 // retrieved value as a content box dimension.
6827 valueIsBorderBox = offsetProp in elem;
6828 if ( valueIsBorderBox ) {
6829 val = elem[ offsetProp ];
6830 }
6382 6831 }
6383 6832
6384 6833 // Normalize "" and auto
@@ -6424,6 +6873,13 jQuery.extend( {
6424 6873 "flexGrow": true,
6425 6874 "flexShrink": true,
6426 6875 "fontWeight": true,
6876 "gridArea": true,
6877 "gridColumn": true,
6878 "gridColumnEnd": true,
6879 "gridColumnStart": true,
6880 "gridRow": true,
6881 "gridRowEnd": true,
6882 "gridRowStart": true,
6427 6883 "lineHeight": true,
6428 6884 "opacity": true,
6429 6885 "order": true,
@@ -6479,7 +6935,9 jQuery.extend( {
6479 6935 }
6480 6936
6481 6937 // If a number was passed in, add the unit (except for certain CSS properties)
6482 if ( type === "number" ) {
6938 // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append
6939 // "px" to a few hardcoded values.
6940 if ( type === "number" && !isCustomProp ) {
6483 6941 value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
6484 6942 }
6485 6943
@@ -6553,7 +7011,7 jQuery.extend( {
6553 7011 }
6554 7012 } );
6555 7013
6556 jQuery.each( [ "height", "width" ], function( i, dimension ) {
7014 jQuery.each( [ "height", "width" ], function( _i, dimension ) {
6557 7015 jQuery.cssHooks[ dimension ] = {
6558 7016 get: function( elem, computed, extra ) {
6559 7017 if ( computed ) {
@@ -6579,18 +7037,29 jQuery.each( [ "height", "width" ], function( i, dimension ) {
6579 7037 set: function( elem, value, extra ) {
6580 7038 var matches,
6581 7039 styles = getStyles( elem ),
6582 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6583 subtract = extra && boxModelAdjustment(
7040
7041 // Only read styles.position if the test has a chance to fail
7042 // to avoid forcing a reflow.
7043 scrollboxSizeBuggy = !support.scrollboxSize() &&
7044 styles.position === "absolute",
7045
7046 // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)
7047 boxSizingNeeded = scrollboxSizeBuggy || extra,
7048 isBorderBox = boxSizingNeeded &&
7049 jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7050 subtract = extra ?
7051 boxModelAdjustment(
6584 7052 elem,
6585 7053 dimension,
6586 7054 extra,
6587 7055 isBorderBox,
6588 7056 styles
6589 );
7057 ) :
7058 0;
6590 7059
6591 7060 // Account for unreliable border-box dimensions by comparing offset* to computed and
6592 7061 // faking a content-box to get border and padding (gh-3699)
6593 if ( isBorderBox && support.scrollboxSize() === styles.position ) {
7062 if ( isBorderBox && scrollboxSizeBuggy ) {
6594 7063 subtract -= Math.ceil(
6595 7064 elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
6596 7065 parseFloat( styles[ dimension ] ) -
@@ -6758,9 +7227,9 Tween.propHooks = {
6758 7227 // Use .style if available and use plain properties where available.
6759 7228 if ( jQuery.fx.step[ tween.prop ] ) {
6760 7229 jQuery.fx.step[ tween.prop ]( tween );
6761 } else if ( tween.elem.nodeType === 1 &&
6762 ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
6763 jQuery.cssHooks[ tween.prop ] ) ) {
7230 } else if ( tween.elem.nodeType === 1 && (
7231 jQuery.cssHooks[ tween.prop ] ||
7232 tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {
6764 7233 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
6765 7234 } else {
6766 7235 tween.elem[ tween.prop ] = tween.now;
@@ -7297,6 +7766,7 jQuery.fn.extend( {
7297 7766 anim.stop( true );
7298 7767 }
7299 7768 };
7769
7300 7770 doAnimation.finish = doAnimation;
7301 7771
7302 7772 return empty || optall.queue === false ?
@@ -7315,7 +7785,7 jQuery.fn.extend( {
7315 7785 clearQueue = type;
7316 7786 type = undefined;
7317 7787 }
7318 if ( clearQueue && type !== false ) {
7788 if ( clearQueue ) {
7319 7789 this.queue( type || "fx", [] );
7320 7790 }
7321 7791
@@ -7398,7 +7868,7 jQuery.fn.extend( {
7398 7868 }
7399 7869 } );
7400 7870
7401 jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
7871 jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) {
7402 7872 var cssFn = jQuery.fn[ name ];
7403 7873 jQuery.fn[ name ] = function( speed, easing, callback ) {
7404 7874 return speed == null || typeof speed === "boolean" ?
@@ -7619,7 +8089,7 boolHook = {
7619 8089 }
7620 8090 };
7621 8091
7622 jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
8092 jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) {
7623 8093 var getter = attrHandle[ name ] || jQuery.find.attr;
7624 8094
7625 8095 attrHandle[ name ] = function( elem, name, isXML ) {
@@ -8243,7 +8713,7 jQuery.extend( jQuery.event, {
8243 8713 special.bindType || type;
8244 8714
8245 8715 // jQuery handler
8246 handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
8716 handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] &&
8247 8717 dataPriv.get( cur, "handle" );
8248 8718 if ( handle ) {
8249 8719 handle.apply( cur, data );
@@ -8354,7 +8824,10 if ( !support.focusin ) {
8354 8824
8355 8825 jQuery.event.special[ fix ] = {
8356 8826 setup: function() {
8357 var doc = this.ownerDocument || this,
8827
8828 // Handle: regular nodes (via `this.ownerDocument`), window
8829 // (via `this.document`) & document (via `this`).
8830 var doc = this.ownerDocument || this.document || this,
8358 8831 attaches = dataPriv.access( doc, fix );
8359 8832
8360 8833 if ( !attaches ) {
@@ -8363,7 +8836,7 if ( !support.focusin ) {
8363 8836 dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
8364 8837 },
8365 8838 teardown: function() {
8366 var doc = this.ownerDocument || this,
8839 var doc = this.ownerDocument || this.document || this,
8367 8840 attaches = dataPriv.access( doc, fix ) - 1;
8368 8841
8369 8842 if ( !attaches ) {
@@ -8379,7 +8852,7 if ( !support.focusin ) {
8379 8852 }
8380 8853 var location = window.location;
8381 8854
8382 var nonce = Date.now();
8855 var nonce = { guid: Date.now() };
8383 8856
8384 8857 var rquery = ( /\?/ );
8385 8858
@@ -8387,7 +8860,7 var rquery = ( /\?/ );
8387 8860
8388 8861 // Cross-browser xml parsing
8389 8862 jQuery.parseXML = function( data ) {
8390 var xml;
8863 var xml, parserErrorElem;
8391 8864 if ( !data || typeof data !== "string" ) {
8392 8865 return null;
8393 8866 }
@@ -8396,12 +8869,17 jQuery.parseXML = function( data ) {
8396 8869 // IE throws on parseFromString with invalid input.
8397 8870 try {
8398 8871 xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
8399 } catch ( e ) {
8400 xml = undefined;
8401 }
8872 } catch ( e ) {}
8402 8873
8403 if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
8404 jQuery.error( "Invalid XML: " + data );
8874 parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ];
8875 if ( !xml || parserErrorElem ) {
8876 jQuery.error( "Invalid XML: " + (
8877 parserErrorElem ?
8878 jQuery.map( parserErrorElem.childNodes, function( el ) {
8879 return el.textContent;
8880 } ).join( "\n" ) :
8881 data
8882 ) );
8405 8883 }
8406 8884 return xml;
8407 8885 };
@@ -8467,6 +8945,10 jQuery.param = function( a, traditional ) {
8467 8945 encodeURIComponent( value == null ? "" : value );
8468 8946 };
8469 8947
8948 if ( a == null ) {
8949 return "";
8950 }
8951
8470 8952 // If an array was passed in, assume that it is an array of form elements.
8471 8953 if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
8472 8954
@@ -8498,16 +8980,14 jQuery.fn.extend( {
8498 8980 // Can add propHook for "elements" to filter or add form elements
8499 8981 var elements = jQuery.prop( this, "elements" );
8500 8982 return elements ? jQuery.makeArray( elements ) : this;
8501 } )
8502 .filter( function() {
8983 } ).filter( function() {
8503 8984 var type = this.type;
8504 8985
8505 8986 // Use .is( ":disabled" ) so that fieldset[disabled] works
8506 8987 return this.name && !jQuery( this ).is( ":disabled" ) &&
8507 8988 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
8508 8989 ( this.checked || !rcheckableType.test( type ) );
8509 } )
8510 .map( function( i, elem ) {
8990 } ).map( function( _i, elem ) {
8511 8991 var val = jQuery( this ).val();
8512 8992
8513 8993 if ( val == null ) {
@@ -8560,6 +9040,7 var
8560 9040
8561 9041 // Anchor tag for parsing the document origin
8562 9042 originAnchor = document.createElement( "a" );
9043
8563 9044 originAnchor.href = location.href;
8564 9045
8565 9046 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
@@ -8969,12 +9450,14 jQuery.extend( {
8969 9450 if ( !responseHeaders ) {
8970 9451 responseHeaders = {};
8971 9452 while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
8972 responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
9453 responseHeaders[ match[ 1 ].toLowerCase() + " " ] =
9454 ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] )
9455 .concat( match[ 2 ] );
8973 9456 }
8974 9457 }
8975 match = responseHeaders[ key.toLowerCase() ];
9458 match = responseHeaders[ key.toLowerCase() + " " ];
8976 9459 }
8977 return match == null ? null : match;
9460 return match == null ? null : match.join( ", " );
8978 9461 },
8979 9462
8980 9463 // Raw string
@@ -9118,7 +9601,8 jQuery.extend( {
9118 9601 // Add or update anti-cache param if needed
9119 9602 if ( s.cache === false ) {
9120 9603 cacheURL = cacheURL.replace( rantiCache, "$1" );
9121 uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
9604 uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) +
9605 uncached;
9122 9606 }
9123 9607
9124 9608 // Put hash and anti-cache on the URL that will be requested (gh-1732)
@@ -9251,6 +9735,13 jQuery.extend( {
9251 9735 response = ajaxHandleResponses( s, jqXHR, responses );
9252 9736 }
9253 9737
9738 // Use a noop converter for missing script but not if jsonp
9739 if ( !isSuccess &&
9740 jQuery.inArray( "script", s.dataTypes ) > -1 &&
9741 jQuery.inArray( "json", s.dataTypes ) < 0 ) {
9742 s.converters[ "text script" ] = function() {};
9743 }
9744
9254 9745 // Convert no matter what (that way responseXXX fields are always set)
9255 9746 response = ajaxConvert( s, response, jqXHR, isSuccess );
9256 9747
@@ -9341,7 +9832,7 jQuery.extend( {
9341 9832 }
9342 9833 } );
9343 9834
9344 jQuery.each( [ "get", "post" ], function( i, method ) {
9835 jQuery.each( [ "get", "post" ], function( _i, method ) {
9345 9836 jQuery[ method ] = function( url, data, callback, type ) {
9346 9837
9347 9838 // Shift arguments if data argument was omitted
@@ -9362,8 +9853,17 jQuery.each( [ "get", "post" ], function( i, method ) {
9362 9853 };
9363 9854 } );
9364 9855
9856 jQuery.ajaxPrefilter( function( s ) {
9857 var i;
9858 for ( i in s.headers ) {
9859 if ( i.toLowerCase() === "content-type" ) {
9860 s.contentType = s.headers[ i ] || "";
9861 }
9862 }
9863 } );
9864
9365 9865
9366 jQuery._evalUrl = function( url ) {
9866 jQuery._evalUrl = function( url, options, doc ) {
9367 9867 return jQuery.ajax( {
9368 9868 url: url,
9369 9869
@@ -9373,7 +9873,16 jQuery._evalUrl = function( url ) {
9373 9873 cache: true,
9374 9874 async: false,
9375 9875 global: false,
9376 "throws": true
9876
9877 // Only evaluate the response if it is successful (gh-4126)
9878 // dataFilter is not invoked for failure responses, so using it instead
9879 // of the default converter is kludgy but it works.
9880 converters: {
9881 "text script": function() {}
9882 },
9883 dataFilter: function( response ) {
9884 jQuery.globalEval( response, options, doc );
9885 }
9377 9886 } );
9378 9887 };
9379 9888
@@ -9656,24 +10165,21 jQuery.ajaxPrefilter( "script", function( s ) {
9656 10165 // Bind script tag hack transport
9657 10166 jQuery.ajaxTransport( "script", function( s ) {
9658 10167
9659 // This transport only deals with cross domain requests
9660 if ( s.crossDomain ) {
10168 // This transport only deals with cross domain or forced-by-attrs requests
10169 if ( s.crossDomain || s.scriptAttrs ) {
9661 10170 var script, callback;
9662 10171 return {
9663 10172 send: function( _, complete ) {
9664 script = jQuery( "<script>" ).prop( {
9665 charset: s.scriptCharset,
9666 src: s.url
9667 } ).on(
9668 "load error",
9669 callback = function( evt ) {
10173 script = jQuery( "<script>" )
10174 .attr( s.scriptAttrs || {} )
10175 .prop( { charset: s.scriptCharset, src: s.url } )
10176 .on( "load error", callback = function( evt ) {
9670 10177 script.remove();
9671 10178 callback = null;
9672 10179 if ( evt ) {
9673 10180 complete( evt.type === "error" ? 404 : 200, evt.type );
9674 10181 }
9675 }
9676 );
10182 } );
9677 10183
9678 10184 // Use native DOM manipulation to avoid our domManip AJAX trickery
9679 10185 document.head.appendChild( script[ 0 ] );
@@ -9697,7 +10203,7 var oldCallbacks = [],
9697 10203 jQuery.ajaxSetup( {
9698 10204 jsonp: "callback",
9699 10205 jsonpCallback: function() {
9700 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
10206 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) );
9701 10207 this[ callback ] = true;
9702 10208 return callback;
9703 10209 }
@@ -9914,23 +10420,6 jQuery.fn.load = function( url, params, callback ) {
9914 10420
9915 10421
9916 10422
9917 // Attach a bunch of functions for handling common AJAX events
9918 jQuery.each( [
9919 "ajaxStart",
9920 "ajaxStop",
9921 "ajaxComplete",
9922 "ajaxError",
9923 "ajaxSuccess",
9924 "ajaxSend"
9925 ], function( i, type ) {
9926 jQuery.fn[ type ] = function( fn ) {
9927 return this.on( type, fn );
9928 };
9929 } );
9930
9931
9932
9933
9934 10423 jQuery.expr.pseudos.animated = function( elem ) {
9935 10424 return jQuery.grep( jQuery.timers, function( fn ) {
9936 10425 return elem === fn.elem;
@@ -10137,7 +10626,7 jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function(
10137 10626 // Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
10138 10627 // getComputedStyle returns percent when specified for top/left/bottom/right;
10139 10628 // rather than make the css module depend on the offset module, just check for it here
10140 jQuery.each( [ "top", "left" ], function( i, prop ) {
10629 jQuery.each( [ "top", "left" ], function( _i, prop ) {
10141 10630 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
10142 10631 function( elem, computed ) {
10143 10632 if ( computed ) {
@@ -10155,8 +10644,11 jQuery.each( [ "top", "left" ], function( i, prop ) {
10155 10644
10156 10645 // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10157 10646 jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10158 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
10159 function( defaultExtra, funcName ) {
10647 jQuery.each( {
10648 padding: "inner" + name,
10649 content: type,
10650 "": "outer" + name
10651 }, function( defaultExtra, funcName ) {
10160 10652
10161 10653 // Margin is only for outerHeight, outerWidth
10162 10654 jQuery.fn[ funcName ] = function( margin, value ) {
@@ -10200,25 +10692,19 jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10200 10692 } );
10201 10693
10202 10694
10203 jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
10204 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
10205 "change select submit keydown keypress keyup contextmenu" ).split( " " ),
10206 function( i, name ) {
10207
10208 // Handle event binding
10209 jQuery.fn[ name ] = function( data, fn ) {
10210 return arguments.length > 0 ?
10211 this.on( name, null, data, fn ) :
10212 this.trigger( name );
10695 jQuery.each( [
10696 "ajaxStart",
10697 "ajaxStop",
10698 "ajaxComplete",
10699 "ajaxError",
10700 "ajaxSuccess",
10701 "ajaxSend"
10702 ], function( _i, type ) {
10703 jQuery.fn[ type ] = function( fn ) {
10704 return this.on( type, fn );
10213 10705 };
10214 10706 } );
10215 10707
10216 jQuery.fn.extend( {
10217 hover: function( fnOver, fnOut ) {
10218 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
10219 }
10220 } );
10221
10222 10708
10223 10709
10224 10710
@@ -10240,9 +10726,35 jQuery.fn.extend( {
10240 10726 return arguments.length === 1 ?
10241 10727 this.off( selector, "**" ) :
10242 10728 this.off( types, selector || "**", fn );
10729 },
10730
10731 hover: function( fnOver, fnOut ) {
10732 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
10243 10733 }
10244 10734 } );
10245 10735
10736 jQuery.each(
10737 ( "blur focus focusin focusout resize scroll click dblclick " +
10738 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
10739 "change select submit keydown keypress keyup contextmenu" ).split( " " ),
10740 function( _i, name ) {
10741
10742 // Handle event binding
10743 jQuery.fn[ name ] = function( data, fn ) {
10744 return arguments.length > 0 ?
10745 this.on( name, null, data, fn ) :
10746 this.trigger( name );
10747 };
10748 }
10749 );
10750
10751
10752
10753
10754 // Support: Android <=4.0 only
10755 // Make sure we trim BOM and NBSP
10756 var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
10757
10246 10758 // Bind a function to a context, optionally partially applying any
10247 10759 // arguments.
10248 10760 // jQuery.proxy is deprecated to promote standards (specifically Function#bind)
@@ -10305,6 +10817,11 jQuery.isNumeric = function( obj ) {
10305 10817 !isNaN( obj - parseFloat( obj ) );
10306 10818 };
10307 10819
10820 jQuery.trim = function( text ) {
10821 return text == null ?
10822 "" :
10823 ( text + "" ).replace( rtrim, "" );
10824 };
10308 10825
10309 10826
10310 10827
@@ -10353,7 +10870,7 jQuery.noConflict = function( deep ) {
10353 10870 // Expose jQuery and $ identifiers, even in AMD
10354 10871 // (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
10355 10872 // and CommonJS for browser emulators (#13566)
10356 if ( !noGlobal ) {
10873 if ( typeof noGlobal === "undefined" ) {
10357 10874 window.jQuery = window.$ = jQuery;
10358 10875 }
10359 10876
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,6 +1,6
1 1 The MIT License (MIT)
2 2
3 Copyright (c) 2012-2015 Kevin Brown, Igor Vaynberg, and Select2 contributors
3 Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors
4 4
5 5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 6 of this software and associated documentation files (the "Software"), to deal
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now