| '+a.addText+"");k=l.find("tr:last a")}else e.filter(":last").after('"),
6 | k=e.filter(":last").next().find("a");k.on("click",t)})();c=""===h.val()||0 tr.form-row",b(c).tabularFormset(c,a.options)}})})};
12 |
--------------------------------------------------------------------------------
/static/admin/js/core.js:
--------------------------------------------------------------------------------
1 | // Core javascript helper functions
2 | 'use strict';
3 |
4 | // quickElement(tagType, parentReference [, textInChildNode, attribute, attributeValue ...]);
5 | function quickElement() {
6 | const obj = document.createElement(arguments[0]);
7 | if (arguments[2]) {
8 | const textNode = document.createTextNode(arguments[2]);
9 | obj.appendChild(textNode);
10 | }
11 | const len = arguments.length;
12 | for (let i = 3; i < len; i += 2) {
13 | obj.setAttribute(arguments[i], arguments[i + 1]);
14 | }
15 | arguments[1].appendChild(obj);
16 | return obj;
17 | }
18 |
19 | // "a" is reference to an object
20 | function removeChildren(a) {
21 | while (a.hasChildNodes()) {
22 | a.removeChild(a.lastChild);
23 | }
24 | }
25 |
26 | // ----------------------------------------------------------------------------
27 | // Find-position functions by PPK
28 | // See https://www.quirksmode.org/js/findpos.html
29 | // ----------------------------------------------------------------------------
30 | function findPosX(obj) {
31 | let curleft = 0;
32 | if (obj.offsetParent) {
33 | while (obj.offsetParent) {
34 | curleft += obj.offsetLeft - obj.scrollLeft;
35 | obj = obj.offsetParent;
36 | }
37 | } else if (obj.x) {
38 | curleft += obj.x;
39 | }
40 | return curleft;
41 | }
42 |
43 | function findPosY(obj) {
44 | let curtop = 0;
45 | if (obj.offsetParent) {
46 | while (obj.offsetParent) {
47 | curtop += obj.offsetTop - obj.scrollTop;
48 | obj = obj.offsetParent;
49 | }
50 | } else if (obj.y) {
51 | curtop += obj.y;
52 | }
53 | return curtop;
54 | }
55 |
56 | //-----------------------------------------------------------------------------
57 | // Date object extensions
58 | // ----------------------------------------------------------------------------
59 | {
60 | Date.prototype.getTwelveHours = function() {
61 | return this.getHours() % 12 || 12;
62 | };
63 |
64 | Date.prototype.getTwoDigitMonth = function() {
65 | return (this.getMonth() < 9) ? '0' + (this.getMonth() + 1) : (this.getMonth() + 1);
66 | };
67 |
68 | Date.prototype.getTwoDigitDate = function() {
69 | return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate();
70 | };
71 |
72 | Date.prototype.getTwoDigitTwelveHour = function() {
73 | return (this.getTwelveHours() < 10) ? '0' + this.getTwelveHours() : this.getTwelveHours();
74 | };
75 |
76 | Date.prototype.getTwoDigitHour = function() {
77 | return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours();
78 | };
79 |
80 | Date.prototype.getTwoDigitMinute = function() {
81 | return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes();
82 | };
83 |
84 | Date.prototype.getTwoDigitSecond = function() {
85 | return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds();
86 | };
87 |
88 | Date.prototype.getFullMonthName = function() {
89 | return typeof window.CalendarNamespace === "undefined"
90 | ? this.getTwoDigitMonth()
91 | : window.CalendarNamespace.monthsOfYear[this.getMonth()];
92 | };
93 |
94 | Date.prototype.strftime = function(format) {
95 | const fields = {
96 | B: this.getFullMonthName(),
97 | c: this.toString(),
98 | d: this.getTwoDigitDate(),
99 | H: this.getTwoDigitHour(),
100 | I: this.getTwoDigitTwelveHour(),
101 | m: this.getTwoDigitMonth(),
102 | M: this.getTwoDigitMinute(),
103 | p: (this.getHours() >= 12) ? 'PM' : 'AM',
104 | S: this.getTwoDigitSecond(),
105 | w: '0' + this.getDay(),
106 | x: this.toLocaleDateString(),
107 | X: this.toLocaleTimeString(),
108 | y: ('' + this.getFullYear()).substr(2, 4),
109 | Y: '' + this.getFullYear(),
110 | '%': '%'
111 | };
112 | let result = '', i = 0;
113 | while (i < format.length) {
114 | if (format.charAt(i) === '%') {
115 | result = result + fields[format.charAt(i + 1)];
116 | ++i;
117 | }
118 | else {
119 | result = result + format.charAt(i);
120 | }
121 | ++i;
122 | }
123 | return result;
124 | };
125 |
126 | // ----------------------------------------------------------------------------
127 | // String object extensions
128 | // ----------------------------------------------------------------------------
129 | String.prototype.strptime = function(format) {
130 | const split_format = format.split(/[.\-/]/);
131 | const date = this.split(/[.\-/]/);
132 | let i = 0;
133 | let day, month, year;
134 | while (i < split_format.length) {
135 | switch (split_format[i]) {
136 | case "%d":
137 | day = date[i];
138 | break;
139 | case "%m":
140 | month = date[i] - 1;
141 | break;
142 | case "%Y":
143 | year = date[i];
144 | break;
145 | case "%y":
146 | // A %y value in the range of [00, 68] is in the current
147 | // century, while [69, 99] is in the previous century,
148 | // according to the Open Group Specification.
149 | if (parseInt(date[i], 10) >= 69) {
150 | year = date[i];
151 | } else {
152 | year = (new Date(Date.UTC(date[i], 0))).getUTCFullYear() + 100;
153 | }
154 | break;
155 | }
156 | ++i;
157 | }
158 | // Create Date object from UTC since the parsed value is supposed to be
159 | // in UTC, not local time. Also, the calendar uses UTC functions for
160 | // date extraction.
161 | return new Date(Date.UTC(year, month, day));
162 | };
163 | }
164 |
--------------------------------------------------------------------------------
/static/admin/js/admin/RelatedObjectLookups.js:
--------------------------------------------------------------------------------
1 | /*global SelectBox, interpolate*/
2 | // Handles related-objects functionality: lookup link for raw_id_fields
3 | // and Add Another links.
4 | 'use strict';
5 | {
6 | const $ = django.jQuery;
7 |
8 | function showAdminPopup(triggeringLink, name_regexp, add_popup) {
9 | const name = triggeringLink.id.replace(name_regexp, '');
10 | let href = triggeringLink.href;
11 | if (add_popup) {
12 | if (href.indexOf('?') === -1) {
13 | href += '?_popup=1';
14 | } else {
15 | href += '&_popup=1';
16 | }
17 | }
18 | const win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
19 | win.focus();
20 | return false;
21 | }
22 |
23 | function showRelatedObjectLookupPopup(triggeringLink) {
24 | return showAdminPopup(triggeringLink, /^lookup_/, true);
25 | }
26 |
27 | function dismissRelatedLookupPopup(win, chosenId) {
28 | const name = win.name;
29 | const elem = document.getElementById(name);
30 | if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) {
31 | elem.value += ',' + chosenId;
32 | } else {
33 | document.getElementById(name).value = chosenId;
34 | }
35 | win.close();
36 | }
37 |
38 | function showRelatedObjectPopup(triggeringLink) {
39 | return showAdminPopup(triggeringLink, /^(change|add|delete)_/, false);
40 | }
41 |
42 | function updateRelatedObjectLinks(triggeringLink) {
43 | const $this = $(triggeringLink);
44 | const siblings = $this.nextAll('.view-related, .change-related, .delete-related');
45 | if (!siblings.length) {
46 | return;
47 | }
48 | const value = $this.val();
49 | if (value) {
50 | siblings.each(function() {
51 | const elm = $(this);
52 | elm.attr('href', elm.attr('data-href-template').replace('__fk__', value));
53 | });
54 | } else {
55 | siblings.removeAttr('href');
56 | }
57 | }
58 |
59 | function dismissAddRelatedObjectPopup(win, newId, newRepr) {
60 | const name = win.name;
61 | const elem = document.getElementById(name);
62 | if (elem) {
63 | const elemName = elem.nodeName.toUpperCase();
64 | if (elemName === 'SELECT') {
65 | elem.options[elem.options.length] = new Option(newRepr, newId, true, true);
66 | } else if (elemName === 'INPUT') {
67 | if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) {
68 | elem.value += ',' + newId;
69 | } else {
70 | elem.value = newId;
71 | }
72 | }
73 | // Trigger a change event to update related links if required.
74 | $(elem).trigger('change');
75 | } else {
76 | const toId = name + "_to";
77 | const o = new Option(newRepr, newId);
78 | SelectBox.add_to_cache(toId, o);
79 | SelectBox.redisplay(toId);
80 | }
81 | win.close();
82 | }
83 |
84 | function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) {
85 | const id = win.name.replace(/^edit_/, '');
86 | const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
87 | const selects = $(selectsSelector);
88 | selects.find('option').each(function() {
89 | if (this.value === objId) {
90 | this.textContent = newRepr;
91 | this.value = newId;
92 | }
93 | });
94 | selects.next().find('.select2-selection__rendered').each(function() {
95 | // The element can have a clear button as a child.
96 | // Use the lastChild to modify only the displayed value.
97 | this.lastChild.textContent = newRepr;
98 | this.title = newRepr;
99 | });
100 | win.close();
101 | }
102 |
103 | function dismissDeleteRelatedObjectPopup(win, objId) {
104 | const id = win.name.replace(/^delete_/, '');
105 | const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]);
106 | const selects = $(selectsSelector);
107 | selects.find('option').each(function() {
108 | if (this.value === objId) {
109 | $(this).remove();
110 | }
111 | }).trigger('change');
112 | win.close();
113 | }
114 |
115 | window.showRelatedObjectLookupPopup = showRelatedObjectLookupPopup;
116 | window.dismissRelatedLookupPopup = dismissRelatedLookupPopup;
117 | window.showRelatedObjectPopup = showRelatedObjectPopup;
118 | window.updateRelatedObjectLinks = updateRelatedObjectLinks;
119 | window.dismissAddRelatedObjectPopup = dismissAddRelatedObjectPopup;
120 | window.dismissChangeRelatedObjectPopup = dismissChangeRelatedObjectPopup;
121 | window.dismissDeleteRelatedObjectPopup = dismissDeleteRelatedObjectPopup;
122 |
123 | // Kept for backward compatibility
124 | window.showAddAnotherPopup = showRelatedObjectPopup;
125 | window.dismissAddAnotherPopup = dismissAddRelatedObjectPopup;
126 |
127 | $(document).ready(function() {
128 | $("a[data-popup-opener]").on('click', function(event) {
129 | event.preventDefault();
130 | opener.dismissRelatedLookupPopup(window, $(this).data("popup-opener"));
131 | });
132 | $('body').on('click', '.related-widget-wrapper-link', function(e) {
133 | e.preventDefault();
134 | if (this.href) {
135 | const event = $.Event('django:show-related', {href: this.href});
136 | $(this).trigger(event);
137 | if (!event.isDefaultPrevented()) {
138 | showRelatedObjectPopup(this);
139 | }
140 | }
141 | });
142 | $('body').on('change', '.related-widget-wrapper select', function(e) {
143 | const event = $.Event('django:update-related');
144 | $(this).trigger(event);
145 | if (!event.isDefaultPrevented()) {
146 | updateRelatedObjectLinks(this);
147 | }
148 | });
149 | $('.related-widget-wrapper select').trigger('change');
150 | $('body').on('click', '.related-lookup', function(e) {
151 | e.preventDefault();
152 | const event = $.Event('django:lookup-related');
153 | $(this).trigger(event);
154 | if (!event.isDefaultPrevented()) {
155 | showRelatedObjectLookupPopup(this);
156 | }
157 | });
158 | });
159 | }
160 |
--------------------------------------------------------------------------------
/static/admin/js/actions.js:
--------------------------------------------------------------------------------
1 | /*global gettext, interpolate, ngettext*/
2 | 'use strict';
3 | {
4 | const $ = django.jQuery;
5 | let lastChecked;
6 |
7 | $.fn.actions = function(opts) {
8 | const options = $.extend({}, $.fn.actions.defaults, opts);
9 | const actionCheckboxes = $(this);
10 | let list_editable_changed = false;
11 | const showQuestion = function() {
12 | $(options.acrossClears).hide();
13 | $(options.acrossQuestions).show();
14 | $(options.allContainer).hide();
15 | },
16 | showClear = function() {
17 | $(options.acrossClears).show();
18 | $(options.acrossQuestions).hide();
19 | $(options.actionContainer).toggleClass(options.selectedClass);
20 | $(options.allContainer).show();
21 | $(options.counterContainer).hide();
22 | },
23 | reset = function() {
24 | $(options.acrossClears).hide();
25 | $(options.acrossQuestions).hide();
26 | $(options.allContainer).hide();
27 | $(options.counterContainer).show();
28 | },
29 | clearAcross = function() {
30 | reset();
31 | $(options.acrossInput).val(0);
32 | $(options.actionContainer).removeClass(options.selectedClass);
33 | },
34 | checker = function(checked) {
35 | if (checked) {
36 | showQuestion();
37 | } else {
38 | reset();
39 | }
40 | $(actionCheckboxes).prop("checked", checked)
41 | .parent().parent().toggleClass(options.selectedClass, checked);
42 | },
43 | updateCounter = function() {
44 | const sel = $(actionCheckboxes).filter(":checked").length;
45 | // data-actions-icnt is defined in the generated HTML
46 | // and contains the total amount of objects in the queryset
47 | const actions_icnt = $('.action-counter').data('actionsIcnt');
48 | $(options.counterContainer).html(interpolate(
49 | ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), {
50 | sel: sel,
51 | cnt: actions_icnt
52 | }, true));
53 | $(options.allToggle).prop("checked", function() {
54 | let value;
55 | if (sel === actionCheckboxes.length) {
56 | value = true;
57 | showQuestion();
58 | } else {
59 | value = false;
60 | clearAcross();
61 | }
62 | return value;
63 | });
64 | };
65 | // Show counter by default
66 | $(options.counterContainer).show();
67 | // Check state of checkboxes and reinit state if needed
68 | $(this).filter(":checked").each(function(i) {
69 | $(this).parent().parent().toggleClass(options.selectedClass);
70 | updateCounter();
71 | if ($(options.acrossInput).val() === 1) {
72 | showClear();
73 | }
74 | });
75 | $(options.allToggle).show().on('click', function() {
76 | checker($(this).prop("checked"));
77 | updateCounter();
78 | });
79 | $("a", options.acrossQuestions).on('click', function(event) {
80 | event.preventDefault();
81 | $(options.acrossInput).val(1);
82 | showClear();
83 | });
84 | $("a", options.acrossClears).on('click', function(event) {
85 | event.preventDefault();
86 | $(options.allToggle).prop("checked", false);
87 | clearAcross();
88 | checker(0);
89 | updateCounter();
90 | });
91 | lastChecked = null;
92 | $(actionCheckboxes).on('click', function(event) {
93 | if (!event) { event = window.event; }
94 | const target = event.target ? event.target : event.srcElement;
95 | if (lastChecked && $.data(lastChecked) !== $.data(target) && event.shiftKey === true) {
96 | let inrange = false;
97 | $(lastChecked).prop("checked", target.checked)
98 | .parent().parent().toggleClass(options.selectedClass, target.checked);
99 | $(actionCheckboxes).each(function() {
100 | if ($.data(this) === $.data(lastChecked) || $.data(this) === $.data(target)) {
101 | inrange = (inrange) ? false : true;
102 | }
103 | if (inrange) {
104 | $(this).prop("checked", target.checked)
105 | .parent().parent().toggleClass(options.selectedClass, target.checked);
106 | }
107 | });
108 | }
109 | $(target).parent().parent().toggleClass(options.selectedClass, target.checked);
110 | lastChecked = target;
111 | updateCounter();
112 | });
113 | $('form#changelist-form table#result_list tr').on('change', 'td:gt(0) :input', function() {
114 | list_editable_changed = true;
115 | });
116 | $('form#changelist-form button[name="index"]').on('click', function(event) {
117 | if (list_editable_changed) {
118 | return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
119 | }
120 | });
121 | $('form#changelist-form input[name="_save"]').on('click', function(event) {
122 | let action_changed = false;
123 | $('select option:selected', options.actionContainer).each(function() {
124 | if ($(this).val()) {
125 | action_changed = true;
126 | }
127 | });
128 | if (action_changed) {
129 | if (list_editable_changed) {
130 | 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."));
131 | } else {
132 | 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."));
133 | }
134 | }
135 | });
136 | };
137 | /* Setup plugin defaults */
138 | $.fn.actions.defaults = {
139 | actionContainer: "div.actions",
140 | counterContainer: "span.action-counter",
141 | allContainer: "div.actions span.all",
142 | acrossInput: "div.actions input.select-across",
143 | acrossQuestions: "div.actions span.question",
144 | acrossClears: "div.actions span.clear",
145 | allToggle: "#action-toggle",
146 | selectedClass: "selected"
147 | };
148 | $(document).ready(function() {
149 | const $actionsEls = $('tr input.action-select');
150 | if ($actionsEls.length > 0) {
151 | $actionsEls.actions();
152 | }
153 | });
154 | }
155 |
--------------------------------------------------------------------------------
/static/admin/css/changelists.css:
--------------------------------------------------------------------------------
1 | /* CHANGELISTS */
2 |
3 | #changelist {
4 | position: relative;
5 | width: 100%;
6 | }
7 |
8 | #changelist table {
9 | width: 100%;
10 | }
11 |
12 | .change-list .hiddenfields { display:none; }
13 |
14 | .change-list .filtered table {
15 | border-right: none;
16 | }
17 |
18 | .change-list .filtered {
19 | min-height: 400px;
20 | }
21 |
22 | .change-list .filtered .results, .change-list .filtered .paginator,
23 | .filtered #toolbar, .filtered div.xfull {
24 | margin-right: 280px;
25 | width: auto;
26 | }
27 |
28 | .change-list .filtered table tbody th {
29 | padding-right: 1em;
30 | }
31 |
32 | #changelist-form .results {
33 | overflow-x: auto;
34 | }
35 |
36 | #changelist .toplinks {
37 | border-bottom: 1px solid #ddd;
38 | }
39 |
40 | #changelist .paginator {
41 | color: #666;
42 | border-bottom: 1px solid #eee;
43 | background: #fff;
44 | overflow: hidden;
45 | }
46 |
47 | /* CHANGELIST TABLES */
48 |
49 | #changelist table thead th {
50 | padding: 0;
51 | white-space: nowrap;
52 | vertical-align: middle;
53 | }
54 |
55 | #changelist table thead th.action-checkbox-column {
56 | width: 1.5em;
57 | text-align: center;
58 | }
59 |
60 | #changelist table tbody td.action-checkbox {
61 | text-align: center;
62 | }
63 |
64 | #changelist table tfoot {
65 | color: #666;
66 | }
67 |
68 | /* TOOLBAR */
69 |
70 | #changelist #toolbar {
71 | padding: 8px 10px;
72 | margin-bottom: 15px;
73 | border-top: 1px solid #eee;
74 | border-bottom: 1px solid #eee;
75 | background: #f8f8f8;
76 | color: #666;
77 | }
78 |
79 | #changelist #toolbar form input {
80 | border-radius: 4px;
81 | font-size: 14px;
82 | padding: 5px;
83 | color: #333;
84 | }
85 |
86 | #changelist #toolbar form #searchbar {
87 | height: 19px;
88 | border: 1px solid #ccc;
89 | padding: 2px 5px;
90 | margin: 0;
91 | vertical-align: top;
92 | font-size: 13px;
93 | max-width: 230px;
94 | }
95 |
96 | #changelist #toolbar form #searchbar:focus {
97 | border-color: #999;
98 | }
99 |
100 | #changelist #toolbar form input[type="submit"] {
101 | border: 1px solid #ccc;
102 | font-size: 13px;
103 | padding: 4px 8px;
104 | margin: 0;
105 | vertical-align: middle;
106 | background: #fff;
107 | box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
108 | cursor: pointer;
109 | color: #333;
110 | }
111 |
112 | #changelist #toolbar form input[type="submit"]:focus,
113 | #changelist #toolbar form input[type="submit"]:hover {
114 | border-color: #999;
115 | }
116 |
117 | #changelist #changelist-search img {
118 | vertical-align: middle;
119 | margin-right: 4px;
120 | }
121 |
122 | /* FILTER COLUMN */
123 |
124 | #changelist-filter {
125 | position: absolute;
126 | top: 0;
127 | right: 0;
128 | z-index: 1000;
129 | width: 240px;
130 | background: #f8f8f8;
131 | border-left: none;
132 | margin: 0;
133 | }
134 |
135 | #changelist-filter h2 {
136 | font-size: 14px;
137 | text-transform: uppercase;
138 | letter-spacing: 0.5px;
139 | padding: 5px 15px;
140 | margin-bottom: 12px;
141 | border-bottom: none;
142 | }
143 |
144 | #changelist-filter h3 {
145 | font-weight: 400;
146 | font-size: 14px;
147 | padding: 0 15px;
148 | margin-bottom: 10px;
149 | }
150 |
151 | #changelist-filter ul {
152 | margin: 5px 0;
153 | padding: 0 15px 15px;
154 | border-bottom: 1px solid #eaeaea;
155 | }
156 |
157 | #changelist-filter ul:last-child {
158 | border-bottom: none;
159 | }
160 |
161 | #changelist-filter li {
162 | list-style-type: none;
163 | margin-left: 0;
164 | padding-left: 0;
165 | }
166 |
167 | #changelist-filter a {
168 | display: block;
169 | color: #999;
170 | text-overflow: ellipsis;
171 | overflow-x: hidden;
172 | }
173 |
174 | #changelist-filter li.selected {
175 | border-left: 5px solid #eaeaea;
176 | padding-left: 10px;
177 | margin-left: -15px;
178 | }
179 |
180 | #changelist-filter li.selected a {
181 | color: #5b80b2;
182 | }
183 |
184 | #changelist-filter a:focus, #changelist-filter a:hover,
185 | #changelist-filter li.selected a:focus,
186 | #changelist-filter li.selected a:hover {
187 | color: #036;
188 | }
189 |
190 | #changelist-filter #changelist-filter-clear a {
191 | font-size: 13px;
192 | padding-bottom: 10px;
193 | border-bottom: 1px solid #eaeaea;
194 | }
195 |
196 | /* DATE DRILLDOWN */
197 |
198 | .change-list ul.toplinks {
199 | display: block;
200 | float: left;
201 | padding: 0;
202 | margin: 0;
203 | width: 100%;
204 | }
205 |
206 | .change-list ul.toplinks li {
207 | padding: 3px 6px;
208 | font-weight: bold;
209 | list-style-type: none;
210 | display: inline-block;
211 | }
212 |
213 | .change-list ul.toplinks .date-back a {
214 | color: #999;
215 | }
216 |
217 | .change-list ul.toplinks .date-back a:focus,
218 | .change-list ul.toplinks .date-back a:hover {
219 | color: #036;
220 | }
221 |
222 | /* PAGINATOR */
223 |
224 | .paginator {
225 | font-size: 13px;
226 | padding-top: 10px;
227 | padding-bottom: 10px;
228 | line-height: 22px;
229 | margin: 0;
230 | border-top: 1px solid #ddd;
231 | }
232 |
233 | .paginator a:link, .paginator a:visited {
234 | padding: 2px 6px;
235 | background: #79aec8;
236 | text-decoration: none;
237 | color: #fff;
238 | }
239 |
240 | .paginator a.showall {
241 | border: none;
242 | background: none;
243 | color: #5b80b2;
244 | }
245 |
246 | .paginator a.showall:focus, .paginator a.showall:hover {
247 | background: none;
248 | color: #036;
249 | }
250 |
251 | .paginator .end {
252 | margin-right: 6px;
253 | }
254 |
255 | .paginator .this-page {
256 | padding: 2px 6px;
257 | font-weight: bold;
258 | font-size: 13px;
259 | vertical-align: top;
260 | }
261 |
262 | .paginator a:focus, .paginator a:hover {
263 | color: white;
264 | background: #036;
265 | }
266 |
267 | /* ACTIONS */
268 |
269 | .filtered .actions {
270 | margin-right: 280px;
271 | border-right: none;
272 | }
273 |
274 | #changelist table input {
275 | margin: 0;
276 | vertical-align: baseline;
277 | }
278 |
279 | #changelist table tbody tr.selected {
280 | background-color: #FFFFCC;
281 | }
282 |
283 | #changelist .actions {
284 | padding: 10px;
285 | background: #fff;
286 | border-top: none;
287 | border-bottom: none;
288 | line-height: 24px;
289 | color: #999;
290 | }
291 |
292 | #changelist .actions.selected {
293 | background: #fffccf;
294 | border-top: 1px solid #fffee8;
295 | border-bottom: 1px solid #edecd6;
296 | }
297 |
298 | #changelist .actions span.all,
299 | #changelist .actions span.action-counter,
300 | #changelist .actions span.clear,
301 | #changelist .actions span.question {
302 | font-size: 13px;
303 | margin: 0 0.5em;
304 | display: none;
305 | }
306 |
307 | #changelist .actions:last-child {
308 | border-bottom: none;
309 | }
310 |
311 | #changelist .actions select {
312 | vertical-align: top;
313 | height: 24px;
314 | background: none;
315 | color: #000;
316 | border: 1px solid #ccc;
317 | border-radius: 4px;
318 | font-size: 14px;
319 | padding: 0 0 0 4px;
320 | margin: 0;
321 | margin-left: 10px;
322 | }
323 |
324 | #changelist .actions select:focus {
325 | border-color: #999;
326 | }
327 |
328 | #changelist .actions label {
329 | display: inline-block;
330 | vertical-align: middle;
331 | font-size: 13px;
332 | }
333 |
334 | #changelist .actions .button {
335 | font-size: 13px;
336 | border: 1px solid #ccc;
337 | border-radius: 4px;
338 | background: #fff;
339 | box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
340 | cursor: pointer;
341 | height: 24px;
342 | line-height: 1;
343 | padding: 4px 8px;
344 | margin: 0;
345 | color: #333;
346 | }
347 |
348 | #changelist .actions .button:focus, #changelist .actions .button:hover {
349 | border-color: #999;
350 | }
351 |
--------------------------------------------------------------------------------
/static/admin/js/calendar.js:
--------------------------------------------------------------------------------
1 | /*global gettext, pgettext, get_format, quickElement, removeChildren*/
2 | /*
3 | calendar.js - Calendar functions by Adrian Holovaty
4 | depends on core.js for utility functions like removeChildren or quickElement
5 | */
6 | 'use strict';
7 | {
8 | // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions
9 | const CalendarNamespace = {
10 | monthsOfYear: [
11 | gettext('January'),
12 | gettext('February'),
13 | gettext('March'),
14 | gettext('April'),
15 | gettext('May'),
16 | gettext('June'),
17 | gettext('July'),
18 | gettext('August'),
19 | gettext('September'),
20 | gettext('October'),
21 | gettext('November'),
22 | gettext('December')
23 | ],
24 | daysOfWeek: [
25 | pgettext('one letter Sunday', 'S'),
26 | pgettext('one letter Monday', 'M'),
27 | pgettext('one letter Tuesday', 'T'),
28 | pgettext('one letter Wednesday', 'W'),
29 | pgettext('one letter Thursday', 'T'),
30 | pgettext('one letter Friday', 'F'),
31 | pgettext('one letter Saturday', 'S')
32 | ],
33 | firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')),
34 | isLeapYear: function(year) {
35 | return (((year % 4) === 0) && ((year % 100) !== 0 ) || ((year % 400) === 0));
36 | },
37 | getDaysInMonth: function(month, year) {
38 | let days;
39 | if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) {
40 | days = 31;
41 | }
42 | else if (month === 4 || month === 6 || month === 9 || month === 11) {
43 | days = 30;
44 | }
45 | else if (month === 2 && CalendarNamespace.isLeapYear(year)) {
46 | days = 29;
47 | }
48 | else {
49 | days = 28;
50 | }
51 | return days;
52 | },
53 | draw: function(month, year, div_id, callback, selected) { // month = 1-12, year = 1-9999
54 | const today = new Date();
55 | const todayDay = today.getDate();
56 | const todayMonth = today.getMonth() + 1;
57 | const todayYear = today.getFullYear();
58 | let todayClass = '';
59 |
60 | // Use UTC functions here because the date field does not contain time
61 | // and using the UTC function variants prevent the local time offset
62 | // from altering the date, specifically the day field. For example:
63 | //
64 | // ```
65 | // var x = new Date('2013-10-02');
66 | // var day = x.getDate();
67 | // ```
68 | //
69 | // The day variable above will be 1 instead of 2 in, say, US Pacific time
70 | // zone.
71 | let isSelectedMonth = false;
72 | if (typeof selected !== 'undefined') {
73 | isSelectedMonth = (selected.getUTCFullYear() === year && (selected.getUTCMonth() + 1) === month);
74 | }
75 |
76 | month = parseInt(month);
77 | year = parseInt(year);
78 | const calDiv = document.getElementById(div_id);
79 | removeChildren(calDiv);
80 | const calTable = document.createElement('table');
81 | quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month - 1] + ' ' + year);
82 | const tableBody = quickElement('tbody', calTable);
83 |
84 | // Draw days-of-week header
85 | let tableRow = quickElement('tr', tableBody);
86 | for (let i = 0; i < 7; i++) {
87 | quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]);
88 | }
89 |
90 | const startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay();
91 | const days = CalendarNamespace.getDaysInMonth(month, year);
92 |
93 | let nonDayCell;
94 |
95 | // Draw blanks before first of month
96 | tableRow = quickElement('tr', tableBody);
97 | for (let i = 0; i < startingPos; i++) {
98 | nonDayCell = quickElement('td', tableRow, ' ');
99 | nonDayCell.className = "nonday";
100 | }
101 |
102 | function calendarMonth(y, m) {
103 | function onClick(e) {
104 | e.preventDefault();
105 | callback(y, m, this.textContent);
106 | }
107 | return onClick;
108 | }
109 |
110 | // Draw days of month
111 | let currentDay = 1;
112 | for (let i = startingPos; currentDay <= days; i++) {
113 | if (i % 7 === 0 && currentDay !== 1) {
114 | tableRow = quickElement('tr', tableBody);
115 | }
116 | if ((currentDay === todayDay) && (month === todayMonth) && (year === todayYear)) {
117 | todayClass = 'today';
118 | } else {
119 | todayClass = '';
120 | }
121 |
122 | // use UTC function; see above for explanation.
123 | if (isSelectedMonth && currentDay === selected.getUTCDate()) {
124 | if (todayClass !== '') {
125 | todayClass += " ";
126 | }
127 | todayClass += "selected";
128 | }
129 |
130 | const cell = quickElement('td', tableRow, '', 'class', todayClass);
131 | const link = quickElement('a', cell, currentDay, 'href', '#');
132 | link.addEventListener('click', calendarMonth(year, month));
133 | currentDay++;
134 | }
135 |
136 | // Draw blanks after end of month (optional, but makes for valid code)
137 | while (tableRow.childNodes.length < 7) {
138 | nonDayCell = quickElement('td', tableRow, ' ');
139 | nonDayCell.className = "nonday";
140 | }
141 |
142 | calDiv.appendChild(calTable);
143 | }
144 | };
145 |
146 | // Calendar -- A calendar instance
147 | function Calendar(div_id, callback, selected) {
148 | // div_id (string) is the ID of the element in which the calendar will
149 | // be displayed
150 | // callback (string) is the name of a JavaScript function that will be
151 | // called with the parameters (year, month, day) when a day in the
152 | // calendar is clicked
153 | this.div_id = div_id;
154 | this.callback = callback;
155 | this.today = new Date();
156 | this.currentMonth = this.today.getMonth() + 1;
157 | this.currentYear = this.today.getFullYear();
158 | if (typeof selected !== 'undefined') {
159 | this.selected = selected;
160 | }
161 | }
162 | Calendar.prototype = {
163 | drawCurrent: function() {
164 | CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback, this.selected);
165 | },
166 | drawDate: function(month, year, selected) {
167 | this.currentMonth = month;
168 | this.currentYear = year;
169 |
170 | if(selected) {
171 | this.selected = selected;
172 | }
173 |
174 | this.drawCurrent();
175 | },
176 | drawPreviousMonth: function() {
177 | if (this.currentMonth === 1) {
178 | this.currentMonth = 12;
179 | this.currentYear--;
180 | }
181 | else {
182 | this.currentMonth--;
183 | }
184 | this.drawCurrent();
185 | },
186 | drawNextMonth: function() {
187 | if (this.currentMonth === 12) {
188 | this.currentMonth = 1;
189 | this.currentYear++;
190 | }
191 | else {
192 | this.currentMonth++;
193 | }
194 | this.drawCurrent();
195 | },
196 | drawPreviousYear: function() {
197 | this.currentYear--;
198 | this.drawCurrent();
199 | },
200 | drawNextYear: function() {
201 | this.currentYear++;
202 | this.drawCurrent();
203 | }
204 | };
205 | window.Calendar = Calendar;
206 | window.CalendarNamespace = CalendarNamespace;
207 | }
208 |
--------------------------------------------------------------------------------
/static/js/jquery.waypoints.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | Waypoints - 4.0.1
3 | Copyright © 2011-2016 Caleb Troughton
4 | Licensed under the MIT license.
5 | https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
6 | */
7 | !function(){"use strict";function t(o){if(!o)throw new Error("No options passed to Waypoint constructor");if(!o.element)throw new Error("No element option passed to Waypoint constructor");if(!o.handler)throw new Error("No handler option passed to Waypoint constructor");this.key="waypoint-"+e,this.options=t.Adapter.extend({},t.defaults,o),this.element=this.options.element,this.adapter=new t.Adapter(this.element),this.callback=o.handler,this.axis=this.options.horizontal?"horizontal":"vertical",this.enabled=this.options.enabled,this.triggerPoint=null,this.group=t.Group.findOrCreate({name:this.options.group,axis:this.axis}),this.context=t.Context.findOrCreateByElement(this.options.context),t.offsetAliases[this.options.offset]&&(this.options.offset=t.offsetAliases[this.options.offset]),this.group.add(this),this.context.add(this),i[this.key]=this,e+=1}var e=0,i={};t.prototype.queueTrigger=function(t){this.group.queueTrigger(this,t)},t.prototype.trigger=function(t){this.enabled&&this.callback&&this.callback.apply(this,t)},t.prototype.destroy=function(){this.context.remove(this),this.group.remove(this),delete i[this.key]},t.prototype.disable=function(){return this.enabled=!1,this},t.prototype.enable=function(){return this.context.refresh(),this.enabled=!0,this},t.prototype.next=function(){return this.group.next(this)},t.prototype.previous=function(){return this.group.previous(this)},t.invokeAll=function(t){var e=[];for(var o in i)e.push(i[o]);for(var n=0,r=e.length;r>n;n++)e[n][t]()},t.destroyAll=function(){t.invokeAll("destroy")},t.disableAll=function(){t.invokeAll("disable")},t.enableAll=function(){t.Context.refreshAll();for(var e in i)i[e].enabled=!0;return this},t.refreshAll=function(){t.Context.refreshAll()},t.viewportHeight=function(){return window.innerHeight||document.documentElement.clientHeight},t.viewportWidth=function(){return document.documentElement.clientWidth},t.adapters=[],t.defaults={context:window,continuous:!0,enabled:!0,group:"default",horizontal:!1,offset:0},t.offsetAliases={"bottom-in-view":function(){return this.context.innerHeight()-this.adapter.outerHeight()},"right-in-view":function(){return this.context.innerWidth()-this.adapter.outerWidth()}},window.Waypoint=t}(),function(){"use strict";function t(t){window.setTimeout(t,1e3/60)}function e(t){this.element=t,this.Adapter=n.Adapter,this.adapter=new this.Adapter(t),this.key="waypoint-context-"+i,this.didScroll=!1,this.didResize=!1,this.oldScroll={x:this.adapter.scrollLeft(),y:this.adapter.scrollTop()},this.waypoints={vertical:{},horizontal:{}},t.waypointContextKey=this.key,o[t.waypointContextKey]=this,i+=1,n.windowContext||(n.windowContext=!0,n.windowContext=new e(window)),this.createThrottledScrollHandler(),this.createThrottledResizeHandler()}var i=0,o={},n=window.Waypoint,r=window.onload;e.prototype.add=function(t){var e=t.options.horizontal?"horizontal":"vertical";this.waypoints[e][t.key]=t,this.refresh()},e.prototype.checkEmpty=function(){var t=this.Adapter.isEmptyObject(this.waypoints.horizontal),e=this.Adapter.isEmptyObject(this.waypoints.vertical),i=this.element==this.element.window;t&&e&&!i&&(this.adapter.off(".waypoints"),delete o[this.key])},e.prototype.createThrottledResizeHandler=function(){function t(){e.handleResize(),e.didResize=!1}var e=this;this.adapter.on("resize.waypoints",function(){e.didResize||(e.didResize=!0,n.requestAnimationFrame(t))})},e.prototype.createThrottledScrollHandler=function(){function t(){e.handleScroll(),e.didScroll=!1}var e=this;this.adapter.on("scroll.waypoints",function(){(!e.didScroll||n.isTouch)&&(e.didScroll=!0,n.requestAnimationFrame(t))})},e.prototype.handleResize=function(){n.Context.refreshAll()},e.prototype.handleScroll=function(){var t={},e={horizontal:{newScroll:this.adapter.scrollLeft(),oldScroll:this.oldScroll.x,forward:"right",backward:"left"},vertical:{newScroll:this.adapter.scrollTop(),oldScroll:this.oldScroll.y,forward:"down",backward:"up"}};for(var i in e){var o=e[i],n=o.newScroll>o.oldScroll,r=n?o.forward:o.backward;for(var s in this.waypoints[i]){var a=this.waypoints[i][s];if(null!==a.triggerPoint){var l=o.oldScroll=a.triggerPoint,p=l&&h,u=!l&&!h;(p||u)&&(a.queueTrigger(r),t[a.group.id]=a.group)}}}for(var c in t)t[c].flushTriggers();this.oldScroll={x:e.horizontal.newScroll,y:e.vertical.newScroll}},e.prototype.innerHeight=function(){return this.element==this.element.window?n.viewportHeight():this.adapter.innerHeight()},e.prototype.remove=function(t){delete this.waypoints[t.axis][t.key],this.checkEmpty()},e.prototype.innerWidth=function(){return this.element==this.element.window?n.viewportWidth():this.adapter.innerWidth()},e.prototype.destroy=function(){var t=[];for(var e in this.waypoints)for(var i in this.waypoints[e])t.push(this.waypoints[e][i]);for(var o=0,n=t.length;n>o;o++)t[o].destroy()},e.prototype.refresh=function(){var t,e=this.element==this.element.window,i=e?void 0:this.adapter.offset(),o={};this.handleScroll(),t={horizontal:{contextOffset:e?0:i.left,contextScroll:e?0:this.oldScroll.x,contextDimension:this.innerWidth(),oldScroll:this.oldScroll.x,forward:"right",backward:"left",offsetProp:"left"},vertical:{contextOffset:e?0:i.top,contextScroll:e?0:this.oldScroll.y,contextDimension:this.innerHeight(),oldScroll:this.oldScroll.y,forward:"down",backward:"up",offsetProp:"top"}};for(var r in t){var s=t[r];for(var a in this.waypoints[r]){var l,h,p,u,c,d=this.waypoints[r][a],f=d.options.offset,w=d.triggerPoint,y=0,g=null==w;d.element!==d.element.window&&(y=d.adapter.offset()[s.offsetProp]),"function"==typeof f?f=f.apply(d):"string"==typeof f&&(f=parseFloat(f),d.options.offset.indexOf("%")>-1&&(f=Math.ceil(s.contextDimension*f/100))),l=s.contextScroll-s.contextOffset,d.triggerPoint=Math.floor(y+l-f),h=w=s.oldScroll,u=h&&p,c=!h&&!p,!g&&u?(d.queueTrigger(s.backward),o[d.group.id]=d.group):!g&&c?(d.queueTrigger(s.forward),o[d.group.id]=d.group):g&&s.oldScroll>=d.triggerPoint&&(d.queueTrigger(s.forward),o[d.group.id]=d.group)}}return n.requestAnimationFrame(function(){for(var t in o)o[t].flushTriggers()}),this},e.findOrCreateByElement=function(t){return e.findByElement(t)||new e(t)},e.refreshAll=function(){for(var t in o)o[t].refresh()},e.findByElement=function(t){return o[t.waypointContextKey]},window.onload=function(){r&&r(),e.refreshAll()},n.requestAnimationFrame=function(e){var i=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||t;i.call(window,e)},n.Context=e}(),function(){"use strict";function t(t,e){return t.triggerPoint-e.triggerPoint}function e(t,e){return e.triggerPoint-t.triggerPoint}function i(t){this.name=t.name,this.axis=t.axis,this.id=this.name+"-"+this.axis,this.waypoints=[],this.clearTriggerQueues(),o[this.axis][this.name]=this}var o={vertical:{},horizontal:{}},n=window.Waypoint;i.prototype.add=function(t){this.waypoints.push(t)},i.prototype.clearTriggerQueues=function(){this.triggerQueues={up:[],down:[],left:[],right:[]}},i.prototype.flushTriggers=function(){for(var i in this.triggerQueues){var o=this.triggerQueues[i],n="up"===i||"left"===i;o.sort(n?e:t);for(var r=0,s=o.length;s>r;r+=1){var a=o[r];(a.options.continuous||r===o.length-1)&&a.trigger([i])}}this.clearTriggerQueues()},i.prototype.next=function(e){this.waypoints.sort(t);var i=n.Adapter.inArray(e,this.waypoints),o=i===this.waypoints.length-1;return o?null:this.waypoints[i+1]},i.prototype.previous=function(e){this.waypoints.sort(t);var i=n.Adapter.inArray(e,this.waypoints);return i?this.waypoints[i-1]:null},i.prototype.queueTrigger=function(t,e){this.triggerQueues[e].push(t)},i.prototype.remove=function(t){var e=n.Adapter.inArray(t,this.waypoints);e>-1&&this.waypoints.splice(e,1)},i.prototype.first=function(){return this.waypoints[0]},i.prototype.last=function(){return this.waypoints[this.waypoints.length-1]},i.findOrCreate=function(t){return o[t.axis][t.name]||new i(t)},n.Group=i}(),function(){"use strict";function t(t){this.$element=e(t)}var e=window.jQuery,i=window.Waypoint;e.each(["innerHeight","innerWidth","off","offset","on","outerHeight","outerWidth","scrollLeft","scrollTop"],function(e,i){t.prototype[i]=function(){var t=Array.prototype.slice.call(arguments);return this.$element[i].apply(this.$element,t)}}),e.each(["extend","inArray","isEmptyObject"],function(i,o){t[o]=e[o]}),i.adapters.push({name:"jquery",Adapter:t}),i.Adapter=t}(),function(){"use strict";function t(t){return function(){var i=[],o=arguments[0];return t.isFunction(arguments[0])&&(o=t.extend({},arguments[1]),o.handler=arguments[0]),this.each(function(){var n=t.extend({},o,{element:this});"string"==typeof n.context&&(n.context=t(this).closest(n.context)[0]),i.push(new e(n))}),i}}var e=window.Waypoint;window.jQuery&&(window.jQuery.fn.waypoint=t(window.jQuery)),window.Zepto&&(window.Zepto.fn.waypoint=t(window.Zepto))}();
--------------------------------------------------------------------------------
/static/admin/js/urlify.js:
--------------------------------------------------------------------------------
1 | /*global XRegExp*/
2 | 'use strict';
3 | {
4 | const LATIN_MAP = {
5 | 'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE',
6 | 'Ç': 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I',
7 | 'Î': 'I', 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O',
8 | 'Õ': 'O', 'Ö': 'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U',
9 | 'Ü': 'U', 'Ű': 'U', 'Ý': 'Y', 'Þ': 'TH', 'Ÿ': 'Y', 'ß': 'ss', 'à': 'a',
10 | 'á': 'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c',
11 | 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e', 'ì': 'i', 'í': 'i', 'î': 'i',
12 | 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o',
13 | 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u',
14 | 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
15 | };
16 | const LATIN_SYMBOLS_MAP = {
17 | '©': '(c)'
18 | };
19 | const GREEK_MAP = {
20 | 'α': 'a', 'β': 'b', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'h',
21 | 'θ': '8', 'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': '3',
22 | 'ο': 'o', 'π': 'p', 'ρ': 'r', 'σ': 's', 'τ': 't', 'υ': 'y', 'φ': 'f',
23 | 'χ': 'x', 'ψ': 'ps', 'ω': 'w', 'ά': 'a', 'έ': 'e', 'ί': 'i', 'ό': 'o',
24 | 'ύ': 'y', 'ή': 'h', 'ώ': 'w', 'ς': 's', 'ϊ': 'i', 'ΰ': 'y', 'ϋ': 'y',
25 | 'ΐ': 'i', 'Α': 'A', 'Β': 'B', 'Γ': 'G', 'Δ': 'D', 'Ε': 'E', 'Ζ': 'Z',
26 | 'Η': 'H', 'Θ': '8', 'Ι': 'I', 'Κ': 'K', 'Λ': 'L', 'Μ': 'M', 'Ν': 'N',
27 | 'Ξ': '3', 'Ο': 'O', 'Π': 'P', 'Ρ': 'R', 'Σ': 'S', 'Τ': 'T', 'Υ': 'Y',
28 | 'Φ': 'F', 'Χ': 'X', 'Ψ': 'PS', 'Ω': 'W', 'Ά': 'A', 'Έ': 'E', 'Ί': 'I',
29 | 'Ό': 'O', 'Ύ': 'Y', 'Ή': 'H', 'Ώ': 'W', 'Ϊ': 'I', 'Ϋ': 'Y'
30 | };
31 | const TURKISH_MAP = {
32 | 'ş': 's', 'Ş': 'S', 'ı': 'i', 'İ': 'I', 'ç': 'c', 'Ç': 'C', 'ü': 'u',
33 | 'Ü': 'U', 'ö': 'o', 'Ö': 'O', 'ğ': 'g', 'Ğ': 'G'
34 | };
35 | const ROMANIAN_MAP = {
36 | 'ă': 'a', 'î': 'i', 'ș': 's', 'ț': 't', 'â': 'a',
37 | 'Ă': 'A', 'Î': 'I', 'Ș': 'S', 'Ț': 'T', 'Â': 'A'
38 | };
39 | const RUSSIAN_MAP = {
40 | 'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo',
41 | 'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm',
42 | 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u',
43 | 'ф': 'f', 'х': 'h', 'ц': 'c', 'ч': 'ch', 'ш': 'sh', 'щ': 'sh', 'ъ': '',
44 | 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu', 'я': 'ya',
45 | 'А': 'A', 'Б': 'B', 'В': 'V', 'Г': 'G', 'Д': 'D', 'Е': 'E', 'Ё': 'Yo',
46 | 'Ж': 'Zh', 'З': 'Z', 'И': 'I', 'Й': 'J', 'К': 'K', 'Л': 'L', 'М': 'M',
47 | 'Н': 'N', 'О': 'O', 'П': 'P', 'Р': 'R', 'С': 'S', 'Т': 'T', 'У': 'U',
48 | 'Ф': 'F', 'Х': 'H', 'Ц': 'C', 'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Sh', 'Ъ': '',
49 | 'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu', 'Я': 'Ya'
50 | };
51 | const UKRAINIAN_MAP = {
52 | 'Є': 'Ye', 'І': 'I', 'Ї': 'Yi', 'Ґ': 'G', 'є': 'ye', 'і': 'i',
53 | 'ї': 'yi', 'ґ': 'g'
54 | };
55 | const CZECH_MAP = {
56 | 'č': 'c', 'ď': 'd', 'ě': 'e', 'ň': 'n', 'ř': 'r', 'š': 's', 'ť': 't',
57 | 'ů': 'u', 'ž': 'z', 'Č': 'C', 'Ď': 'D', 'Ě': 'E', 'Ň': 'N', 'Ř': 'R',
58 | 'Š': 'S', 'Ť': 'T', 'Ů': 'U', 'Ž': 'Z'
59 | };
60 | const SLOVAK_MAP = {
61 | 'á': 'a', 'ä': 'a', 'č': 'c', 'ď': 'd', 'é': 'e', 'í': 'i', 'ľ': 'l',
62 | 'ĺ': 'l', 'ň': 'n', 'ó': 'o', 'ô': 'o', 'ŕ': 'r', 'š': 's', 'ť': 't',
63 | 'ú': 'u', 'ý': 'y', 'ž': 'z',
64 | 'Á': 'a', 'Ä': 'A', 'Č': 'C', 'Ď': 'D', 'É': 'E', 'Í': 'I', 'Ľ': 'L',
65 | 'Ĺ': 'L', 'Ň': 'N', 'Ó': 'O', 'Ô': 'O', 'Ŕ': 'R', 'Š': 'S', 'Ť': 'T',
66 | 'Ú': 'U', 'Ý': 'Y', 'Ž': 'Z'
67 | };
68 | const POLISH_MAP = {
69 | 'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's',
70 | 'ź': 'z', 'ż': 'z',
71 | 'Ą': 'A', 'Ć': 'C', 'Ę': 'E', 'Ł': 'L', 'Ń': 'N', 'Ó': 'O', 'Ś': 'S',
72 | 'Ź': 'Z', 'Ż': 'Z'
73 | };
74 | const LATVIAN_MAP = {
75 | 'ā': 'a', 'č': 'c', 'ē': 'e', 'ģ': 'g', 'ī': 'i', 'ķ': 'k', 'ļ': 'l',
76 | 'ņ': 'n', 'š': 's', 'ū': 'u', 'ž': 'z',
77 | 'Ā': 'A', 'Č': 'C', 'Ē': 'E', 'Ģ': 'G', 'Ī': 'I', 'Ķ': 'K', 'Ļ': 'L',
78 | 'Ņ': 'N', 'Š': 'S', 'Ū': 'U', 'Ž': 'Z'
79 | };
80 | const ARABIC_MAP = {
81 | 'أ': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'g', 'ح': 'h', 'خ': 'kh', 'د': 'd',
82 | 'ذ': 'th', 'ر': 'r', 'ز': 'z', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': 't',
83 | 'ظ': 'th', 'ع': 'aa', 'غ': 'gh', 'ف': 'f', 'ق': 'k', 'ك': 'k', 'ل': 'l', 'م': 'm',
84 | 'ن': 'n', 'ه': 'h', 'و': 'o', 'ي': 'y'
85 | };
86 | const LITHUANIAN_MAP = {
87 | 'ą': 'a', 'č': 'c', 'ę': 'e', 'ė': 'e', 'į': 'i', 'š': 's', 'ų': 'u',
88 | 'ū': 'u', 'ž': 'z',
89 | 'Ą': 'A', 'Č': 'C', 'Ę': 'E', 'Ė': 'E', 'Į': 'I', 'Š': 'S', 'Ų': 'U',
90 | 'Ū': 'U', 'Ž': 'Z'
91 | };
92 | const SERBIAN_MAP = {
93 | 'ђ': 'dj', 'ј': 'j', 'љ': 'lj', 'њ': 'nj', 'ћ': 'c', 'џ': 'dz',
94 | 'đ': 'dj', 'Ђ': 'Dj', 'Ј': 'j', 'Љ': 'Lj', 'Њ': 'Nj', 'Ћ': 'C',
95 | 'Џ': 'Dz', 'Đ': 'Dj'
96 | };
97 | const AZERBAIJANI_MAP = {
98 | 'ç': 'c', 'ə': 'e', 'ğ': 'g', 'ı': 'i', 'ö': 'o', 'ş': 's', 'ü': 'u',
99 | 'Ç': 'C', 'Ə': 'E', 'Ğ': 'G', 'İ': 'I', 'Ö': 'O', 'Ş': 'S', 'Ü': 'U'
100 | };
101 | const GEORGIAN_MAP = {
102 | 'ა': 'a', 'ბ': 'b', 'გ': 'g', 'დ': 'd', 'ე': 'e', 'ვ': 'v', 'ზ': 'z',
103 | 'თ': 't', 'ი': 'i', 'კ': 'k', 'ლ': 'l', 'მ': 'm', 'ნ': 'n', 'ო': 'o',
104 | 'პ': 'p', 'ჟ': 'j', 'რ': 'r', 'ს': 's', 'ტ': 't', 'უ': 'u', 'ფ': 'f',
105 | 'ქ': 'q', 'ღ': 'g', 'ყ': 'y', 'შ': 'sh', 'ჩ': 'ch', 'ც': 'c', 'ძ': 'dz',
106 | 'წ': 'w', 'ჭ': 'ch', 'ხ': 'x', 'ჯ': 'j', 'ჰ': 'h'
107 | };
108 |
109 | const ALL_DOWNCODE_MAPS = [
110 | LATIN_MAP,
111 | LATIN_SYMBOLS_MAP,
112 | GREEK_MAP,
113 | TURKISH_MAP,
114 | ROMANIAN_MAP,
115 | RUSSIAN_MAP,
116 | UKRAINIAN_MAP,
117 | CZECH_MAP,
118 | SLOVAK_MAP,
119 | POLISH_MAP,
120 | LATVIAN_MAP,
121 | ARABIC_MAP,
122 | LITHUANIAN_MAP,
123 | SERBIAN_MAP,
124 | AZERBAIJANI_MAP,
125 | GEORGIAN_MAP
126 | ];
127 |
128 | const Downcoder = {
129 | 'Initialize': function() {
130 | if (Downcoder.map) { // already made
131 | return;
132 | }
133 | Downcoder.map = {};
134 | for (const lookup of ALL_DOWNCODE_MAPS) {
135 | Object.assign(Downcoder.map, lookup);
136 | }
137 | Downcoder.chars = Object.keys(Downcoder.map);
138 | Downcoder.regex = new RegExp(Downcoder.chars.join('|'), 'g');
139 | }
140 | };
141 |
142 | function downcode(slug) {
143 | Downcoder.Initialize();
144 | return slug.replace(Downcoder.regex, function(m) {
145 | return Downcoder.map[m];
146 | });
147 | }
148 |
149 |
150 | function URLify(s, num_chars, allowUnicode) {
151 | // changes, e.g., "Petty theft" to "petty-theft"
152 | // remove all these words from the string before urlifying
153 | if (!allowUnicode) {
154 | s = downcode(s);
155 | }
156 | const hasUnicodeChars = /[^\u0000-\u007f]/.test(s);
157 | // Remove English words only if the string contains ASCII (English)
158 | // characters.
159 | if (!hasUnicodeChars) {
160 | const removeList = [
161 | "a", "an", "as", "at", "before", "but", "by", "for", "from",
162 | "is", "in", "into", "like", "of", "off", "on", "onto", "per",
163 | "since", "than", "the", "this", "that", "to", "up", "via",
164 | "with"
165 | ];
166 | const r = new RegExp('\\b(' + removeList.join('|') + ')\\b', 'gi');
167 | s = s.replace(r, '');
168 | }
169 | s = s.toLowerCase(); // convert to lowercase
170 | // if downcode doesn't hit, the char will be stripped here
171 | if (allowUnicode) {
172 | // Keep Unicode letters including both lowercase and uppercase
173 | // characters, whitespace, and dash; remove other characters.
174 | s = XRegExp.replace(s, XRegExp('[^-_\\p{L}\\p{N}\\s]', 'g'), '');
175 | } else {
176 | s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
177 | }
178 | s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
179 | s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
180 | s = s.substring(0, num_chars); // trim to first num_chars chars
181 | s = s.replace(/-+$/g, ''); // trim any trailing hyphens
182 | return s;
183 | }
184 | window.URLify = URLify;
185 | }
186 |
--------------------------------------------------------------------------------
/static/admin/css/autocomplete.css:
--------------------------------------------------------------------------------
1 | select.admin-autocomplete {
2 | width: 20em;
3 | }
4 |
5 | .select2-container--admin-autocomplete.select2-container {
6 | min-height: 30px;
7 | }
8 |
9 | .select2-container--admin-autocomplete .select2-selection--single,
10 | .select2-container--admin-autocomplete .select2-selection--multiple {
11 | min-height: 30px;
12 | padding: 0;
13 | }
14 |
15 | .select2-container--admin-autocomplete.select2-container--focus .select2-selection,
16 | .select2-container--admin-autocomplete.select2-container--open .select2-selection {
17 | border-color: #999;
18 | min-height: 30px;
19 | }
20 |
21 | .select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--single,
22 | .select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--single {
23 | padding: 0;
24 | }
25 |
26 | .select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--multiple,
27 | .select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--multiple {
28 | padding: 0;
29 | }
30 |
31 | .select2-container--admin-autocomplete .select2-selection--single {
32 | background-color: #fff;
33 | border: 1px solid #ccc;
34 | border-radius: 4px;
35 | }
36 |
37 | .select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered {
38 | color: #444;
39 | line-height: 30px;
40 | }
41 |
42 | .select2-container--admin-autocomplete .select2-selection--single .select2-selection__clear {
43 | cursor: pointer;
44 | float: right;
45 | font-weight: bold;
46 | }
47 |
48 | .select2-container--admin-autocomplete .select2-selection--single .select2-selection__placeholder {
49 | color: #999;
50 | }
51 |
52 | .select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow {
53 | height: 26px;
54 | position: absolute;
55 | top: 1px;
56 | right: 1px;
57 | width: 20px;
58 | }
59 |
60 | .select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow b {
61 | border-color: #888 transparent transparent transparent;
62 | border-style: solid;
63 | border-width: 5px 4px 0 4px;
64 | height: 0;
65 | left: 50%;
66 | margin-left: -4px;
67 | margin-top: -2px;
68 | position: absolute;
69 | top: 50%;
70 | width: 0;
71 | }
72 |
73 | .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__clear {
74 | float: left;
75 | }
76 |
77 | .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__arrow {
78 | left: 1px;
79 | right: auto;
80 | }
81 |
82 | .select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single {
83 | background-color: #eee;
84 | cursor: default;
85 | }
86 |
87 | .select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single .select2-selection__clear {
88 | display: none;
89 | }
90 |
91 | .select2-container--admin-autocomplete.select2-container--open .select2-selection--single .select2-selection__arrow b {
92 | border-color: transparent transparent #888 transparent;
93 | border-width: 0 4px 5px 4px;
94 | }
95 |
96 | .select2-container--admin-autocomplete .select2-selection--multiple {
97 | background-color: white;
98 | border: 1px solid #ccc;
99 | border-radius: 4px;
100 | cursor: text;
101 | }
102 |
103 | .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered {
104 | box-sizing: border-box;
105 | list-style: none;
106 | margin: 0;
107 | padding: 0 5px;
108 | width: 100%;
109 | }
110 |
111 | .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered li {
112 | list-style: none;
113 | }
114 |
115 | .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__placeholder {
116 | color: #999;
117 | margin-top: 5px;
118 | float: left;
119 | }
120 |
121 | .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__clear {
122 | cursor: pointer;
123 | float: right;
124 | font-weight: bold;
125 | margin: 5px;
126 | }
127 |
128 | .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice {
129 | background-color: #e4e4e4;
130 | border: 1px solid #ccc;
131 | border-radius: 4px;
132 | cursor: default;
133 | float: left;
134 | margin-right: 5px;
135 | margin-top: 5px;
136 | padding: 0 5px;
137 | }
138 |
139 | .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove {
140 | color: #999;
141 | cursor: pointer;
142 | display: inline-block;
143 | font-weight: bold;
144 | margin-right: 2px;
145 | }
146 |
147 | .select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove:hover {
148 | color: #333;
149 | }
150 |
151 | .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 {
152 | float: right;
153 | }
154 |
155 | .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
156 | margin-left: 5px;
157 | margin-right: auto;
158 | }
159 |
160 | .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
161 | margin-left: 2px;
162 | margin-right: auto;
163 | }
164 |
165 | .select2-container--admin-autocomplete.select2-container--focus .select2-selection--multiple {
166 | border: solid #999 1px;
167 | outline: 0;
168 | }
169 |
170 | .select2-container--admin-autocomplete.select2-container--disabled .select2-selection--multiple {
171 | background-color: #eee;
172 | cursor: default;
173 | }
174 |
175 | .select2-container--admin-autocomplete.select2-container--disabled .select2-selection__choice__remove {
176 | display: none;
177 | }
178 |
179 | .select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--multiple {
180 | border-top-left-radius: 0;
181 | border-top-right-radius: 0;
182 | }
183 |
184 | .select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--multiple {
185 | border-bottom-left-radius: 0;
186 | border-bottom-right-radius: 0;
187 | }
188 |
189 | .select2-container--admin-autocomplete .select2-search--dropdown .select2-search__field {
190 | border: 1px solid #ccc;
191 | }
192 |
193 | .select2-container--admin-autocomplete .select2-search--inline .select2-search__field {
194 | background: transparent;
195 | border: none;
196 | outline: 0;
197 | box-shadow: none;
198 | -webkit-appearance: textfield;
199 | }
200 |
201 | .select2-container--admin-autocomplete .select2-results > .select2-results__options {
202 | max-height: 200px;
203 | overflow-y: auto;
204 | }
205 |
206 | .select2-container--admin-autocomplete .select2-results__option[role=group] {
207 | padding: 0;
208 | }
209 |
210 | .select2-container--admin-autocomplete .select2-results__option[aria-disabled=true] {
211 | color: #999;
212 | }
213 |
214 | .select2-container--admin-autocomplete .select2-results__option[aria-selected=true] {
215 | background-color: #ddd;
216 | }
217 |
218 | .select2-container--admin-autocomplete .select2-results__option .select2-results__option {
219 | padding-left: 1em;
220 | }
221 |
222 | .select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__group {
223 | padding-left: 0;
224 | }
225 |
226 | .select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option {
227 | margin-left: -1em;
228 | padding-left: 2em;
229 | }
230 |
231 | .select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
232 | margin-left: -2em;
233 | padding-left: 3em;
234 | }
235 |
236 | .select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
237 | margin-left: -3em;
238 | padding-left: 4em;
239 | }
240 |
241 | .select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
242 | margin-left: -4em;
243 | padding-left: 5em;
244 | }
245 |
246 | .select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
247 | margin-left: -5em;
248 | padding-left: 6em;
249 | }
250 |
251 | .select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] {
252 | background-color: #79aec8;
253 | color: white;
254 | }
255 |
256 | .select2-container--admin-autocomplete .select2-results__group {
257 | cursor: default;
258 | display: block;
259 | padding: 6px;
260 | }
261 |
--------------------------------------------------------------------------------
|