vue-cal 4.9.0 → 4.10.0
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/dist/drag-and-drop.amd.js +4 -3
- package/dist/drag-and-drop.cjs.js +4 -3
- package/dist/drag-and-drop.es.js +235 -69
- package/dist/i18n/ar.amd.js +3 -2
- package/dist/i18n/ar.cjs.js +4 -3
- package/dist/i18n/ar.es.js +64 -16
- package/dist/i18n/bg.amd.js +3 -2
- package/dist/i18n/bg.cjs.js +4 -3
- package/dist/i18n/bg.es.js +64 -16
- package/dist/i18n/bn.amd.js +3 -2
- package/dist/i18n/bn.cjs.js +4 -3
- package/dist/i18n/bn.es.js +64 -16
- package/dist/i18n/bs.amd.js +3 -2
- package/dist/i18n/bs.cjs.js +4 -3
- package/dist/i18n/bs.es.js +64 -16
- package/dist/i18n/ca.amd.js +3 -2
- package/dist/i18n/ca.cjs.js +4 -3
- package/dist/i18n/ca.es.js +75 -17
- package/dist/i18n/cs.amd.js +3 -2
- package/dist/i18n/cs.cjs.js +4 -3
- package/dist/i18n/cs.es.js +64 -16
- package/dist/i18n/da.amd.js +3 -2
- package/dist/i18n/da.cjs.js +4 -3
- package/dist/i18n/da.es.js +64 -16
- package/dist/i18n/de.amd.js +3 -2
- package/dist/i18n/de.cjs.js +4 -3
- package/dist/i18n/de.es.js +64 -16
- package/dist/i18n/el.amd.js +3 -2
- package/dist/i18n/el.cjs.js +4 -3
- package/dist/i18n/el.es.js +86 -19
- package/dist/i18n/en.amd.js +3 -2
- package/dist/i18n/en.cjs.js +4 -3
- package/dist/i18n/en.es.js +64 -16
- package/dist/i18n/es.amd.js +3 -2
- package/dist/i18n/es.cjs.js +4 -3
- package/dist/i18n/es.es.js +64 -16
- package/dist/i18n/et.amd.js +3 -2
- package/dist/i18n/et.cjs.js +4 -3
- package/dist/i18n/et.es.js +64 -16
- package/dist/i18n/fa.amd.js +3 -2
- package/dist/i18n/fa.cjs.js +4 -3
- package/dist/i18n/fa.es.js +64 -16
- package/dist/i18n/fi.amd.js +3 -2
- package/dist/i18n/fi.cjs.js +4 -3
- package/dist/i18n/fi.es.js +64 -16
- package/dist/i18n/fr.amd.js +3 -2
- package/dist/i18n/fr.cjs.js +4 -3
- package/dist/i18n/fr.es.js +64 -16
- package/dist/i18n/he.amd.js +3 -2
- package/dist/i18n/he.cjs.js +4 -3
- package/dist/i18n/he.es.js +64 -16
- package/dist/i18n/hr.amd.js +3 -2
- package/dist/i18n/hr.cjs.js +4 -3
- package/dist/i18n/hr.es.js +64 -16
- package/dist/i18n/hu.amd.js +3 -2
- package/dist/i18n/hu.cjs.js +4 -3
- package/dist/i18n/hu.es.js +64 -16
- package/dist/i18n/id.amd.js +3 -2
- package/dist/i18n/id.cjs.js +4 -3
- package/dist/i18n/id.es.js +64 -16
- package/dist/i18n/is.amd.js +3 -2
- package/dist/i18n/is.cjs.js +4 -3
- package/dist/i18n/is.es.js +64 -16
- package/dist/i18n/it.amd.js +3 -2
- package/dist/i18n/it.cjs.js +4 -3
- package/dist/i18n/it.es.js +64 -16
- package/dist/i18n/ja.amd.js +3 -2
- package/dist/i18n/ja.cjs.js +4 -3
- package/dist/i18n/ja.es.js +64 -16
- package/dist/i18n/ka.amd.js +3 -2
- package/dist/i18n/ka.cjs.js +4 -3
- package/dist/i18n/ka.es.js +64 -16
- package/dist/i18n/ko.amd.js +3 -2
- package/dist/i18n/ko.cjs.js +4 -3
- package/dist/i18n/ko.es.js +64 -16
- package/dist/i18n/lt.amd.js +3 -2
- package/dist/i18n/lt.cjs.js +4 -3
- package/dist/i18n/lt.es.js +64 -16
- package/dist/i18n/mn.amd.js +3 -2
- package/dist/i18n/mn.cjs.js +4 -3
- package/dist/i18n/mn.es.js +64 -16
- package/dist/i18n/nl.amd.js +3 -2
- package/dist/i18n/nl.cjs.js +4 -3
- package/dist/i18n/nl.es.js +64 -16
- package/dist/i18n/no.amd.js +3 -2
- package/dist/i18n/no.cjs.js +4 -3
- package/dist/i18n/no.es.js +64 -16
- package/dist/i18n/pl.amd.js +3 -2
- package/dist/i18n/pl.cjs.js +4 -3
- package/dist/i18n/pl.es.js +64 -16
- package/dist/i18n/pt-br.amd.js +3 -2
- package/dist/i18n/pt-br.cjs.js +4 -3
- package/dist/i18n/pt-br.es.js +64 -16
- package/dist/i18n/pt-pt.amd.js +3 -2
- package/dist/i18n/pt-pt.cjs.js +4 -3
- package/dist/i18n/pt-pt.es.js +64 -16
- package/dist/i18n/ro.amd.js +3 -2
- package/dist/i18n/ro.cjs.js +4 -3
- package/dist/i18n/ro.es.js +64 -16
- package/dist/i18n/ru.amd.js +3 -2
- package/dist/i18n/ru.cjs.js +4 -3
- package/dist/i18n/ru.es.js +75 -17
- package/dist/i18n/sk.amd.js +3 -2
- package/dist/i18n/sk.cjs.js +4 -3
- package/dist/i18n/sk.es.js +64 -16
- package/dist/i18n/sl.amd.js +3 -2
- package/dist/i18n/sl.cjs.js +4 -3
- package/dist/i18n/sl.es.js +64 -16
- package/dist/i18n/sq.amd.js +3 -2
- package/dist/i18n/sq.cjs.js +4 -3
- package/dist/i18n/sq.es.js +75 -17
- package/dist/i18n/sr.amd.js +3 -2
- package/dist/i18n/sr.cjs.js +4 -3
- package/dist/i18n/sr.es.js +64 -16
- package/dist/i18n/sv.amd.js +3 -2
- package/dist/i18n/sv.cjs.js +4 -3
- package/dist/i18n/sv.es.js +64 -16
- package/dist/i18n/tr.amd.js +3 -2
- package/dist/i18n/tr.cjs.js +4 -3
- package/dist/i18n/tr.es.js +64 -16
- package/dist/i18n/uk.amd.js +3 -2
- package/dist/i18n/uk.cjs.js +4 -3
- package/dist/i18n/uk.es.js +75 -17
- package/dist/i18n/vi.amd.js +3 -2
- package/dist/i18n/vi.cjs.js +4 -3
- package/dist/i18n/vi.es.js +75 -17
- package/dist/i18n/zh-cn.amd.js +3 -2
- package/dist/i18n/zh-cn.cjs.js +4 -3
- package/dist/i18n/zh-cn.es.js +75 -17
- package/dist/i18n/zh-hk.amd.js +3 -2
- package/dist/i18n/zh-hk.cjs.js +4 -3
- package/dist/i18n/zh-hk.es.js +75 -17
- package/dist/vue-cal.amd.js +4 -4
- package/dist/vue-cal.cjs.js +4 -4
- package/dist/vue-cal.es.js +3398 -916
- package/dist/vue-cal.iife.js +1 -2
- package/dist/vuecal.css +1 -1
- package/package.json +18 -19
package/dist/vue-cal.es.js
CHANGED
|
@@ -1,508 +1,290 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { openBlock as h, createElementBlock as c, Fragment as T, renderList as S, normalizeClass as b, normalizeStyle as $, createVNode as U, Transition as R, withCtx as g, createElementVNode as k, renderSlot as w, toDisplayString as f, createCommentVNode as v, createTextVNode as M, resolveComponent as j, createBlock as H, resolveDynamicComponent as de, createSlots as X, withKeys as Z, withModifiers as L, TransitionGroup as ue, normalizeProps as J, mergeProps as Q } from "vue";
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
4
|
/**
|
|
6
|
-
* vue-cal v4.
|
|
5
|
+
* vue-cal v4.10.0
|
|
7
6
|
* (c) 2024 Antoni Andre <antoniandre.web@gmail.com>
|
|
8
7
|
* @license MIT
|
|
9
8
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this._vuecal.$emit("cell-click", n ? { date: i, split: n } : i), this._vuecal.clickToNavigate || t ? this._vuecal.switchToNarrowerView() : this._vuecal.dblclickToNavigate && "ontouchstart" in window && (this._vuecal.domEvents.dblTapACell.taps++, setTimeout(() => this._vuecal.domEvents.dblTapACell.taps = 0, this._vuecal.domEvents.dblTapACell.timeout), this._vuecal.domEvents.dblTapACell.taps >= 2 && (this._vuecal.domEvents.dblTapACell.taps = 0, this._vuecal.switchToNarrowerView(), this._vuecal.$emit("cell-dblclick", n ? { date: i, split: n } : i)));
|
|
16
|
-
});
|
|
17
|
-
W(this, "keyPressEnterCell", (t, i) => {
|
|
18
|
-
this._vuecal.$emit("cell-keypress-enter", i ? { date: t, split: i } : t), this._vuecal.switchToNarrowerView();
|
|
19
|
-
});
|
|
20
|
-
W(this, "getPosition", (t) => {
|
|
21
|
-
const { left: i, top: n } = this._vuecal.cellsEl.getBoundingClientRect(), { clientX: l, clientY: s } = "ontouchstart" in window && t.touches ? t.touches[0] : t;
|
|
22
|
-
return { x: l - i, y: s - n };
|
|
23
|
-
});
|
|
24
|
-
W(this, "minutesAtCursor", (t) => {
|
|
25
|
-
let i = 0, n = { x: 0, y: 0 };
|
|
26
|
-
const { timeStep: l, timeCellHeight: s, timeFrom: o } = this._vuecal.$props;
|
|
27
|
-
return typeof t == "number" ? i = t : typeof t == "object" && (n = this.getPosition(t), i = Math.round(n.y * l / parseInt(s) + o)), { minutes: Math.max(Math.min(i, 1440), 0), cursorCoords: n };
|
|
28
|
-
});
|
|
29
|
-
this._vuecal = t;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
const q = 1440;
|
|
33
|
-
let y, D, K;
|
|
34
|
-
class ce {
|
|
35
|
-
constructor(t, i) {
|
|
36
|
-
W(this, "_vuecal", null);
|
|
37
|
-
W(this, "eventDefaults", { _eid: null, start: "", startTimeMinutes: 0, end: "", endTimeMinutes: 0, title: "", content: "", background: !1, allDay: !1, segments: null, repeat: null, daysCount: 1, deletable: !0, deleting: !1, titleEditable: !0, resizable: !0, resizing: !1, draggable: !0, dragging: !1, draggingStatic: !1, focused: !1, class: "" });
|
|
38
|
-
this._vuecal = t, y = i;
|
|
39
|
-
}
|
|
40
|
-
createAnEvent(t, i, n) {
|
|
41
|
-
if (typeof t == "string" && (t = y.stringToDate(t)), !(t instanceof Date))
|
|
42
|
-
return !1;
|
|
43
|
-
const l = y.dateToMinutes(t), s = l + (i = 1 * i || 120), o = y.addMinutes(new Date(t), i);
|
|
44
|
-
n.end && (typeof n.end == "string" && (n.end = y.stringToDate(n.end)), n.endTimeMinutes = y.dateToMinutes(n.end));
|
|
45
|
-
const a = { ...this.eventDefaults, _eid: `${this._vuecal._.uid}_${this._vuecal.eventIdIncrement++}`, start: t, startTimeMinutes: l, end: o, endTimeMinutes: s, segments: null, ...n };
|
|
46
|
-
return typeof this._vuecal.onEventCreate != "function" || this._vuecal.onEventCreate(a, () => this.deleteAnEvent(a)) ? (a.startDateF !== a.endDateF && (a.daysCount = y.countDays(a.start, a.end)), this._vuecal.mutableEvents.push(a), this._vuecal.addEventsToView([a]), this._vuecal.emitWithEvent("event-create", a), this._vuecal.$emit("event-change", { event: this._vuecal.cleanupEvent(a), originalEvent: null }), a) : void 0;
|
|
47
|
-
}
|
|
48
|
-
addEventSegment(t) {
|
|
49
|
-
t.segments || (t.segments = {}, t.segments[y.formatDateLite(t.start)] = { start: t.start, startTimeMinutes: t.startTimeMinutes, endTimeMinutes: q, isFirstDay: !0, isLastDay: !1 });
|
|
50
|
-
const i = t.segments[y.formatDateLite(t.end)];
|
|
51
|
-
i && (i.isLastDay = !1, i.endTimeMinutes = q);
|
|
52
|
-
const n = y.addDays(t.end, 1), l = y.formatDateLite(n);
|
|
53
|
-
return n.setHours(0, 0, 0, 0), t.segments[l] = { start: n, startTimeMinutes: 0, endTimeMinutes: t.endTimeMinutes, isFirstDay: !1, isLastDay: !0 }, t.end = y.addMinutes(n, t.endTimeMinutes), t.daysCount = Object.keys(t.segments).length, l;
|
|
54
|
-
}
|
|
55
|
-
removeEventSegment(t) {
|
|
56
|
-
let i = Object.keys(t.segments).length;
|
|
57
|
-
if (i <= 1)
|
|
58
|
-
return y.formatDateLite(t.end);
|
|
59
|
-
delete t.segments[y.formatDateLite(t.end)], i--;
|
|
60
|
-
const n = y.subtractDays(t.end, 1), l = y.formatDateLite(n), s = t.segments[l];
|
|
61
|
-
return i ? s && (s.isLastDay = !0, s.endTimeMinutes = t.endTimeMinutes) : t.segments = null, t.daysCount = i || 1, t.end = n, l;
|
|
62
|
-
}
|
|
63
|
-
createEventSegments(t, i, n) {
|
|
64
|
-
const l = i.getTime(), s = n.getTime();
|
|
65
|
-
let o, a, d, r = t.start.getTime(), u = t.end.getTime(), m = !1;
|
|
66
|
-
for (t.end.getHours() || t.end.getMinutes() || (u -= 1e3), t.segments = {}, t.repeat ? (o = l, a = Math.min(s, t.repeat.until ? y.stringToDate(t.repeat.until).getTime() : s)) : (o = Math.max(l, r), a = Math.min(s, u)); o <= a; ) {
|
|
67
|
-
let p = !1;
|
|
68
|
-
const E = y.addDays(new Date(o), 1).setHours(0, 0, 0, 0);
|
|
69
|
-
let _, x, V, C;
|
|
70
|
-
if (t.repeat) {
|
|
71
|
-
const Y = new Date(o), A = y.formatDateLite(Y);
|
|
72
|
-
(m || t.occurrences && t.occurrences[A]) && (m || (r = t.occurrences[A].start, d = new Date(r).setHours(0, 0, 0, 0), u = t.occurrences[A].end), m = !0, p = !0), _ = o === d, x = A === y.formatDateLite(new Date(u)), V = new Date(_ ? r : o), C = y.formatDateLite(V), x && (m = !1);
|
|
73
|
-
} else
|
|
74
|
-
p = !0, _ = o === r, x = a === u && E > a, V = _ ? t.start : new Date(o), C = y.formatDateLite(_ ? t.start : V);
|
|
75
|
-
p && (t.segments[C] = { start: V, startTimeMinutes: _ ? t.startTimeMinutes : 0, endTimeMinutes: x ? t.endTimeMinutes : q, isFirstDay: _, isLastDay: x }), o = E;
|
|
76
|
-
}
|
|
77
|
-
return t;
|
|
78
|
-
}
|
|
79
|
-
deleteAnEvent(t) {
|
|
80
|
-
this._vuecal.emitWithEvent("event-delete", t), this._vuecal.mutableEvents = this._vuecal.mutableEvents.filter((i) => i._eid !== t._eid), this._vuecal.view.events = this._vuecal.view.events.filter((i) => i._eid !== t._eid);
|
|
81
|
-
}
|
|
82
|
-
checkCellOverlappingEvents(t, i) {
|
|
83
|
-
K = t.slice(0), D = {}, t.forEach((l) => {
|
|
84
|
-
K.shift(), D[l._eid] || (D[l._eid] = { overlaps: [], start: l.start, position: 0 }), D[l._eid].position = 0, K.forEach((s) => {
|
|
85
|
-
D[s._eid] || (D[s._eid] = { overlaps: [], start: s.start, position: 0 });
|
|
86
|
-
const o = this.eventInRange(s, l.start, l.end), a = i.overlapsPerTimeStep ? y.datesInSameTimeStep(l.start, s.start, i.timeStep) : 1;
|
|
87
|
-
if (l.background || l.allDay || s.background || s.allDay || !o || !a) {
|
|
88
|
-
let d, r;
|
|
89
|
-
(d = (D[l._eid] || { overlaps: [] }).overlaps.indexOf(s._eid)) > -1 && D[l._eid].overlaps.splice(d, 1), (r = (D[s._eid] || { overlaps: [] }).overlaps.indexOf(l._eid)) > -1 && D[s._eid].overlaps.splice(r, 1), D[s._eid].position--;
|
|
90
|
-
} else
|
|
91
|
-
D[l._eid].overlaps.push(s._eid), D[l._eid].overlaps = [...new Set(D[l._eid].overlaps)], D[s._eid].overlaps.push(l._eid), D[s._eid].overlaps = [...new Set(D[s._eid].overlaps)], D[s._eid].position++;
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
let n = 0;
|
|
95
|
-
for (const l in D) {
|
|
96
|
-
const s = D[l], o = s.overlaps.map((a) => ({ id: a, start: D[a].start }));
|
|
97
|
-
o.push({ id: l, start: s.start }), o.sort((a, d) => a.start < d.start ? -1 : a.start > d.start ? 1 : a.id > d.id ? -1 : 1), s.position = o.findIndex((a) => a.id === l), n = Math.max(this.getOverlapsStreak(s, D), n);
|
|
98
|
-
}
|
|
99
|
-
return [D, n];
|
|
100
|
-
}
|
|
101
|
-
getOverlapsStreak(t, i = {}) {
|
|
102
|
-
let n = t.overlaps.length + 1, l = [];
|
|
103
|
-
return t.overlaps.forEach((s) => {
|
|
104
|
-
l.includes(s) || t.overlaps.filter((o) => o !== s).forEach((o) => {
|
|
105
|
-
i[o].overlaps.includes(s) || l.push(o);
|
|
106
|
-
});
|
|
107
|
-
}), l = [...new Set(l)], n -= l.length, n;
|
|
108
|
-
}
|
|
109
|
-
eventInRange(t, i, n) {
|
|
110
|
-
if (t.allDay || !this._vuecal.time) {
|
|
111
|
-
const o = new Date(t.start).setHours(0, 0, 0, 0);
|
|
112
|
-
return new Date(t.end).setHours(23, 59, 0, 0) >= new Date(i).setHours(0, 0, 0, 0) && o <= new Date(n).setHours(0, 0, 0, 0);
|
|
113
|
-
}
|
|
114
|
-
const l = t.start.getTime(), s = t.end.getTime();
|
|
115
|
-
return l < n.getTime() && s > i.getTime();
|
|
9
|
+
import { openBlock, createElementBlock, Fragment, renderList, normalizeClass, normalizeStyle, createVNode, Transition, withCtx, createElementVNode, renderSlot, toDisplayString, createCommentVNode, createTextVNode, resolveComponent, createBlock, resolveDynamicComponent, createSlots, withKeys, withModifiers, TransitionGroup, normalizeProps, mergeProps } from "vue";
|
|
10
|
+
const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
|
|
11
|
+
const v = glob[path];
|
|
12
|
+
if (v) {
|
|
13
|
+
return typeof v === "function" ? v() : Promise.resolve(v);
|
|
116
14
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}, cleanupHeading: (e) => ({ label: e.full, date: e.date, ...e.today ? { today: e.today } : {} }) }, computed: { headings() {
|
|
127
|
-
if (!["month", "week"].includes(this.view.id))
|
|
128
|
-
return [];
|
|
129
|
-
let e = !1;
|
|
130
|
-
return this.weekDays.map((t, i) => {
|
|
131
|
-
const n = this.utils.date.addDays(this.view.startDate, this.vuecal.startWeekOnSunday ? i - 1 : i);
|
|
132
|
-
return { hide: t.hide, full: t.label, small: t.short || t.label.substr(0, 3), xsmall: t.short || t.label.substr(0, 1), ...this.view.id === "week" ? { dayOfMonth: n.getDate(), date: n, today: !e && this.utils.date.isToday(n) && !e++ } : {} };
|
|
133
|
-
});
|
|
134
|
-
}, cellWidth() {
|
|
135
|
-
return 100 / (7 - this.weekDays.reduce((e, t) => e + t.hide, 0));
|
|
136
|
-
}, weekdayCellStyles() {
|
|
137
|
-
return { ...this.vuecal.hideWeekdays.length ? { width: `${this.cellWidth}%` } : {} };
|
|
138
|
-
}, cellHeadingsClickable() {
|
|
139
|
-
return this.view.id === "week" && (this.vuecal.clickToNavigate || this.vuecal.dblclickToNavigate);
|
|
140
|
-
} } }, [["render", function(e, t, i, n, l, s) {
|
|
141
|
-
return h(), c("div", ve, [(h(!0), c(T, null, S(s.headings, (o, a) => (h(), c(T, { key: a }, [o.hide ? v("", !0) : (h(), c("div", { key: 0, class: b(["vuecal__flex vuecal__heading", { today: o.today, clickable: s.cellHeadingsClickable }]), style: $(s.weekdayCellStyles), onClick: (d) => s.view.id === "week" && s.selectCell(o.date, d), onDblclick: t[0] || (t[0] = (d) => s.view.id === "week" && s.vuecal.dblclickToNavigate && i.switchToNarrowerView()) }, [U(R, { name: `slide-fade--${i.transitionDirection}`, appear: s.vuecal.transitions }, { default: g(() => [(h(), c("div", { class: "vuecal__flex", column: "", key: !!s.vuecal.transitions && `${a}-${o.dayOfMonth}` }, [k("div", pe, [w(e.$slots, "weekday-heading", { heading: s.cleanupHeading(o), view: s.view }, () => [k("span", we, f(o.full), 1), k("span", ye, f(o.small), 1), k("span", De, f(o.xsmall), 1), o.dayOfMonth ? (h(), c("span", ge, "\xA0" + f(o.dayOfMonth), 1)) : v("", !0)])]), s.vuecal.hasSplits && s.vuecal.stickySplitLabels ? (h(), c("div", fe, [(h(!0), c(T, null, S(s.vuecal.daySplits, (d, r) => (h(), c("div", { class: b(["day-split-header", d.class || !1]), key: r }, [w(e.$slots, "split-label", { split: d, view: s.view }, () => [M(f(d.label), 1)])], 2))), 128))])) : v("", !0)]))]), _: 2 }, 1032, ["name", "appear"])], 46, me))], 64))), 128))]);
|
|
142
|
-
}]]), _e = { class: "vuecal__header" }, ke = { key: 0, class: "vuecal__flex vuecal__menu", role: "tablist", "aria-label": "Calendar views navigation" }, be = ["onDragenter", "onDragleave", "onClick", "aria-label"], Te = { key: 1, class: "vuecal__title-bar" }, Ee = ["aria-label"], Ce = { class: "vuecal__flex vuecal__title", grow: "" }, Me = ["aria-label"], Se = { key: 0, class: "vuecal__flex vuecal__split-days-headers" }, Oe = B({ inject: ["vuecal", "previous", "next", "switchView", "updateSelectedDate", "modules", "view"], components: { WeekdaysHeadings: ne }, props: { options: { type: Object, default: () => ({}) }, editEvents: { type: Object, required: !0 }, hasSplits: { type: [Boolean, Number], default: !1 }, daySplits: { type: Array, default: () => [] }, viewProps: { type: Object, default: () => ({}) }, weekDays: { type: Array, default: () => [] }, switchToNarrowerView: { type: Function, default: () => {
|
|
143
|
-
} } }, data: () => ({ highlightedControl: null }), methods: { goToToday() {
|
|
144
|
-
this.updateSelectedDate(new Date(new Date().setHours(0, 0, 0, 0)));
|
|
145
|
-
}, switchToBroaderView() {
|
|
146
|
-
this.transitionDirection = "left", this.broaderView && this.switchView(this.broaderView);
|
|
147
|
-
} }, computed: { transitionDirection: { get() {
|
|
148
|
-
return this.vuecal.transitionDirection;
|
|
149
|
-
}, set(e) {
|
|
150
|
-
this.vuecal.transitionDirection = e;
|
|
151
|
-
} }, broaderView() {
|
|
152
|
-
const { enabledViews: e } = this.vuecal;
|
|
153
|
-
return e[e.indexOf(this.view.id) - 1];
|
|
154
|
-
}, showDaySplits() {
|
|
155
|
-
return this.view.id === "day" && this.hasSplits && this.options.stickySplitLabels && !this.options.minSplitWidth;
|
|
156
|
-
}, dnd() {
|
|
157
|
-
return this.modules.dnd;
|
|
158
|
-
} } }, [["render", function(e, t, i, n, l, s) {
|
|
159
|
-
const o = j("weekdays-headings");
|
|
160
|
-
return h(), c("div", _e, [i.options.hideViewSelector ? v("", !0) : (h(), c("div", ke, [(h(!0), c(T, null, S(i.viewProps.views, (a, d) => (h(), c(T, { key: d }, [a.enabled ? (h(), c("button", { key: 0, class: b(["vuecal__view-btn", { "vuecal__view-btn--active": s.view.id === d, "vuecal__view-btn--highlighted": e.highlightedControl === d }]), type: "button", onDragenter: (r) => i.editEvents.drag && s.dnd && s.dnd.viewSelectorDragEnter(r, d, e.$data), onDragleave: (r) => i.editEvents.drag && s.dnd && s.dnd.viewSelectorDragLeave(r, d, e.$data), onClick: (r) => s.switchView(d, null, !0), "aria-label": `${a.label} view` }, f(a.label), 43, be)) : v("", !0)], 64))), 128))])), i.options.hideTitleBar ? v("", !0) : (h(), c("div", Te, [k("button", { class: b(["vuecal__arrow vuecal__arrow--prev", { "vuecal__arrow--highlighted": e.highlightedControl === "previous" }]), type: "button", onClick: t[0] || (t[0] = (...a) => s.previous && s.previous(...a)), onDragenter: t[1] || (t[1] = (a) => i.editEvents.drag && s.dnd && s.dnd.viewSelectorDragEnter(a, "previous", e.$data)), onDragleave: t[2] || (t[2] = (a) => i.editEvents.drag && s.dnd && s.dnd.viewSelectorDragLeave(a, "previous", e.$data)), "aria-label": `Previous ${s.view.id}` }, [w(e.$slots, "arrow-prev")], 42, Ee), k("div", Ce, [U(R, { name: i.options.transitions ? `slide-fade--${s.transitionDirection}` : "" }, { default: g(() => [(h(), H(de(s.broaderView ? "button" : "span"), { type: !!s.broaderView && "button", key: `${s.view.id}${s.view.startDate.toString()}`, onClick: t[3] || (t[3] = (a) => !!s.broaderView && s.switchToBroaderView()), "aria-label": !!s.broaderView && `Go to ${s.broaderView} view` }, { default: g(() => [w(e.$slots, "title")]), _: 3 }, 8, ["type", "aria-label"]))]), _: 3 }, 8, ["name"])]), i.options.todayButton ? (h(), c("button", { key: 0, class: b(["vuecal__today-btn", { "vuecal__today-btn--highlighted": e.highlightedControl === "today" }]), type: "button", onClick: t[4] || (t[4] = (...a) => s.goToToday && s.goToToday(...a)), onDragenter: t[5] || (t[5] = (a) => i.editEvents.drag && s.dnd && s.dnd.viewSelectorDragEnter(a, "today", e.$data)), onDragleave: t[6] || (t[6] = (a) => i.editEvents.drag && s.dnd && s.dnd.viewSelectorDragLeave(a, "today", e.$data)), "aria-label": "Today" }, [w(e.$slots, "today-button")], 34)) : v("", !0), k("button", { class: b(["vuecal__arrow vuecal__arrow--next", { "vuecal__arrow--highlighted": e.highlightedControl === "next" }]), type: "button", onClick: t[7] || (t[7] = (...a) => s.next && s.next(...a)), onDragenter: t[8] || (t[8] = (a) => i.editEvents.drag && s.dnd && s.dnd.viewSelectorDragEnter(a, "next", e.$data)), onDragleave: t[9] || (t[9] = (a) => i.editEvents.drag && s.dnd && s.dnd.viewSelectorDragLeave(a, "next", e.$data)), "aria-label": `Next ${s.view.id}` }, [w(e.$slots, "arrow-next")], 42, Me)])), i.viewProps.weekDaysInHeader ? (h(), H(o, { key: 2, "week-days": i.weekDays, "transition-direction": s.transitionDirection, "switch-to-narrower-view": i.switchToNarrowerView }, X({ _: 2 }, [e.$slots["weekday-heading"] ? { name: "weekday-heading", fn: g(({ heading: a, view: d }) => [w(e.$slots, "weekday-heading", { heading: a, view: d })]), key: "0" } : void 0, e.$slots["split-label"] ? { name: "split-label", fn: g(({ split: a }) => [w(e.$slots, "split-label", { split: a, view: s.view })]), key: "1" } : void 0]), 1032, ["week-days", "transition-direction", "switch-to-narrower-view"])) : v("", !0), U(R, { name: `slide-fade--${s.transitionDirection}` }, { default: g(() => [s.showDaySplits ? (h(), c("div", Se, [(h(!0), c(T, null, S(i.daySplits, (a, d) => (h(), c("div", { class: b(["day-split-header", a.class || !1]), key: d }, [w(e.$slots, "split-label", { split: a, view: s.view.id }, () => [M(f(a.label), 1)])], 2))), 128))])) : v("", !0)]), _: 3 }, 8, ["name"])]);
|
|
161
|
-
}]]), $e = ["draggable"], xe = { inject: ["vuecal", "utils", "modules", "view", "domEvents", "editEvents"], props: { cellFormattedDate: { type: String, default: "" }, event: { type: Object, default: () => ({}) }, cellEvents: { type: Array, default: () => [] }, overlaps: { type: Array, default: () => [] }, eventPosition: { type: Number, default: 0 }, overlapsStreak: { type: Number, default: 0 }, allDay: { type: Boolean, default: !1 } }, data: () => ({ touch: { dragThreshold: 30, startX: 0, startY: 0, dragged: !1 } }), methods: { onMouseDown(e, t = !1) {
|
|
162
|
-
if ("ontouchstart" in window && !t)
|
|
163
|
-
return !1;
|
|
164
|
-
const { clickHoldAnEvent: i, focusAnEvent: n, resizeAnEvent: l, dragAnEvent: s } = this.domEvents;
|
|
165
|
-
if (n._eid === this.event._eid && i._eid === this.event._eid)
|
|
166
|
-
return !0;
|
|
167
|
-
this.focusEvent(), i._eid = null, this.vuecal.editEvents.delete && this.event.deletable && (i.timeoutId = setTimeout(() => {
|
|
168
|
-
l._eid || s._eid || (i._eid = this.event._eid, this.event.deleting = !0);
|
|
169
|
-
}, i.timeout));
|
|
170
|
-
}, onMouseUp(e) {
|
|
171
|
-
this.domEvents.focusAnEvent._eid !== this.event._eid || this.touch.dragged || (this.domEvents.focusAnEvent.mousedUp = !0), this.touch.dragged = !1;
|
|
172
|
-
}, onMouseEnter(e) {
|
|
173
|
-
e.preventDefault(), this.vuecal.emitWithEvent("event-mouse-enter", this.event);
|
|
174
|
-
}, onMouseLeave(e) {
|
|
175
|
-
e.preventDefault(), this.vuecal.emitWithEvent("event-mouse-leave", this.event);
|
|
176
|
-
}, onTouchMove(e) {
|
|
177
|
-
if (typeof this.vuecal.onEventClick != "function")
|
|
178
|
-
return;
|
|
179
|
-
const { clientX: t, clientY: i } = e.touches[0], { startX: n, startY: l, dragThreshold: s } = this.touch;
|
|
180
|
-
(Math.abs(t - n) > s || Math.abs(i - l) > s) && (this.touch.dragged = !0);
|
|
181
|
-
}, onTouchStart(e) {
|
|
182
|
-
this.touch.startX = e.touches[0].clientX, this.touch.startY = e.touches[0].clientY, this.onMouseDown(e, !0);
|
|
183
|
-
}, onEnterKeypress(e) {
|
|
184
|
-
if (typeof this.vuecal.onEventClick == "function")
|
|
185
|
-
return this.vuecal.onEventClick(this.event, e);
|
|
186
|
-
}, onDblClick(e) {
|
|
187
|
-
if (typeof this.vuecal.onEventDblclick == "function")
|
|
188
|
-
return this.vuecal.onEventDblclick(this.event, e);
|
|
189
|
-
}, onDragStart(e) {
|
|
190
|
-
this.dnd && this.dnd.eventDragStart(e, this.event);
|
|
191
|
-
}, onDragEnd() {
|
|
192
|
-
this.dnd && this.dnd.eventDragEnd(this.event);
|
|
193
|
-
}, onResizeHandleMouseDown() {
|
|
194
|
-
this.focusEvent(), this.domEvents.dragAnEvent._eid = null, this.domEvents.resizeAnEvent = Object.assign(this.domEvents.resizeAnEvent, { _eid: this.event._eid, start: (this.segment || this.event).start, split: this.event.split || null, segment: !!this.segment && this.utils.date.formatDateLite(this.segment.start), originalEnd: new Date((this.segment || this.event).end), originalEndTimeMinutes: this.event.endTimeMinutes }), this.event.resizing = !0;
|
|
195
|
-
}, deleteEvent(e = !1) {
|
|
196
|
-
if ("ontouchstart" in window && !e)
|
|
197
|
-
return !1;
|
|
198
|
-
this.utils.event.deleteAnEvent(this.event);
|
|
199
|
-
}, touchDeleteEvent(e) {
|
|
200
|
-
this.deleteEvent(!0);
|
|
201
|
-
}, cancelDeleteEvent() {
|
|
202
|
-
this.event.deleting = !1;
|
|
203
|
-
}, focusEvent() {
|
|
204
|
-
const { focusAnEvent: e } = this.domEvents, t = e._eid;
|
|
205
|
-
if (t !== this.event._eid) {
|
|
206
|
-
if (t) {
|
|
207
|
-
const i = this.view.events.find((n) => n._eid === t);
|
|
208
|
-
i && (i.focused = !1);
|
|
209
|
-
}
|
|
210
|
-
this.vuecal.cancelDelete(), this.vuecal.emitWithEvent("event-focus", this.event), e._eid = this.event._eid, this.event.focused = !0;
|
|
211
|
-
}
|
|
212
|
-
} }, computed: { eventDimensions() {
|
|
213
|
-
const { startTimeMinutes: e, endTimeMinutes: t } = this.segment || this.event;
|
|
214
|
-
let i = e - this.vuecal.timeFrom;
|
|
215
|
-
const n = Math.max(Math.round(i * this.vuecal.timeCellHeight / this.vuecal.timeStep), 0);
|
|
216
|
-
i = Math.min(t, this.vuecal.timeTo) - this.vuecal.timeFrom;
|
|
217
|
-
const l = Math.round(i * this.vuecal.timeCellHeight / this.vuecal.timeStep);
|
|
218
|
-
return { top: n, height: Math.max(l - n, 5) };
|
|
219
|
-
}, eventStyles() {
|
|
220
|
-
if (this.event.allDay || !this.vuecal.time || !this.event.endTimeMinutes || this.view.id === "month" || this.allDay)
|
|
221
|
-
return {};
|
|
222
|
-
let e = 100 / Math.min(this.overlaps.length + 1, this.overlapsStreak), t = 100 / (this.overlaps.length + 1) * this.eventPosition;
|
|
223
|
-
this.vuecal.minEventWidth && e < this.vuecal.minEventWidth && (e = this.vuecal.minEventWidth, t = (100 - this.vuecal.minEventWidth) / this.overlaps.length * this.eventPosition);
|
|
224
|
-
const { top: i, height: n } = this.eventDimensions;
|
|
225
|
-
return { top: `${i}px`, height: `${n}px`, width: `${e}%`, left: this.event.left && `${this.event.left}px` || `${t}%` };
|
|
226
|
-
}, eventClasses() {
|
|
227
|
-
const { isFirstDay: e, isLastDay: t } = this.segment || {};
|
|
228
|
-
return { [this.event.class]: !!this.event.class, "vuecal__event--focus": this.event.focused, "vuecal__event--resizing": this.event.resizing, "vuecal__event--background": this.event.background, "vuecal__event--deletable": this.event.deleting, "vuecal__event--all-day": this.event.allDay, "vuecal__event--dragging": !this.event.draggingStatic && this.event.dragging, "vuecal__event--static": this.event.dragging && this.event.draggingStatic, "vuecal__event--multiple-days": !!this.segment, "event-start": this.segment && e && !t, "event-middle": this.segment && !e && !t, "event-end": this.segment && t && !e };
|
|
229
|
-
}, segment() {
|
|
230
|
-
return this.event.segments && this.event.segments[this.cellFormattedDate] || null;
|
|
231
|
-
}, draggable() {
|
|
232
|
-
const { draggable: e, background: t, daysCount: i } = this.event;
|
|
233
|
-
return this.vuecal.editEvents.drag && e && !t && i === 1;
|
|
234
|
-
}, resizable() {
|
|
235
|
-
const { editEvents: e, time: t } = this.vuecal;
|
|
236
|
-
return e.resize && this.event.resizable && t && !this.allDay && (!this.segment || this.segment && this.segment.isLastDay) && this.view.id !== "month";
|
|
237
|
-
}, dnd() {
|
|
238
|
-
return this.modules.dnd;
|
|
239
|
-
} } }, We = ["data-split", "aria-label", "onTouchstart", "onMousedown", "onDragover", "onDrop"], He = { key: 0, class: "cell-time-labels" }, Ve = ["innerHTML"], Ae = { key: 2, class: "vuecal__cell-events" }, je = ["title"], ae = B({ inject: ["vuecal", "utils", "modules", "view", "domEvents"], components: { Event: B(xe, [["render", function(e, t, i, n, l, s) {
|
|
240
|
-
return h(), c("div", { class: b(["vuecal__event", s.eventClasses]), style: $(s.eventStyles), tabindex: "0", onFocus: t[4] || (t[4] = (...o) => s.focusEvent && s.focusEvent(...o)), onKeypress: t[5] || (t[5] = Z(L((...o) => s.onEnterKeypress && s.onEnterKeypress(...o), ["stop"]), ["enter"])), onMouseenter: t[6] || (t[6] = (...o) => s.onMouseEnter && s.onMouseEnter(...o)), onMouseleave: t[7] || (t[7] = (...o) => s.onMouseLeave && s.onMouseLeave(...o)), onTouchstart: t[8] || (t[8] = L((...o) => s.onTouchStart && s.onTouchStart(...o), ["stop"])), onMousedown: t[9] || (t[9] = (o) => s.onMouseDown(o)), onMouseup: t[10] || (t[10] = (...o) => s.onMouseUp && s.onMouseUp(...o)), onTouchend: t[11] || (t[11] = (...o) => s.onMouseUp && s.onMouseUp(...o)), onTouchmove: t[12] || (t[12] = (...o) => s.onTouchMove && s.onTouchMove(...o)), onDblclick: t[13] || (t[13] = (...o) => s.onDblClick && s.onDblClick(...o)), draggable: s.draggable, onDragstart: t[14] || (t[14] = (o) => s.draggable && s.onDragStart(o)), onDragend: t[15] || (t[15] = (o) => s.draggable && s.onDragEnd()) }, [s.vuecal.editEvents.delete && i.event.deletable ? (h(), c("div", { key: 0, class: "vuecal__event-delete", onClick: t[0] || (t[0] = L((...o) => s.deleteEvent && s.deleteEvent(...o), ["stop"])), onTouchstart: t[1] || (t[1] = L((...o) => s.touchDeleteEvent && s.touchDeleteEvent(...o), ["stop"])) }, f(s.vuecal.texts.deleteEvent), 33)) : v("", !0), w(e.$slots, "event", { event: i.event, view: s.view.id }), s.resizable ? (h(), c("div", { key: 1, class: "vuecal__event-resize-handle", contenteditable: "false", onMousedown: t[2] || (t[2] = L((...o) => s.onResizeHandleMouseDown && s.onResizeHandleMouseDown(...o), ["stop", "prevent"])), onTouchstart: t[3] || (t[3] = L((...o) => s.onResizeHandleMouseDown && s.onResizeHandleMouseDown(...o), ["stop", "prevent"])) }, null, 32)) : v("", !0)], 46, $e);
|
|
241
|
-
}]]) }, props: { options: { type: Object, default: () => ({}) }, editEvents: { type: Object, required: !0 }, data: { type: Object, required: !0 }, cellSplits: { type: Array, default: () => [] }, minTimestamp: { type: [Number, null], default: null }, maxTimestamp: { type: [Number, null], default: null }, cellWidth: { type: [Number, Boolean], default: !1 }, allDay: { type: Boolean, default: !1 } }, data: () => ({ cellOverlaps: {}, cellOverlapsStreak: 1, timeAtCursor: null, highlighted: !1, highlightedSplit: null }), methods: { getSplitAtCursor({ target: e }) {
|
|
242
|
-
let t = e.classList.contains("vuecal__cell-split") ? e : this.vuecal.findAncestor(e, "vuecal__cell-split");
|
|
243
|
-
return t && (t = t.attributes["data-split"].value, parseInt(t).toString() === t.toString() && (t = parseInt(t))), t || null;
|
|
244
|
-
}, splitClasses(e) {
|
|
245
|
-
return { "vuecal__cell-split": !0, "vuecal__cell-split--highlighted": this.highlightedSplit === e.id, [e.class]: !!e.class };
|
|
246
|
-
}, checkCellOverlappingEvents() {
|
|
247
|
-
this.options.time && this.eventsCount && !this.splitsCount && (this.eventsCount === 1 ? (this.cellOverlaps = [], this.cellOverlapsStreak = 1) : [this.cellOverlaps, this.cellOverlapsStreak] = this.utils.event.checkCellOverlappingEvents(this.events, this.options));
|
|
248
|
-
}, isDOMElementAnEvent(e) {
|
|
249
|
-
return this.vuecal.isDOMElementAnEvent(e);
|
|
250
|
-
}, selectCell(e, t = !1) {
|
|
251
|
-
const i = this.splitsCount ? this.getSplitAtCursor(e) : null;
|
|
252
|
-
this.utils.cell.selectCell(t, this.timeAtCursor, i), this.timeAtCursor = null;
|
|
253
|
-
}, onCellkeyPressEnter(e) {
|
|
254
|
-
this.isSelected || this.onCellFocus(e);
|
|
255
|
-
const t = this.splitsCount ? this.getSplitAtCursor(e) : null;
|
|
256
|
-
this.utils.cell.keyPressEnterCell(this.timeAtCursor, t), this.timeAtCursor = null;
|
|
257
|
-
}, onCellFocus(e) {
|
|
258
|
-
if (!this.isSelected && !this.isDisabled) {
|
|
259
|
-
this.isSelected = this.data.startDate;
|
|
260
|
-
const t = this.splitsCount ? this.getSplitAtCursor(e) : null, i = this.timeAtCursor || this.data.startDate;
|
|
261
|
-
this.vuecal.$emit("cell-focus", t ? { date: i, split: t } : i);
|
|
262
|
-
}
|
|
263
|
-
}, onCellMouseDown(e, t = null, i = !1) {
|
|
264
|
-
if ("ontouchstart" in window && !i)
|
|
265
|
-
return !1;
|
|
266
|
-
this.isSelected || this.onCellFocus(e);
|
|
267
|
-
const { clickHoldACell: n, focusAnEvent: l } = this.domEvents;
|
|
268
|
-
this.domEvents.cancelClickEventCreation = !1, n.eventCreated = !1, this.timeAtCursor = new Date(this.data.startDate);
|
|
269
|
-
const { minutes: s, cursorCoords: { y: o } } = this.vuecal.minutesAtCursor(e);
|
|
270
|
-
this.timeAtCursor.setMinutes(s);
|
|
271
|
-
const a = this.isDOMElementAnEvent(e.target);
|
|
272
|
-
!a && l._eid && ((this.view.events.find((d) => d._eid === l._eid) || {}).focused = !1), this.editEvents.create && !a && this.setUpEventCreation(e, o);
|
|
273
|
-
}, setUpEventCreation(e, t) {
|
|
274
|
-
if (this.options.dragToCreateEvent && ["week", "day"].includes(this.view.id)) {
|
|
275
|
-
const { dragCreateAnEvent: i } = this.domEvents;
|
|
276
|
-
if (i.startCursorY = t, i.split = this.splitsCount ? this.getSplitAtCursor(e) : null, i.start = this.timeAtCursor, this.options.snapToTime) {
|
|
277
|
-
let n = 60 * this.timeAtCursor.getHours() + this.timeAtCursor.getMinutes();
|
|
278
|
-
const l = n + this.options.snapToTime / 2;
|
|
279
|
-
n = l - l % this.options.snapToTime, i.start.setHours(0, n, 0, 0);
|
|
280
|
-
}
|
|
281
|
-
} else
|
|
282
|
-
this.options.cellClickHold && ["month", "week", "day"].includes(this.view.id) && this.setUpCellHoldTimer(e);
|
|
283
|
-
}, setUpCellHoldTimer(e) {
|
|
284
|
-
const { clickHoldACell: t } = this.domEvents;
|
|
285
|
-
t.cellId = `${this.vuecal._.uid}_${this.data.formattedDate}`, t.split = this.splitsCount ? this.getSplitAtCursor(e) : null, t.timeoutId = setTimeout(() => {
|
|
286
|
-
if (t.cellId && !this.domEvents.cancelClickEventCreation) {
|
|
287
|
-
const { _eid: i } = this.utils.event.createAnEvent(this.timeAtCursor, null, t.split ? { split: t.split } : {});
|
|
288
|
-
t.eventCreated = i;
|
|
289
|
-
}
|
|
290
|
-
}, t.timeout);
|
|
291
|
-
}, onCellTouchStart(e, t = null) {
|
|
292
|
-
this.onCellMouseDown(e, t, !0);
|
|
293
|
-
}, onCellClick(e) {
|
|
294
|
-
this.isDOMElementAnEvent(e.target) || this.selectCell(e);
|
|
295
|
-
}, onCellDblClick(e) {
|
|
296
|
-
const t = new Date(this.data.startDate);
|
|
297
|
-
t.setMinutes(this.vuecal.minutesAtCursor(e).minutes);
|
|
298
|
-
const i = this.splitsCount ? this.getSplitAtCursor(e) : null;
|
|
299
|
-
this.vuecal.$emit("cell-dblclick", i ? { date: t, split: i } : t), this.options.dblclickToNavigate && this.vuecal.switchToNarrowerView();
|
|
300
|
-
}, onCellContextMenu(e) {
|
|
301
|
-
e.stopPropagation(), e.preventDefault();
|
|
302
|
-
const t = new Date(this.data.startDate), { cursorCoords: i, minutes: n } = this.vuecal.minutesAtCursor(e);
|
|
303
|
-
t.setMinutes(n);
|
|
304
|
-
const l = this.splitsCount ? this.getSplitAtCursor(e) : null;
|
|
305
|
-
this.vuecal.$emit("cell-contextmenu", { date: t, ...i, ...l || {}, e });
|
|
306
|
-
} }, computed: { dnd() {
|
|
307
|
-
return this.modules.dnd;
|
|
308
|
-
}, nowInMinutes() {
|
|
309
|
-
return this.utils.date.dateToMinutes(this.vuecal.now);
|
|
310
|
-
}, isBeforeMinDate() {
|
|
311
|
-
return this.minTimestamp !== null && this.minTimestamp > this.data.endDate.getTime();
|
|
312
|
-
}, isAfterMaxDate() {
|
|
313
|
-
return this.maxTimestamp && this.maxTimestamp < this.data.startDate.getTime();
|
|
314
|
-
}, isDisabled() {
|
|
315
|
-
const { disableDays: e } = this.options, { isYearsOrYearView: t } = this.vuecal;
|
|
316
|
-
return !(!e.length || !e.includes(this.data.formattedDate) || t) || this.isBeforeMinDate || this.isAfterMaxDate;
|
|
317
|
-
}, isSelected: { get() {
|
|
318
|
-
let e = !1;
|
|
319
|
-
const { selectedDate: t } = this.view;
|
|
320
|
-
return e = this.view.id === "years" ? t.getFullYear() === this.data.startDate.getFullYear() : this.view.id === "year" ? t.getFullYear() === this.data.startDate.getFullYear() && t.getMonth() === this.data.startDate.getMonth() : t.getTime() === this.data.startDate.getTime(), e;
|
|
321
|
-
}, set(e) {
|
|
322
|
-
this.view.selectedDate = e, this.vuecal.$emit("update:selected-date", this.view.selectedDate);
|
|
323
|
-
} }, isWeekOrDayView() {
|
|
324
|
-
return ["week", "day"].includes(this.view.id);
|
|
325
|
-
}, transitionDirection() {
|
|
326
|
-
return this.vuecal.transitionDirection;
|
|
327
|
-
}, specialHours() {
|
|
328
|
-
return this.data.specialHours.map((e) => {
|
|
329
|
-
let { from: t, to: i } = e;
|
|
330
|
-
return t = Math.max(t, this.options.timeFrom), i = Math.min(i, this.options.timeTo), { ...e, height: (i - t) * this.timeScale, top: (t - this.options.timeFrom) * this.timeScale };
|
|
331
|
-
});
|
|
332
|
-
}, events() {
|
|
333
|
-
const { startDate: e, endDate: t } = this.data;
|
|
334
|
-
let i = [];
|
|
335
|
-
if (!["years", "year"].includes(this.view.id) || this.options.eventsCountOnYearView) {
|
|
336
|
-
if (i = this.view.events.slice(0), this.view.id === "month" && i.push(...this.view.outOfScopeEvents), i = i.filter((n) => this.utils.event.eventInRange(n, e, t)), this.options.showAllDayEvents && this.view.id !== "month" && (i = i.filter((n) => !!n.allDay === this.allDay)), this.options.time && this.isWeekOrDayView && !this.allDay) {
|
|
337
|
-
const { timeFrom: n, timeTo: l } = this.options;
|
|
338
|
-
i = i.filter((s) => {
|
|
339
|
-
const o = s.daysCount > 1 && s.segments[this.data.formattedDate] || {}, a = s.daysCount === 1 && s.startTimeMinutes < l && s.endTimeMinutes > n, d = s.daysCount > 1 && o.startTimeMinutes < l && o.endTimeMinutes > n;
|
|
340
|
-
return s.allDay || a || d || !1;
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
!this.options.time || !this.isWeekOrDayView || this.options.showAllDayEvents && this.allDay || i.sort((n, l) => n.start < l.start ? -1 : 1), this.cellSplits.length || this.$nextTick(this.checkCellOverlappingEvents);
|
|
344
|
-
}
|
|
345
|
-
return i;
|
|
346
|
-
}, eventsCount() {
|
|
347
|
-
return this.events.length;
|
|
348
|
-
}, splits() {
|
|
349
|
-
return this.cellSplits.map((e, t) => {
|
|
350
|
-
const i = this.events.filter((s) => s.split === e.id), [n, l] = this.utils.event.checkCellOverlappingEvents(i.filter((s) => !s.background && !s.allDay), this.options);
|
|
351
|
-
return { ...e, overlaps: n, overlapsStreak: l, events: i };
|
|
15
|
+
return new Promise((_, reject) => {
|
|
16
|
+
(typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
|
|
17
|
+
reject.bind(
|
|
18
|
+
null,
|
|
19
|
+
new Error(
|
|
20
|
+
"Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
|
|
21
|
+
)
|
|
22
|
+
)
|
|
23
|
+
);
|
|
352
24
|
});
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const o = j("event");
|
|
371
|
-
return h(), H(ue, { class: b(["vuecal__cell", s.cellClasses]), name: `slide-fade--${s.transitionDirection}`, tag: "div", appear: i.options.transitions, style: $(s.cellStyles) }, { default: g(() => [(h(!0), c(T, null, S(s.splitsCount ? s.splits : 1, (a, d) => (h(), c("div", { class: b(["vuecal__flex vuecal__cell-content", s.splitsCount && s.splitClasses(a)]), key: i.options.transitions ? `${s.view.id}-${i.data.content}-${d}` : d, "data-split": !!s.splitsCount && a.id, column: "", tabindex: "0", "aria-label": i.data.content, onFocus: t[0] || (t[0] = (r) => s.onCellFocus(r)), onKeypress: t[1] || (t[1] = Z((r) => s.onCellkeyPressEnter(r), ["enter"])), onTouchstart: (r) => !s.isDisabled && s.onCellTouchStart(r, s.splitsCount ? a.id : null), onMousedown: (r) => !s.isDisabled && s.onCellMouseDown(r, s.splitsCount ? a.id : null), onClick: t[2] || (t[2] = (r) => !s.isDisabled && s.onCellClick(r)), onDblclick: t[3] || (t[3] = (r) => !s.isDisabled && s.onCellDblClick(r)), onContextmenu: t[4] || (t[4] = (r) => !s.isDisabled && i.options.cellContextmenu && s.onCellContextMenu(r)), onDragenter: t[5] || (t[5] = (r) => !s.isDisabled && i.editEvents.drag && s.dnd && s.dnd.cellDragEnter(r, e.$data, i.data.startDate)), onDragover: (r) => !s.isDisabled && i.editEvents.drag && s.dnd && s.dnd.cellDragOver(r, e.$data, i.data.startDate, s.splitsCount ? a.id : null), onDragleave: t[6] || (t[6] = (r) => !s.isDisabled && i.editEvents.drag && s.dnd && s.dnd.cellDragLeave(r, e.$data, i.data.startDate)), onDrop: (r) => !s.isDisabled && i.editEvents.drag && s.dnd && s.dnd.cellDragDrop(r, e.$data, i.data.startDate, s.splitsCount ? a.id : null) }, [i.options.showTimeInCells && i.options.time && s.isWeekOrDayView && !i.allDay ? (h(), c("div", He, [(h(!0), c(T, null, S(s.vuecal.timeCells, (r, u) => (h(), c("span", { class: "cell-time-label", key: u }, f(r.label), 1))), 128))])) : v("", !0), s.isWeekOrDayView && !i.allDay && s.specialHours.length ? (h(!0), c(T, { key: 1 }, S(s.specialHours, (r, u) => (h(), c("div", { class: b(["vuecal__special-hours", `vuecal__special-hours--day${r.day} ${r.class}`]), style: $(`height: ${r.height}px;top: ${r.top}px`) }, [r.label ? (h(), c("div", { key: 0, class: "special-hours-label", innerHTML: r.label }, null, 8, Ve)) : v("", !0)], 6))), 256)) : v("", !0), w(e.$slots, "cell-content", { events: s.events, selectCell: (r) => s.selectCell(r, !0), split: !!s.splitsCount && a }), s.eventsCount && (s.isWeekOrDayView || s.view.id === "month" && i.options.eventsOnMonthView) ? (h(), c("div", Ae, [(h(!0), c(T, null, S(s.splitsCount ? a.events : s.events, (r, u) => (h(), H(o, { key: u, "cell-formatted-date": i.data.formattedDate, event: r, "all-day": i.allDay, "cell-events": s.splitsCount ? a.events : s.events, overlaps: ((s.splitsCount ? a.overlaps[r._eid] : e.cellOverlaps[r._eid]) || []).overlaps, "event-position": ((s.splitsCount ? a.overlaps[r._eid] : e.cellOverlaps[r._eid]) || []).position, "overlaps-streak": s.splitsCount ? a.overlapsStreak : e.cellOverlapsStreak }, { event: g(({ event: m, view: p }) => [w(e.$slots, "event", { view: p, event: m })]), _: 2 }, 1032, ["cell-formatted-date", "event", "all-day", "cell-events", "overlaps", "event-position", "overlaps-streak"]))), 128))])) : v("", !0)], 42, We))), 128)), s.timelineVisible ? (h(), c("div", { class: "vuecal__now-line", style: $(`top: ${s.todaysTimePosition}px`), key: i.options.transitions ? `${s.view.id}-now-line` : "now-line", title: s.utils.date.formatTime(s.vuecal.now) }, null, 12, je)) : v("", !0)]), _: 3 }, 8, ["class", "name", "appear", "style"]);
|
|
372
|
-
}]]), Ye = { key: 0, class: "vuecal__all-day-text", style: { width: "3em" } }, Le = B({ inject: ["vuecal", "view", "editEvents"], components: { "vuecal-cell": ae }, props: { options: { type: Object, required: !0 }, cells: { type: Array, required: !0 }, label: { type: String, required: !0 }, daySplits: { type: Array, default: () => [] }, shortEvents: { type: Boolean, default: !0 }, height: { type: String, default: "" }, cellOrSplitMinWidth: { type: Number, default: null } }, computed: { hasCellOrSplitWidth() {
|
|
373
|
-
return !!(this.options.minCellWidth || this.daySplits.length && this.options.minSplitWidth);
|
|
374
|
-
} } }, [["render", function(e, t, i, n, l, s) {
|
|
375
|
-
const o = j("vuecal-cell");
|
|
376
|
-
return h(), c("div", { class: "vuecal__flex vuecal__all-day", style: $(i.cellOrSplitMinWidth && { height: i.height }) }, [i.cellOrSplitMinWidth ? v("", !0) : (h(), c("div", Ye, [k("span", null, f(i.label), 1)])), k("div", { class: b(["vuecal__flex vuecal__cells", `${s.view.id}-view`]), grow: "", style: $(i.cellOrSplitMinWidth ? `min-width: ${i.cellOrSplitMinWidth}px` : "") }, [(h(!0), c(T, null, S(i.cells, (a, d) => (h(), H(o, { key: d, options: i.options, "edit-events": s.editEvents, data: a, "all-day": !0, "cell-width": i.options.hideWeekdays.length && (s.vuecal.isWeekView || s.vuecal.isMonthView) && s.vuecal.cellWidth, "min-timestamp": i.options.minTimestamp, "max-timestamp": i.options.maxTimestamp, "cell-splits": i.daySplits }, { event: g(({ event: r, view: u }) => [w(e.$slots, "event", { view: u, event: r })]), _: 2 }, 1032, ["options", "edit-events", "data", "cell-width", "min-timestamp", "max-timestamp", "cell-splits"]))), 128))], 6)], 4);
|
|
377
|
-
}]]), Fe = ["lang"], Be = k("i", { class: "angle" }, null, -1), Ne = k("i", { class: "angle" }, null, -1), Ie = { class: "default" }, ze = { key: 0, class: "vuecal__flex vuecal__body", grow: "" }, Pe = ["onBlur", "innerHTML"], Ue = ["innerHTML"], Re = ["innerHTML"], qe = { class: "vuecal__flex", row: "", grow: "" }, Ke = { key: 0, class: "vuecal__time-column" }, Xe = k("span", { class: "vuecal__time-cell-line" }, null, -1), Ge = { class: "vuecal__time-cell-label" }, Ze = { key: 1, class: "vuecal__flex vuecal__week-numbers", column: "" }, Je = ["wrap", "column"], Qe = ["onBlur", "innerHTML"], et = ["innerHTML"], tt = ["innerHTML"], it = ["wrap"], st = ["innerHTML"], nt = ["innerHTML"], at = { key: 2, class: "vuecal__cell-events-count" }, lt = { key: 3, class: "vuecal__no-event" }, ot = ["onBlur", "innerHTML"], rt = ["innerHTML"], dt = { key: 2, class: "vuecal__event-time" }, ut = { key: 0 }, ht = { key: 1, class: "days-to-end" }, ct = ["innerHTML"], vt = { key: 0, class: "vuecal__scrollbar-check" }, mt = [k("div", null, null, -1)], z = 1440, P = { weekDays: Array(7).fill(""), weekDaysShort: [], months: Array(12).fill(""), years: "", year: "", month: "", week: "", day: "", today: "", noEvent: "", allDay: "", deleteEvent: "", createEvent: "", dateFormat: "dddd MMMM D, YYYY", am: "am", pm: "pm" }, ie = ["years", "year", "month", "week", "day"], se = new class {
|
|
378
|
-
constructor(e, t = !1) {
|
|
379
|
-
W(this, "texts", {});
|
|
380
|
-
W(this, "dateToMinutes", (e) => 60 * e.getHours() + e.getMinutes());
|
|
381
|
-
O = this, this._texts = e, t || !Date || Date.prototype.addDays || this._initDatePrototypes();
|
|
25
|
+
};
|
|
26
|
+
let now, todayDate, todayF, self;
|
|
27
|
+
let _dateObject = {};
|
|
28
|
+
let _timeObject = {};
|
|
29
|
+
class DateUtils {
|
|
30
|
+
constructor(texts, noPrototypes = false) {
|
|
31
|
+
__publicField(this, "texts", {});
|
|
32
|
+
/**
|
|
33
|
+
* Simply takes a Date and returns the associated time in minutes (sum of hours + minutes).
|
|
34
|
+
*
|
|
35
|
+
* @param {Date} date the JavaScript Date to extract minutes from.
|
|
36
|
+
* @return {Number} the number of minutes (total of hours plus minutes).
|
|
37
|
+
*/
|
|
38
|
+
__publicField(this, "dateToMinutes", (date) => date.getHours() * 60 + date.getMinutes());
|
|
39
|
+
self = this;
|
|
40
|
+
this._texts = texts;
|
|
41
|
+
if (!noPrototypes && Date && !Date.prototype.addDays) this._initDatePrototypes();
|
|
382
42
|
}
|
|
383
43
|
_initDatePrototypes() {
|
|
384
|
-
Date.prototype.addDays = function(
|
|
385
|
-
return
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
return
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
return
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
return
|
|
404
|
-
}
|
|
405
|
-
|
|
44
|
+
Date.prototype.addDays = function(days) {
|
|
45
|
+
return self.addDays(this, days);
|
|
46
|
+
};
|
|
47
|
+
Date.prototype.subtractDays = function(days) {
|
|
48
|
+
return self.subtractDays(this, days);
|
|
49
|
+
};
|
|
50
|
+
Date.prototype.addHours = function(hours) {
|
|
51
|
+
return self.addHours(this, hours);
|
|
52
|
+
};
|
|
53
|
+
Date.prototype.subtractHours = function(hours) {
|
|
54
|
+
return self.subtractHours(this, hours);
|
|
55
|
+
};
|
|
56
|
+
Date.prototype.addMinutes = function(minutes) {
|
|
57
|
+
return self.addMinutes(this, minutes);
|
|
58
|
+
};
|
|
59
|
+
Date.prototype.subtractMinutes = function(minutes) {
|
|
60
|
+
return self.subtractMinutes(this, minutes);
|
|
61
|
+
};
|
|
62
|
+
Date.prototype.getWeek = function() {
|
|
63
|
+
return self.getWeek(this);
|
|
64
|
+
};
|
|
65
|
+
Date.prototype.isToday = function() {
|
|
66
|
+
return self.isToday(this);
|
|
67
|
+
};
|
|
68
|
+
Date.prototype.isLeapYear = function() {
|
|
69
|
+
return self.isLeapYear(this);
|
|
70
|
+
};
|
|
71
|
+
Date.prototype.format = function(format = "YYYY-MM-DD") {
|
|
72
|
+
return self.formatDate(this, format);
|
|
73
|
+
};
|
|
74
|
+
Date.prototype.formatTime = function(format = "HH:mm") {
|
|
75
|
+
return self.formatTime(this, format);
|
|
406
76
|
};
|
|
407
77
|
}
|
|
408
78
|
removePrototypes() {
|
|
409
|
-
delete Date.prototype.addDays
|
|
79
|
+
delete Date.prototype.addDays;
|
|
80
|
+
delete Date.prototype.subtractDays;
|
|
81
|
+
delete Date.prototype.addHours;
|
|
82
|
+
delete Date.prototype.subtractHours;
|
|
83
|
+
delete Date.prototype.addMinutes;
|
|
84
|
+
delete Date.prototype.subtractMinutes;
|
|
85
|
+
delete Date.prototype.getWeek;
|
|
86
|
+
delete Date.prototype.isToday;
|
|
87
|
+
delete Date.prototype.isLeapYear;
|
|
88
|
+
delete Date.prototype.format;
|
|
89
|
+
delete Date.prototype.formatTime;
|
|
410
90
|
}
|
|
411
|
-
updateTexts(
|
|
412
|
-
this._texts =
|
|
91
|
+
updateTexts(texts) {
|
|
92
|
+
this._texts = texts;
|
|
413
93
|
}
|
|
94
|
+
// Cache Today's date (to a maximum) for better isToday() performances. Formatted without leading 0.
|
|
95
|
+
// We still need to update Today's date when Today changes without page refresh.
|
|
414
96
|
_todayFormatted() {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
return
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
return
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
return
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
97
|
+
if (todayDate !== (/* @__PURE__ */ new Date()).getDate()) {
|
|
98
|
+
now = /* @__PURE__ */ new Date();
|
|
99
|
+
todayDate = now.getDate();
|
|
100
|
+
todayF = `${now.getFullYear()}-${now.getMonth()}-${now.getDate()}`;
|
|
101
|
+
}
|
|
102
|
+
return todayF;
|
|
103
|
+
}
|
|
104
|
+
// UTILITIES.
|
|
105
|
+
// ====================================================================
|
|
106
|
+
addDays(date, days) {
|
|
107
|
+
const d = new Date(date.valueOf());
|
|
108
|
+
d.setDate(d.getDate() + days);
|
|
109
|
+
return d;
|
|
110
|
+
}
|
|
111
|
+
subtractDays(date, days) {
|
|
112
|
+
const d = new Date(date.valueOf());
|
|
113
|
+
d.setDate(d.getDate() - days);
|
|
114
|
+
return d;
|
|
115
|
+
}
|
|
116
|
+
addHours(date, hours) {
|
|
117
|
+
const d = new Date(date.valueOf());
|
|
118
|
+
d.setHours(d.getHours() + hours);
|
|
119
|
+
return d;
|
|
120
|
+
}
|
|
121
|
+
subtractHours(date, hours) {
|
|
122
|
+
const d = new Date(date.valueOf());
|
|
123
|
+
d.setHours(d.getHours() - hours);
|
|
124
|
+
return d;
|
|
125
|
+
}
|
|
126
|
+
addMinutes(date, minutes) {
|
|
127
|
+
const d = new Date(date.valueOf());
|
|
128
|
+
d.setMinutes(d.getMinutes() + minutes);
|
|
129
|
+
return d;
|
|
130
|
+
}
|
|
131
|
+
subtractMinutes(date, minutes) {
|
|
132
|
+
const d = new Date(date.valueOf());
|
|
133
|
+
d.setMinutes(d.getMinutes() - minutes);
|
|
134
|
+
return d;
|
|
135
|
+
}
|
|
136
|
+
getWeek(date) {
|
|
137
|
+
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
|
138
|
+
const dayNum = d.getUTCDay() || 7;
|
|
139
|
+
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
|
|
140
|
+
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
141
|
+
return Math.ceil(((d - yearStart) / 864e5 + 1) / 7);
|
|
142
|
+
}
|
|
143
|
+
isToday(date) {
|
|
144
|
+
return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}` === this._todayFormatted();
|
|
145
|
+
}
|
|
146
|
+
isLeapYear(date) {
|
|
147
|
+
const year = date.getFullYear();
|
|
148
|
+
return !(year % 400) || year % 100 && !(year % 4);
|
|
149
|
+
}
|
|
150
|
+
// Returns today if it's FirstDayOfWeek (Monday or Sunday) or previous FirstDayOfWeek otherwise.
|
|
151
|
+
getPreviousFirstDayOfWeek(date = null, weekStartsOnSunday) {
|
|
152
|
+
const prevFirstDayOfWeek = date && new Date(date.valueOf()) || /* @__PURE__ */ new Date();
|
|
153
|
+
const dayModifier = weekStartsOnSunday ? 7 : 6;
|
|
154
|
+
prevFirstDayOfWeek.setDate(prevFirstDayOfWeek.getDate() - (prevFirstDayOfWeek.getDay() + dayModifier) % 7);
|
|
155
|
+
return prevFirstDayOfWeek;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Converts a string to a Javascript Date object. If a Date object is passed, return it as is.
|
|
159
|
+
*
|
|
160
|
+
* @param {String | Date} date the string to convert to Date.
|
|
161
|
+
* @return {Date} the equivalent Javascript Date object.
|
|
162
|
+
*/
|
|
163
|
+
stringToDate(date) {
|
|
164
|
+
if (date instanceof Date) return date;
|
|
165
|
+
if (date.length === 10) date += " 00:00";
|
|
166
|
+
return new Date(date.replace(/-/g, "/"));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Count the number of days this date range spans onto.
|
|
170
|
+
* E.g. countDays(2019-11-02 18:00, 2019-11-03 02:00) = 2
|
|
171
|
+
*
|
|
172
|
+
* @param {String | Date} start the start date
|
|
173
|
+
* @param {String | Date} end the end date
|
|
174
|
+
* @return {Integer} The number of days this date range involves
|
|
175
|
+
*/
|
|
176
|
+
countDays(start, end) {
|
|
177
|
+
if (typeof start === "string") start = start.replace(/-/g, "/");
|
|
178
|
+
if (typeof end === "string") end = end.replace(/-/g, "/");
|
|
179
|
+
start = new Date(start).setHours(0, 0, 0, 0);
|
|
180
|
+
end = new Date(end).setHours(0, 0, 1, 0);
|
|
181
|
+
const timezoneDiffMs = (new Date(end).getTimezoneOffset() - new Date(start).getTimezoneOffset()) * 60 * 1e3;
|
|
182
|
+
return Math.ceil((end - start - timezoneDiffMs) / (24 * 3600 * 1e3));
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Take 2 dates and check if within the same time step (useful in overlapping events).
|
|
186
|
+
*
|
|
187
|
+
* @return {Boolean} `true` if their time is included in the same time step,
|
|
188
|
+
* this means these 2 dates are very close.
|
|
189
|
+
*/
|
|
190
|
+
datesInSameTimeStep(date1, date2, timeStep) {
|
|
191
|
+
return Math.abs(date1.getTime() - date2.getTime()) <= timeStep * 60 * 1e3;
|
|
192
|
+
}
|
|
193
|
+
// ====================================================================
|
|
194
|
+
// FORMATTERS.
|
|
195
|
+
// ====================================================================
|
|
196
|
+
/**
|
|
197
|
+
* Formats a date/time to the given format and returns the formatted string.
|
|
198
|
+
*
|
|
199
|
+
* @param {Date} date a JavaScript Date object to format.
|
|
200
|
+
* @param {String} format the wanted format.
|
|
201
|
+
* @param {Object} texts Optional: the localized texts object to override the vue-cal one in this._texts.
|
|
202
|
+
* This becomes useful when showing multiple instances with different languages,
|
|
203
|
+
* like in the documentation page.
|
|
204
|
+
* @return {String} the formatted date.
|
|
205
|
+
*/
|
|
206
|
+
formatDate(date, format = "YYYY-MM-DD", texts = null) {
|
|
207
|
+
if (!texts) texts = this._texts;
|
|
208
|
+
if (!format) format = "YYYY-MM-DD";
|
|
209
|
+
if (format === "YYYY-MM-DD") return this.formatDateLite(date);
|
|
210
|
+
_dateObject = {};
|
|
211
|
+
_timeObject = {};
|
|
212
|
+
const dateObj = {
|
|
213
|
+
YYYY: () => this._hydrateDateObject(date, texts).YYYY,
|
|
214
|
+
YY: () => this._hydrateDateObject(date, texts).YY(),
|
|
215
|
+
M: () => this._hydrateDateObject(date, texts).M,
|
|
216
|
+
MM: () => this._hydrateDateObject(date, texts).MM(),
|
|
217
|
+
MMM: () => this._hydrateDateObject(date, texts).MMM(),
|
|
218
|
+
MMMM: () => this._hydrateDateObject(date, texts).MMMM(),
|
|
219
|
+
MMMMG: () => this._hydrateDateObject(date, texts).MMMMG(),
|
|
220
|
+
D: () => this._hydrateDateObject(date, texts).D,
|
|
221
|
+
DD: () => this._hydrateDateObject(date, texts).DD(),
|
|
222
|
+
S: () => this._hydrateDateObject(date, texts).S(),
|
|
223
|
+
d: () => this._hydrateDateObject(date, texts).d,
|
|
224
|
+
dd: () => this._hydrateDateObject(date, texts).dd(),
|
|
225
|
+
ddd: () => this._hydrateDateObject(date, texts).ddd(),
|
|
226
|
+
dddd: () => this._hydrateDateObject(date, texts).dddd(),
|
|
227
|
+
HH: () => this._hydrateTimeObject(date, texts).HH,
|
|
228
|
+
H: () => this._hydrateTimeObject(date, texts).H,
|
|
229
|
+
hh: () => this._hydrateTimeObject(date, texts).hh,
|
|
230
|
+
h: () => this._hydrateTimeObject(date, texts).h,
|
|
231
|
+
am: () => this._hydrateTimeObject(date, texts).am,
|
|
232
|
+
AM: () => this._hydrateTimeObject(date, texts).AM,
|
|
233
|
+
mm: () => this._hydrateTimeObject(date, texts).mm,
|
|
234
|
+
m: () => this._hydrateTimeObject(date, texts).m
|
|
235
|
+
};
|
|
236
|
+
return format.replace(/(\{[a-zA-Z]+\}|[a-zA-Z]+)/g, (m, contents) => {
|
|
237
|
+
const result = dateObj[contents.replace(/\{|\}/g, "")];
|
|
238
|
+
return result !== void 0 ? result() : contents;
|
|
477
239
|
});
|
|
478
240
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
241
|
+
// More performant function to convert a Date to `YYYY-MM-DD` formatted string only.
|
|
242
|
+
formatDateLite(date) {
|
|
243
|
+
const m = date.getMonth() + 1;
|
|
244
|
+
const d = date.getDate();
|
|
245
|
+
return `${date.getFullYear()}-${m < 10 ? "0" : ""}${m}-${d < 10 ? "0" : ""}${d}`;
|
|
482
246
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
247
|
+
/**
|
|
248
|
+
* Formats a time (from Date or number of mins) to the given format and returns the formatted string.
|
|
249
|
+
*
|
|
250
|
+
* @param {Date | Number} date a JavaScript Date object or a time in minutes.
|
|
251
|
+
* @param {String} format the wanted format.
|
|
252
|
+
* @param {Object} texts Optional: the localized texts object to override the vue-cal one in this._texts.
|
|
253
|
+
* This becomes useful when showing multiple instances with different languages,
|
|
254
|
+
* like in the documentation page.
|
|
255
|
+
* @param {Boolean} round if time is 23:59:59, rounds up to 24:00 for formatting only.
|
|
256
|
+
* @return {String} the formatted time.
|
|
257
|
+
*/
|
|
258
|
+
formatTime(date, format = "HH:mm", texts = null, round = false) {
|
|
259
|
+
let shouldRound = false;
|
|
260
|
+
if (round) {
|
|
261
|
+
const [h, m, s] = [date.getHours(), date.getMinutes(), date.getSeconds()];
|
|
262
|
+
if (h + m + s === 23 + 59 + 59) shouldRound = true;
|
|
488
263
|
}
|
|
489
|
-
if (
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
const
|
|
493
|
-
|
|
494
|
-
|
|
264
|
+
if (date instanceof Date && format === "HH:mm") return shouldRound ? "24:00" : this.formatTimeLite(date);
|
|
265
|
+
_timeObject = {};
|
|
266
|
+
if (!texts) texts = this._texts;
|
|
267
|
+
const timeObj = this._hydrateTimeObject(date, texts);
|
|
268
|
+
const formatted = format.replace(/(\{[a-zA-Z]+\}|[a-zA-Z]+)/g, (m, contents) => {
|
|
269
|
+
const result = timeObj[contents.replace(/\{|\}/g, "")];
|
|
270
|
+
return result !== void 0 ? result : contents;
|
|
495
271
|
});
|
|
496
|
-
return
|
|
272
|
+
return shouldRound ? formatted.replace("23:59", "24:00") : formatted;
|
|
497
273
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
274
|
+
/**
|
|
275
|
+
* Formats a time to 'HH:mm' from a Date and returns the formatted string.
|
|
276
|
+
*
|
|
277
|
+
* @param {Date} date a JavaScript Date object to format.
|
|
278
|
+
* @return {String} the formatted time.
|
|
279
|
+
*/
|
|
280
|
+
formatTimeLite(date) {
|
|
281
|
+
const h = date.getHours();
|
|
282
|
+
const m = date.getMinutes();
|
|
283
|
+
return `${(h < 10 ? "0" : "") + h}:${(m < 10 ? "0" : "") + m}`;
|
|
501
284
|
}
|
|
502
|
-
_nth(
|
|
503
|
-
if (
|
|
504
|
-
|
|
505
|
-
switch (e % 10) {
|
|
285
|
+
_nth(d) {
|
|
286
|
+
if (d > 3 && d < 21) return "th";
|
|
287
|
+
switch (d % 10) {
|
|
506
288
|
case 1:
|
|
507
289
|
return "st";
|
|
508
290
|
case 2:
|
|
@@ -513,455 +295,3155 @@ const ve = { class: "vuecal__flex vuecal__weekdays-headings" }, me = ["onClick"]
|
|
|
513
295
|
return "th";
|
|
514
296
|
}
|
|
515
297
|
}
|
|
516
|
-
_hydrateDateObject(
|
|
517
|
-
if (
|
|
518
|
-
|
|
519
|
-
const
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
298
|
+
_hydrateDateObject(date, texts) {
|
|
299
|
+
if (_dateObject.D) return _dateObject;
|
|
300
|
+
const YYYY = date.getFullYear();
|
|
301
|
+
const M = date.getMonth() + 1;
|
|
302
|
+
const D = date.getDate();
|
|
303
|
+
const day = date.getDay();
|
|
304
|
+
const dayNumber = (day - 1 + 7) % 7;
|
|
305
|
+
_dateObject = {
|
|
306
|
+
// Year.
|
|
307
|
+
YYYY,
|
|
308
|
+
// 2019.
|
|
309
|
+
YY: () => YYYY.toString().substring(2),
|
|
310
|
+
// 19.
|
|
311
|
+
// Month.
|
|
312
|
+
M,
|
|
313
|
+
// 1 to 12.
|
|
314
|
+
MM: () => (M < 10 ? "0" : "") + M,
|
|
315
|
+
// 01 to 12.
|
|
316
|
+
MMM: () => texts.months[M - 1].substring(0, 3),
|
|
317
|
+
// Jan to Dec.
|
|
318
|
+
MMMM: () => texts.months[M - 1],
|
|
319
|
+
// January to December.
|
|
320
|
+
MMMMG: () => (texts.monthsGenitive || texts.months)[M - 1],
|
|
321
|
+
// January to December in genitive form (Greek...)
|
|
322
|
+
// Day.
|
|
323
|
+
D,
|
|
324
|
+
// 1 to 31.
|
|
325
|
+
DD: () => (D < 10 ? "0" : "") + D,
|
|
326
|
+
// 01 to 31.
|
|
327
|
+
S: () => this._nth(D),
|
|
328
|
+
// st, nd, rd, th.
|
|
329
|
+
// Day of the week.
|
|
330
|
+
d: dayNumber + 1,
|
|
331
|
+
// 1 to 7 with 7 = Sunday.
|
|
332
|
+
dd: () => texts.weekDays[dayNumber][0],
|
|
333
|
+
// M to S.
|
|
334
|
+
ddd: () => texts.weekDays[dayNumber].substr(0, 3),
|
|
335
|
+
// Mon to Sun.
|
|
336
|
+
dddd: () => texts.weekDays[dayNumber]
|
|
337
|
+
// Monday to Sunday.
|
|
338
|
+
};
|
|
339
|
+
return _dateObject;
|
|
340
|
+
}
|
|
341
|
+
_hydrateTimeObject(date, texts) {
|
|
342
|
+
if (_timeObject.am) return _timeObject;
|
|
343
|
+
let H, m;
|
|
344
|
+
if (date instanceof Date) {
|
|
345
|
+
H = date.getHours();
|
|
346
|
+
m = date.getMinutes();
|
|
347
|
+
} else {
|
|
348
|
+
H = Math.floor(date / 60);
|
|
349
|
+
m = Math.floor(date % 60);
|
|
350
|
+
}
|
|
351
|
+
const h = H % 12 ? H % 12 : 12;
|
|
352
|
+
const am = (texts || { am: "am", pm: "pm" })[H === 24 || H < 12 ? "am" : "pm"];
|
|
353
|
+
_timeObject = {
|
|
354
|
+
H,
|
|
355
|
+
h,
|
|
356
|
+
HH: (H < 10 ? "0" : "") + H,
|
|
357
|
+
hh: (h < 10 ? "0" : "") + h,
|
|
358
|
+
am,
|
|
359
|
+
AM: am.toUpperCase(),
|
|
360
|
+
m,
|
|
361
|
+
mm: (m < 10 ? "0" : "") + m
|
|
362
|
+
};
|
|
363
|
+
return _timeObject;
|
|
364
|
+
}
|
|
365
|
+
// ====================================================================
|
|
366
|
+
}
|
|
367
|
+
const minutesInADay$2 = 24 * 60;
|
|
368
|
+
class CellUtils {
|
|
369
|
+
constructor(vuecal) {
|
|
370
|
+
__publicField(this, "_vuecal", null);
|
|
371
|
+
/**
|
|
372
|
+
* Select a cell and go to narrower view on double click or single click according to vuecalProps option.
|
|
373
|
+
*
|
|
374
|
+
* @param {Boolean} force Force switching to narrower view.
|
|
375
|
+
* @param {Date} date The selected cell date at the exact time where it was clicked (through cursor coords).
|
|
376
|
+
* @param {Integer} split The selected cell split if any.
|
|
377
|
+
*/
|
|
378
|
+
__publicField(this, "selectCell", (force = false, date, split) => {
|
|
379
|
+
this._vuecal.$emit("cell-click", split ? { date, split } : date);
|
|
380
|
+
if (this._vuecal.clickToNavigate || force) this._vuecal.switchToNarrowerView();
|
|
381
|
+
else if (this._vuecal.dblclickToNavigate && "ontouchstart" in window) {
|
|
382
|
+
this._vuecal.domEvents.dblTapACell.taps++;
|
|
383
|
+
setTimeout(() => this._vuecal.domEvents.dblTapACell.taps = 0, this._vuecal.domEvents.dblTapACell.timeout);
|
|
384
|
+
if (this._vuecal.domEvents.dblTapACell.taps >= 2) {
|
|
385
|
+
this._vuecal.domEvents.dblTapACell.taps = 0;
|
|
386
|
+
this._vuecal.switchToNarrowerView();
|
|
387
|
+
this._vuecal.$emit("cell-dblclick", split ? { date, split } : date);
|
|
589
388
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
/**
|
|
392
|
+
* Select a cell and go to narrower view on enter.
|
|
393
|
+
*
|
|
394
|
+
* @param {Boolean} force Force switching to narrower view.
|
|
395
|
+
* @param {Date} date The selected cell date at the exact time where it was clicked (through cursor coords).
|
|
396
|
+
* @param {Integer} split The selected cell split if any.
|
|
397
|
+
*/
|
|
398
|
+
__publicField(this, "keyPressEnterCell", (date, split) => {
|
|
399
|
+
this._vuecal.$emit("cell-keypress-enter", split ? { date, split } : date);
|
|
400
|
+
this._vuecal.switchToNarrowerView();
|
|
401
|
+
});
|
|
402
|
+
/**
|
|
403
|
+
* Get the coordinates of the mouse cursor from the cells wrapper referential (`ref="cells"`).
|
|
404
|
+
*
|
|
405
|
+
* @todo Cache bounding box & update it on resize.
|
|
406
|
+
* @param {Object} e the native DOM event object.
|
|
407
|
+
* @return {Object} containing { x: {Number}, y: {Number} }
|
|
408
|
+
*/
|
|
409
|
+
__publicField(this, "getPosition", (e) => {
|
|
410
|
+
const { left, top } = this._vuecal.cellsEl.getBoundingClientRect();
|
|
411
|
+
const { clientX, clientY } = "ontouchstart" in window && e.touches ? e.touches[0] : e;
|
|
412
|
+
return { x: clientX - left, y: clientY - top };
|
|
413
|
+
});
|
|
414
|
+
/**
|
|
415
|
+
* Get the number of minutes from the top to the mouse cursor.
|
|
416
|
+
* Returns a constrained time between 0 and 24 * 60.
|
|
417
|
+
*
|
|
418
|
+
* @param {Object} e the native DOM event object.
|
|
419
|
+
* @return {Object} containing { minutes: {Number}, cursorCoords: { x: {Number}, y: {Number} } }
|
|
420
|
+
*/
|
|
421
|
+
__publicField(this, "minutesAtCursor", (e) => {
|
|
422
|
+
let minutes = 0;
|
|
423
|
+
let cursorCoords = { x: 0, y: 0 };
|
|
424
|
+
const { timeStep, timeCellHeight, timeFrom } = this._vuecal.$props;
|
|
425
|
+
if (typeof e === "number") minutes = e;
|
|
426
|
+
else if (typeof e === "object") {
|
|
427
|
+
cursorCoords = this.getPosition(e);
|
|
428
|
+
minutes = Math.round(cursorCoords.y * timeStep / parseInt(timeCellHeight) + timeFrom);
|
|
429
|
+
}
|
|
430
|
+
return { minutes: Math.max(Math.min(minutes, minutesInADay$2), 0), cursorCoords };
|
|
431
|
+
});
|
|
432
|
+
this._vuecal = vuecal;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
const defaultEventDuration = 2;
|
|
436
|
+
const minutesInADay$1 = 24 * 60;
|
|
437
|
+
let ud;
|
|
438
|
+
let _cellOverlaps, _comparisonArray;
|
|
439
|
+
class EventUtils {
|
|
440
|
+
constructor(vuecal, dateUtils2) {
|
|
441
|
+
__publicField(this, "_vuecal", null);
|
|
442
|
+
__publicField(this, "eventDefaults", {
|
|
443
|
+
_eid: null,
|
|
444
|
+
start: "",
|
|
445
|
+
// Externally given formatted date & time or Date object.
|
|
446
|
+
startTimeMinutes: 0,
|
|
447
|
+
end: "",
|
|
448
|
+
// Externally given formatted date & time or Date object.
|
|
449
|
+
endTimeMinutes: 0,
|
|
450
|
+
title: "",
|
|
451
|
+
content: "",
|
|
452
|
+
background: false,
|
|
453
|
+
allDay: false,
|
|
454
|
+
segments: null,
|
|
455
|
+
repeat: null,
|
|
456
|
+
daysCount: 1,
|
|
457
|
+
deletable: true,
|
|
458
|
+
deleting: false,
|
|
459
|
+
titleEditable: true,
|
|
460
|
+
resizable: true,
|
|
461
|
+
resizing: false,
|
|
462
|
+
draggable: true,
|
|
463
|
+
dragging: false,
|
|
464
|
+
draggingStatic: false,
|
|
465
|
+
// Controls the CSS class of the static clone while dragging.
|
|
466
|
+
focused: false,
|
|
467
|
+
class: ""
|
|
468
|
+
});
|
|
469
|
+
this._vuecal = vuecal;
|
|
470
|
+
ud = dateUtils2;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Create an event at the given date and time, and allow overriding
|
|
474
|
+
* event attributes through the eventOptions object.
|
|
475
|
+
*
|
|
476
|
+
* @param {Date | String} dateTime The date and time of the new event start.
|
|
477
|
+
* @param {Number} duration the event duration in minutes.
|
|
478
|
+
* @param {Object} eventOptions some options to override the `eventDefaults` - optional.
|
|
479
|
+
*/
|
|
480
|
+
createAnEvent(dateTime, duration, eventOptions) {
|
|
481
|
+
if (typeof dateTime === "string") dateTime = ud.stringToDate(dateTime);
|
|
482
|
+
if (!(dateTime instanceof Date)) return false;
|
|
483
|
+
const startTimeMinutes = ud.dateToMinutes(dateTime);
|
|
484
|
+
duration = duration * 1 || defaultEventDuration * 60;
|
|
485
|
+
const endTimeMinutes = startTimeMinutes + duration;
|
|
486
|
+
const end = ud.addMinutes(new Date(dateTime), duration);
|
|
487
|
+
if (eventOptions.end) {
|
|
488
|
+
if (typeof eventOptions.end === "string") eventOptions.end = ud.stringToDate(eventOptions.end);
|
|
489
|
+
eventOptions.endTimeMinutes = ud.dateToMinutes(eventOptions.end);
|
|
490
|
+
}
|
|
491
|
+
const event = {
|
|
492
|
+
...this.eventDefaults,
|
|
493
|
+
_eid: `${this._vuecal._.uid}_${this._vuecal.eventIdIncrement++}`,
|
|
494
|
+
start: dateTime,
|
|
495
|
+
startTimeMinutes,
|
|
496
|
+
end,
|
|
497
|
+
endTimeMinutes,
|
|
498
|
+
segments: null,
|
|
499
|
+
...eventOptions
|
|
500
|
+
};
|
|
501
|
+
if (typeof this._vuecal.onEventCreate === "function") {
|
|
502
|
+
if (!this._vuecal.onEventCreate(event, () => this.deleteAnEvent(event))) return;
|
|
503
|
+
}
|
|
504
|
+
if (event.startDateF !== event.endDateF) {
|
|
505
|
+
event.daysCount = ud.countDays(event.start, event.end);
|
|
506
|
+
}
|
|
507
|
+
this._vuecal.mutableEvents.push(event);
|
|
508
|
+
this._vuecal.addEventsToView([event]);
|
|
509
|
+
this._vuecal.emitWithEvent("event-create", event);
|
|
510
|
+
this._vuecal.$emit("event-change", { event: this._vuecal.cleanupEvent(event), originalEvent: null });
|
|
511
|
+
return event;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Add an event segment (= day) to a multiple-day event.
|
|
515
|
+
*
|
|
516
|
+
* @param {Object} e the multiple-day event to add segment in.
|
|
517
|
+
*/
|
|
518
|
+
addEventSegment(e) {
|
|
519
|
+
if (!e.segments) {
|
|
520
|
+
e.segments = {};
|
|
521
|
+
e.segments[ud.formatDateLite(e.start)] = {
|
|
522
|
+
start: e.start,
|
|
523
|
+
startTimeMinutes: e.startTimeMinutes,
|
|
524
|
+
endTimeMinutes: minutesInADay$1,
|
|
525
|
+
isFirstDay: true,
|
|
526
|
+
isLastDay: false
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
const previousSegment = e.segments[ud.formatDateLite(e.end)];
|
|
530
|
+
if (previousSegment) {
|
|
531
|
+
previousSegment.isLastDay = false;
|
|
532
|
+
previousSegment.endTimeMinutes = minutesInADay$1;
|
|
533
|
+
}
|
|
534
|
+
const start = ud.addDays(e.end, 1);
|
|
535
|
+
const formattedDate = ud.formatDateLite(start);
|
|
536
|
+
start.setHours(0, 0, 0, 0);
|
|
537
|
+
e.segments[formattedDate] = {
|
|
538
|
+
start,
|
|
539
|
+
startTimeMinutes: 0,
|
|
540
|
+
endTimeMinutes: e.endTimeMinutes,
|
|
541
|
+
isFirstDay: false,
|
|
542
|
+
isLastDay: true
|
|
543
|
+
};
|
|
544
|
+
e.end = ud.addMinutes(start, e.endTimeMinutes);
|
|
545
|
+
e.daysCount = Object.keys(e.segments).length;
|
|
546
|
+
return formattedDate;
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Remove an event segment (= day) from a multiple-day event.
|
|
550
|
+
*
|
|
551
|
+
* @param {Object} e the multiple-day event to remove segments from.
|
|
552
|
+
*/
|
|
553
|
+
removeEventSegment(e) {
|
|
554
|
+
let segmentsCount = Object.keys(e.segments).length;
|
|
555
|
+
if (segmentsCount <= 1) return ud.formatDateLite(e.end);
|
|
556
|
+
delete e.segments[ud.formatDateLite(e.end)];
|
|
557
|
+
segmentsCount--;
|
|
558
|
+
const end = ud.subtractDays(e.end, 1);
|
|
559
|
+
const formattedDate = ud.formatDateLite(end);
|
|
560
|
+
const previousSegment = e.segments[formattedDate];
|
|
561
|
+
if (!segmentsCount) e.segments = null;
|
|
562
|
+
else if (previousSegment) {
|
|
563
|
+
previousSegment.isLastDay = true;
|
|
564
|
+
previousSegment.endTimeMinutes = e.endTimeMinutes;
|
|
565
|
+
} else ;
|
|
566
|
+
e.daysCount = segmentsCount || 1;
|
|
567
|
+
e.end = end;
|
|
568
|
+
return formattedDate;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Create 1 segment per day of the given event, but only within the current view.
|
|
572
|
+
* (It won't create segments for all the days in view that are not in the event!)
|
|
573
|
+
*
|
|
574
|
+
* An event segment is a piece of event per day that contains more day-specific data.
|
|
575
|
+
*
|
|
576
|
+
* @param {Object} e the multiple-day event to create segments for.
|
|
577
|
+
* @param {Date} viewStartDate the starting date of the view.
|
|
578
|
+
* @param {Date} viewEndDate the ending date of the view.
|
|
579
|
+
*/
|
|
580
|
+
createEventSegments(e, viewStartDate, viewEndDate) {
|
|
581
|
+
const viewStartTimestamp = viewStartDate.getTime();
|
|
582
|
+
const viewEndTimestamp = viewEndDate.getTime();
|
|
583
|
+
let eventStart = e.start.getTime();
|
|
584
|
+
let eventEnd = e.end.getTime();
|
|
585
|
+
let repeatedEventStartFound = false;
|
|
586
|
+
let timestamp, end, eventStartAtMidnight;
|
|
587
|
+
if (!e.end.getHours() && !e.end.getMinutes()) eventEnd -= 1e3;
|
|
588
|
+
e.segments = {};
|
|
589
|
+
if (!e.repeat) {
|
|
590
|
+
timestamp = Math.max(viewStartTimestamp, eventStart);
|
|
591
|
+
end = Math.min(viewEndTimestamp, eventEnd);
|
|
592
|
+
} else {
|
|
593
|
+
timestamp = viewStartTimestamp;
|
|
594
|
+
end = Math.min(
|
|
595
|
+
viewEndTimestamp,
|
|
596
|
+
e.repeat.until ? ud.stringToDate(e.repeat.until).getTime() : viewEndTimestamp
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
while (timestamp <= end) {
|
|
600
|
+
let createSegment = false;
|
|
601
|
+
const nextMidnight = ud.addDays(new Date(timestamp), 1).setHours(0, 0, 0, 0);
|
|
602
|
+
let isFirstDay, isLastDay, start, formattedDate;
|
|
603
|
+
if (e.repeat) {
|
|
604
|
+
const tmpDate = new Date(timestamp);
|
|
605
|
+
const tmpDateFormatted = ud.formatDateLite(tmpDate);
|
|
606
|
+
if (repeatedEventStartFound || e.occurrences && e.occurrences[tmpDateFormatted]) {
|
|
607
|
+
if (!repeatedEventStartFound) {
|
|
608
|
+
eventStart = e.occurrences[tmpDateFormatted].start;
|
|
609
|
+
eventStartAtMidnight = new Date(eventStart).setHours(0, 0, 0, 0);
|
|
610
|
+
eventEnd = e.occurrences[tmpDateFormatted].end;
|
|
611
|
+
}
|
|
612
|
+
repeatedEventStartFound = true;
|
|
613
|
+
createSegment = true;
|
|
593
614
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
615
|
+
isFirstDay = timestamp === eventStartAtMidnight;
|
|
616
|
+
isLastDay = tmpDateFormatted === ud.formatDateLite(new Date(eventEnd));
|
|
617
|
+
start = new Date(isFirstDay ? eventStart : timestamp);
|
|
618
|
+
formattedDate = ud.formatDateLite(start);
|
|
619
|
+
if (isLastDay) repeatedEventStartFound = false;
|
|
620
|
+
} else {
|
|
621
|
+
createSegment = true;
|
|
622
|
+
isFirstDay = timestamp === eventStart;
|
|
623
|
+
isLastDay = end === eventEnd && nextMidnight > end;
|
|
624
|
+
start = isFirstDay ? e.start : new Date(timestamp);
|
|
625
|
+
formattedDate = ud.formatDateLite(isFirstDay ? e.start : start);
|
|
626
|
+
}
|
|
627
|
+
if (createSegment) {
|
|
628
|
+
e.segments[formattedDate] = {
|
|
629
|
+
start,
|
|
630
|
+
startTimeMinutes: isFirstDay ? e.startTimeMinutes : 0,
|
|
631
|
+
endTimeMinutes: isLastDay ? e.endTimeMinutes : minutesInADay$1,
|
|
632
|
+
isFirstDay,
|
|
633
|
+
isLastDay
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
timestamp = nextMidnight;
|
|
637
|
+
}
|
|
638
|
+
return e;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Delete an event.
|
|
642
|
+
*
|
|
643
|
+
* @param {Object} event the calendar event to delete.
|
|
644
|
+
*/
|
|
645
|
+
deleteAnEvent(event) {
|
|
646
|
+
this._vuecal.emitWithEvent("event-delete", event);
|
|
647
|
+
this._vuecal.mutableEvents = this._vuecal.mutableEvents.filter((e) => e._eid !== event._eid);
|
|
648
|
+
this._vuecal.view.events = this._vuecal.view.events.filter((e) => e._eid !== event._eid);
|
|
649
|
+
}
|
|
650
|
+
// EVENT OVERLAPS.
|
|
651
|
+
// ===================================================================
|
|
652
|
+
// Will recalculate all the overlaps of the current cell OR split.
|
|
653
|
+
// cellEvents will contain only the current split events if in a split.
|
|
654
|
+
checkCellOverlappingEvents(cellEvents, options) {
|
|
655
|
+
_comparisonArray = cellEvents.slice(0);
|
|
656
|
+
_cellOverlaps = {};
|
|
657
|
+
cellEvents.forEach((e) => {
|
|
658
|
+
_comparisonArray.shift();
|
|
659
|
+
if (!_cellOverlaps[e._eid]) _cellOverlaps[e._eid] = { overlaps: [], start: e.start, position: 0 };
|
|
660
|
+
_cellOverlaps[e._eid].position = 0;
|
|
661
|
+
_comparisonArray.forEach((e2) => {
|
|
662
|
+
if (!_cellOverlaps[e2._eid]) _cellOverlaps[e2._eid] = { overlaps: [], start: e2.start, position: 0 };
|
|
663
|
+
const eventIsInRange = this.eventInRange(e2, e.start, e.end);
|
|
664
|
+
const eventsInSameTimeStep = options.overlapsPerTimeStep ? ud.datesInSameTimeStep(e.start, e2.start, options.timeStep) : 1;
|
|
665
|
+
if (!e.background && !e.allDay && !e2.background && !e2.allDay && eventIsInRange && eventsInSameTimeStep) {
|
|
666
|
+
_cellOverlaps[e._eid].overlaps.push(e2._eid);
|
|
667
|
+
_cellOverlaps[e._eid].overlaps = [...new Set(_cellOverlaps[e._eid].overlaps)];
|
|
668
|
+
_cellOverlaps[e2._eid].overlaps.push(e._eid);
|
|
669
|
+
_cellOverlaps[e2._eid].overlaps = [...new Set(_cellOverlaps[e2._eid].overlaps)];
|
|
670
|
+
_cellOverlaps[e2._eid].position++;
|
|
671
|
+
} else {
|
|
672
|
+
let pos1, pos2;
|
|
673
|
+
if ((pos1 = (_cellOverlaps[e._eid] || { overlaps: [] }).overlaps.indexOf(e2._eid)) > -1) _cellOverlaps[e._eid].overlaps.splice(pos1, 1);
|
|
674
|
+
if ((pos2 = (_cellOverlaps[e2._eid] || { overlaps: [] }).overlaps.indexOf(e._eid)) > -1) _cellOverlaps[e2._eid].overlaps.splice(pos2, 1);
|
|
675
|
+
_cellOverlaps[e2._eid].position--;
|
|
597
676
|
}
|
|
677
|
+
});
|
|
678
|
+
});
|
|
679
|
+
let longestStreak = 0;
|
|
680
|
+
for (const id in _cellOverlaps) {
|
|
681
|
+
const item = _cellOverlaps[id];
|
|
682
|
+
const overlapsRow = item.overlaps.map((id2) => ({ id: id2, start: _cellOverlaps[id2].start }));
|
|
683
|
+
overlapsRow.push({ id, start: item.start });
|
|
684
|
+
overlapsRow.sort((a, b) => a.start < b.start ? -1 : a.start > b.start ? 1 : a.id > b.id ? -1 : 1);
|
|
685
|
+
item.position = overlapsRow.findIndex((e) => e.id === id);
|
|
686
|
+
longestStreak = Math.max(this.getOverlapsStreak(item, _cellOverlaps), longestStreak);
|
|
687
|
+
}
|
|
688
|
+
return [_cellOverlaps, longestStreak];
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Overlaps streak is the longest horizontal set of simultaneous events.
|
|
692
|
+
* This is determining the width of each events in this streak.
|
|
693
|
+
* E.g. 3 overlapping events [1, 2, 3]; 1 overlaps 2 & 3; 2 & 3 don't overlap;
|
|
694
|
+
* => streak = 2; each width = 50% not 33%.
|
|
695
|
+
*
|
|
696
|
+
* @param {Object} event The current event we are checking among all the events of the current cell.
|
|
697
|
+
* @param {Object} cellOverlaps An indexed array of all the events overlaps for the current cell.
|
|
698
|
+
* @return {Number} The number of simultaneous event for this event.
|
|
699
|
+
*/
|
|
700
|
+
getOverlapsStreak(event, cellOverlaps = {}) {
|
|
701
|
+
let streak = event.overlaps.length + 1;
|
|
702
|
+
let removeFromStreak = [];
|
|
703
|
+
event.overlaps.forEach((id) => {
|
|
704
|
+
if (!removeFromStreak.includes(id)) {
|
|
705
|
+
const overlapsWithoutSelf = event.overlaps.filter((id2) => id2 !== id);
|
|
706
|
+
overlapsWithoutSelf.forEach((id3) => {
|
|
707
|
+
if (!cellOverlaps[id3].overlaps.includes(id)) removeFromStreak.push(id3);
|
|
708
|
+
});
|
|
598
709
|
}
|
|
599
|
-
|
|
710
|
+
});
|
|
711
|
+
removeFromStreak = [...new Set(removeFromStreak)];
|
|
712
|
+
streak -= removeFromStreak.length;
|
|
713
|
+
return streak;
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Tells whether an event is in a given date range, even partially.
|
|
717
|
+
*
|
|
718
|
+
* @param {Object} event The event to test.
|
|
719
|
+
* @param {Date} start The start of range date object.
|
|
720
|
+
* @param {Date} end The end of range date object.
|
|
721
|
+
* @return {Boolean} true if in range, even partially.
|
|
722
|
+
*/
|
|
723
|
+
eventInRange(event, start, end) {
|
|
724
|
+
if (event.allDay || !this._vuecal.time) {
|
|
725
|
+
const startTimestamp2 = new Date(event.start).setHours(0, 0, 0, 0);
|
|
726
|
+
const endTimestamp2 = new Date(event.end).setHours(23, 59, 0, 0);
|
|
727
|
+
return endTimestamp2 >= new Date(start).setHours(0, 0, 0, 0) && startTimestamp2 <= new Date(end).setHours(0, 0, 0, 0);
|
|
600
728
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
729
|
+
const startTimestamp = event.start.getTime();
|
|
730
|
+
const endTimestamp = event.end.getTime();
|
|
731
|
+
return startTimestamp < end.getTime() && endTimestamp > start.getTime();
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
const _hoisted_1$5 = { class: "vuecal__flex vuecal__weekdays-headings" };
|
|
735
|
+
const _hoisted_2$3 = ["onClick"];
|
|
736
|
+
const _hoisted_3$3 = {
|
|
737
|
+
class: "vuecal__flex weekday-label",
|
|
738
|
+
grow: ""
|
|
739
|
+
};
|
|
740
|
+
const _hoisted_4$3 = { class: "full" };
|
|
741
|
+
const _hoisted_5$3 = { class: "small" };
|
|
742
|
+
const _hoisted_6$2 = { class: "xsmall" };
|
|
743
|
+
const _hoisted_7$2 = { key: 0 };
|
|
744
|
+
const _hoisted_8$2 = {
|
|
745
|
+
key: 0,
|
|
746
|
+
class: "vuecal__flex vuecal__split-days-headers",
|
|
747
|
+
grow: ""
|
|
748
|
+
};
|
|
749
|
+
function render$5(_ctx, _cache, $props, $setup, $data, $options) {
|
|
750
|
+
return openBlock(), createElementBlock("div", _hoisted_1$5, [
|
|
751
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.headings, (heading, i) => {
|
|
752
|
+
return openBlock(), createElementBlock(Fragment, { key: i }, [
|
|
753
|
+
!heading.hide ? (openBlock(), createElementBlock("div", {
|
|
754
|
+
key: 0,
|
|
755
|
+
class: normalizeClass(["vuecal__flex vuecal__heading", { today: heading.today, clickable: $options.cellHeadingsClickable }]),
|
|
756
|
+
style: normalizeStyle($options.weekdayCellStyles),
|
|
757
|
+
onClick: ($event) => $options.view.id === "week" && $options.selectCell(heading.date, $event),
|
|
758
|
+
onDblclick: _cache[0] || (_cache[0] = ($event) => $options.view.id === "week" && $options.vuecal.dblclickToNavigate && $props.switchToNarrowerView())
|
|
759
|
+
}, [
|
|
760
|
+
createVNode(Transition, {
|
|
761
|
+
name: `slide-fade--${$props.transitionDirection}`,
|
|
762
|
+
appear: $options.vuecal.transitions
|
|
763
|
+
}, {
|
|
764
|
+
default: withCtx(() => [
|
|
765
|
+
(openBlock(), createElementBlock("div", {
|
|
766
|
+
class: "vuecal__flex",
|
|
767
|
+
column: "",
|
|
768
|
+
key: $options.vuecal.transitions ? `${i}-${heading.dayOfMonth}` : false
|
|
769
|
+
}, [
|
|
770
|
+
createElementVNode("div", _hoisted_3$3, [
|
|
771
|
+
renderSlot(_ctx.$slots, "weekday-heading", {
|
|
772
|
+
heading: $options.cleanupHeading(heading),
|
|
773
|
+
view: $options.view
|
|
774
|
+
}, () => [
|
|
775
|
+
createElementVNode("span", _hoisted_4$3, toDisplayString(heading.full), 1),
|
|
776
|
+
createElementVNode("span", _hoisted_5$3, toDisplayString(heading.small), 1),
|
|
777
|
+
createElementVNode("span", _hoisted_6$2, toDisplayString(heading.xsmall), 1),
|
|
778
|
+
heading.dayOfMonth ? (openBlock(), createElementBlock("span", _hoisted_7$2, " " + toDisplayString(heading.dayOfMonth), 1)) : createCommentVNode("", true)
|
|
779
|
+
])
|
|
780
|
+
]),
|
|
781
|
+
$options.vuecal.hasSplits && $options.vuecal.stickySplitLabels ? (openBlock(), createElementBlock("div", _hoisted_8$2, [
|
|
782
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.vuecal.daySplits, (split, i2) => {
|
|
783
|
+
return openBlock(), createElementBlock("div", {
|
|
784
|
+
class: normalizeClass(["day-split-header", split.class || false]),
|
|
785
|
+
key: i2
|
|
786
|
+
}, [
|
|
787
|
+
renderSlot(_ctx.$slots, "split-label", {
|
|
788
|
+
split,
|
|
789
|
+
view: $options.view
|
|
790
|
+
}, () => [
|
|
791
|
+
createTextVNode(toDisplayString(split.label), 1)
|
|
792
|
+
])
|
|
793
|
+
], 2);
|
|
794
|
+
}), 128))
|
|
795
|
+
])) : createCommentVNode("", true)
|
|
796
|
+
]))
|
|
797
|
+
]),
|
|
798
|
+
_: 2
|
|
799
|
+
}, 1032, ["name", "appear"])
|
|
800
|
+
], 46, _hoisted_2$3)) : createCommentVNode("", true)
|
|
801
|
+
], 64);
|
|
802
|
+
}), 128))
|
|
803
|
+
]);
|
|
804
|
+
}
|
|
805
|
+
const _export_sfc = (sfc, props) => {
|
|
806
|
+
const target = sfc.__vccOpts || sfc;
|
|
807
|
+
for (const [key, val] of props) {
|
|
808
|
+
target[key] = val;
|
|
809
|
+
}
|
|
810
|
+
return target;
|
|
811
|
+
};
|
|
812
|
+
const _sfc_main$5 = {
|
|
813
|
+
inject: ["vuecal", "utils", "view"],
|
|
814
|
+
props: {
|
|
815
|
+
transitionDirection: { type: String, default: "right" },
|
|
816
|
+
weekDays: { type: Array, default: () => [] },
|
|
817
|
+
switchToNarrowerView: { type: Function, default: () => {
|
|
818
|
+
} }
|
|
819
|
+
},
|
|
820
|
+
methods: {
|
|
821
|
+
selectCell(date, DOMEvent) {
|
|
822
|
+
if (date.getTime() !== this.view.selectedDate.getTime()) {
|
|
823
|
+
this.view.selectedDate = date;
|
|
824
|
+
}
|
|
825
|
+
this.utils.cell.selectCell(false, date, DOMEvent);
|
|
826
|
+
},
|
|
827
|
+
cleanupHeading: (heading) => ({
|
|
828
|
+
label: heading.full,
|
|
829
|
+
date: heading.date,
|
|
830
|
+
...heading.today ? { today: heading.today } : {}
|
|
831
|
+
})
|
|
832
|
+
},
|
|
833
|
+
computed: {
|
|
834
|
+
headings() {
|
|
835
|
+
if (!["month", "week"].includes(this.view.id)) return [];
|
|
836
|
+
let todayFound = false;
|
|
837
|
+
const headings = this.weekDays.map((cell, i) => {
|
|
838
|
+
const date = this.utils.date.addDays(this.view.startDate, this.vuecal.startWeekOnSunday && this.vuecal.hideWeekends ? i - 1 : i);
|
|
839
|
+
return {
|
|
840
|
+
hide: cell.hide,
|
|
841
|
+
full: cell.label,
|
|
842
|
+
// If defined in i18n file, weekDaysShort overrides default truncation of
|
|
843
|
+
// week days when does not fit on screen or with small/xsmall options.
|
|
844
|
+
small: cell.short || cell.label.substr(0, 3),
|
|
845
|
+
xsmall: cell.short || cell.label.substr(0, 1),
|
|
846
|
+
// Only for week view.
|
|
847
|
+
...this.view.id === "week" ? {
|
|
848
|
+
dayOfMonth: date.getDate(),
|
|
849
|
+
date,
|
|
850
|
+
today: !todayFound && this.utils.date.isToday(date) && !todayFound++
|
|
851
|
+
} : {}
|
|
852
|
+
};
|
|
853
|
+
});
|
|
854
|
+
return headings;
|
|
855
|
+
},
|
|
856
|
+
cellWidth() {
|
|
857
|
+
return 100 / (7 - this.weekDays.reduce((total, day) => total + day.hide, 0));
|
|
858
|
+
},
|
|
859
|
+
weekdayCellStyles() {
|
|
860
|
+
return {
|
|
861
|
+
...this.vuecal.hideWeekdays.length ? { width: `${this.cellWidth}%` } : {}
|
|
862
|
+
};
|
|
863
|
+
},
|
|
864
|
+
cellHeadingsClickable() {
|
|
865
|
+
return this.view.id === "week" && (this.vuecal.clickToNavigate || this.vuecal.dblclickToNavigate);
|
|
606
866
|
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
const WeekdaysHeadings = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", render$5]]);
|
|
870
|
+
const _hoisted_1$4 = { class: "vuecal__header" };
|
|
871
|
+
const _hoisted_2$2 = {
|
|
872
|
+
key: 0,
|
|
873
|
+
class: "vuecal__flex vuecal__menu",
|
|
874
|
+
role: "tablist",
|
|
875
|
+
"aria-label": "Calendar views navigation"
|
|
876
|
+
};
|
|
877
|
+
const _hoisted_3$2 = ["onDragenter", "onDragleave", "onClick", "aria-label"];
|
|
878
|
+
const _hoisted_4$2 = {
|
|
879
|
+
key: 1,
|
|
880
|
+
class: "vuecal__title-bar"
|
|
881
|
+
};
|
|
882
|
+
const _hoisted_5$2 = ["aria-label"];
|
|
883
|
+
const _hoisted_6$1 = {
|
|
884
|
+
class: "vuecal__flex vuecal__title",
|
|
885
|
+
grow: ""
|
|
886
|
+
};
|
|
887
|
+
const _hoisted_7$1 = ["aria-label"];
|
|
888
|
+
const _hoisted_8$1 = {
|
|
889
|
+
key: 0,
|
|
890
|
+
class: "vuecal__flex vuecal__split-days-headers"
|
|
891
|
+
};
|
|
892
|
+
function render$4(_ctx, _cache, $props, $setup, $data, $options) {
|
|
893
|
+
const _component_weekdays_headings = resolveComponent("weekdays-headings");
|
|
894
|
+
return openBlock(), createElementBlock("div", _hoisted_1$4, [
|
|
895
|
+
!$props.options.hideViewSelector ? (openBlock(), createElementBlock("div", _hoisted_2$2, [
|
|
896
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($props.viewProps.views, (v, id) => {
|
|
897
|
+
return openBlock(), createElementBlock(Fragment, { key: id }, [
|
|
898
|
+
v.enabled ? (openBlock(), createElementBlock("button", {
|
|
899
|
+
key: 0,
|
|
900
|
+
class: normalizeClass(["vuecal__view-btn", { "vuecal__view-btn--active": $options.view.id === id, "vuecal__view-btn--highlighted": _ctx.highlightedControl === id }]),
|
|
901
|
+
type: "button",
|
|
902
|
+
onDragenter: ($event) => $props.editEvents.drag && $options.dnd && $options.dnd.viewSelectorDragEnter($event, id, _ctx.$data),
|
|
903
|
+
onDragleave: ($event) => $props.editEvents.drag && $options.dnd && $options.dnd.viewSelectorDragLeave($event, id, _ctx.$data),
|
|
904
|
+
onClick: ($event) => $options.switchView(id, null, true),
|
|
905
|
+
"aria-label": `${v.label} view`
|
|
906
|
+
}, toDisplayString(v.label), 43, _hoisted_3$2)) : createCommentVNode("", true)
|
|
907
|
+
], 64);
|
|
908
|
+
}), 128))
|
|
909
|
+
])) : createCommentVNode("", true),
|
|
910
|
+
!$props.options.hideTitleBar ? (openBlock(), createElementBlock("div", _hoisted_4$2, [
|
|
911
|
+
createElementVNode("button", {
|
|
912
|
+
class: normalizeClass(["vuecal__arrow vuecal__arrow--prev", { "vuecal__arrow--highlighted": _ctx.highlightedControl === "previous" }]),
|
|
913
|
+
type: "button",
|
|
914
|
+
onClick: _cache[0] || (_cache[0] = (...args) => $options.previous && $options.previous(...args)),
|
|
915
|
+
onDragenter: _cache[1] || (_cache[1] = ($event) => $props.editEvents.drag && $options.dnd && $options.dnd.viewSelectorDragEnter($event, "previous", _ctx.$data)),
|
|
916
|
+
onDragleave: _cache[2] || (_cache[2] = ($event) => $props.editEvents.drag && $options.dnd && $options.dnd.viewSelectorDragLeave($event, "previous", _ctx.$data)),
|
|
917
|
+
"aria-label": `Previous ${$options.view.id}`
|
|
918
|
+
}, [
|
|
919
|
+
renderSlot(_ctx.$slots, "arrow-prev")
|
|
920
|
+
], 42, _hoisted_5$2),
|
|
921
|
+
createElementVNode("div", _hoisted_6$1, [
|
|
922
|
+
createVNode(Transition, {
|
|
923
|
+
name: $props.options.transitions ? `slide-fade--${$options.transitionDirection}` : ""
|
|
924
|
+
}, {
|
|
925
|
+
default: withCtx(() => [
|
|
926
|
+
(openBlock(), createBlock(resolveDynamicComponent($options.broaderView ? "button" : "span"), {
|
|
927
|
+
type: !!$options.broaderView && "button",
|
|
928
|
+
key: `${$options.view.id}${$options.view.startDate.toString()}`,
|
|
929
|
+
onClick: _cache[3] || (_cache[3] = ($event) => !!$options.broaderView && $options.switchToBroaderView()),
|
|
930
|
+
"aria-label": !!$options.broaderView && `Go to ${$options.broaderView} view`
|
|
931
|
+
}, {
|
|
932
|
+
default: withCtx(() => [
|
|
933
|
+
renderSlot(_ctx.$slots, "title")
|
|
934
|
+
]),
|
|
935
|
+
_: 3
|
|
936
|
+
}, 8, ["type", "aria-label"]))
|
|
937
|
+
]),
|
|
938
|
+
_: 3
|
|
939
|
+
}, 8, ["name"])
|
|
940
|
+
]),
|
|
941
|
+
$props.options.todayButton ? (openBlock(), createElementBlock("button", {
|
|
942
|
+
key: 0,
|
|
943
|
+
class: normalizeClass(["vuecal__today-btn", { "vuecal__today-btn--highlighted": _ctx.highlightedControl === "today" }]),
|
|
944
|
+
type: "button",
|
|
945
|
+
onClick: _cache[4] || (_cache[4] = (...args) => $options.goToToday && $options.goToToday(...args)),
|
|
946
|
+
onDragenter: _cache[5] || (_cache[5] = ($event) => $props.editEvents.drag && $options.dnd && $options.dnd.viewSelectorDragEnter($event, "today", _ctx.$data)),
|
|
947
|
+
onDragleave: _cache[6] || (_cache[6] = ($event) => $props.editEvents.drag && $options.dnd && $options.dnd.viewSelectorDragLeave($event, "today", _ctx.$data)),
|
|
948
|
+
"aria-label": "Today"
|
|
949
|
+
}, [
|
|
950
|
+
renderSlot(_ctx.$slots, "today-button")
|
|
951
|
+
], 34)) : createCommentVNode("", true),
|
|
952
|
+
createElementVNode("button", {
|
|
953
|
+
class: normalizeClass(["vuecal__arrow vuecal__arrow--next", { "vuecal__arrow--highlighted": _ctx.highlightedControl === "next" }]),
|
|
954
|
+
type: "button",
|
|
955
|
+
onClick: _cache[7] || (_cache[7] = (...args) => $options.next && $options.next(...args)),
|
|
956
|
+
onDragenter: _cache[8] || (_cache[8] = ($event) => $props.editEvents.drag && $options.dnd && $options.dnd.viewSelectorDragEnter($event, "next", _ctx.$data)),
|
|
957
|
+
onDragleave: _cache[9] || (_cache[9] = ($event) => $props.editEvents.drag && $options.dnd && $options.dnd.viewSelectorDragLeave($event, "next", _ctx.$data)),
|
|
958
|
+
"aria-label": `Next ${$options.view.id}`
|
|
959
|
+
}, [
|
|
960
|
+
renderSlot(_ctx.$slots, "arrow-next")
|
|
961
|
+
], 42, _hoisted_7$1)
|
|
962
|
+
])) : createCommentVNode("", true),
|
|
963
|
+
$props.viewProps.weekDaysInHeader ? (openBlock(), createBlock(_component_weekdays_headings, {
|
|
964
|
+
key: 2,
|
|
965
|
+
"week-days": $props.weekDays,
|
|
966
|
+
"transition-direction": $options.transitionDirection,
|
|
967
|
+
"switch-to-narrower-view": $props.switchToNarrowerView
|
|
968
|
+
}, createSlots({ _: 2 }, [
|
|
969
|
+
_ctx.$slots["weekday-heading"] ? {
|
|
970
|
+
name: "weekday-heading",
|
|
971
|
+
fn: withCtx(({ heading, view }) => [
|
|
972
|
+
renderSlot(_ctx.$slots, "weekday-heading", {
|
|
973
|
+
heading,
|
|
974
|
+
view
|
|
975
|
+
})
|
|
976
|
+
]),
|
|
977
|
+
key: "0"
|
|
978
|
+
} : void 0,
|
|
979
|
+
_ctx.$slots["split-label"] ? {
|
|
980
|
+
name: "split-label",
|
|
981
|
+
fn: withCtx(({ split }) => [
|
|
982
|
+
renderSlot(_ctx.$slots, "split-label", {
|
|
983
|
+
split,
|
|
984
|
+
view: $options.view
|
|
985
|
+
})
|
|
986
|
+
]),
|
|
987
|
+
key: "1"
|
|
988
|
+
} : void 0
|
|
989
|
+
]), 1032, ["week-days", "transition-direction", "switch-to-narrower-view"])) : createCommentVNode("", true),
|
|
990
|
+
createVNode(Transition, {
|
|
991
|
+
name: `slide-fade--${$options.transitionDirection}`
|
|
992
|
+
}, {
|
|
993
|
+
default: withCtx(() => [
|
|
994
|
+
$options.showDaySplits ? (openBlock(), createElementBlock("div", _hoisted_8$1, [
|
|
995
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($props.daySplits, (split, i) => {
|
|
996
|
+
return openBlock(), createElementBlock("div", {
|
|
997
|
+
class: normalizeClass(["day-split-header", split.class || false]),
|
|
998
|
+
key: i
|
|
999
|
+
}, [
|
|
1000
|
+
renderSlot(_ctx.$slots, "split-label", {
|
|
1001
|
+
split,
|
|
1002
|
+
view: $options.view.id
|
|
1003
|
+
}, () => [
|
|
1004
|
+
createTextVNode(toDisplayString(split.label), 1)
|
|
1005
|
+
])
|
|
1006
|
+
], 2);
|
|
1007
|
+
}), 128))
|
|
1008
|
+
])) : createCommentVNode("", true)
|
|
1009
|
+
]),
|
|
1010
|
+
_: 3
|
|
1011
|
+
}, 8, ["name"])
|
|
1012
|
+
]);
|
|
1013
|
+
}
|
|
1014
|
+
const _sfc_main$4 = {
|
|
1015
|
+
inject: ["vuecal", "previous", "next", "switchView", "updateSelectedDate", "modules", "view"],
|
|
1016
|
+
components: { WeekdaysHeadings },
|
|
1017
|
+
props: {
|
|
1018
|
+
// Vuecal main component options (props).
|
|
1019
|
+
options: { type: Object, default: () => ({}) },
|
|
1020
|
+
editEvents: { type: Object, required: true },
|
|
1021
|
+
hasSplits: { type: [Boolean, Number], default: false },
|
|
1022
|
+
daySplits: { type: Array, default: () => [] },
|
|
1023
|
+
viewProps: { type: Object, default: () => ({}) },
|
|
1024
|
+
weekDays: { type: Array, default: () => [] },
|
|
1025
|
+
switchToNarrowerView: { type: Function, default: () => {
|
|
1026
|
+
} }
|
|
1027
|
+
},
|
|
1028
|
+
data: () => ({
|
|
1029
|
+
highlightedControl: null
|
|
1030
|
+
}),
|
|
1031
|
+
methods: {
|
|
1032
|
+
goToToday() {
|
|
1033
|
+
this.updateSelectedDate(new Date((/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0)));
|
|
1034
|
+
},
|
|
1035
|
+
switchToBroaderView() {
|
|
1036
|
+
this.transitionDirection = "left";
|
|
1037
|
+
if (this.broaderView) this.switchView(this.broaderView);
|
|
679
1038
|
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
}
|
|
689
|
-
}, onKeyUp(e) {
|
|
690
|
-
e.keyCode === 27 && this.cancelDelete();
|
|
691
|
-
}, eventResizing(e) {
|
|
692
|
-
const { resizeAnEvent: t } = this.domEvents, i = this.view.events.find((r) => r._eid === t._eid) || { segments: {} }, { minutes: n, cursorCoords: l } = this.minutesAtCursor(e), s = i.segments && i.segments[t.segment], { date: o, event: a } = this.utils, d = Math.max(n, this.timeFrom + 1, (s || i).startTimeMinutes + 1);
|
|
693
|
-
if (i.endTimeMinutes = t.endTimeMinutes = d, this.snapToTime) {
|
|
694
|
-
const r = i.endTimeMinutes + this.snapToTime / 2;
|
|
695
|
-
i.endTimeMinutes = r - r % this.snapToTime;
|
|
696
|
-
}
|
|
697
|
-
if (s && (s.endTimeMinutes = i.endTimeMinutes), i.end.setHours(0, i.endTimeMinutes, i.endTimeMinutes === z ? -1 : 0, 0), this.resizeX && this.isWeekView) {
|
|
698
|
-
i.daysCount = o.countDays(i.start, i.end);
|
|
699
|
-
const r = this.cellsEl, u = r.offsetWidth / r.childElementCount, m = Math.floor(l.x / u);
|
|
700
|
-
if (t.startCell === null && (t.startCell = m - (i.daysCount - 1)), t.endCell !== m) {
|
|
701
|
-
t.endCell = m;
|
|
702
|
-
const p = o.addDays(i.start, m - t.startCell), E = Math.max(o.countDays(i.start, p), 1);
|
|
703
|
-
if (E !== i.daysCount) {
|
|
704
|
-
let _ = null;
|
|
705
|
-
_ = E > i.daysCount ? a.addEventSegment(i) : a.removeEventSegment(i), t.segment = _, i.endTimeMinutes += 1e-3;
|
|
1039
|
+
},
|
|
1040
|
+
computed: {
|
|
1041
|
+
transitionDirection: {
|
|
1042
|
+
get() {
|
|
1043
|
+
return this.vuecal.transitionDirection;
|
|
1044
|
+
},
|
|
1045
|
+
set(direction) {
|
|
1046
|
+
this.vuecal.transitionDirection = direction;
|
|
706
1047
|
}
|
|
1048
|
+
},
|
|
1049
|
+
broaderView() {
|
|
1050
|
+
const { enabledViews } = this.vuecal;
|
|
1051
|
+
return enabledViews[enabledViews.indexOf(this.view.id) - 1];
|
|
1052
|
+
},
|
|
1053
|
+
showDaySplits() {
|
|
1054
|
+
return this.view.id === "day" && this.hasSplits && this.options.stickySplitLabels && !this.options.minSplitWidth;
|
|
1055
|
+
},
|
|
1056
|
+
// Drag & drop module.
|
|
1057
|
+
dnd() {
|
|
1058
|
+
return this.modules.dnd;
|
|
707
1059
|
}
|
|
708
1060
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
1061
|
+
};
|
|
1062
|
+
const Header = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", render$4]]);
|
|
1063
|
+
const _hoisted_1$3 = ["draggable"];
|
|
1064
|
+
function render$3(_ctx, _cache, $props, $setup, $data, $options) {
|
|
1065
|
+
return openBlock(), createElementBlock("div", {
|
|
1066
|
+
class: normalizeClass(["vuecal__event", $options.eventClasses]),
|
|
1067
|
+
style: normalizeStyle($options.eventStyles),
|
|
1068
|
+
tabindex: "0",
|
|
1069
|
+
onFocus: _cache[4] || (_cache[4] = (...args) => $options.focusEvent && $options.focusEvent(...args)),
|
|
1070
|
+
onKeypress: _cache[5] || (_cache[5] = withKeys(withModifiers((...args) => $options.onEnterKeypress && $options.onEnterKeypress(...args), ["stop"]), ["enter"])),
|
|
1071
|
+
onMouseenter: _cache[6] || (_cache[6] = (...args) => $options.onMouseEnter && $options.onMouseEnter(...args)),
|
|
1072
|
+
onMouseleave: _cache[7] || (_cache[7] = (...args) => $options.onMouseLeave && $options.onMouseLeave(...args)),
|
|
1073
|
+
onTouchstart: _cache[8] || (_cache[8] = withModifiers((...args) => $options.onTouchStart && $options.onTouchStart(...args), ["stop"])),
|
|
1074
|
+
onMousedown: _cache[9] || (_cache[9] = ($event) => $options.onMouseDown($event)),
|
|
1075
|
+
onMouseup: _cache[10] || (_cache[10] = (...args) => $options.onMouseUp && $options.onMouseUp(...args)),
|
|
1076
|
+
onTouchend: _cache[11] || (_cache[11] = (...args) => $options.onMouseUp && $options.onMouseUp(...args)),
|
|
1077
|
+
onTouchmove: _cache[12] || (_cache[12] = (...args) => $options.onTouchMove && $options.onTouchMove(...args)),
|
|
1078
|
+
onDblclick: _cache[13] || (_cache[13] = (...args) => $options.onDblClick && $options.onDblClick(...args)),
|
|
1079
|
+
draggable: $options.draggable,
|
|
1080
|
+
onDragstart: _cache[14] || (_cache[14] = ($event) => $options.draggable && $options.onDragStart($event)),
|
|
1081
|
+
onDragend: _cache[15] || (_cache[15] = ($event) => $options.draggable && $options.onDragEnd())
|
|
1082
|
+
}, [
|
|
1083
|
+
$options.vuecal.editEvents.delete && $props.event.deletable ? (openBlock(), createElementBlock("div", {
|
|
1084
|
+
key: 0,
|
|
1085
|
+
class: "vuecal__event-delete",
|
|
1086
|
+
onClick: _cache[0] || (_cache[0] = withModifiers((...args) => $options.deleteEvent && $options.deleteEvent(...args), ["stop"])),
|
|
1087
|
+
onTouchstart: _cache[1] || (_cache[1] = withModifiers((...args) => $options.touchDeleteEvent && $options.touchDeleteEvent(...args), ["stop"]))
|
|
1088
|
+
}, toDisplayString($options.vuecal.texts.deleteEvent), 33)) : createCommentVNode("", true),
|
|
1089
|
+
renderSlot(_ctx.$slots, "event", {
|
|
1090
|
+
event: $props.event,
|
|
1091
|
+
view: $options.view.id
|
|
1092
|
+
}),
|
|
1093
|
+
$options.resizable ? (openBlock(), createElementBlock("div", {
|
|
1094
|
+
key: 1,
|
|
1095
|
+
class: "vuecal__event-resize-handle",
|
|
1096
|
+
contenteditable: "false",
|
|
1097
|
+
onMousedown: _cache[2] || (_cache[2] = withModifiers((...args) => $options.onResizeHandleMouseDown && $options.onResizeHandleMouseDown(...args), ["stop", "prevent"])),
|
|
1098
|
+
onTouchstart: _cache[3] || (_cache[3] = withModifiers((...args) => $options.onResizeHandleMouseDown && $options.onResizeHandleMouseDown(...args), ["stop", "prevent"]))
|
|
1099
|
+
}, null, 32)) : createCommentVNode("", true)
|
|
1100
|
+
], 46, _hoisted_1$3);
|
|
1101
|
+
}
|
|
1102
|
+
const _sfc_main$3 = {
|
|
1103
|
+
inject: ["vuecal", "utils", "modules", "view", "domEvents", "editEvents"],
|
|
1104
|
+
props: {
|
|
1105
|
+
cellFormattedDate: { type: String, default: "" },
|
|
1106
|
+
event: { type: Object, default: () => ({}) },
|
|
1107
|
+
cellEvents: { type: Array, default: () => [] },
|
|
1108
|
+
overlaps: { type: Array, default: () => [] },
|
|
1109
|
+
// If multiple simultaneous events, the events are placed from left to right from the
|
|
1110
|
+
// one starting first to the last. (See utils/event.js > checkCellOverlappingEvents)
|
|
1111
|
+
eventPosition: { type: Number, default: 0 },
|
|
1112
|
+
overlapsStreak: { type: Number, default: 0 },
|
|
1113
|
+
allDay: { type: Boolean, default: false }
|
|
1114
|
+
// Is the event displayed in the all-day bar.
|
|
1115
|
+
},
|
|
1116
|
+
data: () => ({
|
|
1117
|
+
// Event touch detection with 30px threshold.
|
|
1118
|
+
touch: {
|
|
1119
|
+
dragThreshold: 30,
|
|
1120
|
+
// px.
|
|
1121
|
+
startX: 0,
|
|
1122
|
+
startY: 0,
|
|
1123
|
+
// Detect if the event touch start + touch end was a drag or a tap.
|
|
1124
|
+
// If it was a drag, don't call the event-click handler.
|
|
1125
|
+
dragged: false
|
|
725
1126
|
}
|
|
726
|
-
},
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
},
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
},
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1127
|
+
}),
|
|
1128
|
+
methods: {
|
|
1129
|
+
/**
|
|
1130
|
+
* On event mousedown.
|
|
1131
|
+
* Do not prevent propagation to trigger cell mousedown which highlights the cell if not highlighted.
|
|
1132
|
+
*/
|
|
1133
|
+
onMouseDown(e, touch = false) {
|
|
1134
|
+
if ("ontouchstart" in window && !touch) return false;
|
|
1135
|
+
const { clickHoldAnEvent, focusAnEvent, resizeAnEvent, dragAnEvent } = this.domEvents;
|
|
1136
|
+
if (focusAnEvent._eid === this.event._eid && clickHoldAnEvent._eid === this.event._eid) {
|
|
1137
|
+
return true;
|
|
1138
|
+
}
|
|
1139
|
+
this.focusEvent();
|
|
1140
|
+
clickHoldAnEvent._eid = null;
|
|
1141
|
+
if (this.vuecal.editEvents.delete && this.event.deletable) {
|
|
1142
|
+
clickHoldAnEvent.timeoutId = setTimeout(() => {
|
|
1143
|
+
if (!resizeAnEvent._eid && !dragAnEvent._eid) {
|
|
1144
|
+
clickHoldAnEvent._eid = this.event._eid;
|
|
1145
|
+
this.event.deleting = true;
|
|
1146
|
+
}
|
|
1147
|
+
}, clickHoldAnEvent.timeout);
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
/**
|
|
1151
|
+
* The mouseup handler is global (whole document) and initialized in index.vue on mounted.
|
|
1152
|
+
* It handles the mouseup on cell, events, and everything.
|
|
1153
|
+
* All mouseup on event, should be put there to avoid conflicts with other cases.
|
|
1154
|
+
* This function is also called on touchend on the event.
|
|
1155
|
+
*/
|
|
1156
|
+
onMouseUp(e) {
|
|
1157
|
+
if (this.domEvents.focusAnEvent._eid === this.event._eid && !this.touch.dragged) {
|
|
1158
|
+
this.domEvents.focusAnEvent.mousedUp = true;
|
|
1159
|
+
}
|
|
1160
|
+
this.touch.dragged = false;
|
|
1161
|
+
},
|
|
1162
|
+
onMouseEnter(e) {
|
|
1163
|
+
e.preventDefault();
|
|
1164
|
+
this.vuecal.emitWithEvent("event-mouse-enter", this.event);
|
|
1165
|
+
},
|
|
1166
|
+
onMouseLeave(e) {
|
|
1167
|
+
e.preventDefault();
|
|
1168
|
+
this.vuecal.emitWithEvent("event-mouse-leave", this.event);
|
|
1169
|
+
},
|
|
1170
|
+
// Detect if user taps on an event or drags it. If dragging, don't fire the event-click handler (if any).
|
|
1171
|
+
onTouchMove(e) {
|
|
1172
|
+
if (typeof this.vuecal.onEventClick !== "function") return;
|
|
1173
|
+
const { clientX, clientY } = e.touches[0];
|
|
1174
|
+
const { startX, startY, dragThreshold } = this.touch;
|
|
1175
|
+
if (Math.abs(clientX - startX) > dragThreshold || Math.abs(clientY - startY) > dragThreshold) {
|
|
1176
|
+
this.touch.dragged = true;
|
|
1177
|
+
}
|
|
1178
|
+
},
|
|
1179
|
+
onTouchStart(e) {
|
|
1180
|
+
this.touch.startX = e.touches[0].clientX;
|
|
1181
|
+
this.touch.startY = e.touches[0].clientY;
|
|
1182
|
+
this.onMouseDown(e, true);
|
|
1183
|
+
},
|
|
1184
|
+
onEnterKeypress(e) {
|
|
1185
|
+
if (typeof this.vuecal.onEventClick === "function") return this.vuecal.onEventClick(this.event, e);
|
|
1186
|
+
},
|
|
1187
|
+
onDblClick(e) {
|
|
1188
|
+
if (typeof this.vuecal.onEventDblclick === "function") return this.vuecal.onEventDblclick(this.event, e);
|
|
1189
|
+
},
|
|
1190
|
+
onDragStart(e) {
|
|
1191
|
+
this.dnd && this.dnd.eventDragStart(e, this.event);
|
|
1192
|
+
},
|
|
1193
|
+
onDragEnd() {
|
|
1194
|
+
this.dnd && this.dnd.eventDragEnd(this.event);
|
|
1195
|
+
},
|
|
1196
|
+
onResizeHandleMouseDown() {
|
|
1197
|
+
this.focusEvent();
|
|
1198
|
+
this.domEvents.dragAnEvent._eid = null;
|
|
1199
|
+
this.domEvents.resizeAnEvent = Object.assign(this.domEvents.resizeAnEvent, {
|
|
1200
|
+
_eid: this.event._eid,
|
|
1201
|
+
start: (this.segment || this.event).start,
|
|
1202
|
+
split: this.event.split || null,
|
|
1203
|
+
segment: !!this.segment && this.utils.date.formatDateLite(this.segment.start),
|
|
1204
|
+
originalEnd: new Date((this.segment || this.event).end),
|
|
1205
|
+
originalEndTimeMinutes: this.event.endTimeMinutes
|
|
1206
|
+
});
|
|
1207
|
+
this.event.resizing = true;
|
|
1208
|
+
},
|
|
1209
|
+
deleteEvent(touch = false) {
|
|
1210
|
+
if ("ontouchstart" in window && !touch) return false;
|
|
1211
|
+
this.utils.event.deleteAnEvent(this.event);
|
|
1212
|
+
},
|
|
1213
|
+
touchDeleteEvent(event) {
|
|
1214
|
+
this.deleteEvent(true);
|
|
1215
|
+
},
|
|
1216
|
+
cancelDeleteEvent() {
|
|
1217
|
+
this.event.deleting = false;
|
|
1218
|
+
},
|
|
1219
|
+
focusEvent() {
|
|
1220
|
+
const { focusAnEvent } = this.domEvents;
|
|
1221
|
+
const focusedEvent = focusAnEvent._eid;
|
|
1222
|
+
if (focusedEvent === this.event._eid) return;
|
|
1223
|
+
else if (focusedEvent) {
|
|
1224
|
+
const event = this.view.events.find((e) => e._eid === focusedEvent);
|
|
1225
|
+
if (event) event.focused = false;
|
|
1226
|
+
}
|
|
1227
|
+
this.vuecal.cancelDelete();
|
|
1228
|
+
this.vuecal.emitWithEvent("event-focus", this.event);
|
|
1229
|
+
focusAnEvent._eid = this.event._eid;
|
|
1230
|
+
this.event.focused = true;
|
|
1231
|
+
}
|
|
1232
|
+
},
|
|
1233
|
+
computed: {
|
|
1234
|
+
eventDimensions() {
|
|
1235
|
+
const { startTimeMinutes, endTimeMinutes } = this.segment || this.event;
|
|
1236
|
+
let minutesFromTop = startTimeMinutes - this.vuecal.timeFrom;
|
|
1237
|
+
const top = Math.max(Math.round(minutesFromTop * this.vuecal.timeCellHeight / this.vuecal.timeStep), 0);
|
|
1238
|
+
minutesFromTop = Math.min(endTimeMinutes, this.vuecal.timeTo) - this.vuecal.timeFrom;
|
|
1239
|
+
const bottom = Math.round(minutesFromTop * this.vuecal.timeCellHeight / this.vuecal.timeStep);
|
|
1240
|
+
const height = Math.max(bottom - top, 5);
|
|
1241
|
+
return { top, height };
|
|
1242
|
+
},
|
|
1243
|
+
eventStyles() {
|
|
1244
|
+
if (this.event.allDay || !this.vuecal.time || !this.event.endTimeMinutes || this.view.id === "month" || this.allDay) return {};
|
|
1245
|
+
let width = 100 / Math.min(this.overlaps.length + 1, this.overlapsStreak);
|
|
1246
|
+
let left = 100 / (this.overlaps.length + 1) * this.eventPosition;
|
|
1247
|
+
if (this.vuecal.minEventWidth && width < this.vuecal.minEventWidth) {
|
|
1248
|
+
width = this.vuecal.minEventWidth;
|
|
1249
|
+
left = (100 - this.vuecal.minEventWidth) / this.overlaps.length * this.eventPosition;
|
|
1250
|
+
}
|
|
1251
|
+
const { top, height } = this.eventDimensions;
|
|
1252
|
+
return {
|
|
1253
|
+
top: `${top}px`,
|
|
1254
|
+
height: `${height}px`,
|
|
1255
|
+
width: `${width}%`,
|
|
1256
|
+
left: this.event.left && `${this.event.left}px` || `${left}%`
|
|
1257
|
+
};
|
|
1258
|
+
},
|
|
1259
|
+
// Don't rely on global variables otherwise whenever it would change all the events would be redrawn.
|
|
1260
|
+
eventClasses() {
|
|
1261
|
+
const { isFirstDay, isLastDay } = this.segment || {};
|
|
1262
|
+
return {
|
|
1263
|
+
[this.event.class]: !!this.event.class,
|
|
1264
|
+
"vuecal__event--focus": this.event.focused,
|
|
1265
|
+
"vuecal__event--resizing": this.event.resizing,
|
|
1266
|
+
"vuecal__event--background": this.event.background,
|
|
1267
|
+
"vuecal__event--deletable": this.event.deleting,
|
|
1268
|
+
"vuecal__event--all-day": this.event.allDay,
|
|
1269
|
+
// Only apply the dragging class on the event copy that is being dragged.
|
|
1270
|
+
"vuecal__event--dragging": !this.event.draggingStatic && this.event.dragging,
|
|
1271
|
+
// Only apply the static class on the event original that remains static while a copy is being dragged.
|
|
1272
|
+
// Sometimes when dragging fast the static class would get stuck and events stays invisible,
|
|
1273
|
+
// So if dragging is false disable the static class as well.
|
|
1274
|
+
"vuecal__event--static": this.event.dragging && this.event.draggingStatic,
|
|
1275
|
+
// Multiple days events.
|
|
1276
|
+
"vuecal__event--multiple-days": !!this.segment,
|
|
1277
|
+
"event-start": this.segment && isFirstDay && !isLastDay,
|
|
1278
|
+
"event-middle": this.segment && !isFirstDay && !isLastDay,
|
|
1279
|
+
"event-end": this.segment && isLastDay && !isFirstDay
|
|
1280
|
+
};
|
|
1281
|
+
},
|
|
1282
|
+
// When multiple-day events, a segment is a portion of event spanning on 1 day.
|
|
1283
|
+
segment() {
|
|
1284
|
+
return this.event.segments && this.event.segments[this.cellFormattedDate] || null;
|
|
1285
|
+
},
|
|
1286
|
+
draggable() {
|
|
1287
|
+
const { draggable, background, daysCount } = this.event;
|
|
1288
|
+
return this.vuecal.editEvents.drag && draggable && !background && daysCount === 1;
|
|
1289
|
+
},
|
|
1290
|
+
resizable() {
|
|
1291
|
+
const { editEvents, time } = this.vuecal;
|
|
1292
|
+
return editEvents.resize && this.event.resizable && time && !this.allDay && (!this.segment || this.segment && this.segment.isLastDay) && this.view.id !== "month";
|
|
1293
|
+
},
|
|
1294
|
+
// Drag & drop module.
|
|
1295
|
+
dnd() {
|
|
1296
|
+
return this.modules.dnd;
|
|
876
1297
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
const Event = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", render$3]]);
|
|
1301
|
+
const _hoisted_1$2 = ["data-split", "aria-label", "onTouchstart", "onMousedown", "onDragover", "onDrop"];
|
|
1302
|
+
const _hoisted_2$1 = {
|
|
1303
|
+
key: 0,
|
|
1304
|
+
class: "cell-time-labels"
|
|
1305
|
+
};
|
|
1306
|
+
const _hoisted_3$1 = ["innerHTML"];
|
|
1307
|
+
const _hoisted_4$1 = {
|
|
1308
|
+
key: 2,
|
|
1309
|
+
class: "vuecal__cell-events"
|
|
1310
|
+
};
|
|
1311
|
+
const _hoisted_5$1 = ["title"];
|
|
1312
|
+
function render$2(_ctx, _cache, $props, $setup, $data, $options) {
|
|
1313
|
+
const _component_event = resolveComponent("event");
|
|
1314
|
+
return openBlock(), createBlock(TransitionGroup, {
|
|
1315
|
+
class: normalizeClass(["vuecal__cell", $options.cellClasses]),
|
|
1316
|
+
name: `slide-fade--${$options.transitionDirection}`,
|
|
1317
|
+
tag: "div",
|
|
1318
|
+
appear: $props.options.transitions,
|
|
1319
|
+
style: normalizeStyle($options.cellStyles)
|
|
1320
|
+
}, {
|
|
1321
|
+
default: withCtx(() => [
|
|
1322
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.splitsCount ? $options.splits : 1, (split, i) => {
|
|
1323
|
+
return openBlock(), createElementBlock("div", {
|
|
1324
|
+
class: normalizeClass(["vuecal__flex vuecal__cell-content", $options.splitsCount && $options.splitClasses(split)]),
|
|
1325
|
+
key: $props.options.transitions ? `${$options.view.id}-${$props.data.content}-${i}` : i,
|
|
1326
|
+
"data-split": $options.splitsCount ? split.id : false,
|
|
1327
|
+
column: "",
|
|
1328
|
+
tabindex: "0",
|
|
1329
|
+
"aria-label": $props.data.content,
|
|
1330
|
+
onFocus: _cache[0] || (_cache[0] = ($event) => $options.onCellFocus($event)),
|
|
1331
|
+
onKeypress: _cache[1] || (_cache[1] = withKeys(($event) => $options.onCellkeyPressEnter($event), ["enter"])),
|
|
1332
|
+
onTouchstart: ($event) => !$options.isDisabled && $options.onCellTouchStart($event, $options.splitsCount ? split.id : null),
|
|
1333
|
+
onMousedown: ($event) => !$options.isDisabled && $options.onCellMouseDown($event, $options.splitsCount ? split.id : null),
|
|
1334
|
+
onClick: _cache[2] || (_cache[2] = ($event) => !$options.isDisabled && $options.onCellClick($event)),
|
|
1335
|
+
onDblclick: _cache[3] || (_cache[3] = ($event) => !$options.isDisabled && $options.onCellDblClick($event)),
|
|
1336
|
+
onContextmenu: _cache[4] || (_cache[4] = ($event) => !$options.isDisabled && $props.options.cellContextmenu && $options.onCellContextMenu($event)),
|
|
1337
|
+
onDragenter: _cache[5] || (_cache[5] = ($event) => !$options.isDisabled && $props.editEvents.drag && $options.dnd && $options.dnd.cellDragEnter($event, _ctx.$data, $props.data.startDate)),
|
|
1338
|
+
onDragover: ($event) => !$options.isDisabled && $props.editEvents.drag && $options.dnd && $options.dnd.cellDragOver($event, _ctx.$data, $props.data.startDate, $options.splitsCount ? split.id : null),
|
|
1339
|
+
onDragleave: _cache[6] || (_cache[6] = ($event) => !$options.isDisabled && $props.editEvents.drag && $options.dnd && $options.dnd.cellDragLeave($event, _ctx.$data, $props.data.startDate)),
|
|
1340
|
+
onDrop: ($event) => !$options.isDisabled && $props.editEvents.drag && $options.dnd && $options.dnd.cellDragDrop($event, _ctx.$data, $props.data.startDate, $options.splitsCount ? split.id : null)
|
|
1341
|
+
}, [
|
|
1342
|
+
$props.options.showTimeInCells && $props.options.time && $options.isWeekOrDayView && !$props.allDay ? (openBlock(), createElementBlock("div", _hoisted_2$1, [
|
|
1343
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.vuecal.timeCells, (cell, i2) => {
|
|
1344
|
+
return openBlock(), createElementBlock("span", {
|
|
1345
|
+
class: "cell-time-label",
|
|
1346
|
+
key: i2
|
|
1347
|
+
}, toDisplayString(cell.label), 1);
|
|
1348
|
+
}), 128))
|
|
1349
|
+
])) : createCommentVNode("", true),
|
|
1350
|
+
$options.isWeekOrDayView && !$props.allDay && $options.specialHours.length ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList($options.specialHours, (block, i2) => {
|
|
1351
|
+
return openBlock(), createElementBlock("div", {
|
|
1352
|
+
class: normalizeClass(["vuecal__special-hours", `vuecal__special-hours--day${block.day} ${block.class}`]),
|
|
1353
|
+
style: normalizeStyle(`height: ${block.height}px;top: ${block.top}px`)
|
|
1354
|
+
}, [
|
|
1355
|
+
block.label ? (openBlock(), createElementBlock("div", {
|
|
1356
|
+
key: 0,
|
|
1357
|
+
class: "special-hours-label",
|
|
1358
|
+
innerHTML: block.label
|
|
1359
|
+
}, null, 8, _hoisted_3$1)) : createCommentVNode("", true)
|
|
1360
|
+
], 6);
|
|
1361
|
+
}), 256)) : createCommentVNode("", true),
|
|
1362
|
+
renderSlot(_ctx.$slots, "cell-content", {
|
|
1363
|
+
events: $options.events,
|
|
1364
|
+
selectCell: ($event) => $options.selectCell($event, true),
|
|
1365
|
+
split: $options.splitsCount ? split : false
|
|
1366
|
+
}),
|
|
1367
|
+
$options.eventsCount && ($options.isWeekOrDayView || $options.view.id === "month" && $props.options.eventsOnMonthView) ? (openBlock(), createElementBlock("div", _hoisted_4$1, [
|
|
1368
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.splitsCount ? split.events : $options.events, (event, j) => {
|
|
1369
|
+
return openBlock(), createBlock(_component_event, {
|
|
1370
|
+
key: j,
|
|
1371
|
+
"cell-formatted-date": $props.data.formattedDate,
|
|
1372
|
+
event,
|
|
1373
|
+
"all-day": $props.allDay,
|
|
1374
|
+
"cell-events": $options.splitsCount ? split.events : $options.events,
|
|
1375
|
+
overlaps: (($options.splitsCount ? split.overlaps[event._eid] : _ctx.cellOverlaps[event._eid]) || []).overlaps,
|
|
1376
|
+
"event-position": (($options.splitsCount ? split.overlaps[event._eid] : _ctx.cellOverlaps[event._eid]) || []).position,
|
|
1377
|
+
"overlaps-streak": $options.splitsCount ? split.overlapsStreak : _ctx.cellOverlapsStreak
|
|
1378
|
+
}, {
|
|
1379
|
+
event: withCtx(({ event: event2, view }) => [
|
|
1380
|
+
renderSlot(_ctx.$slots, "event", {
|
|
1381
|
+
view,
|
|
1382
|
+
event: event2
|
|
1383
|
+
})
|
|
1384
|
+
]),
|
|
1385
|
+
_: 2
|
|
1386
|
+
}, 1032, ["cell-formatted-date", "event", "all-day", "cell-events", "overlaps", "event-position", "overlaps-streak"]);
|
|
1387
|
+
}), 128))
|
|
1388
|
+
])) : createCommentVNode("", true)
|
|
1389
|
+
], 42, _hoisted_1$2);
|
|
1390
|
+
}), 128)),
|
|
1391
|
+
$options.timelineVisible ? (openBlock(), createElementBlock("div", {
|
|
1392
|
+
class: "vuecal__now-line",
|
|
1393
|
+
style: normalizeStyle(`top: ${$options.todaysTimePosition}px`),
|
|
1394
|
+
key: $props.options.transitions ? `${$options.view.id}-now-line` : "now-line",
|
|
1395
|
+
title: $options.utils.date.formatTime($options.vuecal.now)
|
|
1396
|
+
}, null, 12, _hoisted_5$1)) : createCommentVNode("", true)
|
|
1397
|
+
]),
|
|
1398
|
+
_: 3
|
|
1399
|
+
}, 8, ["class", "name", "appear", "style"]);
|
|
1400
|
+
}
|
|
1401
|
+
const _sfc_main$2 = {
|
|
1402
|
+
inject: ["vuecal", "utils", "modules", "view", "domEvents"],
|
|
1403
|
+
components: { Event },
|
|
1404
|
+
props: {
|
|
1405
|
+
// Vue-cal main component options (props).
|
|
1406
|
+
options: { type: Object, default: () => ({}) },
|
|
1407
|
+
editEvents: { type: Object, required: true },
|
|
1408
|
+
data: { type: Object, required: true },
|
|
1409
|
+
cellSplits: { type: Array, default: () => [] },
|
|
1410
|
+
minTimestamp: { type: [Number, null], default: null },
|
|
1411
|
+
maxTimestamp: { type: [Number, null], default: null },
|
|
1412
|
+
cellWidth: { type: [Number, Boolean], default: false },
|
|
1413
|
+
allDay: { type: Boolean, default: false }
|
|
1414
|
+
},
|
|
1415
|
+
data: () => ({
|
|
1416
|
+
cellOverlaps: {},
|
|
1417
|
+
cellOverlapsStreak: 1,
|
|
1418
|
+
// Largest amount of simultaneous events in cell.
|
|
1419
|
+
// On mouse down, save the time at cursor so it can be reused on cell focus event
|
|
1420
|
+
// where there is no cursor coords.
|
|
1421
|
+
timeAtCursor: null,
|
|
1422
|
+
highlighted: false,
|
|
1423
|
+
// On event drag over.
|
|
1424
|
+
highlightedSplit: null
|
|
1425
|
+
}),
|
|
1426
|
+
methods: {
|
|
1427
|
+
getSplitAtCursor({ target }) {
|
|
1428
|
+
const targetIsSplit = target.classList.contains("vuecal__cell-split");
|
|
1429
|
+
let split = targetIsSplit ? target : this.vuecal.findAncestor(target, "vuecal__cell-split");
|
|
1430
|
+
if (split) {
|
|
1431
|
+
split = split.attributes["data-split"].value;
|
|
1432
|
+
if (parseInt(split).toString() === split.toString()) split = parseInt(split);
|
|
1433
|
+
}
|
|
1434
|
+
return split || null;
|
|
1435
|
+
},
|
|
1436
|
+
splitClasses(split) {
|
|
1437
|
+
return {
|
|
1438
|
+
"vuecal__cell-split": true,
|
|
1439
|
+
"vuecal__cell-split--highlighted": this.highlightedSplit === split.id,
|
|
1440
|
+
[split.class]: !!split.class
|
|
1441
|
+
};
|
|
1442
|
+
},
|
|
1443
|
+
checkCellOverlappingEvents() {
|
|
1444
|
+
if (this.options.time && this.eventsCount && !this.splitsCount) {
|
|
1445
|
+
if (this.eventsCount === 1) {
|
|
1446
|
+
this.cellOverlaps = [];
|
|
1447
|
+
this.cellOverlapsStreak = 1;
|
|
1448
|
+
} else [this.cellOverlaps, this.cellOverlapsStreak] = this.utils.event.checkCellOverlappingEvents(this.events, this.options);
|
|
1449
|
+
}
|
|
1450
|
+
},
|
|
1451
|
+
isDOMElementAnEvent(el) {
|
|
1452
|
+
return this.vuecal.isDOMElementAnEvent(el);
|
|
1453
|
+
},
|
|
1454
|
+
/**
|
|
1455
|
+
* Select a cell and go to narrower view on double click or single click according to vuecalProps option.
|
|
1456
|
+
*/
|
|
1457
|
+
selectCell(DOMEvent, force = false) {
|
|
1458
|
+
const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;
|
|
1459
|
+
this.utils.cell.selectCell(force, this.timeAtCursor, split);
|
|
1460
|
+
this.timeAtCursor = null;
|
|
1461
|
+
},
|
|
1462
|
+
onCellkeyPressEnter(DOMEvent) {
|
|
1463
|
+
if (!this.isSelected) this.onCellFocus(DOMEvent);
|
|
1464
|
+
const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;
|
|
1465
|
+
this.utils.cell.keyPressEnterCell(this.timeAtCursor, split);
|
|
1466
|
+
this.timeAtCursor = null;
|
|
1467
|
+
},
|
|
1468
|
+
/**
|
|
1469
|
+
* On cell focus, from tab key or from mousedown, highlight the cell and emit
|
|
1470
|
+
* the cell-focus event with the date of the cell start when focusing from tab or
|
|
1471
|
+
* the date & time at cursor if click/touch.
|
|
1472
|
+
*/
|
|
1473
|
+
onCellFocus(DOMEvent) {
|
|
1474
|
+
if (!this.isSelected && !this.isDisabled) {
|
|
1475
|
+
this.isSelected = this.data.startDate;
|
|
1476
|
+
const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;
|
|
1477
|
+
const date = this.timeAtCursor || this.data.startDate;
|
|
1478
|
+
this.vuecal.$emit("cell-focus", split ? { date, split } : date);
|
|
1479
|
+
}
|
|
1480
|
+
},
|
|
1481
|
+
onCellMouseDown(DOMEvent, split = null, touch = false) {
|
|
1482
|
+
if ("ontouchstart" in window && !touch) return false;
|
|
1483
|
+
if (!this.isSelected) this.onCellFocus(DOMEvent);
|
|
1484
|
+
const { clickHoldACell, focusAnEvent } = this.domEvents;
|
|
1485
|
+
this.domEvents.cancelClickEventCreation = false;
|
|
1486
|
+
clickHoldACell.eventCreated = false;
|
|
1487
|
+
this.timeAtCursor = new Date(this.data.startDate);
|
|
1488
|
+
const { minutes, cursorCoords: { y } } = this.vuecal.minutesAtCursor(DOMEvent);
|
|
1489
|
+
this.timeAtCursor.setMinutes(minutes);
|
|
1490
|
+
const mouseDownOnEvent = this.isDOMElementAnEvent(DOMEvent.target);
|
|
1491
|
+
if (!mouseDownOnEvent && focusAnEvent._eid) {
|
|
1492
|
+
(this.view.events.find((e) => e._eid === focusAnEvent._eid) || {}).focused = false;
|
|
1493
|
+
}
|
|
1494
|
+
if (this.editEvents.create && !mouseDownOnEvent) this.setUpEventCreation(DOMEvent, y);
|
|
1495
|
+
},
|
|
1496
|
+
setUpEventCreation(DOMEvent, startCursorY) {
|
|
1497
|
+
if (this.options.dragToCreateEvent && ["week", "day"].includes(this.view.id)) {
|
|
1498
|
+
const { dragCreateAnEvent } = this.domEvents;
|
|
1499
|
+
dragCreateAnEvent.startCursorY = startCursorY;
|
|
1500
|
+
dragCreateAnEvent.split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;
|
|
1501
|
+
dragCreateAnEvent.start = this.timeAtCursor;
|
|
1502
|
+
if (this.options.snapToTime) {
|
|
1503
|
+
let timeMinutes = this.timeAtCursor.getHours() * 60 + this.timeAtCursor.getMinutes();
|
|
1504
|
+
const plusHalfSnapTime = timeMinutes + this.options.snapToTime / 2;
|
|
1505
|
+
timeMinutes = plusHalfSnapTime - plusHalfSnapTime % this.options.snapToTime;
|
|
1506
|
+
dragCreateAnEvent.start.setHours(0, timeMinutes, 0, 0);
|
|
1507
|
+
}
|
|
1508
|
+
} else if (this.options.cellClickHold && ["month", "week", "day"].includes(this.view.id)) {
|
|
1509
|
+
this.setUpCellHoldTimer(DOMEvent);
|
|
1510
|
+
}
|
|
1511
|
+
},
|
|
1512
|
+
// When click & holding a cell, and if allowed, set a timeout to create an event (can be cancelled).
|
|
1513
|
+
setUpCellHoldTimer(DOMEvent) {
|
|
1514
|
+
const { clickHoldACell } = this.domEvents;
|
|
1515
|
+
clickHoldACell.cellId = `${this.vuecal._.uid}_${this.data.formattedDate}`;
|
|
1516
|
+
clickHoldACell.split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;
|
|
1517
|
+
clickHoldACell.timeoutId = setTimeout(() => {
|
|
1518
|
+
if (clickHoldACell.cellId && !this.domEvents.cancelClickEventCreation) {
|
|
1519
|
+
const { _eid } = this.utils.event.createAnEvent(
|
|
1520
|
+
this.timeAtCursor,
|
|
1521
|
+
null,
|
|
1522
|
+
clickHoldACell.split ? { split: clickHoldACell.split } : {}
|
|
1523
|
+
);
|
|
1524
|
+
clickHoldACell.eventCreated = _eid;
|
|
1525
|
+
}
|
|
1526
|
+
}, clickHoldACell.timeout);
|
|
1527
|
+
},
|
|
1528
|
+
onCellTouchStart(DOMEvent, split = null) {
|
|
1529
|
+
this.onCellMouseDown(DOMEvent, split, true);
|
|
1530
|
+
},
|
|
1531
|
+
onCellClick(DOMEvent) {
|
|
1532
|
+
if (!this.isDOMElementAnEvent(DOMEvent.target)) this.selectCell(DOMEvent);
|
|
1533
|
+
},
|
|
1534
|
+
onCellDblClick(DOMEvent) {
|
|
1535
|
+
const date = new Date(this.data.startDate);
|
|
1536
|
+
date.setMinutes(this.vuecal.minutesAtCursor(DOMEvent).minutes);
|
|
1537
|
+
const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;
|
|
1538
|
+
this.vuecal.$emit("cell-dblclick", split ? { date, split } : date);
|
|
1539
|
+
if (this.options.dblclickToNavigate) this.vuecal.switchToNarrowerView();
|
|
1540
|
+
},
|
|
1541
|
+
onCellContextMenu(DOMEvent) {
|
|
1542
|
+
DOMEvent.stopPropagation();
|
|
1543
|
+
DOMEvent.preventDefault();
|
|
1544
|
+
const date = new Date(this.data.startDate);
|
|
1545
|
+
const { cursorCoords, minutes } = this.vuecal.minutesAtCursor(DOMEvent);
|
|
1546
|
+
date.setMinutes(minutes);
|
|
1547
|
+
const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;
|
|
1548
|
+
this.vuecal.$emit("cell-contextmenu", { date, ...cursorCoords, ...split || {}, e: DOMEvent });
|
|
1549
|
+
}
|
|
1550
|
+
},
|
|
1551
|
+
computed: {
|
|
1552
|
+
// Drag & drop module.
|
|
1553
|
+
dnd() {
|
|
1554
|
+
return this.modules.dnd;
|
|
1555
|
+
},
|
|
1556
|
+
nowInMinutes() {
|
|
1557
|
+
return this.utils.date.dateToMinutes(this.vuecal.now);
|
|
1558
|
+
},
|
|
1559
|
+
isBeforeMinDate() {
|
|
1560
|
+
return this.minTimestamp !== null && this.minTimestamp > this.data.endDate.getTime();
|
|
1561
|
+
},
|
|
1562
|
+
isAfterMaxDate() {
|
|
1563
|
+
return this.maxTimestamp && this.maxTimestamp < this.data.startDate.getTime();
|
|
1564
|
+
},
|
|
1565
|
+
// Is the current cell disabled or not.
|
|
1566
|
+
isDisabled() {
|
|
1567
|
+
const { disableDays } = this.options;
|
|
1568
|
+
const { isYearsOrYearView } = this.vuecal;
|
|
1569
|
+
if (disableDays.length && disableDays.includes(this.data.formattedDate) && !isYearsOrYearView) return true;
|
|
1570
|
+
return this.isBeforeMinDate || this.isAfterMaxDate;
|
|
1571
|
+
},
|
|
1572
|
+
// Is the current cell selected or not.
|
|
1573
|
+
isSelected: {
|
|
1574
|
+
get() {
|
|
1575
|
+
let selected = false;
|
|
1576
|
+
const { selectedDate } = this.view;
|
|
1577
|
+
if (this.view.id === "years") {
|
|
1578
|
+
selected = selectedDate.getFullYear() === this.data.startDate.getFullYear();
|
|
1579
|
+
} else if (this.view.id === "year") {
|
|
1580
|
+
selected = selectedDate.getFullYear() === this.data.startDate.getFullYear() && selectedDate.getMonth() === this.data.startDate.getMonth();
|
|
1581
|
+
} else selected = selectedDate.getTime() === this.data.startDate.getTime();
|
|
1582
|
+
return selected;
|
|
1583
|
+
},
|
|
1584
|
+
set(date) {
|
|
1585
|
+
this.view.selectedDate = date;
|
|
1586
|
+
this.vuecal.$emit("update:selected-date", this.view.selectedDate);
|
|
1587
|
+
}
|
|
1588
|
+
},
|
|
1589
|
+
// Cache result for performance.
|
|
1590
|
+
isWeekOrDayView() {
|
|
1591
|
+
return ["week", "day"].includes(this.view.id);
|
|
1592
|
+
},
|
|
1593
|
+
transitionDirection() {
|
|
1594
|
+
return this.vuecal.transitionDirection;
|
|
1595
|
+
},
|
|
1596
|
+
specialHours() {
|
|
1597
|
+
return this.data.specialHours.map((block) => {
|
|
1598
|
+
let { from, to } = block;
|
|
1599
|
+
from = Math.max(from, this.options.timeFrom);
|
|
1600
|
+
to = Math.min(to, this.options.timeTo);
|
|
1601
|
+
return {
|
|
1602
|
+
...block,
|
|
1603
|
+
height: (to - from) * this.timeScale,
|
|
1604
|
+
top: (from - this.options.timeFrom) * this.timeScale
|
|
1605
|
+
};
|
|
891
1606
|
});
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
1607
|
+
},
|
|
1608
|
+
events() {
|
|
1609
|
+
const { startDate: cellStart, endDate: cellEnd } = this.data;
|
|
1610
|
+
let events = [];
|
|
1611
|
+
if (!(["years", "year"].includes(this.view.id) && !this.options.eventsCountOnYearView)) {
|
|
1612
|
+
events = this.view.events.slice(0);
|
|
1613
|
+
if (this.view.id === "month") {
|
|
1614
|
+
events.push(...this.view.outOfScopeEvents);
|
|
1615
|
+
}
|
|
1616
|
+
events = events.filter((e) => this.utils.event.eventInRange(e, cellStart, cellEnd));
|
|
1617
|
+
if (this.options.showAllDayEvents && this.view.id !== "month") events = events.filter((e) => !!e.allDay === this.allDay);
|
|
1618
|
+
if (this.options.time && this.isWeekOrDayView && !this.allDay) {
|
|
1619
|
+
const { timeFrom, timeTo } = this.options;
|
|
1620
|
+
events = events.filter((e) => {
|
|
1621
|
+
const segment = e.daysCount > 1 && e.segments[this.data.formattedDate] || {};
|
|
1622
|
+
const singleDayInRange = e.daysCount === 1 && e.startTimeMinutes < timeTo && e.endTimeMinutes > timeFrom;
|
|
1623
|
+
const multipleDayInRange = e.daysCount > 1 && (segment.startTimeMinutes < timeTo && segment.endTimeMinutes > timeFrom);
|
|
1624
|
+
const recurrMultDayInRange = false;
|
|
1625
|
+
return e.allDay || singleDayInRange || multipleDayInRange || recurrMultDayInRange;
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1628
|
+
if (this.options.time && this.isWeekOrDayView && !(this.options.showAllDayEvents && this.allDay)) {
|
|
1629
|
+
events.sort((a, b) => a.start < b.start ? -1 : 1);
|
|
1630
|
+
}
|
|
1631
|
+
if (!this.cellSplits.length) this.$nextTick(this.checkCellOverlappingEvents);
|
|
1632
|
+
}
|
|
1633
|
+
return events;
|
|
1634
|
+
},
|
|
1635
|
+
eventsCount() {
|
|
1636
|
+
return this.events.length;
|
|
1637
|
+
},
|
|
1638
|
+
splits() {
|
|
1639
|
+
return this.cellSplits.map((item, i) => {
|
|
1640
|
+
const events = this.events.filter((e) => e.split === item.id);
|
|
1641
|
+
const [overlaps, streak] = this.utils.event.checkCellOverlappingEvents(events.filter((e) => !e.background && !e.allDay), this.options);
|
|
1642
|
+
return {
|
|
1643
|
+
...item,
|
|
1644
|
+
overlaps,
|
|
1645
|
+
overlapsStreak: streak,
|
|
1646
|
+
events
|
|
1647
|
+
};
|
|
897
1648
|
});
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
1649
|
+
},
|
|
1650
|
+
splitsCount() {
|
|
1651
|
+
return this.splits.length;
|
|
1652
|
+
},
|
|
1653
|
+
cellClasses() {
|
|
1654
|
+
return {
|
|
1655
|
+
[this.data.class]: !!this.data.class,
|
|
1656
|
+
"vuecal__cell--current": this.data.current,
|
|
1657
|
+
// E.g. Current year in years view.
|
|
1658
|
+
"vuecal__cell--today": this.data.today,
|
|
1659
|
+
"vuecal__cell--out-of-scope": this.data.outOfScope,
|
|
1660
|
+
"vuecal__cell--before-min": this.isDisabled && this.isBeforeMinDate,
|
|
1661
|
+
"vuecal__cell--after-max": this.isDisabled && this.isAfterMaxDate,
|
|
1662
|
+
"vuecal__cell--disabled": this.isDisabled,
|
|
1663
|
+
"vuecal__cell--selected": this.isSelected,
|
|
1664
|
+
"vuecal__cell--highlighted": this.highlighted,
|
|
1665
|
+
"vuecal__cell--has-splits": this.splitsCount,
|
|
1666
|
+
"vuecal__cell--has-events": this.eventsCount
|
|
1667
|
+
};
|
|
1668
|
+
},
|
|
1669
|
+
cellStyles() {
|
|
1670
|
+
return {
|
|
1671
|
+
// cellWidth is only applied when hiding weekdays on month and week views.
|
|
1672
|
+
...this.cellWidth ? { width: `${this.cellWidth}%` } : {}
|
|
1673
|
+
};
|
|
1674
|
+
},
|
|
1675
|
+
timelineVisible() {
|
|
1676
|
+
const { time, timeTo } = this.options;
|
|
1677
|
+
return this.data.today && this.isWeekOrDayView && time && !this.allDay && this.nowInMinutes <= timeTo;
|
|
1678
|
+
},
|
|
1679
|
+
todaysTimePosition() {
|
|
1680
|
+
if (!this.data.today || !this.options.time) return;
|
|
1681
|
+
const minutesFromTop = this.nowInMinutes - this.options.timeFrom;
|
|
1682
|
+
return Math.round(minutesFromTop * this.timeScale);
|
|
1683
|
+
},
|
|
1684
|
+
timeScale() {
|
|
1685
|
+
return this.options.timeCellHeight / this.options.timeStep;
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
const Cell = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", render$2]]);
|
|
1690
|
+
const _hoisted_1$1 = {
|
|
1691
|
+
key: 0,
|
|
1692
|
+
class: "vuecal__all-day-text",
|
|
1693
|
+
style: { "width": "3em" }
|
|
1694
|
+
};
|
|
1695
|
+
function render$1(_ctx, _cache, $props, $setup, $data, $options) {
|
|
1696
|
+
const _component_vuecal_cell = resolveComponent("vuecal-cell");
|
|
1697
|
+
return openBlock(), createElementBlock("div", {
|
|
1698
|
+
class: "vuecal__flex vuecal__all-day",
|
|
1699
|
+
style: normalizeStyle($props.cellOrSplitMinWidth && { height: $props.height })
|
|
1700
|
+
}, [
|
|
1701
|
+
!$props.cellOrSplitMinWidth ? (openBlock(), createElementBlock("div", _hoisted_1$1, [
|
|
1702
|
+
createElementVNode("span", null, toDisplayString($props.label), 1)
|
|
1703
|
+
])) : createCommentVNode("", true),
|
|
1704
|
+
createElementVNode("div", {
|
|
1705
|
+
class: normalizeClass(["vuecal__flex vuecal__cells", `${$options.view.id}-view`]),
|
|
1706
|
+
grow: "",
|
|
1707
|
+
style: normalizeStyle($props.cellOrSplitMinWidth ? `min-width: ${$props.cellOrSplitMinWidth}px` : "")
|
|
1708
|
+
}, [
|
|
1709
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($props.cells, (cell, i) => {
|
|
1710
|
+
return openBlock(), createBlock(_component_vuecal_cell, {
|
|
1711
|
+
key: i,
|
|
1712
|
+
options: $props.options,
|
|
1713
|
+
"edit-events": $options.editEvents,
|
|
1714
|
+
data: cell,
|
|
1715
|
+
"all-day": true,
|
|
1716
|
+
"cell-width": $props.options.hideWeekdays.length && ($options.vuecal.isWeekView || $options.vuecal.isMonthView) && $options.vuecal.cellWidth,
|
|
1717
|
+
"min-timestamp": $props.options.minTimestamp,
|
|
1718
|
+
"max-timestamp": $props.options.maxTimestamp,
|
|
1719
|
+
"cell-splits": $props.daySplits
|
|
1720
|
+
}, {
|
|
1721
|
+
event: withCtx(({ event, view }) => [
|
|
1722
|
+
renderSlot(_ctx.$slots, "event", {
|
|
1723
|
+
view,
|
|
1724
|
+
event
|
|
1725
|
+
})
|
|
1726
|
+
]),
|
|
1727
|
+
_: 2
|
|
1728
|
+
}, 1032, ["options", "edit-events", "data", "cell-width", "min-timestamp", "max-timestamp", "cell-splits"]);
|
|
1729
|
+
}), 128))
|
|
1730
|
+
], 6)
|
|
1731
|
+
], 4);
|
|
1732
|
+
}
|
|
1733
|
+
const _sfc_main$1 = {
|
|
1734
|
+
inject: ["vuecal", "view", "editEvents"],
|
|
1735
|
+
components: { "vuecal-cell": Cell },
|
|
1736
|
+
props: {
|
|
1737
|
+
// Vue-cal main component options (props).
|
|
1738
|
+
options: { type: Object, required: true },
|
|
1739
|
+
cells: { type: Array, required: true },
|
|
1740
|
+
label: { type: String, required: true },
|
|
1741
|
+
daySplits: { type: Array, default: () => [] },
|
|
1742
|
+
shortEvents: { type: Boolean, default: true },
|
|
1743
|
+
height: { type: String, default: "" },
|
|
1744
|
+
cellOrSplitMinWidth: { type: Number, default: null }
|
|
1745
|
+
},
|
|
1746
|
+
computed: {
|
|
1747
|
+
hasCellOrSplitWidth() {
|
|
1748
|
+
return !!(this.options.minCellWidth || this.daySplits.length && this.options.minSplitWidth);
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
};
|
|
1752
|
+
const AllDayBar = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", render$1]]);
|
|
1753
|
+
const _hoisted_1 = ["lang"];
|
|
1754
|
+
const _hoisted_2 = { class: "default" };
|
|
1755
|
+
const _hoisted_3 = {
|
|
1756
|
+
key: 0,
|
|
1757
|
+
class: "vuecal__flex vuecal__body",
|
|
1758
|
+
grow: ""
|
|
1759
|
+
};
|
|
1760
|
+
const _hoisted_4 = ["onBlur", "innerHTML"];
|
|
1761
|
+
const _hoisted_5 = ["innerHTML"];
|
|
1762
|
+
const _hoisted_6 = ["innerHTML"];
|
|
1763
|
+
const _hoisted_7 = {
|
|
1764
|
+
class: "vuecal__flex",
|
|
1765
|
+
row: "",
|
|
1766
|
+
grow: ""
|
|
1767
|
+
};
|
|
1768
|
+
const _hoisted_8 = {
|
|
1769
|
+
key: 0,
|
|
1770
|
+
class: "vuecal__time-column"
|
|
1771
|
+
};
|
|
1772
|
+
const _hoisted_9 = { class: "vuecal__time-cell-label" };
|
|
1773
|
+
const _hoisted_10 = {
|
|
1774
|
+
key: 1,
|
|
1775
|
+
class: "vuecal__flex vuecal__week-numbers",
|
|
1776
|
+
column: ""
|
|
1777
|
+
};
|
|
1778
|
+
const _hoisted_11 = ["wrap", "column"];
|
|
1779
|
+
const _hoisted_12 = ["onBlur", "innerHTML"];
|
|
1780
|
+
const _hoisted_13 = ["innerHTML"];
|
|
1781
|
+
const _hoisted_14 = ["innerHTML"];
|
|
1782
|
+
const _hoisted_15 = ["wrap"];
|
|
1783
|
+
const _hoisted_16 = ["innerHTML"];
|
|
1784
|
+
const _hoisted_17 = ["innerHTML"];
|
|
1785
|
+
const _hoisted_18 = {
|
|
1786
|
+
key: 2,
|
|
1787
|
+
class: "vuecal__cell-events-count"
|
|
1788
|
+
};
|
|
1789
|
+
const _hoisted_19 = {
|
|
1790
|
+
key: 3,
|
|
1791
|
+
class: "vuecal__no-event"
|
|
1792
|
+
};
|
|
1793
|
+
const _hoisted_20 = ["onBlur", "innerHTML"];
|
|
1794
|
+
const _hoisted_21 = ["innerHTML"];
|
|
1795
|
+
const _hoisted_22 = {
|
|
1796
|
+
key: 2,
|
|
1797
|
+
class: "vuecal__event-time"
|
|
1798
|
+
};
|
|
1799
|
+
const _hoisted_23 = { key: 0 };
|
|
1800
|
+
const _hoisted_24 = {
|
|
1801
|
+
key: 1,
|
|
1802
|
+
class: "days-to-end"
|
|
1803
|
+
};
|
|
1804
|
+
const _hoisted_25 = ["innerHTML"];
|
|
1805
|
+
const _hoisted_26 = {
|
|
1806
|
+
key: 0,
|
|
1807
|
+
class: "vuecal__scrollbar-check"
|
|
1808
|
+
};
|
|
1809
|
+
function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
1810
|
+
const _component_vuecal_header = resolveComponent("vuecal-header");
|
|
1811
|
+
const _component_all_day_bar = resolveComponent("all-day-bar");
|
|
1812
|
+
const _component_weekdays_headings = resolveComponent("weekdays-headings");
|
|
1813
|
+
const _component_vuecal_cell = resolveComponent("vuecal-cell");
|
|
1814
|
+
return openBlock(), createElementBlock("div", {
|
|
1815
|
+
class: normalizeClass(["vuecal__flex vuecal", $options.cssClasses]),
|
|
1816
|
+
column: "",
|
|
1817
|
+
ref: "vuecal",
|
|
1818
|
+
lang: $props.locale
|
|
1819
|
+
}, [
|
|
1820
|
+
createVNode(_component_vuecal_header, {
|
|
1821
|
+
options: _ctx.$props,
|
|
1822
|
+
"edit-events": $options.editEvents,
|
|
1823
|
+
"view-props": { views: $options.views, weekDaysInHeader: $options.weekDaysInHeader },
|
|
1824
|
+
"week-days": $options.weekDays,
|
|
1825
|
+
"has-splits": $options.hasSplits,
|
|
1826
|
+
"day-splits": $options.daySplits,
|
|
1827
|
+
"switch-to-narrower-view": $options.switchToNarrowerView
|
|
1828
|
+
}, createSlots({
|
|
1829
|
+
"arrow-prev": withCtx(() => [
|
|
1830
|
+
renderSlot(_ctx.$slots, "arrow-prev", {}, () => [
|
|
1831
|
+
_cache[0] || (_cache[0] = createTextVNode(" ")),
|
|
1832
|
+
_cache[1] || (_cache[1] = createElementVNode("i", { class: "angle" }, null, -1)),
|
|
1833
|
+
_cache[2] || (_cache[2] = createTextVNode(" "))
|
|
1834
|
+
])
|
|
1835
|
+
]),
|
|
1836
|
+
"arrow-next": withCtx(() => [
|
|
1837
|
+
renderSlot(_ctx.$slots, "arrow-next", {}, () => [
|
|
1838
|
+
_cache[3] || (_cache[3] = createTextVNode(" ")),
|
|
1839
|
+
_cache[4] || (_cache[4] = createElementVNode("i", { class: "angle" }, null, -1)),
|
|
1840
|
+
_cache[5] || (_cache[5] = createTextVNode(" "))
|
|
1841
|
+
])
|
|
1842
|
+
]),
|
|
1843
|
+
"today-button": withCtx(() => [
|
|
1844
|
+
renderSlot(_ctx.$slots, "today-button", {}, () => [
|
|
1845
|
+
createElementVNode("span", _hoisted_2, toDisplayString($data.texts.today), 1)
|
|
1846
|
+
])
|
|
1847
|
+
]),
|
|
1848
|
+
title: withCtx(() => [
|
|
1849
|
+
renderSlot(_ctx.$slots, "title", {
|
|
1850
|
+
title: $options.viewTitle,
|
|
1851
|
+
view: $data.view
|
|
1852
|
+
}, () => [
|
|
1853
|
+
createTextVNode(toDisplayString($options.viewTitle), 1)
|
|
1854
|
+
])
|
|
1855
|
+
]),
|
|
1856
|
+
_: 2
|
|
1857
|
+
}, [
|
|
1858
|
+
_ctx.$slots["weekday-heading"] ? {
|
|
1859
|
+
name: "weekday-heading",
|
|
1860
|
+
fn: withCtx(({ heading, view }) => [
|
|
1861
|
+
renderSlot(_ctx.$slots, "weekday-heading", {
|
|
1862
|
+
heading,
|
|
1863
|
+
view
|
|
1864
|
+
})
|
|
1865
|
+
]),
|
|
1866
|
+
key: "0"
|
|
1867
|
+
} : void 0,
|
|
1868
|
+
_ctx.$slots["split-label"] ? {
|
|
1869
|
+
name: "split-label",
|
|
1870
|
+
fn: withCtx(({ split }) => [
|
|
1871
|
+
renderSlot(_ctx.$slots, "split-label", {
|
|
1872
|
+
split,
|
|
1873
|
+
view: $data.view.id
|
|
1874
|
+
})
|
|
1875
|
+
]),
|
|
1876
|
+
key: "1"
|
|
1877
|
+
} : void 0
|
|
1878
|
+
]), 1032, ["options", "edit-events", "view-props", "week-days", "has-splits", "day-splits", "switch-to-narrower-view"]),
|
|
1879
|
+
!$props.hideBody ? (openBlock(), createElementBlock("div", _hoisted_3, [
|
|
1880
|
+
createVNode(Transition, {
|
|
1881
|
+
name: `slide-fade--${$data.transitionDirection}`,
|
|
1882
|
+
appear: $props.transitions
|
|
1883
|
+
}, {
|
|
1884
|
+
default: withCtx(() => [
|
|
1885
|
+
(openBlock(), createElementBlock("div", {
|
|
1886
|
+
class: "vuecal__flex",
|
|
1887
|
+
style: { "min-width": "100%" },
|
|
1888
|
+
key: $props.transitions ? $data.view.id : false,
|
|
1889
|
+
column: ""
|
|
1890
|
+
}, [
|
|
1891
|
+
$props.showAllDayEvents && $options.hasTimeColumn && (!$options.cellOrSplitMinWidth || $options.isDayView && !$props.minSplitWidth) ? (openBlock(), createBlock(_component_all_day_bar, normalizeProps(mergeProps({ key: 0 }, $options.allDayBar)), {
|
|
1892
|
+
event: withCtx(({ event, view }) => [
|
|
1893
|
+
renderSlot(_ctx.$slots, "event", {
|
|
1894
|
+
view,
|
|
1895
|
+
event
|
|
1896
|
+
}, () => [
|
|
1897
|
+
$options.editEvents.title && event.titleEditable ? (openBlock(), createElementBlock("div", {
|
|
1898
|
+
key: 0,
|
|
1899
|
+
class: "vuecal__event-title vuecal__event-title--edit",
|
|
1900
|
+
contenteditable: "",
|
|
1901
|
+
onBlur: ($event) => $options.onEventTitleBlur($event, event),
|
|
1902
|
+
innerHTML: event.title
|
|
1903
|
+
}, null, 40, _hoisted_4)) : event.title ? (openBlock(), createElementBlock("div", {
|
|
1904
|
+
key: 1,
|
|
1905
|
+
class: "vuecal__event-title",
|
|
1906
|
+
innerHTML: event.title
|
|
1907
|
+
}, null, 8, _hoisted_5)) : createCommentVNode("", true),
|
|
1908
|
+
event.content && !$options.hasShortEvents && !$options.isShortMonthView ? (openBlock(), createElementBlock("div", {
|
|
1909
|
+
key: 2,
|
|
1910
|
+
class: "vuecal__event-content",
|
|
1911
|
+
innerHTML: event.content
|
|
1912
|
+
}, null, 8, _hoisted_6)) : createCommentVNode("", true)
|
|
1913
|
+
])
|
|
1914
|
+
]),
|
|
1915
|
+
_: 3
|
|
1916
|
+
}, 16)) : createCommentVNode("", true),
|
|
1917
|
+
createElementVNode("div", {
|
|
1918
|
+
class: normalizeClass(["vuecal__bg", { vuecal__flex: !$options.hasTimeColumn }]),
|
|
1919
|
+
column: ""
|
|
1920
|
+
}, [
|
|
1921
|
+
createElementVNode("div", _hoisted_7, [
|
|
1922
|
+
$options.hasTimeColumn ? (openBlock(), createElementBlock("div", _hoisted_8, [
|
|
1923
|
+
$props.showAllDayEvents && $options.cellOrSplitMinWidth && !($options.isDayView && !$props.minSplitWidth) ? (openBlock(), createElementBlock("div", {
|
|
1924
|
+
key: 0,
|
|
1925
|
+
class: "vuecal__all-day-text",
|
|
1926
|
+
style: normalizeStyle({ height: $options.allDayBar.height })
|
|
1927
|
+
}, [
|
|
1928
|
+
createElementVNode("span", null, toDisplayString($data.texts.allDay), 1)
|
|
1929
|
+
], 4)) : createCommentVNode("", true),
|
|
1930
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.timeCells, (cell, i) => {
|
|
1931
|
+
return openBlock(), createElementBlock("div", {
|
|
1932
|
+
class: "vuecal__time-cell",
|
|
1933
|
+
key: i,
|
|
1934
|
+
style: normalizeStyle(`height: ${$props.timeCellHeight}px`)
|
|
1935
|
+
}, [
|
|
1936
|
+
renderSlot(_ctx.$slots, "time-cell", {
|
|
1937
|
+
hours: cell.hours,
|
|
1938
|
+
minutes: cell.minutes
|
|
1939
|
+
}, () => [
|
|
1940
|
+
_cache[6] || (_cache[6] = createElementVNode("span", { class: "vuecal__time-cell-line" }, null, -1)),
|
|
1941
|
+
createElementVNode("span", _hoisted_9, toDisplayString(cell.label), 1)
|
|
1942
|
+
])
|
|
1943
|
+
], 4);
|
|
1944
|
+
}), 128))
|
|
1945
|
+
])) : createCommentVNode("", true),
|
|
1946
|
+
$props.showWeekNumbers && $options.isMonthView ? (openBlock(), createElementBlock("div", _hoisted_10, [
|
|
1947
|
+
(openBlock(), createElementBlock(Fragment, null, renderList(6, (i) => {
|
|
1948
|
+
return createElementVNode("div", {
|
|
1949
|
+
class: "vuecal__flex vuecal__week-number-cell",
|
|
1950
|
+
key: i,
|
|
1951
|
+
grow: ""
|
|
1952
|
+
}, [
|
|
1953
|
+
renderSlot(_ctx.$slots, "week-number-cell", {
|
|
1954
|
+
week: $options.getWeekNumber(i - 1)
|
|
1955
|
+
}, () => [
|
|
1956
|
+
createTextVNode(toDisplayString($options.getWeekNumber(i - 1)), 1)
|
|
1957
|
+
])
|
|
1958
|
+
]);
|
|
1959
|
+
}), 64))
|
|
1960
|
+
])) : createCommentVNode("", true),
|
|
1961
|
+
createElementVNode("div", {
|
|
1962
|
+
class: normalizeClass(["vuecal__flex vuecal__cells", `${$data.view.id}-view`]),
|
|
1963
|
+
grow: "",
|
|
1964
|
+
wrap: !$options.cellOrSplitMinWidth || !$options.isWeekView,
|
|
1965
|
+
column: !!$options.cellOrSplitMinWidth
|
|
1966
|
+
}, [
|
|
1967
|
+
$options.cellOrSplitMinWidth && $options.isWeekView ? (openBlock(), createBlock(_component_weekdays_headings, {
|
|
1968
|
+
key: 0,
|
|
1969
|
+
"transition-direction": $data.transitionDirection,
|
|
1970
|
+
"week-days": $options.weekDays,
|
|
1971
|
+
"switch-to-narrower-view": $options.switchToNarrowerView,
|
|
1972
|
+
style: normalizeStyle($options.cellOrSplitMinWidth ? `min-width: ${$options.cellOrSplitMinWidth}px` : "")
|
|
1973
|
+
}, createSlots({ _: 2 }, [
|
|
1974
|
+
_ctx.$slots["weekday-heading"] ? {
|
|
1975
|
+
name: "weekday-heading",
|
|
1976
|
+
fn: withCtx(({ heading, view }) => [
|
|
1977
|
+
renderSlot(_ctx.$slots, "weekday-heading", {
|
|
1978
|
+
heading,
|
|
1979
|
+
view
|
|
1980
|
+
})
|
|
1981
|
+
]),
|
|
1982
|
+
key: "0"
|
|
1983
|
+
} : void 0,
|
|
1984
|
+
_ctx.$slots["split-label"] ? {
|
|
1985
|
+
name: "split-label",
|
|
1986
|
+
fn: withCtx(({ split }) => [
|
|
1987
|
+
renderSlot(_ctx.$slots, "split-label", {
|
|
1988
|
+
split,
|
|
1989
|
+
view: $data.view.id
|
|
1990
|
+
})
|
|
1991
|
+
]),
|
|
1992
|
+
key: "1"
|
|
1993
|
+
} : void 0
|
|
1994
|
+
]), 1032, ["transition-direction", "week-days", "switch-to-narrower-view", "style"])) : $options.hasSplits && $props.stickySplitLabels && $props.minSplitWidth ? (openBlock(), createElementBlock("div", {
|
|
1995
|
+
key: 1,
|
|
1996
|
+
class: "vuecal__flex vuecal__split-days-headers",
|
|
1997
|
+
style: normalizeStyle($options.cellOrSplitMinWidth ? `min-width: ${$options.cellOrSplitMinWidth}px` : "")
|
|
1998
|
+
}, [
|
|
1999
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.daySplits, (split, i) => {
|
|
2000
|
+
return openBlock(), createElementBlock("div", {
|
|
2001
|
+
class: normalizeClass(["day-split-header", split.class || false]),
|
|
2002
|
+
key: i
|
|
2003
|
+
}, [
|
|
2004
|
+
renderSlot(_ctx.$slots, "split-label", {
|
|
2005
|
+
split,
|
|
2006
|
+
view: $data.view.id
|
|
2007
|
+
}, () => [
|
|
2008
|
+
createTextVNode(toDisplayString(split.label), 1)
|
|
2009
|
+
])
|
|
2010
|
+
], 2);
|
|
2011
|
+
}), 128))
|
|
2012
|
+
], 4)) : createCommentVNode("", true),
|
|
2013
|
+
$props.showAllDayEvents && $options.hasTimeColumn && ($options.isWeekView && $options.cellOrSplitMinWidth || $options.isDayView && $options.hasSplits && $props.minSplitWidth) ? (openBlock(), createBlock(_component_all_day_bar, normalizeProps(mergeProps({ key: 2 }, $options.allDayBar)), {
|
|
2014
|
+
event: withCtx(({ event, view }) => [
|
|
2015
|
+
renderSlot(_ctx.$slots, "event", {
|
|
2016
|
+
view,
|
|
2017
|
+
event
|
|
2018
|
+
}, () => [
|
|
2019
|
+
$options.editEvents.title && event.titleEditable ? (openBlock(), createElementBlock("div", {
|
|
2020
|
+
key: 0,
|
|
2021
|
+
class: "vuecal__event-title vuecal__event-title--edit",
|
|
2022
|
+
contenteditable: "",
|
|
2023
|
+
onBlur: ($event) => $options.onEventTitleBlur($event, event),
|
|
2024
|
+
innerHTML: event.title
|
|
2025
|
+
}, null, 40, _hoisted_12)) : event.title ? (openBlock(), createElementBlock("div", {
|
|
2026
|
+
key: 1,
|
|
2027
|
+
class: "vuecal__event-title",
|
|
2028
|
+
innerHTML: event.title
|
|
2029
|
+
}, null, 8, _hoisted_13)) : createCommentVNode("", true),
|
|
2030
|
+
event.content && !$options.hasShortEvents && !$options.isShortMonthView ? (openBlock(), createElementBlock("div", {
|
|
2031
|
+
key: 2,
|
|
2032
|
+
class: "vuecal__event-content",
|
|
2033
|
+
innerHTML: event.content
|
|
2034
|
+
}, null, 8, _hoisted_14)) : createCommentVNode("", true)
|
|
2035
|
+
])
|
|
2036
|
+
]),
|
|
2037
|
+
_: 3
|
|
2038
|
+
}, 16)) : createCommentVNode("", true),
|
|
2039
|
+
createElementVNode("div", {
|
|
2040
|
+
class: "vuecal__flex",
|
|
2041
|
+
ref: (el) => $data.cellsEl = el,
|
|
2042
|
+
grow: "",
|
|
2043
|
+
wrap: !$options.cellOrSplitMinWidth || !$options.isWeekView,
|
|
2044
|
+
style: normalizeStyle($options.cellOrSplitMinWidth ? `min-width: ${$options.cellOrSplitMinWidth}px` : "")
|
|
2045
|
+
}, [
|
|
2046
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.viewCells, (cell, i) => {
|
|
2047
|
+
return openBlock(), createBlock(_component_vuecal_cell, {
|
|
2048
|
+
key: i,
|
|
2049
|
+
options: _ctx.$props,
|
|
2050
|
+
"edit-events": $options.editEvents,
|
|
2051
|
+
data: cell,
|
|
2052
|
+
"cell-width": $props.hideWeekdays.length && ($options.isWeekView || $options.isMonthView) && $options.cellWidth,
|
|
2053
|
+
"min-timestamp": $options.minTimestamp,
|
|
2054
|
+
"max-timestamp": $options.maxTimestamp,
|
|
2055
|
+
"cell-splits": $options.hasSplits && $options.daySplits || []
|
|
2056
|
+
}, {
|
|
2057
|
+
"cell-content": withCtx(({ events, split, selectCell }) => [
|
|
2058
|
+
renderSlot(_ctx.$slots, "cell-content", {
|
|
2059
|
+
cell,
|
|
2060
|
+
view: $data.view,
|
|
2061
|
+
goNarrower: selectCell,
|
|
2062
|
+
events
|
|
2063
|
+
}, () => [
|
|
2064
|
+
split && !$props.stickySplitLabels ? (openBlock(), createElementBlock("div", {
|
|
2065
|
+
key: 0,
|
|
2066
|
+
class: "split-label",
|
|
2067
|
+
innerHTML: split.label
|
|
2068
|
+
}, null, 8, _hoisted_16)) : createCommentVNode("", true),
|
|
2069
|
+
cell.content ? (openBlock(), createElementBlock("div", {
|
|
2070
|
+
key: 1,
|
|
2071
|
+
class: "vuecal__cell-date",
|
|
2072
|
+
innerHTML: cell.content
|
|
2073
|
+
}, null, 8, _hoisted_17)) : createCommentVNode("", true),
|
|
2074
|
+
($options.isMonthView && !$props.eventsOnMonthView || $options.isYearsOrYearView && $props.eventsCountOnYearView) && events.length ? (openBlock(), createElementBlock("div", _hoisted_18, [
|
|
2075
|
+
renderSlot(_ctx.$slots, "events-count", {
|
|
2076
|
+
view: $data.view,
|
|
2077
|
+
events
|
|
2078
|
+
}, () => [
|
|
2079
|
+
createTextVNode(toDisplayString(events.length), 1)
|
|
2080
|
+
])
|
|
2081
|
+
])) : createCommentVNode("", true),
|
|
2082
|
+
!$options.cellOrSplitHasEvents(events, split) && $options.isWeekOrDayView ? (openBlock(), createElementBlock("div", _hoisted_19, [
|
|
2083
|
+
renderSlot(_ctx.$slots, "no-event", {}, () => [
|
|
2084
|
+
createTextVNode(toDisplayString($data.texts.noEvent), 1)
|
|
2085
|
+
])
|
|
2086
|
+
])) : createCommentVNode("", true)
|
|
2087
|
+
])
|
|
2088
|
+
]),
|
|
2089
|
+
event: withCtx(({ event, view }) => [
|
|
2090
|
+
renderSlot(_ctx.$slots, "event", {
|
|
2091
|
+
view,
|
|
2092
|
+
event
|
|
2093
|
+
}, () => [
|
|
2094
|
+
$options.editEvents.title && event.titleEditable ? (openBlock(), createElementBlock("div", {
|
|
2095
|
+
key: 0,
|
|
2096
|
+
class: "vuecal__event-title vuecal__event-title--edit",
|
|
2097
|
+
contenteditable: "",
|
|
2098
|
+
onBlur: ($event) => $options.onEventTitleBlur($event, event),
|
|
2099
|
+
innerHTML: event.title
|
|
2100
|
+
}, null, 40, _hoisted_20)) : event.title ? (openBlock(), createElementBlock("div", {
|
|
2101
|
+
key: 1,
|
|
2102
|
+
class: "vuecal__event-title",
|
|
2103
|
+
innerHTML: event.title
|
|
2104
|
+
}, null, 8, _hoisted_21)) : createCommentVNode("", true),
|
|
2105
|
+
$props.time && !event.allDay && !($options.isMonthView && (event.allDay || $props.showAllDayEvents === "short")) && !$options.isShortMonthView ? (openBlock(), createElementBlock("div", _hoisted_22, [
|
|
2106
|
+
createTextVNode(toDisplayString($data.utils.date.formatTime(event.start, $options.TimeFormat)), 1),
|
|
2107
|
+
event.endTimeMinutes ? (openBlock(), createElementBlock("span", _hoisted_23, " - " + toDisplayString($data.utils.date.formatTime(event.end, $options.TimeFormat, null, true)), 1)) : createCommentVNode("", true),
|
|
2108
|
+
event.daysCount > 1 && (event.segments[cell.formattedDate] || {}).isFirstDay ? (openBlock(), createElementBlock("small", _hoisted_24, " +" + toDisplayString(event.daysCount - 1) + toDisplayString(($data.texts.day[0] || "").toLowerCase()), 1)) : createCommentVNode("", true)
|
|
2109
|
+
])) : createCommentVNode("", true),
|
|
2110
|
+
event.content && !($options.isMonthView && event.allDay && $props.showAllDayEvents === "short") && !$options.isShortMonthView ? (openBlock(), createElementBlock("div", {
|
|
2111
|
+
key: 3,
|
|
2112
|
+
class: "vuecal__event-content",
|
|
2113
|
+
innerHTML: event.content
|
|
2114
|
+
}, null, 8, _hoisted_25)) : createCommentVNode("", true)
|
|
2115
|
+
])
|
|
2116
|
+
]),
|
|
2117
|
+
"no-event": withCtx(() => [
|
|
2118
|
+
renderSlot(_ctx.$slots, "no-event", {}, () => [
|
|
2119
|
+
createTextVNode(toDisplayString($data.texts.noEvent), 1)
|
|
2120
|
+
])
|
|
2121
|
+
]),
|
|
2122
|
+
_: 2
|
|
2123
|
+
}, 1032, ["options", "edit-events", "data", "cell-width", "min-timestamp", "max-timestamp", "cell-splits"]);
|
|
2124
|
+
}), 128))
|
|
2125
|
+
], 12, _hoisted_15)
|
|
2126
|
+
], 10, _hoisted_11)
|
|
2127
|
+
])
|
|
2128
|
+
], 2)
|
|
2129
|
+
]))
|
|
2130
|
+
]),
|
|
2131
|
+
_: 3
|
|
2132
|
+
}, 8, ["name", "appear"]),
|
|
2133
|
+
!$data.ready ? (openBlock(), createElementBlock("div", _hoisted_26, _cache[7] || (_cache[7] = [
|
|
2134
|
+
createElementVNode("div", null, null, -1)
|
|
2135
|
+
]))) : createCommentVNode("", true)
|
|
2136
|
+
])) : createCommentVNode("", true)
|
|
2137
|
+
], 10, _hoisted_1);
|
|
2138
|
+
}
|
|
2139
|
+
const minutesInADay = 24 * 60;
|
|
2140
|
+
const textsDefaults = {
|
|
2141
|
+
weekDays: Array(7).fill(""),
|
|
2142
|
+
weekDaysShort: [],
|
|
2143
|
+
months: Array(12).fill(""),
|
|
2144
|
+
years: "",
|
|
2145
|
+
year: "",
|
|
2146
|
+
month: "",
|
|
2147
|
+
week: "",
|
|
2148
|
+
day: "",
|
|
2149
|
+
today: "",
|
|
2150
|
+
noEvent: "",
|
|
2151
|
+
allDay: "",
|
|
2152
|
+
deleteEvent: "",
|
|
2153
|
+
createEvent: "",
|
|
2154
|
+
dateFormat: "dddd MMMM D, YYYY",
|
|
2155
|
+
am: "am",
|
|
2156
|
+
pm: "pm"
|
|
2157
|
+
};
|
|
2158
|
+
const validViews = ["years", "year", "month", "week", "day"];
|
|
2159
|
+
const dateUtils = new DateUtils(textsDefaults);
|
|
2160
|
+
const _sfc_main = {
|
|
2161
|
+
name: "vue-cal",
|
|
2162
|
+
components: { "vuecal-cell": Cell, "vuecal-header": Header, WeekdaysHeadings, AllDayBar },
|
|
2163
|
+
// By Vue design, passing props loses the reactivity unless it's a method or reactive OBJECT.
|
|
2164
|
+
provide() {
|
|
2165
|
+
return {
|
|
2166
|
+
vuecal: this,
|
|
2167
|
+
utils: this.utils,
|
|
2168
|
+
modules: this.modules,
|
|
2169
|
+
// Methods.
|
|
2170
|
+
previous: this.previous,
|
|
2171
|
+
next: this.next,
|
|
2172
|
+
switchView: this.switchView,
|
|
2173
|
+
updateSelectedDate: this.updateSelectedDate,
|
|
2174
|
+
editEvents: this.editEvents,
|
|
2175
|
+
// Objects.
|
|
2176
|
+
view: this.view,
|
|
2177
|
+
domEvents: this.domEvents
|
|
2178
|
+
};
|
|
2179
|
+
},
|
|
2180
|
+
props: {
|
|
2181
|
+
activeView: { type: String, default: "week" },
|
|
2182
|
+
// Only used if there are daySplits with minSplitWidth, to add the same height top spacer on time column.
|
|
2183
|
+
allDayBarHeight: { type: [String, Number], default: "25px" },
|
|
2184
|
+
cellClickHold: { type: Boolean, default: true },
|
|
2185
|
+
cellContextmenu: { type: Boolean, default: false },
|
|
2186
|
+
clickToNavigate: { type: Boolean, default: false },
|
|
2187
|
+
dblclickToNavigate: { type: Boolean, default: true },
|
|
2188
|
+
disableDatePrototypes: { type: Boolean, default: false },
|
|
2189
|
+
disableDays: { type: Array, default: () => [] },
|
|
2190
|
+
disableViews: { type: Array, default: () => [] },
|
|
2191
|
+
dragToCreateEvent: { type: Boolean, default: true },
|
|
2192
|
+
// Start a drag creation after dragging a certain amount of pixels.
|
|
2193
|
+
// This prevents drag creation by mistake when you want to navigate.
|
|
2194
|
+
dragToCreateThreshold: { type: Number, default: 15 },
|
|
2195
|
+
editableEvents: { type: [Boolean, Object], default: false },
|
|
2196
|
+
events: { type: Array, default: () => [] },
|
|
2197
|
+
eventsCountOnYearView: { type: Boolean, default: false },
|
|
2198
|
+
eventsOnMonthView: { type: [Boolean, String], default: false },
|
|
2199
|
+
hideBody: { type: Boolean, default: false },
|
|
2200
|
+
hideTitleBar: { type: Boolean, default: false },
|
|
2201
|
+
hideViewSelector: { type: Boolean, default: false },
|
|
2202
|
+
hideWeekdays: { type: Array, default: () => [] },
|
|
2203
|
+
hideWeekends: { type: Boolean, default: false },
|
|
2204
|
+
locale: { type: [String, Object], default: "en" },
|
|
2205
|
+
maxDate: { type: [String, Date], default: "" },
|
|
2206
|
+
minCellWidth: { type: Number, default: 0 },
|
|
2207
|
+
minDate: { type: [String, Date], default: "" },
|
|
2208
|
+
minEventWidth: { type: Number, default: 0 },
|
|
2209
|
+
minSplitWidth: { type: Number, default: 0 },
|
|
2210
|
+
onEventClick: { type: [Function, null], default: null },
|
|
2211
|
+
onEventCreate: { type: [Function, null], default: null },
|
|
2212
|
+
onEventDblclick: { type: [Function, null], default: null },
|
|
2213
|
+
overlapsPerTimeStep: { type: Boolean, default: false },
|
|
2214
|
+
resizeX: { type: Boolean, default: false },
|
|
2215
|
+
selectedDate: { type: [String, Date], default: "" },
|
|
2216
|
+
showAllDayEvents: { type: [Boolean, String], default: false },
|
|
2217
|
+
showTimeInCells: { type: Boolean, default: false },
|
|
2218
|
+
showWeekNumbers: { type: [Boolean, String], default: false },
|
|
2219
|
+
snapToTime: { type: Number, default: 0 },
|
|
2220
|
+
small: { type: Boolean, default: false },
|
|
2221
|
+
specialHours: { type: Object, default: () => ({}) },
|
|
2222
|
+
splitDays: { type: Array, default: () => [] },
|
|
2223
|
+
startWeekOnSunday: { type: Boolean, default: false },
|
|
2224
|
+
stickySplitLabels: { type: Boolean, default: false },
|
|
2225
|
+
time: { type: Boolean, default: true },
|
|
2226
|
+
timeCellHeight: { type: Number, default: 40 },
|
|
2227
|
+
// In pixels.
|
|
2228
|
+
timeFormat: { type: String, default: "" },
|
|
2229
|
+
timeFrom: { type: Number, default: 0 },
|
|
2230
|
+
// In minutes.
|
|
2231
|
+
timeStep: { type: Number, default: 60 },
|
|
2232
|
+
// In minutes.
|
|
2233
|
+
timeTo: { type: Number, default: minutesInADay },
|
|
2234
|
+
// In minutes.
|
|
2235
|
+
todayButton: { type: Boolean, default: false },
|
|
2236
|
+
transitions: { type: Boolean, default: true },
|
|
2237
|
+
twelveHour: { type: Boolean, default: false },
|
|
2238
|
+
watchRealTime: { type: Boolean, default: false },
|
|
2239
|
+
// Expensive, so only trigger on demand.
|
|
2240
|
+
xsmall: { type: Boolean, default: false }
|
|
2241
|
+
},
|
|
2242
|
+
data() {
|
|
2243
|
+
return {
|
|
2244
|
+
ready: false,
|
|
2245
|
+
// Is vue-cal ready.
|
|
2246
|
+
// Make texts reactive before a locale is loaded.
|
|
2247
|
+
texts: { ...textsDefaults },
|
|
2248
|
+
utils: {
|
|
2249
|
+
// Remove prototypes ASAP if the user wants so.
|
|
2250
|
+
date: (this.disableDatePrototypes ? dateUtils.removePrototypes() : false) || dateUtils,
|
|
2251
|
+
cell: null,
|
|
2252
|
+
// Note: Destructuring class method loses the `this` context and Vue Cal becomes inaccessible
|
|
2253
|
+
// from the event utils function. Don't do:
|
|
2254
|
+
// const { eventInRange, createEventSegments } = this.utils.event
|
|
2255
|
+
event: null
|
|
2256
|
+
},
|
|
2257
|
+
modules: { dnd: null },
|
|
2258
|
+
cellsEl: null,
|
|
2259
|
+
// At any time this object will be filled with current view, visible events and selected date.
|
|
2260
|
+
view: {
|
|
2261
|
+
id: "",
|
|
2262
|
+
title: "",
|
|
2263
|
+
startDate: null,
|
|
2264
|
+
endDate: null,
|
|
2265
|
+
firstCellDate: null,
|
|
2266
|
+
lastCellDate: null,
|
|
2267
|
+
selectedDate: null,
|
|
2268
|
+
// All the events are stored in the mutableEvents array, but subset of visible ones are passed
|
|
2269
|
+
// Into the current view for fast lookup and manipulation.
|
|
2270
|
+
events: []
|
|
2271
|
+
},
|
|
2272
|
+
eventIdIncrement: 1,
|
|
2273
|
+
// Internal unique id.
|
|
2274
|
+
// Preset at now date on load, but updated every minute if watchRealTime,
|
|
2275
|
+
// or updated at least on each cells rerender, in order to keep Today's date accurate.
|
|
2276
|
+
now: /* @__PURE__ */ new Date(),
|
|
2277
|
+
// Useful when watchRealTime = true, 2 timeouts: 1 to snap to round minutes, then 1 every minute.
|
|
2278
|
+
timeTickerIds: [null, null],
|
|
2279
|
+
// All the possible events/cells interractions:
|
|
2280
|
+
// e.g. focus, click, click & hold, resize, drag & drop (coming).
|
|
2281
|
+
domEvents: {
|
|
2282
|
+
resizeAnEvent: {
|
|
2283
|
+
_eid: null,
|
|
2284
|
+
// Only one at a time.
|
|
2285
|
+
start: null,
|
|
2286
|
+
split: null,
|
|
2287
|
+
segment: null,
|
|
2288
|
+
originalEndTimeMinutes: 0,
|
|
2289
|
+
originalEnd: null,
|
|
2290
|
+
end: null,
|
|
2291
|
+
startCell: null,
|
|
2292
|
+
endCell: null
|
|
2293
|
+
},
|
|
2294
|
+
dragAnEvent: {
|
|
2295
|
+
// Only one at a time, only needed for vuecal dragging-event class.
|
|
2296
|
+
_eid: null
|
|
2297
|
+
},
|
|
2298
|
+
dragCreateAnEvent: {
|
|
2299
|
+
startCursorY: null,
|
|
2300
|
+
start: null,
|
|
2301
|
+
// The cell date where we start the drag.
|
|
2302
|
+
split: null,
|
|
2303
|
+
event: null
|
|
2304
|
+
},
|
|
2305
|
+
focusAnEvent: {
|
|
2306
|
+
_eid: null,
|
|
2307
|
+
// Only one at a time.
|
|
2308
|
+
// Useful to detect a full click (mousedown + mouseup on same event).
|
|
2309
|
+
// E.g. Only call onEventClick function (if any) on full click.
|
|
2310
|
+
mousedUp: false
|
|
2311
|
+
},
|
|
2312
|
+
clickHoldAnEvent: {
|
|
2313
|
+
_eid: null,
|
|
2314
|
+
// Only one at a time.
|
|
2315
|
+
timeout: 1200,
|
|
2316
|
+
// Hold for 1.2s to delete an event.
|
|
2317
|
+
timeoutId: null
|
|
2318
|
+
},
|
|
2319
|
+
dblTapACell: {
|
|
2320
|
+
taps: 0,
|
|
2321
|
+
timeout: 500
|
|
2322
|
+
// Allowed latency between first and second click.
|
|
2323
|
+
},
|
|
2324
|
+
clickHoldACell: {
|
|
2325
|
+
cellId: null,
|
|
2326
|
+
split: null,
|
|
2327
|
+
timeout: 1200,
|
|
2328
|
+
// Hold for 1.2s to create an event.
|
|
2329
|
+
timeoutId: null,
|
|
2330
|
+
eventCreated: false
|
|
2331
|
+
},
|
|
2332
|
+
// A single click can trigger event creation if the user decides so.
|
|
2333
|
+
// But prevent this to happen on click & hold, on event click and on resize event.
|
|
2334
|
+
cancelClickEventCreation: false
|
|
2335
|
+
},
|
|
2336
|
+
// The events source of truth.
|
|
2337
|
+
// An array of mutable events updated each time given external events array changes.
|
|
2338
|
+
mutableEvents: [],
|
|
2339
|
+
// Transition when switching view. left when going toward the past, right when going toward future.
|
|
2340
|
+
transitionDirection: "right"
|
|
2341
|
+
};
|
|
2342
|
+
},
|
|
2343
|
+
methods: {
|
|
2344
|
+
/**
|
|
2345
|
+
* Only import locale on demand to keep a small library weight.
|
|
2346
|
+
*
|
|
2347
|
+
* @param {String|Object} locale the language user whishes to have on vue-cal.
|
|
2348
|
+
*/
|
|
2349
|
+
async loadLocale(locale) {
|
|
2350
|
+
if (typeof this.locale === "object") {
|
|
2351
|
+
this.texts = Object.assign({}, textsDefaults, locale);
|
|
2352
|
+
this.utils.date.updateTexts(this.texts);
|
|
2353
|
+
return;
|
|
2354
|
+
}
|
|
2355
|
+
const texts = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./i18n/ar.json": () => import("./i18n/ar.es.js"), "./i18n/bg.json": () => import("./i18n/bg.es.js"), "./i18n/bn.json": () => import("./i18n/bn.es.js"), "./i18n/bs.json": () => import("./i18n/bs.es.js"), "./i18n/ca.json": () => import("./i18n/ca.es.js"), "./i18n/cs.json": () => import("./i18n/cs.es.js"), "./i18n/da.json": () => import("./i18n/da.es.js"), "./i18n/de.json": () => import("./i18n/de.es.js"), "./i18n/el.json": () => import("./i18n/el.es.js"), "./i18n/en.json": () => import("./i18n/en.es.js"), "./i18n/es.json": () => import("./i18n/es.es.js"), "./i18n/et.json": () => import("./i18n/et.es.js"), "./i18n/fa.json": () => import("./i18n/fa.es.js"), "./i18n/fi.json": () => import("./i18n/fi.es.js"), "./i18n/fr.json": () => import("./i18n/fr.es.js"), "./i18n/he.json": () => import("./i18n/he.es.js"), "./i18n/hr.json": () => import("./i18n/hr.es.js"), "./i18n/hu.json": () => import("./i18n/hu.es.js"), "./i18n/id.json": () => import("./i18n/id.es.js"), "./i18n/is.json": () => import("./i18n/is.es.js"), "./i18n/it.json": () => import("./i18n/it.es.js"), "./i18n/ja.json": () => import("./i18n/ja.es.js"), "./i18n/ka.json": () => import("./i18n/ka.es.js"), "./i18n/ko.json": () => import("./i18n/ko.es.js"), "./i18n/lt.json": () => import("./i18n/lt.es.js"), "./i18n/mn.json": () => import("./i18n/mn.es.js"), "./i18n/nl.json": () => import("./i18n/nl.es.js"), "./i18n/no.json": () => import("./i18n/no.es.js"), "./i18n/pl.json": () => import("./i18n/pl.es.js"), "./i18n/pt-br.json": () => import("./i18n/pt-br.es.js"), "./i18n/pt-pt.json": () => import("./i18n/pt-pt.es.js"), "./i18n/ro.json": () => import("./i18n/ro.es.js"), "./i18n/ru.json": () => import("./i18n/ru.es.js"), "./i18n/sk.json": () => import("./i18n/sk.es.js"), "./i18n/sl.json": () => import("./i18n/sl.es.js"), "./i18n/sq.json": () => import("./i18n/sq.es.js"), "./i18n/sr.json": () => import("./i18n/sr.es.js"), "./i18n/sv.json": () => import("./i18n/sv.es.js"), "./i18n/tr.json": () => import("./i18n/tr.es.js"), "./i18n/uk.json": () => import("./i18n/uk.es.js"), "./i18n/vi.json": () => import("./i18n/vi.es.js"), "./i18n/zh-cn.json": () => import("./i18n/zh-cn.es.js"), "./i18n/zh-hk.json": () => import("./i18n/zh-hk.es.js") }), `./i18n/${locale}.json`, 3);
|
|
2356
|
+
this.texts = Object.assign({}, textsDefaults, texts);
|
|
2357
|
+
this.utils.date.updateTexts(this.texts);
|
|
2358
|
+
},
|
|
2359
|
+
/**
|
|
2360
|
+
* Only import drag and drop module on demand to keep a small library weight.
|
|
2361
|
+
*/
|
|
2362
|
+
loadDragAndDrop() {
|
|
2363
|
+
import("./drag-and-drop.es.js").then((response) => {
|
|
2364
|
+
const { DragAndDrop } = response;
|
|
2365
|
+
this.modules.dnd = new DragAndDrop(this);
|
|
2366
|
+
}).catch(() => console.warn("Vue Cal: Missing drag & drop module."));
|
|
2367
|
+
},
|
|
2368
|
+
/**
|
|
2369
|
+
* Checks that the given view is in the array of valid views or use 'week' otherwise.
|
|
2370
|
+
* Then check the view is enabled or use the first enabled view instead.
|
|
2371
|
+
* Raises error and warning if needed.
|
|
2372
|
+
*
|
|
2373
|
+
* @param {String} view The view to validate.
|
|
2374
|
+
* @return {String} a valid view.
|
|
2375
|
+
*/
|
|
2376
|
+
validateView(view) {
|
|
2377
|
+
if (!validViews.includes(view)) {
|
|
2378
|
+
console.error(`Vue Cal: invalid active-view parameter provided: "${view}".
|
|
2379
|
+
A valid view must be one of: ${validViews.join(", ")}.`);
|
|
2380
|
+
view = "week";
|
|
2381
|
+
}
|
|
2382
|
+
if (!this.enabledViews.includes(view)) {
|
|
2383
|
+
console.warn(`Vue Cal: the provided active-view "${view}" is disabled. Using the "${this.enabledViews[0]}" view instead.`);
|
|
2384
|
+
view = this.enabledViews[0];
|
|
2385
|
+
}
|
|
2386
|
+
return view;
|
|
2387
|
+
},
|
|
2388
|
+
/**
|
|
2389
|
+
* On click/dblclick of a cell go to a narrower view if available.
|
|
2390
|
+
* E.g. Click on month cell takes you to week view if not hidden, otherwise on day view if not hidden.
|
|
2391
|
+
*
|
|
2392
|
+
* @param {String | Date} date A starting date for the view, if none, fallbacks to the selected date,
|
|
2393
|
+
* If also empty fallbacks to the current view start date.
|
|
2394
|
+
*/
|
|
2395
|
+
switchToNarrowerView(date = null) {
|
|
2396
|
+
this.transitionDirection = "right";
|
|
2397
|
+
const view = this.enabledViews[this.enabledViews.indexOf(this.view.id) + 1];
|
|
2398
|
+
if (view) this.switchView(view, date);
|
|
2399
|
+
},
|
|
2400
|
+
/**
|
|
2401
|
+
* Switches to the specified view on view selector click, or programmatically form external call (via $refs).
|
|
2402
|
+
* If a date is given, it will be selected and if the view does not contain it, it will go to that date.
|
|
2403
|
+
*
|
|
2404
|
+
* @param {String} view the view to go to. Among `years`, `year`, `month`, `week`, `day`.
|
|
2405
|
+
* @param {String | Date} date A starting date for the view, if none, fallbacks to the selected date,
|
|
2406
|
+
* If also empty fallbacks to the current view start date.
|
|
2407
|
+
* @param {Boolean} fromViewSelector to know if the caller is the built-in view selector.
|
|
2408
|
+
*/
|
|
2409
|
+
switchView(view, date = null, fromViewSelector = false) {
|
|
2410
|
+
view = this.validateView(view);
|
|
2411
|
+
const ud2 = this.utils.date;
|
|
2412
|
+
const viewDateBeforeChange = this.view.startDate && this.view.startDate.getTime();
|
|
2413
|
+
if (this.transitions && fromViewSelector) {
|
|
2414
|
+
if (this.view.id === view) return;
|
|
2415
|
+
const views = this.enabledViews;
|
|
2416
|
+
this.transitionDirection = views.indexOf(this.view.id) > views.indexOf(view) ? "left" : "right";
|
|
2417
|
+
}
|
|
2418
|
+
const oldView = this.view.id;
|
|
2419
|
+
this.view.events = [];
|
|
2420
|
+
this.view.id = view;
|
|
2421
|
+
this.view.firstCellDate = null;
|
|
2422
|
+
this.view.lastCellDate = null;
|
|
2423
|
+
if (!date) date = this.view.selectedDate || this.view.startDate;
|
|
2424
|
+
switch (view) {
|
|
2425
|
+
case "years": {
|
|
2426
|
+
this.view.startDate = new Date(Math.floor(date.getFullYear() / 25) * 25 || 2e3, 0, 1);
|
|
2427
|
+
this.view.endDate = new Date(this.view.startDate.getFullYear() + 25, 0, 1);
|
|
2428
|
+
this.view.endDate.setSeconds(-1);
|
|
2429
|
+
break;
|
|
2430
|
+
}
|
|
2431
|
+
case "year": {
|
|
2432
|
+
this.view.startDate = new Date(date.getFullYear(), 0, 1);
|
|
2433
|
+
this.view.endDate = new Date(date.getFullYear() + 1, 0, 1);
|
|
2434
|
+
this.view.endDate.setSeconds(-1);
|
|
2435
|
+
break;
|
|
2436
|
+
}
|
|
2437
|
+
case "month": {
|
|
2438
|
+
this.view.startDate = new Date(date.getFullYear(), date.getMonth(), 1);
|
|
2439
|
+
this.view.endDate = new Date(date.getFullYear(), date.getMonth() + 1, 1);
|
|
2440
|
+
this.view.endDate.setSeconds(-1);
|
|
2441
|
+
let startDate = new Date(this.view.startDate);
|
|
2442
|
+
if (startDate.getDay() !== (this.startWeekOnSunday ? 0 : 1)) {
|
|
2443
|
+
startDate = ud2.getPreviousFirstDayOfWeek(startDate, this.startWeekOnSunday);
|
|
2444
|
+
}
|
|
2445
|
+
this.view.firstCellDate = startDate;
|
|
2446
|
+
this.view.lastCellDate = ud2.addDays(startDate, 41);
|
|
2447
|
+
this.view.lastCellDate.setHours(23, 59, 59, 0);
|
|
2448
|
+
if (this.hideWeekends) {
|
|
2449
|
+
if ([0, 6].includes(this.view.firstCellDate.getDay())) {
|
|
2450
|
+
const daysToAdd = this.view.firstCellDate.getDay() === 6 && !this.startWeekOnSunday ? 2 : 1;
|
|
2451
|
+
this.view.firstCellDate = ud2.addDays(this.view.firstCellDate, daysToAdd);
|
|
2452
|
+
}
|
|
2453
|
+
if ([0, 6].includes(this.view.startDate.getDay())) {
|
|
2454
|
+
const daysToAdd = this.view.startDate.getDay() === 6 ? 2 : 1;
|
|
2455
|
+
this.view.startDate = ud2.addDays(this.view.startDate, daysToAdd);
|
|
2456
|
+
}
|
|
2457
|
+
if ([0, 6].includes(this.view.lastCellDate.getDay())) {
|
|
2458
|
+
const daysToSubtract = this.view.lastCellDate.getDay() === 0 && !this.startWeekOnSunday ? 2 : 1;
|
|
2459
|
+
this.view.lastCellDate = ud2.subtractDays(this.view.lastCellDate, daysToSubtract);
|
|
2460
|
+
}
|
|
2461
|
+
if ([0, 6].includes(this.view.endDate.getDay())) {
|
|
2462
|
+
const daysToSubtract = this.view.endDate.getDay() === 0 ? 2 : 1;
|
|
2463
|
+
this.view.endDate = ud2.subtractDays(this.view.endDate, daysToSubtract);
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
break;
|
|
2467
|
+
}
|
|
2468
|
+
case "week": {
|
|
2469
|
+
date = ud2.getPreviousFirstDayOfWeek(date, this.startWeekOnSunday);
|
|
2470
|
+
const weekDaysCount = this.hideWeekends ? 5 : 7;
|
|
2471
|
+
this.view.startDate = this.hideWeekends && this.startWeekOnSunday ? ud2.addDays(date, 1) : date;
|
|
2472
|
+
this.view.startDate.setHours(0, 0, 0, 0);
|
|
2473
|
+
this.view.endDate = ud2.addDays(date, weekDaysCount);
|
|
2474
|
+
this.view.endDate.setSeconds(-1);
|
|
2475
|
+
break;
|
|
2476
|
+
}
|
|
2477
|
+
case "day": {
|
|
2478
|
+
this.view.startDate = date;
|
|
2479
|
+
this.view.startDate.setHours(0, 0, 0, 0);
|
|
2480
|
+
this.view.endDate = new Date(date);
|
|
2481
|
+
this.view.endDate.setHours(23, 59, 59, 0);
|
|
2482
|
+
break;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
this.addEventsToView();
|
|
2486
|
+
const viewDate = this.view.startDate && this.view.startDate.getTime();
|
|
2487
|
+
if (oldView === view && viewDate === viewDateBeforeChange) return;
|
|
2488
|
+
this.$emit("update:activeView", view);
|
|
2489
|
+
if (this.ready) {
|
|
2490
|
+
const startDate = this.view.startDate;
|
|
2491
|
+
const params = {
|
|
2492
|
+
view,
|
|
2493
|
+
startDate,
|
|
2494
|
+
endDate: this.view.endDate,
|
|
2495
|
+
...this.isMonthView ? {
|
|
2496
|
+
firstCellDate: this.view.firstCellDate,
|
|
2497
|
+
lastCellDate: this.view.lastCellDate,
|
|
2498
|
+
outOfScopeEvents: this.view.outOfScopeEvents.map(this.cleanupEvent)
|
|
2499
|
+
} : {},
|
|
2500
|
+
events: this.view.events.map(this.cleanupEvent),
|
|
2501
|
+
...this.isWeekView ? { week: ud2.getWeek(this.startWeekOnSunday ? ud2.addDays(startDate, 1) : startDate) } : {}
|
|
2502
|
+
};
|
|
2503
|
+
this.$emit("view-change", params);
|
|
2504
|
+
}
|
|
2505
|
+
},
|
|
2506
|
+
/**
|
|
2507
|
+
* Shorthand function for external call (via $refs).
|
|
2508
|
+
*/
|
|
2509
|
+
previous() {
|
|
2510
|
+
this.previousNext(false);
|
|
2511
|
+
},
|
|
2512
|
+
/**
|
|
2513
|
+
* Shorthand function for external call (via $refs).
|
|
2514
|
+
*/
|
|
2515
|
+
next() {
|
|
2516
|
+
this.previousNext();
|
|
2517
|
+
},
|
|
2518
|
+
/**
|
|
2519
|
+
* On click on previous or next arrow, update the calendar visible date range.
|
|
2520
|
+
*
|
|
2521
|
+
* @param {Boolean} next
|
|
2522
|
+
*/
|
|
2523
|
+
previousNext(next = true) {
|
|
2524
|
+
const ud2 = this.utils.date;
|
|
2525
|
+
this.transitionDirection = next ? "right" : "left";
|
|
2526
|
+
const modifier = next ? 1 : -1;
|
|
2527
|
+
let firstCellDate = null;
|
|
2528
|
+
const { startDate, id: viewId } = this.view;
|
|
2529
|
+
switch (viewId) {
|
|
2530
|
+
case "years":
|
|
2531
|
+
firstCellDate = new Date(startDate.getFullYear() + 25 * modifier, 0, 1);
|
|
2532
|
+
break;
|
|
2533
|
+
case "year":
|
|
2534
|
+
firstCellDate = new Date(startDate.getFullYear() + 1 * modifier, 1, 1);
|
|
2535
|
+
break;
|
|
2536
|
+
case "month":
|
|
2537
|
+
firstCellDate = new Date(startDate.getFullYear(), startDate.getMonth() + 1 * modifier, 1);
|
|
2538
|
+
break;
|
|
2539
|
+
case "week":
|
|
2540
|
+
firstCellDate = ud2[next ? "addDays" : "subtractDays"](ud2.getPreviousFirstDayOfWeek(startDate, this.startWeekOnSunday), 7);
|
|
2541
|
+
break;
|
|
2542
|
+
case "day":
|
|
2543
|
+
firstCellDate = ud2[next ? "addDays" : "subtractDays"](startDate, 1);
|
|
2544
|
+
const weekDay = firstCellDate.getDay();
|
|
2545
|
+
const weekDayIndex = this.startWeekOnSunday ? weekDay : (weekDay || 7) - 1;
|
|
2546
|
+
const isDayHidden = this.weekDays[weekDayIndex].hide;
|
|
2547
|
+
if (isDayHidden) {
|
|
2548
|
+
const daysWithIndex = this.weekDays.map((day, i) => ({ ...day, i }));
|
|
2549
|
+
let daysFromDate = 0;
|
|
2550
|
+
if (next) {
|
|
2551
|
+
[...daysWithIndex.slice(weekDayIndex), ...daysWithIndex].find((day) => {
|
|
2552
|
+
daysFromDate++;
|
|
2553
|
+
return !day.hide;
|
|
2554
|
+
}).i;
|
|
2555
|
+
daysFromDate--;
|
|
2556
|
+
} else {
|
|
2557
|
+
[...daysWithIndex, ...daysWithIndex.slice(0, weekDayIndex)].reverse().find((day) => {
|
|
2558
|
+
daysFromDate++;
|
|
2559
|
+
return !day.hide;
|
|
2560
|
+
}).i;
|
|
2561
|
+
}
|
|
2562
|
+
firstCellDate = ud2[next ? "addDays" : "subtractDays"](firstCellDate, daysFromDate);
|
|
2563
|
+
}
|
|
2564
|
+
break;
|
|
2565
|
+
}
|
|
2566
|
+
if (firstCellDate) this.switchView(viewId, firstCellDate);
|
|
2567
|
+
},
|
|
2568
|
+
/**
|
|
2569
|
+
* Add events (subset from mutableEvents) to the current view (in `this.view.events`).
|
|
2570
|
+
* This is done for performance, so that all the cells have a quick lookup of only what's needed.
|
|
2571
|
+
*
|
|
2572
|
+
* @param {Array} events
|
|
2573
|
+
*/
|
|
2574
|
+
addEventsToView(events = []) {
|
|
2575
|
+
const ue = this.utils.event;
|
|
2576
|
+
const { startDate, endDate, firstCellDate, lastCellDate } = this.view;
|
|
2577
|
+
if (!events.length) this.view.events = [];
|
|
2578
|
+
events = events.length ? events : [...this.mutableEvents];
|
|
2579
|
+
if (!events || this.isYearsOrYearView && !this.eventsCountOnYearView) return;
|
|
2580
|
+
let filteredEvents = events.filter((e) => ue.eventInRange(e, startDate, endDate));
|
|
2581
|
+
if (!this.isYearsOrYearView && !(this.isMonthView && !this.eventsOnMonthView)) {
|
|
2582
|
+
filteredEvents = filteredEvents.map((e) => {
|
|
2583
|
+
return e.daysCount > 1 ? ue.createEventSegments(e, firstCellDate || startDate, lastCellDate || endDate) : e;
|
|
2584
|
+
});
|
|
2585
|
+
}
|
|
2586
|
+
this.view.events.push(...filteredEvents);
|
|
2587
|
+
if (this.isMonthView) {
|
|
2588
|
+
this.view.outOfScopeEvents = [];
|
|
2589
|
+
events.forEach((e) => {
|
|
2590
|
+
if (ue.eventInRange(e, firstCellDate, startDate) || ue.eventInRange(e, endDate, lastCellDate)) {
|
|
2591
|
+
if (!this.view.events.some((e2) => e2._eid === e._eid)) this.view.outOfScopeEvents.push(e);
|
|
2592
|
+
}
|
|
2593
|
+
});
|
|
2594
|
+
}
|
|
2595
|
+
},
|
|
2596
|
+
/**
|
|
2597
|
+
* find a DOM ancestor of a given DOM node `el` matching given class name.
|
|
2598
|
+
*
|
|
2599
|
+
* @param {Object} el a DOM node to find ancestor from.
|
|
2600
|
+
* @param {String} Class the CSS class name of the ancestor.
|
|
2601
|
+
* @return {Object} The matched DOM node or null if no match.
|
|
2602
|
+
*/
|
|
2603
|
+
findAncestor(el, Class) {
|
|
2604
|
+
while ((el = el.parentElement) && !el.classList.contains(Class)) {
|
|
2605
|
+
}
|
|
2606
|
+
return el;
|
|
2607
|
+
},
|
|
2608
|
+
/**
|
|
2609
|
+
* Tells whether a clicked DOM node is or is within a calendar event.
|
|
2610
|
+
*
|
|
2611
|
+
* @param {Object} el a DOM node to check if event.
|
|
2612
|
+
* @return {Boolean} true if the given DOM node is - or is in - an event.
|
|
2613
|
+
*/
|
|
2614
|
+
isDOMElementAnEvent(el) {
|
|
2615
|
+
return el.classList.contains("vuecal__event") || this.findAncestor(el, "vuecal__event");
|
|
2616
|
+
},
|
|
2617
|
+
/**
|
|
2618
|
+
* Capture mousemove anywhere in the page.
|
|
2619
|
+
* If resizing an event was started earlier, this will update event end.
|
|
2620
|
+
* If resizing was not started, this method is calculation is avoided with a premature return.
|
|
2621
|
+
* Notes: Event resizing is started in cell component (onMouseDown) but place onMouseMove & onMouseUp
|
|
2622
|
+
* handlers in the single-instance parent for performance.
|
|
2623
|
+
*
|
|
2624
|
+
* @param {Object} e the native DOM event object.
|
|
2625
|
+
*/
|
|
2626
|
+
onMouseMove(e) {
|
|
2627
|
+
const { resizeAnEvent, dragAnEvent, dragCreateAnEvent } = this.domEvents;
|
|
2628
|
+
if (resizeAnEvent._eid === null && dragAnEvent._eid === null && !dragCreateAnEvent.start) return;
|
|
2629
|
+
e.preventDefault();
|
|
2630
|
+
if (resizeAnEvent._eid) this.eventResizing(e);
|
|
2631
|
+
else if (this.dragToCreateEvent && dragCreateAnEvent.start) this.eventDragCreation(e);
|
|
2632
|
+
},
|
|
2633
|
+
/**
|
|
2634
|
+
* Capture mouseup anywhere in the page, not only on a cell or event.
|
|
2635
|
+
* Then end up any resize, drag & drop, click & hold or event or cell.
|
|
2636
|
+
* Notes: Mouseup can never cancel a click with preventDefault or stopPropagation,
|
|
2637
|
+
* But it always happens before the click event.
|
|
2638
|
+
*
|
|
2639
|
+
* @param {Object} e the native DOM event object.
|
|
2640
|
+
*/
|
|
2641
|
+
onMouseUp(e) {
|
|
2642
|
+
const {
|
|
2643
|
+
focusAnEvent,
|
|
2644
|
+
resizeAnEvent,
|
|
2645
|
+
clickHoldAnEvent,
|
|
2646
|
+
clickHoldACell,
|
|
2647
|
+
dragCreateAnEvent
|
|
2648
|
+
} = this.domEvents;
|
|
2649
|
+
const { _eid: isClickHoldingEvent } = clickHoldAnEvent;
|
|
2650
|
+
const { _eid: wasResizing } = resizeAnEvent;
|
|
2651
|
+
let hasResized = false;
|
|
2652
|
+
const { event: dragCreatedEvent, start: dragCreateStarted } = dragCreateAnEvent;
|
|
2653
|
+
const mouseUpOnEvent = this.isDOMElementAnEvent(e.target);
|
|
2654
|
+
const eventClicked = focusAnEvent.mousedUp;
|
|
2655
|
+
focusAnEvent.mousedUp = false;
|
|
2656
|
+
if (mouseUpOnEvent) this.domEvents.cancelClickEventCreation = true;
|
|
2657
|
+
if (clickHoldACell.eventCreated) return;
|
|
2658
|
+
if (wasResizing) {
|
|
2659
|
+
const { originalEnd, originalEndTimeMinutes, endTimeMinutes } = resizeAnEvent;
|
|
2660
|
+
const event = this.view.events.find((e2) => e2._eid === resizeAnEvent._eid);
|
|
2661
|
+
hasResized = endTimeMinutes && endTimeMinutes !== originalEndTimeMinutes;
|
|
2662
|
+
if (event && event.end.getTime() !== originalEnd.getTime()) {
|
|
2663
|
+
const mutableEvent = this.mutableEvents.find((e2) => e2._eid === resizeAnEvent._eid);
|
|
2664
|
+
mutableEvent.endTimeMinutes = event.endTimeMinutes;
|
|
2665
|
+
mutableEvent.end = event.end;
|
|
2666
|
+
const cleanEvent = this.cleanupEvent(event);
|
|
2667
|
+
const originalEvent = {
|
|
2668
|
+
...this.cleanupEvent(event),
|
|
2669
|
+
end: originalEnd,
|
|
2670
|
+
endTimeMinutes: event.originalEndTimeMinutes
|
|
2671
|
+
};
|
|
2672
|
+
this.$emit("event-duration-change", { event: cleanEvent, oldDate: resizeAnEvent.originalEnd, originalEvent });
|
|
2673
|
+
this.$emit("event-change", { event: cleanEvent, originalEvent });
|
|
2674
|
+
}
|
|
2675
|
+
if (event) event.resizing = false;
|
|
2676
|
+
resizeAnEvent._eid = null;
|
|
2677
|
+
resizeAnEvent.start = null;
|
|
2678
|
+
resizeAnEvent.split = null;
|
|
2679
|
+
resizeAnEvent.segment = null;
|
|
2680
|
+
resizeAnEvent.originalEndTimeMinutes = null;
|
|
2681
|
+
resizeAnEvent.originalEnd = null;
|
|
2682
|
+
resizeAnEvent.endTimeMinutes = null;
|
|
2683
|
+
resizeAnEvent.startCell = null;
|
|
2684
|
+
resizeAnEvent.endCell = null;
|
|
2685
|
+
} else if (dragCreateStarted) {
|
|
2686
|
+
if (dragCreatedEvent) {
|
|
2687
|
+
this.emitWithEvent("event-drag-create", dragCreatedEvent);
|
|
2688
|
+
dragCreateAnEvent.event.resizing = false;
|
|
2689
|
+
}
|
|
2690
|
+
dragCreateAnEvent.start = null;
|
|
2691
|
+
dragCreateAnEvent.split = null;
|
|
2692
|
+
dragCreateAnEvent.event = null;
|
|
2693
|
+
}
|
|
2694
|
+
if (!mouseUpOnEvent && !wasResizing) this.unfocusEvent();
|
|
2695
|
+
if (clickHoldAnEvent.timeoutId && !isClickHoldingEvent) {
|
|
2696
|
+
clearTimeout(clickHoldAnEvent.timeoutId);
|
|
2697
|
+
clickHoldAnEvent.timeoutId = null;
|
|
2698
|
+
}
|
|
2699
|
+
if (clickHoldACell.timeoutId) {
|
|
2700
|
+
clearTimeout(clickHoldACell.timeoutId);
|
|
2701
|
+
clickHoldACell.timeoutId = null;
|
|
2702
|
+
}
|
|
2703
|
+
const eventClickHandler = typeof this.onEventClick === "function";
|
|
2704
|
+
if (eventClicked && !hasResized && !isClickHoldingEvent && !dragCreatedEvent && eventClickHandler) {
|
|
2705
|
+
let event = this.view.events.find((e2) => e2._eid === focusAnEvent._eid);
|
|
2706
|
+
if (!event && this.isMonthView) event = this.view.outOfScopeEvents.find((e2) => e2._eid === focusAnEvent._eid);
|
|
2707
|
+
return event && this.onEventClick(event, e);
|
|
2708
|
+
}
|
|
2709
|
+
},
|
|
2710
|
+
/**
|
|
2711
|
+
* Capture `escape` keypress when delete button is visible, and cancel deletion.
|
|
2712
|
+
*
|
|
2713
|
+
* @param {Object} e the native DOM event object.
|
|
2714
|
+
*/
|
|
2715
|
+
onKeyUp(e) {
|
|
2716
|
+
if (e.keyCode === 27) this.cancelDelete();
|
|
2717
|
+
},
|
|
2718
|
+
/**
|
|
2719
|
+
* On mousemove while resising an event.
|
|
2720
|
+
*
|
|
2721
|
+
* @param {Object} e the native DOM event object.
|
|
2722
|
+
*/
|
|
2723
|
+
eventResizing(e) {
|
|
2724
|
+
const { resizeAnEvent } = this.domEvents;
|
|
2725
|
+
const event = this.view.events.find((e2) => e2._eid === resizeAnEvent._eid) || { segments: {} };
|
|
2726
|
+
const { minutes, cursorCoords } = this.minutesAtCursor(e);
|
|
2727
|
+
const segment = event.segments && event.segments[resizeAnEvent.segment];
|
|
2728
|
+
const { date: ud2, event: ue } = this.utils;
|
|
2729
|
+
const newEndTimeMins = Math.max(minutes, this.timeFrom + 1, (segment || event).startTimeMinutes + 1);
|
|
2730
|
+
event.endTimeMinutes = resizeAnEvent.endTimeMinutes = newEndTimeMins;
|
|
2731
|
+
if (this.snapToTime) {
|
|
2732
|
+
const plusHalfSnapTime = event.endTimeMinutes + this.snapToTime / 2;
|
|
2733
|
+
event.endTimeMinutes = plusHalfSnapTime - plusHalfSnapTime % this.snapToTime;
|
|
2734
|
+
}
|
|
2735
|
+
if (segment) segment.endTimeMinutes = event.endTimeMinutes;
|
|
2736
|
+
event.end.setHours(0, event.endTimeMinutes, event.endTimeMinutes === minutesInADay ? -1 : 0, 0);
|
|
2737
|
+
if (this.resizeX && this.isWeekView) {
|
|
2738
|
+
event.daysCount = ud2.countDays(event.start, event.end);
|
|
2739
|
+
const cells = this.cellsEl;
|
|
2740
|
+
const cellWidth = cells.offsetWidth / cells.childElementCount;
|
|
2741
|
+
const endCell = Math.floor(cursorCoords.x / cellWidth);
|
|
2742
|
+
if (resizeAnEvent.startCell === null) resizeAnEvent.startCell = endCell - (event.daysCount - 1);
|
|
2743
|
+
if (resizeAnEvent.endCell !== endCell) {
|
|
2744
|
+
resizeAnEvent.endCell = endCell;
|
|
2745
|
+
const newEnd = ud2.addDays(event.start, endCell - resizeAnEvent.startCell);
|
|
2746
|
+
const newDaysCount = Math.max(ud2.countDays(event.start, newEnd), 1);
|
|
2747
|
+
if (newDaysCount !== event.daysCount) {
|
|
2748
|
+
let lastSegmentFormattedDate = null;
|
|
2749
|
+
if (newDaysCount > event.daysCount) lastSegmentFormattedDate = ue.addEventSegment(event);
|
|
2750
|
+
else lastSegmentFormattedDate = ue.removeEventSegment(event);
|
|
2751
|
+
resizeAnEvent.segment = lastSegmentFormattedDate;
|
|
2752
|
+
event.endTimeMinutes += 1e-3;
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
this.$emit("event-resizing", { _eid: event._eid, end: event.end, endTimeMinutes: event.endTimeMinutes });
|
|
2757
|
+
},
|
|
2758
|
+
/**
|
|
2759
|
+
* On mousemove while dragging to create an event.
|
|
2760
|
+
*
|
|
2761
|
+
* @param {Object} e the native DOM event object.
|
|
2762
|
+
*/
|
|
2763
|
+
eventDragCreation(e) {
|
|
2764
|
+
const { dragCreateAnEvent } = this.domEvents;
|
|
2765
|
+
const { start, startCursorY, split } = dragCreateAnEvent;
|
|
2766
|
+
const timeAtCursor = new Date(start);
|
|
2767
|
+
const { minutes, cursorCoords: { y } } = this.minutesAtCursor(e);
|
|
2768
|
+
if (!dragCreateAnEvent.event && Math.abs(startCursorY - y) < this.dragToCreateThreshold) return;
|
|
2769
|
+
if (!dragCreateAnEvent.event) {
|
|
2770
|
+
dragCreateAnEvent.event = this.utils.event.createAnEvent(start, 1, { split });
|
|
2771
|
+
if (!dragCreateAnEvent.event) {
|
|
2772
|
+
dragCreateAnEvent.start = null;
|
|
2773
|
+
dragCreateAnEvent.split = null;
|
|
2774
|
+
dragCreateAnEvent.event = null;
|
|
2775
|
+
return;
|
|
2776
|
+
}
|
|
2777
|
+
dragCreateAnEvent.event.resizing = true;
|
|
2778
|
+
} else {
|
|
2779
|
+
timeAtCursor.setHours(0, minutes, minutes === minutesInADay ? -1 : 0, 0);
|
|
2780
|
+
if (this.snapToTime) {
|
|
2781
|
+
let timeMinutes = timeAtCursor.getHours() * 60 + timeAtCursor.getMinutes();
|
|
2782
|
+
const plusHalfSnapTime = timeMinutes + this.snapToTime / 2;
|
|
2783
|
+
timeMinutes = plusHalfSnapTime - plusHalfSnapTime % this.snapToTime;
|
|
2784
|
+
timeAtCursor.setHours(0, timeMinutes, 0, 0);
|
|
2785
|
+
}
|
|
2786
|
+
const dragFromBottom = start < timeAtCursor;
|
|
2787
|
+
const { event } = dragCreateAnEvent;
|
|
2788
|
+
event.start = dragFromBottom ? start : timeAtCursor;
|
|
2789
|
+
event.end = dragFromBottom ? timeAtCursor : start;
|
|
2790
|
+
event.startTimeMinutes = event.start.getHours() * 60 + event.start.getMinutes();
|
|
2791
|
+
event.endTimeMinutes = event.end.getHours() * 60 + event.end.getMinutes();
|
|
2792
|
+
}
|
|
2793
|
+
},
|
|
2794
|
+
/**
|
|
2795
|
+
* Unfocus an event (e.g. when clicking outside of focused event).
|
|
2796
|
+
*/
|
|
2797
|
+
unfocusEvent() {
|
|
2798
|
+
const { focusAnEvent, clickHoldAnEvent } = this.domEvents;
|
|
2799
|
+
const event = this.view.events.find((e) => e._eid === (focusAnEvent._eid || clickHoldAnEvent._eid));
|
|
2800
|
+
focusAnEvent._eid = null;
|
|
2801
|
+
clickHoldAnEvent._eid = null;
|
|
2802
|
+
if (event) {
|
|
2803
|
+
event.focused = false;
|
|
2804
|
+
event.deleting = false;
|
|
2805
|
+
}
|
|
2806
|
+
},
|
|
2807
|
+
/**
|
|
2808
|
+
* Cancel an event deletion (e.g. when clicking outside of visible delete button).
|
|
2809
|
+
*/
|
|
2810
|
+
cancelDelete() {
|
|
2811
|
+
const { clickHoldAnEvent } = this.domEvents;
|
|
2812
|
+
if (clickHoldAnEvent._eid) {
|
|
2813
|
+
const event = this.view.events.find((e) => e._eid === clickHoldAnEvent._eid);
|
|
2814
|
+
if (event) event.deleting = false;
|
|
2815
|
+
clickHoldAnEvent._eid = null;
|
|
2816
|
+
clickHoldAnEvent.timeoutId = null;
|
|
2817
|
+
}
|
|
2818
|
+
},
|
|
2819
|
+
/**
|
|
2820
|
+
* After editing an event title (if `this.editable`), save the new string into the event object
|
|
2821
|
+
* and emit event to the outside world.
|
|
2822
|
+
*
|
|
2823
|
+
* @param {Object} e the native DOM event object.
|
|
2824
|
+
* @param {Object} event the vue-cal event object.
|
|
2825
|
+
*/
|
|
2826
|
+
onEventTitleBlur(e, event) {
|
|
2827
|
+
if (event.title === e.target.innerHTML) return;
|
|
2828
|
+
const oldTitle = event.title;
|
|
2829
|
+
event.title = e.target.innerHTML;
|
|
2830
|
+
const cleanEvent = this.cleanupEvent(event);
|
|
2831
|
+
this.$emit("event-title-change", { event: cleanEvent, oldTitle });
|
|
2832
|
+
this.$emit("event-change", { event: cleanEvent, originalEvent: { ...cleanEvent, title: oldTitle } });
|
|
2833
|
+
},
|
|
2834
|
+
/**
|
|
2835
|
+
* The `mutableEvents` array of events is the source of truth.
|
|
2836
|
+
* It is first populated from the `events` prop and every time the `events` prop changes.
|
|
2837
|
+
* When the user updates an event through interractions, the event gets updated here.
|
|
2838
|
+
* Notes: mutableEvents couldn't be a computed variable based on this.events, because we add
|
|
2839
|
+
* items to the array. (Cannot mutate props)
|
|
2840
|
+
*/
|
|
2841
|
+
updateMutableEvents() {
|
|
2842
|
+
const ud2 = this.utils.date;
|
|
2843
|
+
this.mutableEvents = [];
|
|
2844
|
+
this.events.forEach((event) => {
|
|
2845
|
+
const start = typeof event.start === "string" ? ud2.stringToDate(event.start) : event.start;
|
|
2846
|
+
const startDateF = ud2.formatDateLite(start);
|
|
2847
|
+
const startTimeMinutes = ud2.dateToMinutes(start);
|
|
2848
|
+
let end = null;
|
|
2849
|
+
if (typeof event.end === "string" && event.end.includes("24:00")) {
|
|
2850
|
+
end = new Date(event.end.replace(" 24:00", ""));
|
|
2851
|
+
end.setHours(23, 59, 59, 0);
|
|
2852
|
+
} else end = typeof event.end === "string" ? ud2.stringToDate(event.end) : event.end;
|
|
2853
|
+
let endDateF = ud2.formatDateLite(end);
|
|
2854
|
+
let endTimeMinutes = ud2.dateToMinutes(end);
|
|
2855
|
+
if (!endTimeMinutes || endTimeMinutes === minutesInADay) {
|
|
2856
|
+
if (!this.time || typeof event.end === "string" && event.end.length === 10) {
|
|
2857
|
+
end.setHours(23, 59, 59, 0);
|
|
2858
|
+
} else end.setSeconds(end.getSeconds() - 1);
|
|
2859
|
+
endDateF = ud2.formatDateLite(end);
|
|
2860
|
+
endTimeMinutes = minutesInADay;
|
|
2861
|
+
}
|
|
2862
|
+
const multipleDays = startDateF !== endDateF;
|
|
2863
|
+
event = Object.assign({ ...this.utils.event.eventDefaults }, event, {
|
|
2864
|
+
// Keep the event ids scoped to this calendar instance.
|
|
2865
|
+
_eid: `${this._.uid}_${this.eventIdIncrement++}`,
|
|
2866
|
+
segments: multipleDays ? {} : null,
|
|
2867
|
+
start,
|
|
2868
|
+
startTimeMinutes,
|
|
2869
|
+
end,
|
|
2870
|
+
endTimeMinutes,
|
|
2871
|
+
daysCount: multipleDays ? ud2.countDays(start, end) : 1,
|
|
2872
|
+
class: event.class
|
|
2873
|
+
});
|
|
2874
|
+
this.mutableEvents.push(event);
|
|
2875
|
+
});
|
|
2876
|
+
},
|
|
2877
|
+
/**
|
|
2878
|
+
* Get the number of minutes from the top to the mouse cursor.
|
|
2879
|
+
*
|
|
2880
|
+
* @param {Object} e the native DOM event object.
|
|
2881
|
+
* @return {Object} containing { minutes: {Number}, cursorCoords: { x: {Number}, y: {Number} } }
|
|
2882
|
+
*/
|
|
2883
|
+
minutesAtCursor(e) {
|
|
2884
|
+
return this.utils.cell.minutesAtCursor(e);
|
|
2885
|
+
},
|
|
2886
|
+
/**
|
|
2887
|
+
* Creates a new event in vue-cal memory (in the mutableEvents array) starting at the given date & time.
|
|
2888
|
+
* Proxy method to allow call from cell click & hold or external call (via $refs).
|
|
2889
|
+
* Notes: Event duration is by default 2 hours. You can override the event end through eventOptions.
|
|
2890
|
+
*
|
|
2891
|
+
* @param {String | Date} dateTime date & time at which the event will start.
|
|
2892
|
+
* @param {Number} duration the event duration in minutes.
|
|
2893
|
+
* @param {Object} eventOptions an object of options to override the event creation defaults.
|
|
2894
|
+
* (can be any key allowed in an event object)
|
|
2895
|
+
* @return {Object} the created event.
|
|
2896
|
+
*/
|
|
2897
|
+
createEvent(dateTime, duration, eventOptions = {}) {
|
|
2898
|
+
return this.utils.event.createAnEvent(dateTime, duration, eventOptions);
|
|
2899
|
+
},
|
|
2900
|
+
/**
|
|
2901
|
+
* Remove all the vue-cal private vars from the event (before returning it through $emit()).
|
|
2902
|
+
*
|
|
2903
|
+
* @param {Object} event the event object to cleanup.
|
|
2904
|
+
*/
|
|
2905
|
+
cleanupEvent(event) {
|
|
2906
|
+
event = { ...event };
|
|
2907
|
+
const discardProps = [
|
|
2908
|
+
"segments",
|
|
2909
|
+
"deletable",
|
|
2910
|
+
"deleting",
|
|
2911
|
+
"titleEditable",
|
|
2912
|
+
"resizable",
|
|
2913
|
+
"resizing",
|
|
2914
|
+
"draggable",
|
|
2915
|
+
"dragging",
|
|
2916
|
+
"draggingStatic",
|
|
2917
|
+
"focused"
|
|
2918
|
+
];
|
|
2919
|
+
discardProps.forEach((prop) => {
|
|
2920
|
+
if (prop in event) delete event[prop];
|
|
2921
|
+
});
|
|
2922
|
+
if (!event.repeat) delete event.repeat;
|
|
2923
|
+
return event;
|
|
2924
|
+
},
|
|
2925
|
+
/**
|
|
2926
|
+
* Emits an event (custom DOM event) to the outside world.
|
|
2927
|
+
* This event has an event name and a clean calendar event as a parameter.
|
|
2928
|
+
*
|
|
2929
|
+
* @param {String} eventName the name of the custom emitted event (e.g. `event-focus`).
|
|
2930
|
+
* @param {Object} event the event to return to the outside world.
|
|
2931
|
+
*/
|
|
2932
|
+
emitWithEvent(eventName, event) {
|
|
2933
|
+
this.$emit(eventName, this.cleanupEvent(event));
|
|
2934
|
+
},
|
|
2935
|
+
/**
|
|
2936
|
+
* Update the selected date:
|
|
2937
|
+
* - on created, from given selectedDate prop
|
|
2938
|
+
* - on click/dblClick of another cell
|
|
2939
|
+
* - from external call (via $refs)
|
|
2940
|
+
* - when the given selectedDate prop changes.
|
|
2941
|
+
* If date is not in the view, the view will change to show it.
|
|
2942
|
+
*
|
|
2943
|
+
* @param {String | Date} date The date to select.
|
|
2944
|
+
*/
|
|
2945
|
+
updateSelectedDate(date) {
|
|
2946
|
+
if (date && typeof date === "string") date = this.utils.date.stringToDate(date);
|
|
2947
|
+
else date = new Date(date);
|
|
2948
|
+
if (date && date instanceof Date) {
|
|
2949
|
+
const { selectedDate } = this.view;
|
|
2950
|
+
if (selectedDate) this.transitionDirection = selectedDate.getTime() > date.getTime() ? "left" : "right";
|
|
2951
|
+
date.setHours(0, 0, 0, 0);
|
|
2952
|
+
if (!selectedDate || selectedDate.getTime() !== date.getTime()) this.view.selectedDate = date;
|
|
2953
|
+
this.switchView(this.view.id);
|
|
2954
|
+
}
|
|
2955
|
+
this.$emit("update:selected-date", this.view.selectedDate);
|
|
2956
|
+
},
|
|
2957
|
+
/**
|
|
2958
|
+
* Double checks the week number is correct. Read below to understand!
|
|
2959
|
+
* this is a wrapper around the `getWeek()` function for performance:
|
|
2960
|
+
* As this is called multiple times from the template and cannot be in computed since there is
|
|
2961
|
+
* a parameter, this wrapper function avoids the `getWeek()` function call 5 times out of 6
|
|
2962
|
+
* using the computed `firstCellDateWeekNumber`.
|
|
2963
|
+
*
|
|
2964
|
+
* Reason why:
|
|
2965
|
+
* Getting the week number is not that straightforward as there might be a 53rd week in the year.
|
|
2966
|
+
* Whenever the year starts on a Thursday or any leap year starting on a Wednesday, this week will be 53.
|
|
2967
|
+
*
|
|
2968
|
+
* @param {Number} weekFromFirstCell Number from 0 to 6.
|
|
2969
|
+
*/
|
|
2970
|
+
getWeekNumber(weekFromFirstCell) {
|
|
2971
|
+
const ud2 = this.utils.date;
|
|
2972
|
+
const firstCellWeekNumber = this.firstCellDateWeekNumber;
|
|
2973
|
+
const currentWeekNumber = firstCellWeekNumber + weekFromFirstCell;
|
|
2974
|
+
const modifier = this.startWeekOnSunday ? 1 : 0;
|
|
2975
|
+
if (currentWeekNumber > 52) {
|
|
2976
|
+
return ud2.getWeek(ud2.addDays(this.view.firstCellDate, 7 * weekFromFirstCell + modifier));
|
|
2977
|
+
} else return currentWeekNumber;
|
|
2978
|
+
},
|
|
2979
|
+
/**
|
|
2980
|
+
* Only if watchRealTime is true.
|
|
2981
|
+
* Pull the current time from user machine every minute to keep vue-cal accurate even when idle.
|
|
2982
|
+
* This will redraw the now line every minute and ensure that Today's date is always accurate.
|
|
2983
|
+
*/
|
|
2984
|
+
timeTick() {
|
|
2985
|
+
this.now = /* @__PURE__ */ new Date();
|
|
2986
|
+
this.timeTickerIds[1] = setTimeout(this.timeTick, 60 * 1e3);
|
|
2987
|
+
},
|
|
2988
|
+
/**
|
|
2989
|
+
* Updates the localized texts in use in the Date prototypes. (E.g. new Date().format())
|
|
2990
|
+
* Callable from outside of Vue Cal.
|
|
2991
|
+
*/
|
|
2992
|
+
updateDateTexts() {
|
|
2993
|
+
this.utils.date.updateTexts(this.texts);
|
|
2994
|
+
},
|
|
2995
|
+
/**
|
|
2996
|
+
* On Windows devices, the .vuecal__bg's vertical scrollbar takes space and pushes the content.
|
|
2997
|
+
* This function will also push the weekdays-headings and all-day bar to have them properly aligned.
|
|
2998
|
+
* The calculated style will be placed in the document head in a style tag so it's only done once
|
|
2999
|
+
* (the scrollbar width never changes).
|
|
3000
|
+
* Ref. https://github.com/antoniandre/vue-cal/issues/221
|
|
3001
|
+
*/
|
|
3002
|
+
alignWithScrollbar() {
|
|
3003
|
+
if (document.getElementById("vuecal-align-with-scrollbar")) return;
|
|
3004
|
+
const bg = this.$refs.vuecal.getElementsByClassName("vuecal__scrollbar-check")[0];
|
|
3005
|
+
const scrollbarWidth = bg.offsetWidth - bg.children[0].offsetWidth;
|
|
3006
|
+
if (scrollbarWidth) {
|
|
3007
|
+
const style = document.createElement("style");
|
|
3008
|
+
style.id = "vuecal-align-with-scrollbar";
|
|
3009
|
+
style.type = "text/css";
|
|
3010
|
+
style.innerHTML = `.vuecal--view-with-time .vuecal__weekdays-headings,.vuecal--view-with-time .vuecal__all-day {padding-right: ${scrollbarWidth}px}`;
|
|
3011
|
+
document.head.appendChild(style);
|
|
3012
|
+
}
|
|
3013
|
+
},
|
|
3014
|
+
/**
|
|
3015
|
+
* Tells wether there are events in the given cell or split and returns a Boolean.
|
|
3016
|
+
* This function simplifies the template.
|
|
3017
|
+
*
|
|
3018
|
+
* @param {Array} events The cell events.
|
|
3019
|
+
* @param {Object|Boolean} split The current split object if any or false.
|
|
3020
|
+
* @return {Boolean} true if there are events, false otherwise.
|
|
3021
|
+
*/
|
|
3022
|
+
cellOrSplitHasEvents(events, split = null) {
|
|
3023
|
+
return events.length && (!split && events.length || split && events.some((e) => e.split === split.id));
|
|
3024
|
+
}
|
|
3025
|
+
},
|
|
3026
|
+
created() {
|
|
3027
|
+
this.utils.cell = new CellUtils(this);
|
|
3028
|
+
this.utils.event = new EventUtils(this, this.utils.date);
|
|
3029
|
+
this.loadLocale(this.locale);
|
|
3030
|
+
if (this.editEvents.drag) this.loadDragAndDrop();
|
|
3031
|
+
this.updateMutableEvents(this.events);
|
|
3032
|
+
this.view.id = this.currentView;
|
|
3033
|
+
if (this.selectedDate) this.updateSelectedDate(this.selectedDate);
|
|
3034
|
+
else {
|
|
3035
|
+
this.view.selectedDate = /* @__PURE__ */ new Date();
|
|
3036
|
+
this.switchView(this.currentView);
|
|
3037
|
+
}
|
|
3038
|
+
if (this.time && this.watchRealTime) {
|
|
3039
|
+
this.timeTickerIds[0] = setTimeout(this.timeTick, (60 - this.now.getSeconds()) * 1e3);
|
|
3040
|
+
}
|
|
3041
|
+
},
|
|
3042
|
+
mounted() {
|
|
3043
|
+
const ud2 = this.utils.date;
|
|
3044
|
+
const hasTouch = "ontouchstart" in window;
|
|
3045
|
+
const { resize, drag, create, delete: deletable, title } = this.editEvents;
|
|
3046
|
+
const hasEventClickHandler = this.onEventClick && typeof this.onEventClick === "function";
|
|
3047
|
+
if (resize || drag || create || deletable || title || hasEventClickHandler) {
|
|
3048
|
+
window.addEventListener(hasTouch ? "touchend" : "mouseup", this.onMouseUp);
|
|
911
3049
|
}
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
const s = this.view.startDate, o = this.weekDays;
|
|
915
|
-
t = o.map((a, d) => {
|
|
916
|
-
const r = e.addDays(s, this.startWeekOnSunday ? d - 1 : d), u = new Date(r);
|
|
917
|
-
u.setHours(23, 59, 59, 0);
|
|
918
|
-
const m = (r.getDay() || 7) - 1;
|
|
919
|
-
return { startDate: r, formattedDate: e.formatDateLite(r), endDate: u, today: !n && e.isToday(r) && !n++, specialHours: this.specialDayHours[m] || [] };
|
|
920
|
-
}).filter((a, d) => !o[d].hide);
|
|
921
|
-
break;
|
|
3050
|
+
if (resize || drag || create && this.dragToCreateEvent) {
|
|
3051
|
+
window.addEventListener(hasTouch ? "touchmove" : "mousemove", this.onMouseMove, { passive: false });
|
|
922
3052
|
}
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
3053
|
+
if (title) window.addEventListener("keyup", this.onKeyUp);
|
|
3054
|
+
if (hasTouch) {
|
|
3055
|
+
this.$refs.vuecal.oncontextmenu = function(e) {
|
|
3056
|
+
e.preventDefault();
|
|
3057
|
+
e.stopPropagation();
|
|
3058
|
+
};
|
|
3059
|
+
}
|
|
3060
|
+
if (!this.hideBody) this.alignWithScrollbar();
|
|
3061
|
+
const startDate = this.view.startDate;
|
|
3062
|
+
const params = {
|
|
3063
|
+
view: this.view.id,
|
|
3064
|
+
startDate,
|
|
3065
|
+
endDate: this.view.endDate,
|
|
3066
|
+
...this.isMonthView ? { firstCellDate: this.view.firstCellDate, lastCellDate: this.view.lastCellDate } : {},
|
|
3067
|
+
events: this.view.events.map(this.cleanupEvent),
|
|
3068
|
+
...this.isWeekView ? { week: ud2.getWeek(this.startWeekOnSunday ? ud2.addDays(startDate, 1) : startDate) } : {}
|
|
3069
|
+
};
|
|
3070
|
+
this.$emit("ready", params);
|
|
3071
|
+
this.ready = true;
|
|
3072
|
+
},
|
|
3073
|
+
beforeUnmount() {
|
|
3074
|
+
const hasTouch = "ontouchstart" in window;
|
|
3075
|
+
window.removeEventListener(hasTouch ? "touchmove" : "mousemove", this.onMouseMove, { passive: false });
|
|
3076
|
+
window.removeEventListener(hasTouch ? "touchend" : "mouseup", this.onMouseUp);
|
|
3077
|
+
window.removeEventListener("keyup", this.onKeyUp);
|
|
3078
|
+
if (this.timeTickerIds[0]) clearTimeout(this.timeTickerIds[0]);
|
|
3079
|
+
if (this.timeTickerIds[1]) clearTimeout(this.timeTickerIds[1]);
|
|
3080
|
+
this.timeTickerIds = [null, null];
|
|
3081
|
+
},
|
|
3082
|
+
computed: {
|
|
3083
|
+
editEvents() {
|
|
3084
|
+
if (this.editableEvents && typeof this.editableEvents === "object") {
|
|
3085
|
+
return {
|
|
3086
|
+
title: !!this.editableEvents.title,
|
|
3087
|
+
drag: !!this.editableEvents.drag,
|
|
3088
|
+
resize: !!this.editableEvents.resize,
|
|
3089
|
+
create: !!this.editableEvents.create,
|
|
3090
|
+
delete: !!this.editableEvents.delete
|
|
3091
|
+
};
|
|
3092
|
+
}
|
|
3093
|
+
return {
|
|
3094
|
+
title: !!this.editableEvents,
|
|
3095
|
+
drag: !!this.editableEvents,
|
|
3096
|
+
resize: !!this.editableEvents,
|
|
3097
|
+
create: !!this.editableEvents,
|
|
3098
|
+
delete: !!this.editableEvents
|
|
3099
|
+
};
|
|
3100
|
+
},
|
|
3101
|
+
views() {
|
|
3102
|
+
return {
|
|
3103
|
+
years: { label: this.texts.years, enabled: !this.disableViews.includes("years") },
|
|
3104
|
+
year: { label: this.texts.year, enabled: !this.disableViews.includes("year") },
|
|
3105
|
+
month: { label: this.texts.month, enabled: !this.disableViews.includes("month") },
|
|
3106
|
+
week: { label: this.texts.week, enabled: !this.disableViews.includes("week") },
|
|
3107
|
+
day: { label: this.texts.day, enabled: !this.disableViews.includes("day") }
|
|
3108
|
+
};
|
|
3109
|
+
},
|
|
3110
|
+
currentView() {
|
|
3111
|
+
return this.validateView(this.activeView);
|
|
3112
|
+
},
|
|
3113
|
+
enabledViews() {
|
|
3114
|
+
return Object.keys(this.views).filter((view) => this.views[view].enabled);
|
|
3115
|
+
},
|
|
3116
|
+
hasTimeColumn() {
|
|
3117
|
+
return this.time && this.isWeekOrDayView;
|
|
3118
|
+
},
|
|
3119
|
+
isShortMonthView() {
|
|
3120
|
+
return this.isMonthView && this.eventsOnMonthView === "short";
|
|
3121
|
+
},
|
|
3122
|
+
firstCellDateWeekNumber() {
|
|
3123
|
+
const ud2 = this.utils.date;
|
|
3124
|
+
const date = this.view.firstCellDate;
|
|
3125
|
+
return ud2.getWeek(this.startWeekOnSunday ? ud2.addDays(date, 1) : date);
|
|
3126
|
+
},
|
|
3127
|
+
// For week & day views.
|
|
3128
|
+
timeCells() {
|
|
3129
|
+
const timeCells = [];
|
|
3130
|
+
for (let i = this.timeFrom, max = this.timeTo; i < max; i += this.timeStep) {
|
|
3131
|
+
timeCells.push({
|
|
3132
|
+
hours: Math.floor(i / 60),
|
|
3133
|
+
minutes: i % 60,
|
|
3134
|
+
label: this.utils.date.formatTime(i, this.TimeFormat),
|
|
3135
|
+
// The texts (3rd param) are given on Vue Cal init.
|
|
3136
|
+
value: i
|
|
3137
|
+
});
|
|
3138
|
+
}
|
|
3139
|
+
return timeCells;
|
|
3140
|
+
},
|
|
3141
|
+
TimeFormat() {
|
|
3142
|
+
return this.timeFormat || (this.twelveHour ? "h:mm{am}" : "HH:mm");
|
|
3143
|
+
},
|
|
3144
|
+
// Filter out the day splits that are hidden.
|
|
3145
|
+
daySplits() {
|
|
3146
|
+
return (this.splitDays.filter((item) => !item.hide) || []).map((item, i) => ({ ...item, id: item.id || i + 1 }));
|
|
3147
|
+
},
|
|
3148
|
+
// Whether the current view has days splits.
|
|
3149
|
+
hasSplits() {
|
|
3150
|
+
return this.daySplits.length && this.isWeekOrDayView;
|
|
3151
|
+
},
|
|
3152
|
+
hasShortEvents() {
|
|
3153
|
+
return this.showAllDayEvents === "short";
|
|
3154
|
+
},
|
|
3155
|
+
// Returns the min cell width or the min split width if any.
|
|
3156
|
+
cellOrSplitMinWidth() {
|
|
3157
|
+
let minWidth = null;
|
|
3158
|
+
if (this.hasSplits && this.minSplitWidth) minWidth = this.visibleDaysCount * this.minSplitWidth * this.daySplits.length;
|
|
3159
|
+
else if (this.minCellWidth && this.isWeekView) minWidth = this.visibleDaysCount * this.minCellWidth;
|
|
3160
|
+
return minWidth;
|
|
3161
|
+
},
|
|
3162
|
+
allDayBar() {
|
|
3163
|
+
let height = this.allDayBarHeight || null;
|
|
3164
|
+
if (height && !isNaN(height)) height += "px";
|
|
3165
|
+
return {
|
|
3166
|
+
cells: this.viewCells,
|
|
3167
|
+
options: this.$props,
|
|
3168
|
+
label: this.texts.allDay,
|
|
3169
|
+
shortEvents: this.hasShortEvents,
|
|
3170
|
+
daySplits: this.hasSplits && this.daySplits || [],
|
|
3171
|
+
cellOrSplitMinWidth: this.cellOrSplitMinWidth,
|
|
3172
|
+
height
|
|
3173
|
+
};
|
|
3174
|
+
},
|
|
3175
|
+
minTimestamp() {
|
|
3176
|
+
let date = null;
|
|
3177
|
+
if (this.minDate && typeof this.minDate === "string") date = this.utils.date.stringToDate(this.minDate);
|
|
3178
|
+
else if (this.minDate && this.minDate instanceof Date) date = this.minDate;
|
|
3179
|
+
return date ? date.getTime() : null;
|
|
3180
|
+
},
|
|
3181
|
+
maxTimestamp() {
|
|
3182
|
+
let date = null;
|
|
3183
|
+
if (this.maxDate && typeof this.maxDate === "string") date = this.utils.date.stringToDate(this.maxDate);
|
|
3184
|
+
else if (this.maxDate && this.maxDate instanceof Date) date = this.maxDate;
|
|
3185
|
+
return date ? date.getTime() : null;
|
|
3186
|
+
},
|
|
3187
|
+
weekDays() {
|
|
3188
|
+
let { weekDays, weekDaysShort = [] } = this.texts;
|
|
3189
|
+
weekDays = weekDays.slice(0).map((day, i) => ({
|
|
3190
|
+
label: day,
|
|
3191
|
+
...weekDaysShort.length ? { short: weekDaysShort[i] } : {},
|
|
3192
|
+
hide: this.hideWeekends && i >= 5 || this.hideWeekdays.length && this.hideWeekdays.includes(i + 1)
|
|
3193
|
+
}));
|
|
3194
|
+
if (this.startWeekOnSunday) weekDays.unshift(weekDays.pop());
|
|
3195
|
+
return weekDays;
|
|
3196
|
+
},
|
|
3197
|
+
weekDaysInHeader() {
|
|
3198
|
+
return this.isMonthView || // hasSplits check is important here in case the user toggles the splits but keep minSplitWidth.
|
|
3199
|
+
this.isWeekView && !this.minCellWidth && !(this.hasSplits && this.minSplitWidth);
|
|
3200
|
+
},
|
|
3201
|
+
months() {
|
|
3202
|
+
return this.texts.months.map((month) => ({ label: month }));
|
|
3203
|
+
},
|
|
3204
|
+
// Validate and fill up the special hours object once for all at root level and not in cell.
|
|
3205
|
+
specialDayHours() {
|
|
3206
|
+
if (!this.specialHours || !Object.keys(this.specialHours).length) return {};
|
|
3207
|
+
return Array(7).fill("").map((cell, i) => {
|
|
3208
|
+
let day = this.specialHours[i + 1] || [];
|
|
3209
|
+
if (!Array.isArray(day)) day = [day];
|
|
3210
|
+
cell = [];
|
|
3211
|
+
day.forEach(({ from, to, class: Class, label }, j) => {
|
|
3212
|
+
cell[j] = {
|
|
3213
|
+
day: i + 1,
|
|
3214
|
+
from: ![null, void 0].includes(from) ? from * 1 : null,
|
|
3215
|
+
to: ![null, void 0].includes(to) ? to * 1 : null,
|
|
3216
|
+
class: Class || "",
|
|
3217
|
+
label: label || ""
|
|
3218
|
+
};
|
|
3219
|
+
});
|
|
3220
|
+
return cell;
|
|
3221
|
+
});
|
|
3222
|
+
},
|
|
3223
|
+
viewTitle() {
|
|
3224
|
+
const ud2 = this.utils.date;
|
|
3225
|
+
let title = "";
|
|
3226
|
+
const date = this.view.startDate;
|
|
3227
|
+
const year = date.getFullYear();
|
|
3228
|
+
const month = date.getMonth();
|
|
3229
|
+
switch (this.view.id) {
|
|
3230
|
+
case "years": {
|
|
3231
|
+
title = this.texts.years;
|
|
3232
|
+
break;
|
|
3233
|
+
}
|
|
3234
|
+
case "year": {
|
|
3235
|
+
title = year;
|
|
3236
|
+
break;
|
|
3237
|
+
}
|
|
3238
|
+
case "month": {
|
|
3239
|
+
title = `${this.months[month].label} ${year}`;
|
|
3240
|
+
break;
|
|
3241
|
+
}
|
|
3242
|
+
case "week": {
|
|
3243
|
+
const lastDayOfWeek = this.view.endDate;
|
|
3244
|
+
const y1 = date.getFullYear();
|
|
3245
|
+
let m1 = this.texts.months[date.getMonth()];
|
|
3246
|
+
if (this.xsmall) m1 = m1.substring(0, 3);
|
|
3247
|
+
let formattedMonthYear = `${m1} ${y1}`;
|
|
3248
|
+
if (lastDayOfWeek.getMonth() !== date.getMonth()) {
|
|
3249
|
+
const y2 = lastDayOfWeek.getFullYear();
|
|
3250
|
+
let m2 = this.texts.months[lastDayOfWeek.getMonth()];
|
|
3251
|
+
if (this.xsmall) m2 = m2.substring(0, 3);
|
|
3252
|
+
if (y1 === y2) formattedMonthYear = `${m1} - ${m2} ${y1}`;
|
|
3253
|
+
else {
|
|
3254
|
+
if (this.small) formattedMonthYear = `${m1.substring(0, 3)} ${y1} - ${m2.substring(0, 3)} ${y2}`;
|
|
3255
|
+
else formattedMonthYear = `${m1} ${y1} - ${m2} ${y2}`;
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
title = `${this.texts.week} ${ud2.getWeek(this.startWeekOnSunday ? ud2.addDays(date, 1) : date)} (${formattedMonthYear})`;
|
|
3259
|
+
break;
|
|
3260
|
+
}
|
|
3261
|
+
case "day": {
|
|
3262
|
+
title = this.utils.date.formatDate(date, this.texts.dateFormat, this.texts);
|
|
3263
|
+
break;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
return title;
|
|
3267
|
+
},
|
|
3268
|
+
viewCells() {
|
|
3269
|
+
const ud2 = this.utils.date;
|
|
3270
|
+
let cells = [];
|
|
3271
|
+
let fromYear = null;
|
|
3272
|
+
let todayFound = false;
|
|
3273
|
+
if (!this.watchRealTime) this.now = /* @__PURE__ */ new Date();
|
|
3274
|
+
const now2 = this.now;
|
|
3275
|
+
switch (this.view.id) {
|
|
3276
|
+
case "years": {
|
|
3277
|
+
fromYear = this.view.startDate.getFullYear();
|
|
3278
|
+
cells = Array.apply(null, Array(25)).map((cell, i) => {
|
|
3279
|
+
const startDate = new Date(fromYear + i, 0, 1);
|
|
3280
|
+
const endDate = new Date(fromYear + i + 1, 0, 1);
|
|
3281
|
+
endDate.setSeconds(-1);
|
|
3282
|
+
return {
|
|
3283
|
+
startDate,
|
|
3284
|
+
formattedDate: ud2.formatDateLite(startDate),
|
|
3285
|
+
endDate,
|
|
3286
|
+
content: fromYear + i,
|
|
3287
|
+
current: fromYear + i === now2.getFullYear()
|
|
3288
|
+
};
|
|
3289
|
+
});
|
|
3290
|
+
break;
|
|
3291
|
+
}
|
|
3292
|
+
case "year": {
|
|
3293
|
+
fromYear = this.view.startDate.getFullYear();
|
|
3294
|
+
cells = Array.apply(null, Array(12)).map((cell, i) => {
|
|
3295
|
+
const startDate = new Date(fromYear, i, 1);
|
|
3296
|
+
const endDate = new Date(fromYear, i + 1, 1);
|
|
3297
|
+
endDate.setSeconds(-1);
|
|
3298
|
+
return {
|
|
3299
|
+
startDate,
|
|
3300
|
+
formattedDate: ud2.formatDateLite(startDate),
|
|
3301
|
+
endDate,
|
|
3302
|
+
content: this.xsmall ? this.months[i].label.substr(0, 3) : this.months[i].label,
|
|
3303
|
+
current: i === now2.getMonth() && fromYear === now2.getFullYear()
|
|
3304
|
+
};
|
|
3305
|
+
});
|
|
3306
|
+
break;
|
|
3307
|
+
}
|
|
3308
|
+
case "month": {
|
|
3309
|
+
const month = this.view.startDate.getMonth();
|
|
3310
|
+
const firstCellDate = new Date(this.view.firstCellDate);
|
|
3311
|
+
todayFound = false;
|
|
3312
|
+
cells = Array.apply(null, Array(42)).map((cell, i) => {
|
|
3313
|
+
const startDate = ud2.addDays(firstCellDate, i);
|
|
3314
|
+
const endDate = new Date(startDate);
|
|
3315
|
+
endDate.setHours(23, 59, 59, 0);
|
|
3316
|
+
const isToday = !todayFound && ud2.isToday(startDate) && !todayFound++;
|
|
3317
|
+
return {
|
|
3318
|
+
startDate,
|
|
3319
|
+
formattedDate: ud2.formatDateLite(startDate),
|
|
3320
|
+
endDate,
|
|
3321
|
+
content: startDate.getDate(),
|
|
3322
|
+
today: isToday,
|
|
3323
|
+
outOfScope: startDate.getMonth() !== month,
|
|
3324
|
+
class: `vuecal__cell--day${startDate.getDay() || 7}`
|
|
3325
|
+
};
|
|
3326
|
+
});
|
|
3327
|
+
if (this.hideWeekends || this.hideWeekdays.length) {
|
|
3328
|
+
cells = cells.filter((cell) => {
|
|
3329
|
+
const day = cell.startDate.getDay() || 7;
|
|
3330
|
+
return !(this.hideWeekends && day >= 6 || this.hideWeekdays.length && this.hideWeekdays.includes(day));
|
|
3331
|
+
});
|
|
3332
|
+
}
|
|
3333
|
+
break;
|
|
3334
|
+
}
|
|
3335
|
+
case "week": {
|
|
3336
|
+
todayFound = false;
|
|
3337
|
+
const firstDayOfWeek = this.view.startDate;
|
|
3338
|
+
const weekDays = this.weekDays;
|
|
3339
|
+
cells = weekDays.map((cell, i) => {
|
|
3340
|
+
const startDate = ud2.addDays(firstDayOfWeek, this.startWeekOnSunday && this.hideWeekends ? i - 1 : i);
|
|
3341
|
+
const endDate = new Date(startDate);
|
|
3342
|
+
endDate.setHours(23, 59, 59, 0);
|
|
3343
|
+
const dayOfWeek = (startDate.getDay() || 7) - 1;
|
|
3344
|
+
return {
|
|
3345
|
+
startDate,
|
|
3346
|
+
formattedDate: ud2.formatDateLite(startDate),
|
|
3347
|
+
endDate,
|
|
3348
|
+
// To increase performance skip checking isToday if today already found.
|
|
3349
|
+
today: !todayFound && ud2.isToday(startDate) && !todayFound++,
|
|
3350
|
+
specialHours: this.specialDayHours[dayOfWeek] || []
|
|
3351
|
+
};
|
|
3352
|
+
}).filter((cell, i) => !weekDays[i].hide);
|
|
3353
|
+
break;
|
|
3354
|
+
}
|
|
3355
|
+
case "day": {
|
|
3356
|
+
const startDate = this.view.startDate;
|
|
3357
|
+
const endDate = new Date(this.view.startDate);
|
|
3358
|
+
endDate.setHours(23, 59, 59, 0);
|
|
3359
|
+
const dayOfWeek = (startDate.getDay() || 7) - 1;
|
|
3360
|
+
cells = [{
|
|
3361
|
+
startDate,
|
|
3362
|
+
formattedDate: ud2.formatDateLite(startDate),
|
|
3363
|
+
endDate,
|
|
3364
|
+
today: ud2.isToday(startDate),
|
|
3365
|
+
specialHours: this.specialDayHours[dayOfWeek] || []
|
|
3366
|
+
}];
|
|
3367
|
+
break;
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
return cells;
|
|
3371
|
+
},
|
|
3372
|
+
// Only when hiding weekdays on month and week views.
|
|
3373
|
+
visibleDaysCount() {
|
|
3374
|
+
if (this.isDayView) return 1;
|
|
3375
|
+
return 7 - this.weekDays.reduce((total, day) => total + day.hide, 0);
|
|
3376
|
+
},
|
|
3377
|
+
cellWidth() {
|
|
3378
|
+
return 100 / this.visibleDaysCount;
|
|
3379
|
+
},
|
|
3380
|
+
cssClasses() {
|
|
3381
|
+
const { resizeAnEvent, dragAnEvent, dragCreateAnEvent } = this.domEvents;
|
|
3382
|
+
return {
|
|
3383
|
+
[`vuecal--${this.view.id}-view`]: true,
|
|
3384
|
+
[`vuecal--${this.locale}`]: this.locale,
|
|
3385
|
+
"vuecal--no-time": !this.time,
|
|
3386
|
+
"vuecal--view-with-time": this.hasTimeColumn,
|
|
3387
|
+
"vuecal--week-numbers": this.showWeekNumbers && this.isMonthView,
|
|
3388
|
+
"vuecal--twelve-hour": this.twelveHour,
|
|
3389
|
+
"vuecal--click-to-navigate": this.clickToNavigate,
|
|
3390
|
+
"vuecal--hide-weekends": this.hideWeekends,
|
|
3391
|
+
"vuecal--split-days": this.hasSplits,
|
|
3392
|
+
"vuecal--sticky-split-labels": this.hasSplits && this.stickySplitLabels,
|
|
3393
|
+
"vuecal--overflow-x": this.minCellWidth && this.isWeekView || this.hasSplits && this.minSplitWidth,
|
|
3394
|
+
"vuecal--small": this.small,
|
|
3395
|
+
"vuecal--xsmall": this.xsmall,
|
|
3396
|
+
"vuecal--resizing-event": resizeAnEvent._eid,
|
|
3397
|
+
"vuecal--drag-creating-event": dragCreateAnEvent.event,
|
|
3398
|
+
"vuecal--dragging-event": dragAnEvent._eid,
|
|
3399
|
+
"vuecal--events-on-month-view": this.eventsOnMonthView,
|
|
3400
|
+
"vuecal--short-events": this.isMonthView && this.eventsOnMonthView === "short",
|
|
3401
|
+
"vuecal--has-touch": typeof window !== "undefined" && "ontouchstart" in window
|
|
3402
|
+
};
|
|
3403
|
+
},
|
|
3404
|
+
isYearsOrYearView() {
|
|
3405
|
+
return ["years", "year"].includes(this.view.id);
|
|
3406
|
+
},
|
|
3407
|
+
isYearsView() {
|
|
3408
|
+
return this.view.id === "years";
|
|
3409
|
+
},
|
|
3410
|
+
isYearView() {
|
|
3411
|
+
return this.view.id === "year";
|
|
3412
|
+
},
|
|
3413
|
+
isMonthView() {
|
|
3414
|
+
return this.view.id === "month";
|
|
3415
|
+
},
|
|
3416
|
+
isWeekOrDayView() {
|
|
3417
|
+
return ["week", "day"].includes(this.view.id);
|
|
3418
|
+
},
|
|
3419
|
+
isWeekView() {
|
|
3420
|
+
return this.view.id === "week";
|
|
3421
|
+
},
|
|
3422
|
+
isDayView() {
|
|
3423
|
+
return this.view.id === "day";
|
|
3424
|
+
}
|
|
3425
|
+
},
|
|
3426
|
+
watch: {
|
|
3427
|
+
events: {
|
|
3428
|
+
// To be able to detect an event attribute change, it has to be first initialized with a value.
|
|
3429
|
+
handler(events, oldEvents) {
|
|
3430
|
+
this.updateMutableEvents(events);
|
|
3431
|
+
this.addEventsToView();
|
|
3432
|
+
},
|
|
3433
|
+
deep: true
|
|
3434
|
+
},
|
|
3435
|
+
locale(locale) {
|
|
3436
|
+
this.loadLocale(locale);
|
|
3437
|
+
},
|
|
3438
|
+
selectedDate(date) {
|
|
3439
|
+
this.updateSelectedDate(date);
|
|
3440
|
+
},
|
|
3441
|
+
activeView(newVal) {
|
|
3442
|
+
this.switchView(newVal);
|
|
929
3443
|
}
|
|
930
3444
|
}
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
return this.isDayView ? 1 : 7 - this.weekDays.reduce((e, t) => e + t.hide, 0);
|
|
934
|
-
}, cellWidth() {
|
|
935
|
-
return 100 / this.visibleDaysCount;
|
|
936
|
-
}, cssClasses() {
|
|
937
|
-
const { resizeAnEvent: e, dragAnEvent: t, dragCreateAnEvent: i } = this.domEvents;
|
|
938
|
-
return { [`vuecal--${this.view.id}-view`]: !0, [`vuecal--${this.locale}`]: this.locale, "vuecal--no-time": !this.time, "vuecal--view-with-time": this.hasTimeColumn, "vuecal--week-numbers": this.showWeekNumbers && this.isMonthView, "vuecal--twelve-hour": this.twelveHour, "vuecal--click-to-navigate": this.clickToNavigate, "vuecal--hide-weekends": this.hideWeekends, "vuecal--split-days": this.hasSplits, "vuecal--sticky-split-labels": this.hasSplits && this.stickySplitLabels, "vuecal--overflow-x": this.minCellWidth && this.isWeekView || this.hasSplits && this.minSplitWidth, "vuecal--small": this.small, "vuecal--xsmall": this.xsmall, "vuecal--resizing-event": e._eid, "vuecal--drag-creating-event": i.event, "vuecal--dragging-event": t._eid, "vuecal--events-on-month-view": this.eventsOnMonthView, "vuecal--short-events": this.isMonthView && this.eventsOnMonthView === "short", "vuecal--has-touch": typeof window < "u" && "ontouchstart" in window };
|
|
939
|
-
}, isYearsOrYearView() {
|
|
940
|
-
return ["years", "year"].includes(this.view.id);
|
|
941
|
-
}, isYearsView() {
|
|
942
|
-
return this.view.id === "years";
|
|
943
|
-
}, isYearView() {
|
|
944
|
-
return this.view.id === "year";
|
|
945
|
-
}, isMonthView() {
|
|
946
|
-
return this.view.id === "month";
|
|
947
|
-
}, isWeekOrDayView() {
|
|
948
|
-
return ["week", "day"].includes(this.view.id);
|
|
949
|
-
}, isWeekView() {
|
|
950
|
-
return this.view.id === "week";
|
|
951
|
-
}, isDayView() {
|
|
952
|
-
return this.view.id === "day";
|
|
953
|
-
} }, watch: { events: { handler(e, t) {
|
|
954
|
-
this.updateMutableEvents(e), this.addEventsToView();
|
|
955
|
-
}, deep: !0 }, locale(e) {
|
|
956
|
-
this.loadLocale(e);
|
|
957
|
-
}, selectedDate(e) {
|
|
958
|
-
this.updateSelectedDate(e);
|
|
959
|
-
}, activeView(e) {
|
|
960
|
-
this.switchView(e);
|
|
961
|
-
} } }, Dt = B(pt, [["render", function(e, t, i, n, l, s) {
|
|
962
|
-
const o = j("vuecal-header"), a = j("all-day-bar"), d = j("weekdays-headings"), r = j("vuecal-cell");
|
|
963
|
-
return h(), c("div", { class: b(["vuecal__flex vuecal", s.cssClasses]), column: "", ref: "vuecal", lang: i.locale }, [U(o, { options: e.$props, "edit-events": s.editEvents, "view-props": { views: s.views, weekDaysInHeader: s.weekDaysInHeader }, "week-days": s.weekDays, "has-splits": s.hasSplits, "day-splits": s.daySplits, "switch-to-narrower-view": s.switchToNarrowerView }, X({ "arrow-prev": g(() => [w(e.$slots, "arrow-prev", {}, () => [M("\xA0"), Be, M("\xA0")])]), "arrow-next": g(() => [w(e.$slots, "arrow-next", {}, () => [M("\xA0"), Ne, M("\xA0")])]), "today-button": g(() => [w(e.$slots, "today-button", {}, () => [k("span", Ie, f(l.texts.today), 1)])]), title: g(() => [w(e.$slots, "title", { title: s.viewTitle, view: l.view }, () => [M(f(s.viewTitle), 1)])]), _: 2 }, [e.$slots["weekday-heading"] ? { name: "weekday-heading", fn: g(({ heading: u, view: m }) => [w(e.$slots, "weekday-heading", { heading: u, view: m })]), key: "0" } : void 0, e.$slots["split-label"] ? { name: "split-label", fn: g(({ split: u }) => [w(e.$slots, "split-label", { split: u, view: l.view.id })]), key: "1" } : void 0]), 1032, ["options", "edit-events", "view-props", "week-days", "has-splits", "day-splits", "switch-to-narrower-view"]), i.hideBody ? v("", !0) : (h(), c("div", ze, [U(R, { name: `slide-fade--${l.transitionDirection}`, appear: i.transitions }, { default: g(() => [(h(), c("div", { class: "vuecal__flex", style: { "min-width": "100%" }, key: !!i.transitions && l.view.id, column: "" }, [i.showAllDayEvents && s.hasTimeColumn && (!s.cellOrSplitMinWidth || s.isDayView && !i.minSplitWidth) ? (h(), H(a, J(Q({ key: 0 }, s.allDayBar)), { event: g(({ event: u, view: m }) => [w(e.$slots, "event", { view: m, event: u }, () => [s.editEvents.title && u.titleEditable ? (h(), c("div", { key: 0, class: "vuecal__event-title vuecal__event-title--edit", contenteditable: "", onBlur: (p) => s.onEventTitleBlur(p, u), innerHTML: u.title }, null, 40, Pe)) : u.title ? (h(), c("div", { key: 1, class: "vuecal__event-title", innerHTML: u.title }, null, 8, Ue)) : v("", !0), !u.content || s.hasShortEvents || s.isShortMonthView ? v("", !0) : (h(), c("div", { key: 2, class: "vuecal__event-content", innerHTML: u.content }, null, 8, Re))])]), _: 3 }, 16)) : v("", !0), k("div", { class: b(["vuecal__bg", { vuecal__flex: !s.hasTimeColumn }]), column: "" }, [k("div", qe, [s.hasTimeColumn ? (h(), c("div", Ke, [i.showAllDayEvents && s.cellOrSplitMinWidth && (!s.isDayView || i.minSplitWidth) ? (h(), c("div", { key: 0, class: "vuecal__all-day-text", style: $({ height: s.allDayBar.height }) }, [k("span", null, f(l.texts.allDay), 1)], 4)) : v("", !0), (h(!0), c(T, null, S(s.timeCells, (u, m) => (h(), c("div", { class: "vuecal__time-cell", key: m, style: $(`height: ${i.timeCellHeight}px`) }, [w(e.$slots, "time-cell", { hours: u.hours, minutes: u.minutes }, () => [Xe, k("span", Ge, f(u.label), 1)])], 4))), 128))])) : v("", !0), i.showWeekNumbers && s.isMonthView ? (h(), c("div", Ze, [(h(), c(T, null, S(6, (u) => k("div", { class: "vuecal__flex vuecal__week-number-cell", key: u, grow: "" }, [w(e.$slots, "week-number-cell", { week: s.getWeekNumber(u - 1) }, () => [M(f(s.getWeekNumber(u - 1)), 1)])])), 64))])) : v("", !0), k("div", { class: b(["vuecal__flex vuecal__cells", `${l.view.id}-view`]), grow: "", wrap: !s.cellOrSplitMinWidth || !s.isWeekView, column: !!s.cellOrSplitMinWidth }, [s.cellOrSplitMinWidth && s.isWeekView ? (h(), H(d, { key: 0, "transition-direction": l.transitionDirection, "week-days": s.weekDays, "switch-to-narrower-view": s.switchToNarrowerView, style: $(s.cellOrSplitMinWidth ? `min-width: ${s.cellOrSplitMinWidth}px` : "") }, X({ _: 2 }, [e.$slots["weekday-heading"] ? { name: "weekday-heading", fn: g(({ heading: u, view: m }) => [w(e.$slots, "weekday-heading", { heading: u, view: m })]), key: "0" } : void 0, e.$slots["split-label"] ? { name: "split-label", fn: g(({ split: u }) => [w(e.$slots, "split-label", { split: u, view: l.view.id })]), key: "1" } : void 0]), 1032, ["transition-direction", "week-days", "switch-to-narrower-view", "style"])) : s.hasSplits && i.stickySplitLabels && i.minSplitWidth ? (h(), c("div", { key: 1, class: "vuecal__flex vuecal__split-days-headers", style: $(s.cellOrSplitMinWidth ? `min-width: ${s.cellOrSplitMinWidth}px` : "") }, [(h(!0), c(T, null, S(s.daySplits, (u, m) => (h(), c("div", { class: b(["day-split-header", u.class || !1]), key: m }, [w(e.$slots, "split-label", { split: u, view: l.view.id }, () => [M(f(u.label), 1)])], 2))), 128))], 4)) : v("", !0), i.showAllDayEvents && s.hasTimeColumn && (s.isWeekView && s.cellOrSplitMinWidth || s.isDayView && s.hasSplits && i.minSplitWidth) ? (h(), H(a, J(Q({ key: 2 }, s.allDayBar)), { event: g(({ event: u, view: m }) => [w(e.$slots, "event", { view: m, event: u }, () => [s.editEvents.title && u.titleEditable ? (h(), c("div", { key: 0, class: "vuecal__event-title vuecal__event-title--edit", contenteditable: "", onBlur: (p) => s.onEventTitleBlur(p, u), innerHTML: u.title }, null, 40, Qe)) : u.title ? (h(), c("div", { key: 1, class: "vuecal__event-title", innerHTML: u.title }, null, 8, et)) : v("", !0), !u.content || s.hasShortEvents || s.isShortMonthView ? v("", !0) : (h(), c("div", { key: 2, class: "vuecal__event-content", innerHTML: u.content }, null, 8, tt))])]), _: 3 }, 16)) : v("", !0), k("div", { class: "vuecal__flex", ref: (u) => l.cellsEl = u, grow: "", wrap: !s.cellOrSplitMinWidth || !s.isWeekView, style: $(s.cellOrSplitMinWidth ? `min-width: ${s.cellOrSplitMinWidth}px` : "") }, [(h(!0), c(T, null, S(s.viewCells, (u, m) => (h(), H(r, { key: m, options: e.$props, "edit-events": s.editEvents, data: u, "cell-width": i.hideWeekdays.length && (s.isWeekView || s.isMonthView) && s.cellWidth, "min-timestamp": s.minTimestamp, "max-timestamp": s.maxTimestamp, "cell-splits": s.hasSplits && s.daySplits || [] }, { "cell-content": g(({ events: p, split: E, selectCell: _ }) => [w(e.$slots, "cell-content", { cell: u, view: l.view, goNarrower: _, events: p }, () => [E && !i.stickySplitLabels ? (h(), c("div", { key: 0, class: "split-label", innerHTML: E.label }, null, 8, st)) : v("", !0), u.content ? (h(), c("div", { key: 1, class: "vuecal__cell-date", innerHTML: u.content }, null, 8, nt)) : v("", !0), (s.isMonthView && !i.eventsOnMonthView || s.isYearsOrYearView && i.eventsCountOnYearView) && p.length ? (h(), c("div", at, [w(e.$slots, "events-count", { view: l.view, events: p }, () => [M(f(p.length), 1)])])) : v("", !0), !s.cellOrSplitHasEvents(p, E) && s.isWeekOrDayView ? (h(), c("div", lt, [w(e.$slots, "no-event", {}, () => [M(f(l.texts.noEvent), 1)])])) : v("", !0)])]), event: g(({ event: p, view: E }) => [w(e.$slots, "event", { view: E, event: p }, () => [s.editEvents.title && p.titleEditable ? (h(), c("div", { key: 0, class: "vuecal__event-title vuecal__event-title--edit", contenteditable: "", onBlur: (_) => s.onEventTitleBlur(_, p), innerHTML: p.title }, null, 40, ot)) : p.title ? (h(), c("div", { key: 1, class: "vuecal__event-title", innerHTML: p.title }, null, 8, rt)) : v("", !0), !i.time || p.allDay || s.isMonthView && (p.allDay || i.showAllDayEvents === "short") || s.isShortMonthView ? v("", !0) : (h(), c("div", dt, [M(f(l.utils.date.formatTime(p.start, s.TimeFormat)), 1), p.endTimeMinutes ? (h(), c("span", ut, "\xA0- " + f(l.utils.date.formatTime(p.end, s.TimeFormat, null, !0)), 1)) : v("", !0), p.daysCount > 1 && (p.segments[u.formattedDate] || {}).isFirstDay ? (h(), c("small", ht, "\xA0+" + f(p.daysCount - 1) + f((l.texts.day[0] || "").toLowerCase()), 1)) : v("", !0)])), !p.content || s.isMonthView && p.allDay && i.showAllDayEvents === "short" || s.isShortMonthView ? v("", !0) : (h(), c("div", { key: 3, class: "vuecal__event-content", innerHTML: p.content }, null, 8, ct))])]), "no-event": g(() => [w(e.$slots, "no-event", {}, () => [M(f(l.texts.noEvent), 1)])]), _: 2 }, 1032, ["options", "edit-events", "data", "cell-width", "min-timestamp", "max-timestamp", "cell-splits"]))), 128))], 12, it)], 10, Je)])], 2)]))]), _: 3 }, 8, ["name", "appear"]), l.ready ? v("", !0) : (h(), c("div", vt, mt))]))], 10, Fe);
|
|
964
|
-
}]]);
|
|
3445
|
+
};
|
|
3446
|
+
const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", render]]);
|
|
965
3447
|
export {
|
|
966
|
-
|
|
3448
|
+
index as default
|
|
967
3449
|
};
|