blob: 445016e4350cd6178023ccb34b7442df89f984c1 [file] [log] [blame]
Copybara botbe50d492023-11-30 00:16:42 +01001/**
2 * Functions hasClass(), addClass() and removeClass() developed by Jake Trent (http://jaketrent.com/post/addremove-classes-raw-javascript/)
3 */
4function hasClass(el, className) {
5 if (el.classList)
6 return el.classList.contains(className)
7 else
8 return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'))
9}
10
11function addClass(el, className) {
12 if (el.classList)
13 el.classList.add(className)
14 else if (!hasClass(el, className)) el.className += " " + className
15}
16
17function removeClass(el, className) {
18 if (el.classList)
19 el.classList.remove(className)
20 else if (hasClass(el, className)) {
21 var reg = new RegExp('(\\s|^)' + className + '(\\s|$)')
22 el.className=el.className.replace(reg, ' ')
23 }
24}
25
26// MultiSelect implementation:
27var MultiSelect = function MultiSelect(element) {
28 this.element_ = element;
29 this.selected_ = [];
30
31 var forElId = this.element_.getAttribute("for") || this.element_.getAttribute("data-for");
32 if (forElId) {
33 this.forEl_ = (forElId ? document.getElementById(this.element_.getAttribute("for")) : null);
34 }
35
36 this.init();
37};
38
39MultiSelect.prototype.renderSummary = function() {
40 if (this.forEl_) {
41 this.forEl_.innerText = this.selected_.join(", ") || "-";
42 }
43};
44
45MultiSelect.prototype.init = function() {
46 if (this.element_) {
47 this.element_.addEventListener("click", e => {
48 e.stopImmediatePropagation();
49 }, true);
50
51 this.element_.querySelectorAll(".mdl-custom-multiselect__item").forEach(item => {
52 var checkbox = item.querySelector("input[type=\"checkbox\"]");
53 var label = item.querySelector(".mdl-checkbox__label").innerText;
54 checkbox.addEventListener("change", e => {
55 if(checkbox.checked) {
56 this.selected_.push(label);
57 } else {
58 this.selected_ = this.selected_.filter(item => item !== label);
59 }
60 this.renderSummary();
61
62 var customEvent = new Event('custom-multiselect-change');
63 this.element_.dispatchEvent(customEvent);
64 });
65 });
66 }
67};
68
69var dynDialog = {
70 didItInit: false,
71 dialog: null,
72 url: null,
73 load: function(url, reload) {
74 if (this.didItInit === false) {
75 this.init();
76 }
77
78 if (this.url == url && reload !== true) {
79 this.show();
80 return;
81 }
82
83 this.url = url;
84
85 fetch(url).then(response => response.text()).then(response => {
86 if (this.dialog.open) {
87 this.close();
88 }
89
90 this.dialog.innerHTML = response;
91 componentHandler.upgradeElements(this.dialog);
92
93 this.dialog.querySelectorAll("[data-required]").forEach(input => {
94 input.setAttribute("required", "true");
95 });
96
97 var script = this.dialog.querySelectorAll("dynscript");
98 if (script.length > 0) {
99 for (var i = 0; i < script.length; i++) {
100 eval(script[i].innerText);
101 }
102 }
103 this.dialog.querySelectorAll("[data-dyndialog-close]").forEach(btn => {
104 btn.addEventListener("click", e => {
105 e.preventDefault();
106 this.close();
107 });
108 });
109
110 this.dialog.showModal();
111 });
112 },
113 reload: function() {
114 this.load(this.url, true);
115 },
116 show: function() {
117 this.dialog.showModal();
118 },
119 close: function() {
120 this.dialog.close();
121 },
122 init: function() {
123 this.dialog = document.createElement("dialog");
124 this.dialog.setAttribute("id", "dynDialog");
125 this.dialog.setAttribute("class", "mdl-dialog");
126 dialogPolyfill.registerDialog(this.dialog);
127 document.body.appendChild(this.dialog);
128
129 this.didItInit = true;
130 }
131};
132
133// From nodep-date-input-polyfill
134function isDateInputSupported() {
135 const input = document.createElement("input");
136 input.setAttribute("type", "date");
137
138 const notADateValue = "not-a-date";
139 input.setAttribute("value", notADateValue);
140
141 return (input.value !== notADateValue);
142}
143
144document.addEventListener("DOMContentLoaded", function() {
145 var dialogs = document.querySelectorAll("dialog");
146 for (var i = 0; i < dialogs.length; i++) {
147 dialogPolyfill.registerDialog(dialogs[i]);
148 }
149
150 document.querySelectorAll("[data-dyndialog-href]").forEach(link => {
151 link.addEventListener("click", e => {
152 e.preventDefault();
153 dynDialog.load(link.getAttribute("data-dyndialog-href"));
154 });
155 });
156
157 document.querySelectorAll(".mdl-custom-multiselect-js").forEach(menu => {
158 new MultiSelect(menu);
159 });
160});
161
162function importCSS(url) {
163 var link = document.createElement("link");
164 link.setAttribute("rel", "stylesheet");
165 link.setAttribute("href", url);
166 document.head.appendChild(link);
167}
168
169var loadScriptAsync = function(uri) {
170 return new Promise((resolve, reject) => {
171 var script = document.createElement('script');
172 script.src = uri;
173 script.async = true;
174 script.onload = () => {
175 resolve();
176 };
177 document.head.appendChild(script);
178 });
179}
180
181function hasParentDialog(el) {
182 while (el != document.documentElement) {
183 if (el.tagName == "DIALOG") {
184 return el;
185 }
186
187 el = el.parentNode;
188 }
189
190 return undefined;
191}
192
193function polyfillDateSupport(container) {
194 container.querySelectorAll("input[type=\"date\"]").forEach(el => {
195 el.setAttribute("type", "text");
196
197 dialogParent = hasParentDialog(el);
198
199 var options = {
200 format: "yyyy-mm-dd",
201 todayHighlight: true,
202 weekStart: 1,
203 zIndexOffset: 100,
204 container: dialogParent || container
205 };
206
207 if (el.hasAttribute("max")) {
208 options.endDate = el.getAttribute("max");
209 }
210
211 $(el).datepicker(options);
212 });
213
214 container.querySelectorAll("input[type=\"time\"]").forEach(el => {
215 el.setAttribute("placeholder", "hh:mm");
216 });
217}
218
219function initPolyfillDateSupport() {
220 console.info("Polyfilling date support");
221
222 importCSS("https://unpkg.com/bootstrap-datepicker@1.9.0/dist/css/bootstrap-datepicker3.standalone.min.css", "css");
223
224 loadScriptAsync("https://unpkg.com/jquery@3.4.1/dist/jquery.min.js", "js").then(_ => {
225 return loadScriptAsync("https://unpkg.com/bootstrap-datepicker@1.9.0/dist/js/bootstrap-datepicker.min.js");
226 }).then(_ => {
227 return loadScriptAsync("https://unpkg.com/bootstrap-datepicker@1.9.0/dist/locales/bootstrap-datepicker.es.min.js");
228 }).then(_ => {
229 console.log("[Date polyfill] Scripts loaded.");
230 polyfillDateSupport(document.documentElement);
231 });
232}
233
234window.addEventListener("load", function() {
235 document.querySelectorAll("[data-required]").forEach(input => {
236 input.setAttribute("required", "true");
237 });
238
239 if (!isDateInputSupported()) {
240 initPolyfillDateSupport();
241 }
242});