Copybara bot | be50d49 | 2023-11-30 00:16:42 +0100 | [diff] [blame] | 1 | /** |
| 2 | * Functions hasClass(), addClass() and removeClass() developed by Jake Trent (http://jaketrent.com/post/addremove-classes-raw-javascript/) |
| 3 | */ |
| 4 | function 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 | |
| 11 | function addClass(el, className) { |
| 12 | if (el.classList) |
| 13 | el.classList.add(className) |
| 14 | else if (!hasClass(el, className)) el.className += " " + className |
| 15 | } |
| 16 | |
| 17 | function 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: |
| 27 | var 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 | |
| 39 | MultiSelect.prototype.renderSummary = function() { |
| 40 | if (this.forEl_) { |
| 41 | this.forEl_.innerText = this.selected_.join(", ") || "-"; |
| 42 | } |
| 43 | }; |
| 44 | |
| 45 | MultiSelect.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 | |
| 69 | var 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 |
| 134 | function 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 | |
| 144 | document.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 | |
| 162 | function 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 | |
| 169 | var 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 | |
| 181 | function 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 | |
| 193 | function 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 | |
| 219 | function 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 | |
| 234 | window.addEventListener("load", function() { |
| 235 | document.querySelectorAll("[data-required]").forEach(input => { |
| 236 | input.setAttribute("required", "true"); |
| 237 | }); |
| 238 | |
| 239 | if (!isDateInputSupported()) { |
| 240 | initPolyfillDateSupport(); |
| 241 | } |
| 242 | }); |