bootstrap-time 0.1.6-beta → 0.1.7-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -3
- package/dist/css/bootstrap-time.css +0 -1
- package/dist/css/bootstrap-time.min.css +1 -1
- package/dist/js/bootstrap-time.js +86 -39
- package/dist/js/bootstrap-time.min.js +1 -1
- package/package.json +1 -1
- package/src/js/bootstrap-time.js +86 -39
- package/src/scss/bootstrap-time.scss +0 -1
package/README.md
CHANGED
|
@@ -33,8 +33,8 @@ Or load the published files from jsDelivr:
|
|
|
33
33
|
```html
|
|
34
34
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@6.0.0-alpha.1/dist/css/bootstrap.min.css">
|
|
35
35
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.2/font/bootstrap-icons.min.css">
|
|
36
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-time@0.1.
|
|
37
|
-
<script src="https://cdn.jsdelivr.net/npm/bootstrap-time@0.1.
|
|
36
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-time@0.1.7-beta/dist/css/bootstrap-time.min.css">
|
|
37
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap-time@0.1.7-beta/dist/js/bootstrap-time.min.js"></script>
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Local builds use the same paths under `dist/`:
|
|
@@ -44,10 +44,21 @@ Local builds use the same paths under `dist/`:
|
|
|
44
44
|
<script src="dist/js/bootstrap-time.min.js"></script>
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
Add `bs-time` to a time field. The script builds the clock and places it under that field, so it works in an existing Bootstrap form.
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<label class="form-label" for="time">Time</label>
|
|
51
|
+
<input type="time" class="form-control bs-time" id="time" step="60">
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Minute selection follows the input `step`, including when `step` changes: `60` allows every minute by clicking between the numbers, `900` enables only 00, 15, 30 and 45. See `examples/bootstrap-time.html`.
|
|
48
55
|
|
|
49
56
|
## Changelog
|
|
50
57
|
|
|
58
|
+
### 0.1.7-beta
|
|
59
|
+
|
|
60
|
+
- Attach the clock to any field with class `bs-time`.
|
|
61
|
+
|
|
51
62
|
### 0.1.6-beta
|
|
52
63
|
|
|
53
64
|
- The example starts on the current time.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.clock-picker{position:relative
|
|
1
|
+
.clock-picker{position:relative}.clock-picker input[type=time]::-webkit-calendar-picker-indicator{display:none;appearance:none}.clock-toggle{pointer-events:auto;width:2.25rem;height:2.25rem;margin:-0.25rem;border:0;border-radius:50%;background:rgba(0,0,0,0);color:var(--bs-form-adorn-icon-color, var(--bs-secondary-color))}.clock-toggle .bi{font-size:1rem;line-height:1}.clock-toggle:hover,.clock-toggle:focus-visible{background-color:var(--bs-bg-3);color:var(--bs-body-color)}.clock-widget{position:absolute;top:100%;left:0;z-index:5;width:20rem;margin-top:.25rem;padding:.25rem .5rem 1rem;background-color:var(--bs-secondary-bg-subtle);color:var(--bs-secondary-fg)}.clock-arrows{display:flex;justify-content:flex-end;gap:.25rem}.btn.clock-arrow{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;min-height:0;padding:0;border-radius:50%;background-color:rgba(0,0,0,0);color:var(--bs-body-color);text-decoration:none}.btn.clock-arrow svg{width:1.5rem;height:1.5rem;fill:currentColor}.btn.clock-arrow:hover,.btn.clock-arrow:focus-visible{background-color:var(--bs-bg-3);color:var(--bs-body-color)}.btn.clock-arrow:disabled,.btn.clock-arrow:disabled:hover{background-color:rgba(0,0,0,0);color:var(--bs-secondary-color);opacity:.45}.clock{width:16rem;height:16rem;border-radius:50%;touch-action:none;cursor:pointer}.clock-hand{position:absolute;left:50%;bottom:50%;width:2px;height:var(--hand);transform-origin:center bottom;transform:translateX(-50%) rotate(var(--angle));transition:transform .3s ease,height .3s ease;border-radius:1px;pointer-events:none}.clock-knob{position:absolute;left:50%;top:0;width:2.25rem;height:2.25rem;border-radius:50%;transform:translate(-50%, -50%)}.clock-number{position:absolute;left:50%;top:50%;z-index:1;width:2.25rem;height:2.25rem;margin:-1.125rem;border:0;border-radius:50%;background:rgba(0,0,0,0);color:inherit;transform:rotate(var(--angle)) translateY(calc(var(--radius) * -1)) rotate(calc(var(--angle) * -1))}.clock-number[aria-pressed=true]{color:var(--bs-white, #fff)}.clock-number:disabled{opacity:.35;cursor:default}
|
|
@@ -7,20 +7,69 @@
|
|
|
7
7
|
|
|
8
8
|
var INNER_RADIUS = "4.6rem";
|
|
9
9
|
var OUTER_RADIUS = "6.4rem";
|
|
10
|
+
var LEFT = "M15.41 16.59 10.83 12l4.58-4.59L14 6l-6 6 6 6z";
|
|
11
|
+
var RIGHT = "M8.59 16.59 13.17 12 8.59 7.41 10 6l6 6-6 6z";
|
|
10
12
|
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
function svg(path) {
|
|
14
|
+
return '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="' + path + '"></path></svg>';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function mount(field) {
|
|
18
|
+
if (field.dataset.bsTime === "ready") return;
|
|
19
|
+
field.dataset.bsTime = "ready";
|
|
20
|
+
|
|
21
|
+
var host = field.closest(".form-control") || field;
|
|
22
|
+
var picker = host.closest(".clock-picker");
|
|
23
|
+
if (!picker) {
|
|
24
|
+
picker = document.createElement("div");
|
|
25
|
+
picker.className = "clock-picker";
|
|
26
|
+
host.parentNode.insertBefore(picker, host);
|
|
27
|
+
picker.append(host);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var adorn = field.closest(".form-adorn");
|
|
31
|
+
if (!adorn && field.classList.contains("form-control")) {
|
|
32
|
+
adorn = document.createElement("div");
|
|
33
|
+
adorn.className = "form-control form-adorn form-adorn-end";
|
|
34
|
+
field.parentNode.insertBefore(adorn, field);
|
|
35
|
+
adorn.append(field);
|
|
36
|
+
field.classList.remove("form-control");
|
|
37
|
+
field.classList.add("form-ghost");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
var toggle = picker.querySelector(".clock-toggle");
|
|
41
|
+
if (!toggle && adorn) {
|
|
42
|
+
toggle = document.createElement("button");
|
|
43
|
+
toggle.type = "button";
|
|
44
|
+
toggle.className = "form-adorn-icon clock-toggle";
|
|
45
|
+
toggle.setAttribute("aria-label", "Klok");
|
|
46
|
+
toggle.setAttribute("aria-pressed", "false");
|
|
47
|
+
toggle.innerHTML = '<i class="bi bi-clock" aria-hidden="true"></i>';
|
|
48
|
+
adorn.insertBefore(toggle, adorn.firstChild);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
var widget = picker.querySelector(".clock-widget");
|
|
52
|
+
if (!widget) {
|
|
53
|
+
widget = document.createElement("div");
|
|
54
|
+
widget.className = "clock-widget card theme-secondary theme-subtle";
|
|
55
|
+
widget.hidden = true;
|
|
56
|
+
widget.innerHTML =
|
|
57
|
+
'<div class="clock-arrows">' +
|
|
58
|
+
'<button class="btn btn-link clock-arrow clock-hour" type="button" aria-label="Uren">' + svg(LEFT) + "</button>" +
|
|
59
|
+
'<button class="btn btn-link clock-arrow clock-minute" type="button" aria-label="Minuten">' + svg(RIGHT) + "</button>" +
|
|
60
|
+
"</div>" +
|
|
61
|
+
'<div class="clock position-relative mx-auto theme-inverse theme-subtle" role="group" aria-label="Kies een uur"></div>';
|
|
62
|
+
picker.append(widget);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
var clock = widget.querySelector(".clock");
|
|
66
|
+
var hourArrow = widget.querySelector(".clock-hour");
|
|
67
|
+
var minuteArrow = widget.querySelector(".clock-minute");
|
|
68
|
+
if (!clock || !hourArrow || !minuteArrow) return;
|
|
20
69
|
|
|
21
70
|
var now = new Date();
|
|
22
|
-
var initial =
|
|
23
|
-
?
|
|
71
|
+
var initial = field.value
|
|
72
|
+
? field.value.split(":")
|
|
24
73
|
: [now.getHours(), now.getMinutes()];
|
|
25
74
|
var hour = Number(initial[0]) || 0;
|
|
26
75
|
var minute = snapMinute(Number(initial[1]) || 0);
|
|
@@ -40,7 +89,7 @@
|
|
|
40
89
|
}
|
|
41
90
|
|
|
42
91
|
function minuteStep() {
|
|
43
|
-
var step = Number(
|
|
92
|
+
var step = Number(field.getAttribute("step") || field.step);
|
|
44
93
|
if (!step || step < 60) step = 60;
|
|
45
94
|
return Math.max(1, Math.round(step / 60));
|
|
46
95
|
}
|
|
@@ -78,7 +127,7 @@
|
|
|
78
127
|
}
|
|
79
128
|
|
|
80
129
|
function writeInput() {
|
|
81
|
-
|
|
130
|
+
field.value = pad(hour) + ":" + pad(minute);
|
|
82
131
|
}
|
|
83
132
|
|
|
84
133
|
function showMode(nextMode) {
|
|
@@ -131,19 +180,17 @@
|
|
|
131
180
|
}
|
|
132
181
|
|
|
133
182
|
function showWidget() {
|
|
134
|
-
if (!widget) return;
|
|
135
183
|
widget.hidden = false;
|
|
136
|
-
if (
|
|
184
|
+
if (toggle) toggle.setAttribute("aria-pressed", "true");
|
|
137
185
|
}
|
|
138
186
|
|
|
139
187
|
function hideWidget() {
|
|
140
|
-
if (!widget) return;
|
|
141
188
|
widget.hidden = true;
|
|
142
|
-
if (
|
|
189
|
+
if (toggle) toggle.setAttribute("aria-pressed", "false");
|
|
143
190
|
}
|
|
144
191
|
|
|
145
192
|
function toggleWidget() {
|
|
146
|
-
if (widget
|
|
193
|
+
if (widget.hidden) showWidget();
|
|
147
194
|
else hideWidget();
|
|
148
195
|
}
|
|
149
196
|
|
|
@@ -178,13 +225,11 @@
|
|
|
178
225
|
minuteArrow.addEventListener("click", function () {
|
|
179
226
|
showMode("minute");
|
|
180
227
|
});
|
|
181
|
-
if (
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (!timeInput.value) return;
|
|
187
|
-
var parts = timeInput.value.split(":");
|
|
228
|
+
if (toggle) toggle.addEventListener("click", toggleWidget);
|
|
229
|
+
field.addEventListener("focus", showWidget);
|
|
230
|
+
field.addEventListener("input", function () {
|
|
231
|
+
if (!field.value) return;
|
|
232
|
+
var parts = field.value.split(":");
|
|
188
233
|
var nextHour = Number(parts[0]);
|
|
189
234
|
var nextMinute = Number(parts[1]);
|
|
190
235
|
if (nextMinute !== minute) mode = "minute";
|
|
@@ -194,48 +239,50 @@
|
|
|
194
239
|
updateArrows();
|
|
195
240
|
renderClock();
|
|
196
241
|
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
});
|
|
203
|
-
}
|
|
242
|
+
picker.addEventListener("mousedown", function (event) {
|
|
243
|
+
if (event.target === field) return;
|
|
244
|
+
if (toggle && toggle.contains(event.target)) return;
|
|
245
|
+
event.preventDefault();
|
|
246
|
+
});
|
|
204
247
|
document.addEventListener("mousedown", function (event) {
|
|
205
|
-
if (
|
|
248
|
+
if (picker.contains(event.target)) return;
|
|
206
249
|
hideWidget();
|
|
207
250
|
});
|
|
208
251
|
|
|
209
252
|
function applyStep() {
|
|
210
253
|
minute = snapMinute(minute);
|
|
211
|
-
|
|
254
|
+
field.value = pad(hour) + ":" + pad(minute);
|
|
212
255
|
renderClock();
|
|
213
256
|
}
|
|
214
257
|
|
|
215
258
|
var stepDescriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "step");
|
|
216
259
|
if (stepDescriptor && stepDescriptor.set) {
|
|
217
|
-
Object.defineProperty(
|
|
260
|
+
Object.defineProperty(field, "step", {
|
|
218
261
|
configurable: true,
|
|
219
262
|
get: function () {
|
|
220
|
-
return stepDescriptor.get.call(
|
|
263
|
+
return stepDescriptor.get.call(field);
|
|
221
264
|
},
|
|
222
265
|
set: function (value) {
|
|
223
|
-
stepDescriptor.set.call(
|
|
266
|
+
stepDescriptor.set.call(field, value);
|
|
224
267
|
applyStep();
|
|
225
268
|
}
|
|
226
269
|
});
|
|
227
270
|
}
|
|
228
|
-
new MutationObserver(applyStep).observe(
|
|
271
|
+
new MutationObserver(applyStep).observe(field, {
|
|
229
272
|
attributes: true,
|
|
230
273
|
attributeFilter: ["step"]
|
|
231
274
|
});
|
|
232
275
|
|
|
233
276
|
updateArrows();
|
|
234
|
-
|
|
277
|
+
if (!field.value) field.value = pad(hour) + ":" + pad(minute);
|
|
235
278
|
renderClock();
|
|
236
279
|
hideWidget();
|
|
237
280
|
}
|
|
238
281
|
|
|
282
|
+
function init() {
|
|
283
|
+
document.querySelectorAll(".bs-time").forEach(mount);
|
|
284
|
+
}
|
|
285
|
+
|
|
239
286
|
if (document.readyState === "loading") {
|
|
240
287
|
document.addEventListener("DOMContentLoaded", init);
|
|
241
288
|
} else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(){"use strict";var e="4.6rem",t="6.4rem";function n(){var
|
|
1
|
+
!function(){"use strict";var e="4.6rem",t="6.4rem";function n(e){return'<svg viewBox="0 0 24 24" aria-hidden="true"><path d="'+e+'"></path></svg>'}function r(r){if("ready"!==r.dataset.bsTime){r.dataset.bsTime="ready";var o=r.closest(".form-control")||r,a=o.closest(".clock-picker");a||((a=document.createElement("div")).className="clock-picker",o.parentNode.insertBefore(a,o),a.append(o));var i=r.closest(".form-adorn");!i&&r.classList.contains("form-control")&&((i=document.createElement("div")).className="form-control form-adorn form-adorn-end",r.parentNode.insertBefore(i,r),i.append(r),r.classList.remove("form-control"),r.classList.add("form-ghost"));var c=a.querySelector(".clock-toggle");!c&&i&&((c=document.createElement("button")).type="button",c.className="form-adorn-icon clock-toggle",c.setAttribute("aria-label","Klok"),c.setAttribute("aria-pressed","false"),c.innerHTML='<i class="bi bi-clock" aria-hidden="true"></i>',i.insertBefore(c,i.firstChild));var u=a.querySelector(".clock-widget");u||((u=document.createElement("div")).className="clock-widget card theme-secondary theme-subtle",u.hidden=!0,u.innerHTML='<div class="clock-arrows"><button class="btn btn-link clock-arrow clock-hour" type="button" aria-label="Uren">'+n("M15.41 16.59 10.83 12l4.58-4.59L14 6l-6 6 6 6z")+'</button><button class="btn btn-link clock-arrow clock-minute" type="button" aria-label="Minuten">'+n("M8.59 16.59 13.17 12 8.59 7.41 10 6l6 6-6 6z")+'</button></div><div class="clock position-relative mx-auto theme-inverse theme-subtle" role="group" aria-label="Kies een uur"></div>',a.append(u));var s=u.querySelector(".clock"),l=u.querySelector(".clock-hour"),d=u.querySelector(".clock-minute");if(s&&l&&d){var m=new Date,f=r.value?r.value.split(":"):[m.getHours(),m.getMinutes()],b=Number(f[0])||0,p=M(Number(f[1])||0),v="hour",h=150,g=document.createElement("div"),k=document.createElement("span");g.className="clock-hand bg-primary",k.className="clock-knob bg-primary",k.setAttribute("aria-hidden","true"),g.append(k),s.append(g),s.addEventListener("click",function(e){if(!e.target.closest(".clock-number")){var t=function(e){var t=s.getBoundingClientRect(),n=e.clientX-(t.left+t.width/2),r=e.clientY-(t.top+t.height/2),o=(180*Math.atan2(n,-r)/Math.PI+360)%360;if("minute"===v)return M(Math.round(o/6)%60);var a=Math.round(o/30)%12;return Math.hypot(n,r)<.32*t.width?0===a?0:a+12:0===a?12:a}(e);"minute"===v?p=t:(b=t,v="minute"),S(),w(),q()}}),l.addEventListener("click",function(){A("hour")}),d.addEventListener("click",function(){A("minute")}),c&&c.addEventListener("click",function(){u.hidden?P():B()}),r.addEventListener("focus",P),r.addEventListener("input",function(){if(r.value){var e=r.value.split(":"),t=Number(e[0]),n=Number(e[1]);n!==p?v="minute":t!==b&&(v="hour"),b=t,p=n,w(),q()}}),a.addEventListener("mousedown",function(e){e.target!==r&&(c&&c.contains(e.target)||e.preventDefault())}),document.addEventListener("mousedown",function(e){a.contains(e.target)||B()});var y=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"step");y&&y.set&&Object.defineProperty(r,"step",{configurable:!0,get:function(){return y.get.call(r)},set:function(e){y.set.call(r,e),O()}}),new MutationObserver(O).observe(r,{attributes:!0,attributeFilter:["step"]}),w(),r.value||(r.value=E(b)+":"+E(p)),q(),B()}}function E(e){return String(e).padStart(2,"0")}function L(){var e=Number(r.getAttribute("step")||r.step);return(!e||e<60)&&(e=60),Math.max(1,Math.round(e/60))}function M(e){var t=L();return(Math.round(e/t)*t%60+60)%60}function N(){h+=((("hour"===v?b%12*30:6*p)-h)%360+540)%360-180,g.style.setProperty("--angle",h+"deg"),g.style.setProperty("--hand","hour"===v&&(0===b||b>12)?e:t)}function w(){l.disabled="hour"===v,d.disabled="minute"===v}function S(){r.value=E(b)+":"+E(p)}function A(e){v!==e&&(v=e,w(),q())}function q(){s.querySelectorAll(".clock-number").forEach(function(e){e.remove()}),s.setAttribute("aria-label","hour"===v?"Kies een uur":"Kies de minuten");var n="hour"===v?[12,1,2,3,4,5,6,7,8,9,10,11,0,13,14,15,16,17,18,19,20,21,22,23]:[0,5,10,15,20,25,30,35,40,45,50,55],r="hour"===v?b:p;N(),n.forEach(function(n,o){var a=document.createElement("button"),i="hour"===v&&o>=12,c=30*("hour"===v?o%12:o),u="minute"===v&&!function(e){return e%L()===0}(n);a.type="button",a.className="clock-number",a.textContent=0===n?"00":String(n),a.dataset.value=String(n),a.disabled=u,a.setAttribute("aria-pressed",u||n!==r?"false":"true"),a.style.setProperty("--angle",c+"deg"),a.style.setProperty("--radius",i?e:t),a.addEventListener("click",function(){a.disabled||("hour"===v?(b=n,v="minute"):p=n,S(),w(),q())}),s.append(a)})}function P(){u.hidden=!1,c&&c.setAttribute("aria-pressed","true")}function B(){u.hidden=!0,c&&c.setAttribute("aria-pressed","false")}function O(){p=M(p),r.value=E(b)+":"+E(p),q()}}function o(){document.querySelectorAll(".bs-time").forEach(r)}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",o):o()}();
|
package/package.json
CHANGED
package/src/js/bootstrap-time.js
CHANGED
|
@@ -7,20 +7,69 @@
|
|
|
7
7
|
|
|
8
8
|
var INNER_RADIUS = "4.6rem";
|
|
9
9
|
var OUTER_RADIUS = "6.4rem";
|
|
10
|
+
var LEFT = "M15.41 16.59 10.83 12l4.58-4.59L14 6l-6 6 6 6z";
|
|
11
|
+
var RIGHT = "M8.59 16.59 13.17 12 8.59 7.41 10 6l6 6-6 6z";
|
|
10
12
|
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
function svg(path) {
|
|
14
|
+
return '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="' + path + '"></path></svg>';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function mount(field) {
|
|
18
|
+
if (field.dataset.bsTime === "ready") return;
|
|
19
|
+
field.dataset.bsTime = "ready";
|
|
20
|
+
|
|
21
|
+
var host = field.closest(".form-control") || field;
|
|
22
|
+
var picker = host.closest(".clock-picker");
|
|
23
|
+
if (!picker) {
|
|
24
|
+
picker = document.createElement("div");
|
|
25
|
+
picker.className = "clock-picker";
|
|
26
|
+
host.parentNode.insertBefore(picker, host);
|
|
27
|
+
picker.append(host);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var adorn = field.closest(".form-adorn");
|
|
31
|
+
if (!adorn && field.classList.contains("form-control")) {
|
|
32
|
+
adorn = document.createElement("div");
|
|
33
|
+
adorn.className = "form-control form-adorn form-adorn-end";
|
|
34
|
+
field.parentNode.insertBefore(adorn, field);
|
|
35
|
+
adorn.append(field);
|
|
36
|
+
field.classList.remove("form-control");
|
|
37
|
+
field.classList.add("form-ghost");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
var toggle = picker.querySelector(".clock-toggle");
|
|
41
|
+
if (!toggle && adorn) {
|
|
42
|
+
toggle = document.createElement("button");
|
|
43
|
+
toggle.type = "button";
|
|
44
|
+
toggle.className = "form-adorn-icon clock-toggle";
|
|
45
|
+
toggle.setAttribute("aria-label", "Klok");
|
|
46
|
+
toggle.setAttribute("aria-pressed", "false");
|
|
47
|
+
toggle.innerHTML = '<i class="bi bi-clock" aria-hidden="true"></i>';
|
|
48
|
+
adorn.insertBefore(toggle, adorn.firstChild);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
var widget = picker.querySelector(".clock-widget");
|
|
52
|
+
if (!widget) {
|
|
53
|
+
widget = document.createElement("div");
|
|
54
|
+
widget.className = "clock-widget card theme-secondary theme-subtle";
|
|
55
|
+
widget.hidden = true;
|
|
56
|
+
widget.innerHTML =
|
|
57
|
+
'<div class="clock-arrows">' +
|
|
58
|
+
'<button class="btn btn-link clock-arrow clock-hour" type="button" aria-label="Uren">' + svg(LEFT) + "</button>" +
|
|
59
|
+
'<button class="btn btn-link clock-arrow clock-minute" type="button" aria-label="Minuten">' + svg(RIGHT) + "</button>" +
|
|
60
|
+
"</div>" +
|
|
61
|
+
'<div class="clock position-relative mx-auto theme-inverse theme-subtle" role="group" aria-label="Kies een uur"></div>';
|
|
62
|
+
picker.append(widget);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
var clock = widget.querySelector(".clock");
|
|
66
|
+
var hourArrow = widget.querySelector(".clock-hour");
|
|
67
|
+
var minuteArrow = widget.querySelector(".clock-minute");
|
|
68
|
+
if (!clock || !hourArrow || !minuteArrow) return;
|
|
20
69
|
|
|
21
70
|
var now = new Date();
|
|
22
|
-
var initial =
|
|
23
|
-
?
|
|
71
|
+
var initial = field.value
|
|
72
|
+
? field.value.split(":")
|
|
24
73
|
: [now.getHours(), now.getMinutes()];
|
|
25
74
|
var hour = Number(initial[0]) || 0;
|
|
26
75
|
var minute = snapMinute(Number(initial[1]) || 0);
|
|
@@ -40,7 +89,7 @@
|
|
|
40
89
|
}
|
|
41
90
|
|
|
42
91
|
function minuteStep() {
|
|
43
|
-
var step = Number(
|
|
92
|
+
var step = Number(field.getAttribute("step") || field.step);
|
|
44
93
|
if (!step || step < 60) step = 60;
|
|
45
94
|
return Math.max(1, Math.round(step / 60));
|
|
46
95
|
}
|
|
@@ -78,7 +127,7 @@
|
|
|
78
127
|
}
|
|
79
128
|
|
|
80
129
|
function writeInput() {
|
|
81
|
-
|
|
130
|
+
field.value = pad(hour) + ":" + pad(minute);
|
|
82
131
|
}
|
|
83
132
|
|
|
84
133
|
function showMode(nextMode) {
|
|
@@ -131,19 +180,17 @@
|
|
|
131
180
|
}
|
|
132
181
|
|
|
133
182
|
function showWidget() {
|
|
134
|
-
if (!widget) return;
|
|
135
183
|
widget.hidden = false;
|
|
136
|
-
if (
|
|
184
|
+
if (toggle) toggle.setAttribute("aria-pressed", "true");
|
|
137
185
|
}
|
|
138
186
|
|
|
139
187
|
function hideWidget() {
|
|
140
|
-
if (!widget) return;
|
|
141
188
|
widget.hidden = true;
|
|
142
|
-
if (
|
|
189
|
+
if (toggle) toggle.setAttribute("aria-pressed", "false");
|
|
143
190
|
}
|
|
144
191
|
|
|
145
192
|
function toggleWidget() {
|
|
146
|
-
if (widget
|
|
193
|
+
if (widget.hidden) showWidget();
|
|
147
194
|
else hideWidget();
|
|
148
195
|
}
|
|
149
196
|
|
|
@@ -178,13 +225,11 @@
|
|
|
178
225
|
minuteArrow.addEventListener("click", function () {
|
|
179
226
|
showMode("minute");
|
|
180
227
|
});
|
|
181
|
-
if (
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (!timeInput.value) return;
|
|
187
|
-
var parts = timeInput.value.split(":");
|
|
228
|
+
if (toggle) toggle.addEventListener("click", toggleWidget);
|
|
229
|
+
field.addEventListener("focus", showWidget);
|
|
230
|
+
field.addEventListener("input", function () {
|
|
231
|
+
if (!field.value) return;
|
|
232
|
+
var parts = field.value.split(":");
|
|
188
233
|
var nextHour = Number(parts[0]);
|
|
189
234
|
var nextMinute = Number(parts[1]);
|
|
190
235
|
if (nextMinute !== minute) mode = "minute";
|
|
@@ -194,48 +239,50 @@
|
|
|
194
239
|
updateArrows();
|
|
195
240
|
renderClock();
|
|
196
241
|
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
});
|
|
203
|
-
}
|
|
242
|
+
picker.addEventListener("mousedown", function (event) {
|
|
243
|
+
if (event.target === field) return;
|
|
244
|
+
if (toggle && toggle.contains(event.target)) return;
|
|
245
|
+
event.preventDefault();
|
|
246
|
+
});
|
|
204
247
|
document.addEventListener("mousedown", function (event) {
|
|
205
|
-
if (
|
|
248
|
+
if (picker.contains(event.target)) return;
|
|
206
249
|
hideWidget();
|
|
207
250
|
});
|
|
208
251
|
|
|
209
252
|
function applyStep() {
|
|
210
253
|
minute = snapMinute(minute);
|
|
211
|
-
|
|
254
|
+
field.value = pad(hour) + ":" + pad(minute);
|
|
212
255
|
renderClock();
|
|
213
256
|
}
|
|
214
257
|
|
|
215
258
|
var stepDescriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "step");
|
|
216
259
|
if (stepDescriptor && stepDescriptor.set) {
|
|
217
|
-
Object.defineProperty(
|
|
260
|
+
Object.defineProperty(field, "step", {
|
|
218
261
|
configurable: true,
|
|
219
262
|
get: function () {
|
|
220
|
-
return stepDescriptor.get.call(
|
|
263
|
+
return stepDescriptor.get.call(field);
|
|
221
264
|
},
|
|
222
265
|
set: function (value) {
|
|
223
|
-
stepDescriptor.set.call(
|
|
266
|
+
stepDescriptor.set.call(field, value);
|
|
224
267
|
applyStep();
|
|
225
268
|
}
|
|
226
269
|
});
|
|
227
270
|
}
|
|
228
|
-
new MutationObserver(applyStep).observe(
|
|
271
|
+
new MutationObserver(applyStep).observe(field, {
|
|
229
272
|
attributes: true,
|
|
230
273
|
attributeFilter: ["step"]
|
|
231
274
|
});
|
|
232
275
|
|
|
233
276
|
updateArrows();
|
|
234
|
-
|
|
277
|
+
if (!field.value) field.value = pad(hour) + ":" + pad(minute);
|
|
235
278
|
renderClock();
|
|
236
279
|
hideWidget();
|
|
237
280
|
}
|
|
238
281
|
|
|
282
|
+
function init() {
|
|
283
|
+
document.querySelectorAll(".bs-time").forEach(mount);
|
|
284
|
+
}
|
|
285
|
+
|
|
239
286
|
if (document.readyState === "loading") {
|
|
240
287
|
document.addEventListener("DOMContentLoaded", init);
|
|
241
288
|
} else {
|