##// 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 }
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
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
13 #ports:
14 # - 8030:8030
15 env_file: .env
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
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 RUN mkdir -p "$PGDATA" && chmod 700 "$PGDATA" No newline at end of file
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
@@ -30,17 +35,18
30 35 }
31 36
32 37 #changelist-form .results {
33 overflow-x: auto;
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 box-sizing: border-box;
61 }
62
63 .login span.help {
64 font-size: 10px;
65 display: block;
50 box-sizing: border-box;
66 51 }
67 52
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,64 +1,50
1 (function($) {
2 'use strict';
3 var SelectBox = {
1 'use strict';
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 break; // Once the first token isn't found we're done
38 break; // Once the first token isn't found we're done
52 39 }
53 40 }
54 41 }
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 if (a > b) {
122 return 1;
123 }
124 if (a < b) {
125 return -1;
126 }
95 if (a > b) {
96 return 1;
127 97 }
128 catch (e) {
129 // silently fail on IE 'unknown' exception
98 if (a < b) {
99 return -1;
130 100 }
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 '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
7 'use strict';
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 // 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 }
160 // Temporarily add the required attribute and check validity.
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 '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) {
34 if (checked) {
35 showQuestion();
36 } else {
37 reset();
38 }
39 $(actionCheckboxes).prop("checked", checked)
40 .parent().parent().toggleClass(options.selectedClass, checked);
41 },
42 updateCounter = function() {
43 var sel = $(actionCheckboxes).filter(":checked").length;
44 // data-actions-icnt is defined in the generated HTML
45 // and contains the total amount of objects in the queryset
46 var actions_icnt = $('.action-counter').data('actionsIcnt');
47 $(options.counterContainer).html(interpolate(
2 'use strict';
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) {
47 if (checked) {
48 showQuestion(options);
49 } else {
50 reset(options);
51 }
52 actionCheckboxes.forEach(function(el) {
53 el.checked = checked;
54 el.closest('tr').classList.toggle(options.selectedClass, checked);
55 });
56 }
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);
63 // data-actions-icnt is defined in the generated HTML
64 // and contains the total amount of objects in the queryset
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();
57 } else {
58 value = false;
59 clearAcross();
60 }
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 }
73 });
74 $(options.allToggle).show().on('click', function() {
75 checker($(this).prop("checked"));
76 updateCounter();
70 }, true);
71 const allToggle = document.getElementById(options.allToggleId);
72 allToggle.checked = sel === actionCheckboxes.length;
73 if (allToggle.checked) {
74 showQuestion(options);
75 } else {
76 clearAcross(options);
77 }
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;
77 99 });
78 $("a", options.acrossQuestions).on('click', function(event) {
79 event.preventDefault();
80 $(options.acrossInput).val(1);
81 showClear();
100
101 document.addEventListener('keyup', (event) => {
102 shiftPressed = event.shiftKey;
82 103 });
83 $("a", options.acrossClears).on('click', function(event) {
84 event.preventDefault();
85 $(options.allToggle).prop("checked", false);
86 clearAcross();
87 checker(0);
88 updateCounter();
104
105 document.getElementById(options.allToggleId).addEventListener('click', function(event) {
106 checker(actionCheckboxes, options, this.checked);
107 updateCounter(actionCheckboxes, options);
89 108 });
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 }
109
110 document.querySelectorAll(options.acrossQuestions + " a").forEach(function(el) {
111 el.addEventListener('click', function(event) {
112 event.preventDefault();
113 const acrossInputs = document.querySelectorAll(options.acrossInput);
114 acrossInputs.forEach(function(acrossInput) {
115 acrossInput.value = 1;
106 116 });
107 }
108 $(target).parent().parent().toggleClass(options.selectedClass, target.checked);
109 lastChecked = target;
110 updateCounter();
117 showClear(options);
118 });
111 119 });
112 $('form#changelist-form table#result_list tr').on('change', 'td:gt(0) :input', function() {
113 list_editable_changed = true;
120
121 document.querySelectorAll(options.acrossClears + " a").forEach(function(el) {
122 el.addEventListener('click', function(event) {
123 event.preventDefault();
124 document.getElementById(options.allToggleId).checked = false;
125 clearAcross(options);
126 checker(actionCheckboxes, options, false);
127 updateCounter(actionCheckboxes, options);
128 });
114 129 });
115 $('form#changelist-form button[name="index"]').on('click', function(event) {
116 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."));
130
131 function affectedCheckboxes(target, withModifier) {
132 const multiSelect = (lastChecked && withModifier && lastChecked !== target);
133 if (!multiSelect) {
134 return [target];
118 135 }
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;
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 {
154 list_editable_changed = true;
125 155 }
126 156 });
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."));
157 });
158
159 document.querySelector('#changelist-form button[name=index]').addEventListener('click', function(event) {
160 if (list_editable_changed) {
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();
132 164 }
133 165 }
134 166 });
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();
178 }
179 }
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 'use strict';
7 var DateTimeShortcuts = {
5 'use strict';
6 {
7 const DateTimeShortcuts = {
8 8 calendars: [],
9 9 calendarInputs: [],
10 10 clockInputs: [],
@@ -20,29 +20,26
20 20 dismissClockFunc: [],
21 21 dismissCalendarFunc: [],
22 22 calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
23 calendarDivName2: 'calendarin', // name of <div> that contains calendar
24 calendarLinkName: 'calendarlink',// name of the link that is used to toggle
25 clockDivName: 'clockbox', // name of clock <div> that gets toggled
26 clockLinkName: 'clocklink', // name of the link that is used to toggle
23 calendarDivName2: 'calendarin', // name of <div> that contains calendar
24 calendarLinkName: 'calendarlink', // name of the link that is used to toggle
25 clockDivName: 'clockbox', // name of clock <div> that gets toggled
26 clockLinkName: 'clocklink', // name of the link that is used to toggle
27 27 shortCutsClass: 'datetimeshortcuts', // class of the clock and cal shortcuts
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 '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 }
4 27
5 (function($) {
6 'use strict';
7
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 'use strict';
3 var init = function($element, options) {
4 var settings = $.extend({
5 ajax: {
6 data: function(params) {
7 return {
8 term: params.term,
9 page: params.page
10 };
11 }
12 }
13 }, options);
14 $element.select2(settings);
15 };
1 'use strict';
2 {
3 const $ = django.jQuery;
16 4
17 $.fn.djangoAdminSelect2 = function(options) {
18 var settings = $.extend({}, options);
5 $.fn.djangoAdminSelect2 = function() {
19 6 $.each(this, function(i, element) {
20 var $element = $(element);
21 init($element, settings);
7 $(element).select2({
8 ajax: {
9 data: (params) => {
10 return {
11 term: params.term,
12 page: params.page,
13 app_label: element.dataset.appLabel,
14 model_name: element.dataset.modelName,
15 field_name: element.dataset.fieldName
16 };
17 }
18 }
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 'use strict';
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 '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.
1 'use strict';
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();
9 } else {
10 document.addEventListener('DOMContentLoaded', fn);
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.
8 20 } else {
9 window.close(); // Otherwise, close the popup.
21 window.history.back(); // Otherwise, go back.
10 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 '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);
1 'use strict';
2 {
3 const inputTags = ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA'];
4 const modelName = document.getElementById('django-admin-form-add-constants').dataset.modelName;
5 if (modelName) {
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 13 }
14 });
15
16 if (modelName) {
17 $('form#' + modelName + '_form :input:visible:enabled:first').focus();
18 14 }
19 });
20 })(django.jQuery);
15 }
16 }
@@ -1,52 +1,43
1 1 /*global gettext*/
2 (function() {
3 '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
2 'use strict';
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) {
36 ev.preventDefault();
37 var fieldset = closestElem(this, 'fieldset');
38 if (fieldset.classList.contains('collapsed')) {
39 // Show
40 this.textContent = gettext('Hide');
41 fieldset.classList.remove('collapsed');
42 } else {
43 // Hide
44 this.textContent = gettext('Show');
45 fieldset.classList.add('collapsed');
22 // Add toggle to hide/show anchor tag
23 const toggleFunc = function(ev) {
24 if (ev.target.matches('.collapse-toggle')) {
25 ev.preventDefault();
26 ev.stopPropagation();
27 const fieldset = ev.target.closest('fieldset');
28 if (fieldset.classList.contains('collapsed')) {
29 // Show
30 ev.target.textContent = gettext('Hide');
31 fieldset.classList.remove('collapsed');
32 } else {
33 // Hide
34 ev.target.textContent = gettext('Show');
35 fieldset.classList.add('collapsed');
36 }
46 37 }
47 38 };
48 for (i = 0; i < toggles.length; i++) {
49 toggles[i].addEventListener('click', toggleFunc);
50 }
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)];
@@ -153,36 +130,35 function findPosY(obj) {
153 130 return result;
154 131 };
155 132
156 // ----------------------------------------------------------------------------
157 // String object extensions
158 // ----------------------------------------------------------------------------
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
133 // ----------------------------------------------------------------------------
134 // String object extensions
135 // ----------------------------------------------------------------------------
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 case "%d":
175 day = date[i];
176 break;
177 case "%m":
178 month = date[i] - 1;
179 break;
180 case "%Y":
143 case "%d":
144 day = date[i];
145 break;
146 case "%m":
147 month = date[i] - 1;
148 break;
149 case "%Y":
150 year = date[i];
151 break;
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) {
181 157 year = date[i];
182 break;
183 case "%y":
184 year = date[i];
185 break;
158 } else {
159 year = (new Date(Date.UTC(date[i], 0))).getUTCFullYear() + 100;
160 }
161 break;
186 162 }
187 163 ++i;
188 164 }
@@ -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 'use strict';
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,102 +58,163
58 58 addButton = $this.filter(":last").next().find("a");
59 59 }
60 60 }
61 addButton.on('click', function(e) {
62 e.preventDefault();
63 var template = $("#" + options.prefix + "-empty");
64 var row = template.clone(true);
65 row.removeClass(options.emptyCssClass)
61 addButton.on('click', addInlineClickHandler);
62 };
63
64 const addInlineClickHandler = function(e) {
65 e.preventDefault();
66 const template = $("#" + options.prefix + "-empty");
67 const row = template.clone(true);
68 row.removeClass(options.emptyCssClass)
66 69 .addClass(options.formCssClass)
67 70 .attr("id", options.prefix + "-" + nextIndex);
68 if (row.is("tr")) {
69 // If the forms are laid out in table rows, insert
70 // the remove button into the last table cell:
71 row.children(":last").append('<div><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></div>");
72 } else if (row.is("ul") || row.is("ol")) {
73 // If they're laid out as an ordered/unordered list,
74 // insert an <li> after the last list item:
75 row.append('<li><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></li>");
76 } else {
77 // Otherwise, just insert the remove button as the
78 // last child element of the form's container:
79 row.children(":first").append('<span><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></span>");
80 }
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();
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
92 95 }
93 // The delete button of each row triggers a bunch of other things
94 row.find("a." + options.deleteCssClass).on('click', function(e1) {
95 e1.preventDefault();
96 // Remove the parent form containing this button:
97 row.remove();
98 nextIndex -= 1;
99 // If a post-delete callback was provided, call it with the deleted form:
100 if (options.removed) {
101 options.removed(row);
102 }
103 $(document).trigger('formset:removed', [row, options.prefix]);
104 // Update the TOTAL_FORMS form count.
105 var forms = $("." + options.formCssClass);
106 $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
107 // Show add button again once we drop below max
108 if ((maxForms.val() === '') || (maxForms.val() - forms.length) > 0) {
109 addButton.parent().show();
110 }
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() {
115 updateElementIndex(this, options.prefix, i);
116 };
117 for (i = 0, formCount = forms.length; i < formCount; i++) {
118 updateElementIndex($(forms).get(i), options.prefix, i);
119 $(forms.get(i)).find("*").each(updateElementCallback);
120 }
121 });
122 // If a post-add callback was supplied, call it with the added form:
123 if (options.added) {
124 options.added(row);
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) {
104 if (row.is("tr")) {
105 // If the forms are laid out in table rows, insert
106 // the remove button into the last table cell:
107 row.children(":last").append('<div><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></div>");
108 } else if (row.is("ul") || row.is("ol")) {
109 // If they're laid out as an ordered/unordered list,
110 // insert an <li> after the last list item:
111 row.append('<li><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></li>");
112 } else {
113 // Otherwise, just insert the remove button as the
114 // last child element of the form's container:
115 row.children(":first").append('<span><a class="' + options.deleteCssClass + '" href="#">' + options.deleteText + "</a></span>");
116 }
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) {
122 e1.preventDefault();
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 }
132 row.remove();
133 nextIndex -= 1;
134 // Pass the deleted form to the post-delete callback, if provided.
135 if (options.removed) {
136 options.removed(row);
137 }
138 document.dispatchEvent(new CustomEvent("formset:removed", {
139 detail: {
140 formsetName: options.prefix
125 141 }
126 $(document).trigger('formset:added', [row, options.prefix]);
127 });
142 }));
143 // Update the TOTAL_FORMS form count.
144 const forms = $("." + options.formCssClass);
145 $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
146 // Show add button again once below maximum number.
147 if ((maxForms.val() === '') || (maxForms.val() - forms.length) > 0) {
148 addButton.parent().show();
149 }
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() {
156 updateElementIndex(this, options.prefix, i);
157 };
158 for (i = 0, formCount = forms.length; i < formCount; i++) {
159 updateElementIndex($(forms).get(i), options.prefix, i);
160 $(forms.get(i)).find("*").each(updateElementCallback);
161 }
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();
169 }
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));
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
132 198 /* Setup plugin defaults */
133 199 $.fn.formset.defaults = {
134 prefix: "form", // The form prefix for your django formset
135 addText: "add another", // Text for the add link
136 deleteText: "remove", // Text for the delete link
137 addCssClass: "add-row", // CSS class applied to the add link
138 deleteCssClass: "delete-row", // CSS class applied to the delete link
139 emptyCssClass: "empty-row", // CSS class applied to the empty row
140 formCssClass: "dynamic-form", // CSS class applied to each form in a formset
141 added: null, // Function called each time a new form is added
142 removed: null, // Function called each time a form is deleted
143 addButton: null // Existing add button to use
200 prefix: "form", // The form prefix for your django formset
201 addText: "add another", // Text for the add link
202 deleteText: "remove", // Text for the delete link
203 addCssClass: "add-row", // CSS class applied to the add link
204 deleteCssClass: "delete-row", // CSS class applied to the delete link
205 emptyCssClass: "empty-row", // CSS class applied to the empty row
206 formCssClass: "dynamic-form", // CSS class applied to each form in a formset
207 added: null, // Function called each time a new form is added
208 removed: null, // Function called each time a form is deleted
209 addButton: null // Existing add button to use
144 210 };
145 211
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 'use strict';
4 var initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
2 'use strict';
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 'use strict';
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 'use strict';
3 var fields = $('#django-admin-prepopulated-fields-constants').data('prepopulatedFields');
1 'use strict';
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 'use strict';
4
5 var LATIN_MAP = {
2 'use strict';
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 if (Downcoder.map) { // already made
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);
147 }
134 for (const lookup of ALL_DOWNCODE_MAPS) {
135 Object.assign(Downcoder.map, lookup);
148 136 }
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,36 +148,23
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
183 158 // characters, whitespace, and dash; remove other characters.
184 159 s = XRegExp.replace(s, XRegExp('[^-_\\p{L}\\p{N}\\s]', 'g'), '');
185 160 } else {
186 s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
161 s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
187 162 }
188 s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
189 s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
190 s = s.substring(0, num_chars); // trim to first num_chars chars
191 s = s.replace(/-+$/g, ''); // trim any trailing hyphens
192 return s.toLowerCase(); // convert to lowercase
163 s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
164 s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
165 s = s.substring(0, num_chars); // trim to first num_chars chars
166 s = s.replace(/-+$/g, ''); // trim any trailing hyphens
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
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: 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