dhtmlx-scheduler 7.2.11 → 7.2.13

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.
@@ -1,6 +1,6 @@
1
1
  /** @license
2
2
 
3
- dhtmlxScheduler v.7.2.11 Standard
3
+ dhtmlxScheduler v.7.2.13 Standard
4
4
 
5
5
  To use dhtmlxScheduler in non-GPL projects (and get Pro version of the product), please obtain Commercial/Enterprise or Ultimate license on our site https://dhtmlx.com/docs/products/dhtmlxScheduler/#licensing or contact us at sales@dhtmlx.com
6
6
 
@@ -1297,7 +1297,7 @@ function createHandlers(scheduler2) {
1297
1297
  if (scheduler2._dp && scheduler2._dp._in_progress[event2.id]) {
1298
1298
  return;
1299
1299
  }
1300
- if (type === "add-event") {
1300
+ if (type === "add-event" && scheduler2._dp) {
1301
1301
  for (const id in scheduler2._dp._in_progress) {
1302
1302
  if (scheduler2._dp.getState(id) === "inserted") {
1303
1303
  scheduler2._dp.attachEvent("onFullSync", function() {
@@ -1336,9 +1336,13 @@ function createHandlers(scheduler2) {
1336
1336
  console.warn(`Event with ID ${eventData.id} already exists. Skipping add.`);
1337
1337
  return;
1338
1338
  }
1339
- eventData.start_date = scheduler2.templates.parse_date(eventData.start_date);
1340
- eventData.end_date = scheduler2.templates.parse_date(eventData.end_date);
1341
- if (eventData.original_start) {
1339
+ if (typeof eventData.start_date === "string") {
1340
+ eventData.start_date = scheduler2.templates.parse_date(eventData.start_date);
1341
+ }
1342
+ if (typeof eventData.end_date === "string") {
1343
+ eventData.end_date = scheduler2.templates.parse_date(eventData.end_date);
1344
+ }
1345
+ if (eventData.original_start && typeof eventData.original_start === "string") {
1342
1346
  eventData.original_start = scheduler2.templates.parse_date(eventData.original_start);
1343
1347
  }
1344
1348
  ignore(() => {
@@ -1358,10 +1362,14 @@ function createHandlers(scheduler2) {
1358
1362
  existingEvent[key] = eventData[key];
1359
1363
  }
1360
1364
  }
1361
- existingEvent.start_date = scheduler2.templates.parse_date(eventData.start_date);
1362
- existingEvent.end_date = scheduler2.templates.parse_date(eventData.end_date);
1363
- if (eventData.original_start) {
1364
- eventData.original_start = scheduler2.templates.parse_date(eventData.original_start);
1365
+ if (typeof eventData.start_date === "string") {
1366
+ existingEvent.start_date = scheduler2.templates.parse_date(eventData.start_date);
1367
+ }
1368
+ if (typeof eventData.end_date === "string") {
1369
+ existingEvent.end_date = scheduler2.templates.parse_date(eventData.end_date);
1370
+ }
1371
+ if (eventData.original_start && typeof eventData.original_start === "string") {
1372
+ existingEvent.original_start = scheduler2.templates.parse_date(eventData.original_start);
1365
1373
  }
1366
1374
  scheduler2.callEvent("onEventChanged", [sid, existingEvent]);
1367
1375
  scheduler2.updateEvent(sid);
@@ -2091,18 +2099,21 @@ function extend$j(scheduler2) {
2091
2099
  });
2092
2100
  return views.concat(date).concat(nav);
2093
2101
  }
2102
+ scheduler2._getInitialState = function(provided) {
2103
+ const initialDate = provided.date || this._currentDate();
2104
+ const initialView = provided.mode || "week";
2105
+ return { date: initialDate, mode: initialView };
2106
+ };
2094
2107
  scheduler2.init = function(id, date, mode) {
2095
2108
  if (this.$destroyed) {
2096
2109
  return;
2097
2110
  }
2098
- date = date || scheduler2._currentDate();
2099
- mode = mode || "week";
2100
- if (this._obj) {
2101
- this.unset_actions();
2102
- }
2103
2111
  this._obj = typeof id == "string" ? document.getElementById(id) : id;
2104
2112
  this.$container = this._obj;
2105
2113
  this.$root = this._obj;
2114
+ if (this._obj) {
2115
+ this.unset_actions();
2116
+ }
2106
2117
  if (!this.$container.offsetHeight && this.$container.offsetWidth && this.$container.style.height === "100%") {
2107
2118
  window.console.error(scheduler2._commonErrorMessages.collapsedContainer(), this.$container);
2108
2119
  }
@@ -2140,9 +2151,12 @@ function extend$j(scheduler2) {
2140
2151
  this._init_once();
2141
2152
  this._init_touch_events();
2142
2153
  this.set_sizes();
2154
+ const initialState = scheduler2._getInitialState({ date, mode });
2155
+ const initialDate = initialState.date;
2156
+ const initialMode = initialState.mode;
2143
2157
  scheduler2.callEvent("onSchedulerReady", []);
2144
2158
  scheduler2.$initialized = true;
2145
- this.setCurrentView(date, mode);
2159
+ this.setCurrentView(initialDate, initialMode);
2146
2160
  };
2147
2161
  scheduler2.xy = { min_event_height: 20, bar_height: 24, scale_width: 50, scroll_width: 18, scale_height: 20, month_scale_height: 20, menu_width: 25, margin_top: 0, margin_left: 0, editor_width: 140, month_head_height: 22, event_header_height: 14 };
2148
2162
  scheduler2.keys = { edit_save: 13, edit_cancel: 27 };
@@ -9253,7 +9267,7 @@ class DatePicker {
9253
9267
  }
9254
9268
  }
9255
9269
  function factoryMethod(extensionManager) {
9256
- const scheduler2 = { version: "7.2.11" };
9270
+ const scheduler2 = { version: "7.2.13" };
9257
9271
  scheduler2.$stateProvider = StateService();
9258
9272
  scheduler2.getState = scheduler2.$stateProvider.getState;
9259
9273
  extend$n(scheduler2);
@@ -10305,74 +10319,95 @@ function container_autoresize(scheduler2) {
10305
10319
  }
10306
10320
  }
10307
10321
  function cookie(scheduler2) {
10308
- function setCookie(name, cookie_param, value) {
10309
- const str = `${name}=${value}${cookie_param ? `; ${cookie_param}` : ""}`;
10310
- document.cookie = `${str}; Secure`;
10311
- }
10312
- function getCookie(name) {
10313
- var search = name + "=";
10314
- if (document.cookie.length > 0) {
10315
- var offset = document.cookie.indexOf(search);
10316
- if (offset != -1) {
10317
- offset += search.length;
10318
- var end = document.cookie.indexOf(";", offset);
10319
- if (end == -1)
10320
- end = document.cookie.length;
10321
- return document.cookie.substring(offset, end);
10322
- }
10322
+ function getStorageKey() {
10323
+ return (scheduler2._obj.id || "scheduler") + "_settings";
10324
+ }
10325
+ const dateToString = scheduler2.date.date_to_str("%Y-%m-%d %H:%i");
10326
+ const stringToDate = scheduler2.date.str_to_date("%Y-%m-%d %H:%i");
10327
+ function safeLocalStorageGet(key) {
10328
+ try {
10329
+ return window.localStorage.getItem(key);
10330
+ } catch (e) {
10331
+ return null;
10323
10332
  }
10324
- return "";
10325
10333
  }
10326
- function getCookieName(scheduler3) {
10327
- return (scheduler3._obj.id || "scheduler") + "_settings";
10334
+ function safeLocalStorageSet(key, value) {
10335
+ try {
10336
+ window.localStorage.setItem(key, value);
10337
+ return true;
10338
+ } catch (e) {
10339
+ return false;
10340
+ }
10328
10341
  }
10329
- var first = true;
10330
- scheduler2.attachEvent("onBeforeViewChange", function(oldMode, oldDate, mode, date) {
10331
- if (first && scheduler2._get_url_nav) {
10332
- var urlNavigationPlugin = scheduler2._get_url_nav();
10333
- if (urlNavigationPlugin.date || urlNavigationPlugin.mode || urlNavigationPlugin.event) {
10334
- first = false;
10342
+ function readStoredState() {
10343
+ const storageKey = getStorageKey();
10344
+ const raw = safeLocalStorageGet(storageKey);
10345
+ if (!raw) {
10346
+ return { date: null, mode: null };
10347
+ }
10348
+ let parsed;
10349
+ try {
10350
+ parsed = JSON.parse(raw);
10351
+ } catch (e) {
10352
+ return { date: null, mode: null };
10353
+ }
10354
+ if (!parsed || typeof parsed !== "object") {
10355
+ return { date: null, mode: null };
10356
+ }
10357
+ let parsedDate = null;
10358
+ if (typeof parsed.date === "string" && parsed.date.length > 0) {
10359
+ try {
10360
+ parsedDate = stringToDate(parsed.date);
10361
+ if (isNaN(+parsedDate)) {
10362
+ parsedDate = null;
10363
+ }
10364
+ } catch (e) {
10365
+ parsedDate = null;
10335
10366
  }
10336
10367
  }
10337
- var cookie2 = getCookieName(scheduler2);
10338
- if (first) {
10339
- first = false;
10340
- var schedulerCookie = getCookie(cookie2);
10341
- if (schedulerCookie) {
10342
- if (!scheduler2._min_date) {
10343
- scheduler2._min_date = date;
10368
+ const parsedMode = typeof parsed.mode === "string" ? parsed.mode : null;
10369
+ return { date: parsedDate, mode: parsedMode };
10370
+ }
10371
+ function urlHasExplicitNavigation() {
10372
+ if (!scheduler2._get_url_nav) {
10373
+ return false;
10374
+ }
10375
+ const urlState = scheduler2._get_url_nav();
10376
+ if (!urlState) {
10377
+ return false;
10378
+ }
10379
+ if (urlState.date || urlState.mode || urlState.event) {
10380
+ return true;
10381
+ }
10382
+ return false;
10383
+ }
10384
+ const originalGetInitialState = scheduler2._getInitialState;
10385
+ scheduler2._getInitialState = function(provided) {
10386
+ const baseState = originalGetInitialState.call(this, provided);
10387
+ if (urlHasExplicitNavigation()) {
10388
+ return baseState;
10389
+ }
10390
+ const storedState = readStoredState();
10391
+ const nextState = { date: baseState.date, mode: baseState.mode };
10392
+ if (storedState.date) {
10393
+ nextState.date = storedState.date;
10394
+ }
10395
+ if (storedState.mode) {
10396
+ try {
10397
+ if (this.isViewExists(storedState.mode)) {
10398
+ nextState.mode = storedState.mode;
10344
10399
  }
10345
- schedulerCookie = unescape(schedulerCookie).split("@");
10346
- schedulerCookie[0] = this._helpers.parseDate(schedulerCookie[0]);
10347
- var view = this.isViewExists(schedulerCookie[1]) ? schedulerCookie[1] : mode, date = !isNaN(+schedulerCookie[0]) ? schedulerCookie[0] : date;
10348
- window.setTimeout(function() {
10349
- if (scheduler2.$destroyed) {
10350
- return;
10351
- }
10352
- scheduler2.setCurrentView(date, view);
10353
- }, 1);
10354
- return false;
10400
+ } catch (e) {
10355
10401
  }
10356
10402
  }
10357
- return true;
10358
- });
10403
+ return nextState;
10404
+ };
10359
10405
  scheduler2.attachEvent("onViewChange", function(newMode, newDate) {
10360
- var cookie2 = getCookieName(scheduler2);
10361
- var text = escape(this._helpers.formatDate(newDate) + "@" + newMode);
10362
- setCookie(cookie2, "expires=Sun, 31 Jan 9999 22:00:00 GMT", text);
10406
+ const storageKey = getStorageKey();
10407
+ const payload = { date: dateToString(newDate), mode: newMode };
10408
+ safeLocalStorageSet(storageKey, JSON.stringify(payload));
10409
+ return true;
10363
10410
  });
10364
- var old_load = scheduler2._load;
10365
- scheduler2._load = function() {
10366
- var args = arguments;
10367
- if (!scheduler2._date) {
10368
- var that = this;
10369
- window.setTimeout(function() {
10370
- old_load.apply(that, args);
10371
- }, 1);
10372
- } else {
10373
- old_load.apply(this, args);
10374
- }
10375
- };
10376
10411
  }
10377
10412
  const notImplemented = { alert: (extension, assert2) => {
10378
10413
  assert2(false, `The ${extension} extension is not included in this version of dhtmlxScheduler.<br>
@@ -15438,41 +15473,39 @@ function quick_info(scheduler2) {
15438
15473
  scheduler2.hideQuickInfo();
15439
15474
  };
15440
15475
  scheduler2._init_quick_info = function() {
15441
- if (!this._quick_info_box) {
15442
- var qi = this._quick_info_box = document.createElement("div");
15443
- this._waiAria.quickInfoAttr(qi);
15444
- qi.className = "dhx_cal_quick_info";
15445
- if (scheduler2.$testmode)
15446
- qi.className += " dhx_no_animate";
15447
- if (scheduler2.config.rtl)
15448
- qi.className += " dhx_quick_info_rtl";
15449
- var ariaAttr = this._waiAria.quickInfoHeaderAttrString();
15450
- var html = `
15451
- <div class="dhx_cal_qi_tcontrols">
15452
- <a class="dhx_cal_qi_close_btn scheduler_icon close"></a>
15476
+ let qi = this._quick_info_box = document.createElement("div");
15477
+ this._waiAria.quickInfoAttr(qi);
15478
+ qi.className = "dhx_cal_quick_info";
15479
+ if (scheduler2.$testmode)
15480
+ qi.className += " dhx_no_animate";
15481
+ if (scheduler2.config.rtl)
15482
+ qi.className += " dhx_quick_info_rtl";
15483
+ let ariaAttr = this._waiAria.quickInfoHeaderAttrString();
15484
+ let html = `
15485
+ <div class="dhx_cal_qi_tcontrols">
15486
+ <a class="dhx_cal_qi_close_btn scheduler_icon close"></a>
15487
+ </div>
15488
+ <div class="dhx_cal_qi_title" ${ariaAttr}>
15489
+
15490
+ <div class="dhx_cal_qi_tcontent"></div>
15491
+ <div class="dhx_cal_qi_tdate"></div>
15453
15492
  </div>
15454
- <div class="dhx_cal_qi_title" ${ariaAttr}>
15455
-
15456
- <div class="dhx_cal_qi_tcontent"></div>
15457
- <div class="dhx_cal_qi_tdate"></div>
15458
- </div>
15459
- <div class="dhx_cal_qi_content"></div>`;
15460
- html += '<div class="dhx_cal_qi_controls">';
15461
- var buttons = scheduler2.config.icons_select;
15462
- for (var i = 0; i < buttons.length; i++) {
15463
- var ariaAttr = this._waiAria.quickInfoButtonAttrString(this.locale.labels[buttons[i]]);
15464
- html += `<div ${ariaAttr} class="dhx_qi_big_icon ${buttons[i]}" title="${scheduler2.locale.labels[buttons[i]]}">
15465
- <div class='dhx_menu_icon ${buttons[i]}'></div><div>${scheduler2.locale.labels[buttons[i]]}</div></div>`;
15466
- }
15467
- html += "</div>";
15468
- qi.innerHTML = html;
15469
- scheduler2.event(qi, "click", function(ev) {
15470
- scheduler2._qi_button_click(ev.target || ev.srcElement);
15471
- });
15472
- if (scheduler2.config.quick_info_detached) {
15473
- scheduler2._detachDomEvent(scheduler2._els["dhx_cal_data"][0], "scroll", scheduler2._quick_info_onscroll_handler);
15474
- scheduler2.event(scheduler2._els["dhx_cal_data"][0], "scroll", scheduler2._quick_info_onscroll_handler);
15475
- }
15493
+ <div class="dhx_cal_qi_content"></div>`;
15494
+ html += '<div class="dhx_cal_qi_controls">';
15495
+ let buttons = scheduler2.config.icons_select;
15496
+ for (let i = 0; i < buttons.length; i++) {
15497
+ let ariaAttr2 = this._waiAria.quickInfoButtonAttrString(this.locale.labels[buttons[i]]);
15498
+ html += `<div ${ariaAttr2} class="dhx_qi_big_icon ${buttons[i]}" title="${scheduler2.locale.labels[buttons[i]]}">
15499
+ <div class='dhx_menu_icon ${buttons[i]}'></div><div>${scheduler2.locale.labels[buttons[i]]}</div></div>`;
15500
+ }
15501
+ html += "</div>";
15502
+ qi.innerHTML = html;
15503
+ scheduler2.event(qi, "click", function(ev) {
15504
+ scheduler2._qi_button_click(ev.target || ev.srcElement);
15505
+ });
15506
+ if (scheduler2.config.quick_info_detached) {
15507
+ scheduler2._detachDomEvent(scheduler2._els["dhx_cal_data"][0], "scroll", scheduler2._quick_info_onscroll_handler);
15508
+ scheduler2.event(scheduler2._els["dhx_cal_data"][0], "scroll", scheduler2._quick_info_onscroll_handler);
15476
15509
  }
15477
15510
  return this._quick_info_box;
15478
15511
  };
@@ -18206,6 +18239,73 @@ function rdatesToString(param, rdates, tzid) {
18206
18239
  return "".concat(header).concat(dateString);
18207
18240
  }
18208
18241
  function recurring(scheduler2) {
18242
+ scheduler2.ext.recurring = { confirm: function(context) {
18243
+ }, confirmDefault: function showRecurringConfirmModal(context) {
18244
+ const labels = context.labels || {};
18245
+ const options = Array.isArray(context.options) ? context.options : [];
18246
+ if (options.length === 0) {
18247
+ return Promise.resolve(null);
18248
+ }
18249
+ if (options.length === 1) {
18250
+ return Promise.resolve(options[0]);
18251
+ }
18252
+ const modalOptions = options.map((decision, index) => ({ value: decision, label: labelForDecision(decision, labels), checked: index === 0 }));
18253
+ return new Promise((resolve) => {
18254
+ scheduler2.modalbox({ text: `<div class="dhx_edit_recurrence_options">
18255
+ ${modalOptions.map((option) => `<label class="dhx_styled_radio">
18256
+ <input type="radio" value="${option.value}" name="option" ${option.checked ? "checked" : ""}>
18257
+ ${option.label}
18258
+ </label>`).join("")}
18259
+ </div>`, type: "recurring_mode", title: labels.title || scheduler2.locale.labels.confirm_recurring, width: "auto", position: "middle", buttons: [{ label: labels.ok || scheduler2.locale.labels.message_ok, value: "ok", css: "rec_ok" }, { label: labels.cancel || scheduler2.locale.labels.message_cancel, value: "cancel" }], callback: function onModalClose(value, event2) {
18260
+ if (value === "cancel") {
18261
+ resolve(null);
18262
+ return;
18263
+ }
18264
+ const box = event2.target.closest(".scheduler_modal_box");
18265
+ const checked = box && box.querySelector("input[type='radio']:checked");
18266
+ const selected = checked ? checked.value : null;
18267
+ if (!selected) {
18268
+ resolve(null);
18269
+ return;
18270
+ }
18271
+ resolve(selected);
18272
+ } });
18273
+ });
18274
+ }, _getDecision: async function _getDecision(context) {
18275
+ const confirmHandler = scheduler2.ext.recurring.confirm;
18276
+ let decision;
18277
+ if (typeof confirmHandler === "function") {
18278
+ decision = await confirmHandler(context);
18279
+ } else {
18280
+ decision = void 0;
18281
+ }
18282
+ if (decision === void 0) {
18283
+ decision = await scheduler2.ext.recurring.confirmDefault(context);
18284
+ }
18285
+ if (decision === null) {
18286
+ return null;
18287
+ }
18288
+ if (context.options && context.options.length > 0) {
18289
+ if (context.options.indexOf(decision) === -1) {
18290
+ console.warning(`[recurring extension] - the custom confirm handler returned a value ("${decision}") which is not in the allowed options list. The allowed options are: [${context.options.join(", ")}]. The operation will be cancelled.`);
18291
+ return null;
18292
+ }
18293
+ }
18294
+ return decision;
18295
+ } };
18296
+ scheduler2.ext.recurring.confirm = scheduler2.ext.recurring.confirmDefault;
18297
+ function labelForDecision(decision, labels) {
18298
+ if (decision === "occurrence") {
18299
+ return labels.occurrence || scheduler2.locale.labels.button_edit_occurrence;
18300
+ }
18301
+ if (decision === "following") {
18302
+ return labels.following || scheduler2.locale.labels.button_edit_occurrence_and_following;
18303
+ }
18304
+ if (decision === "series") {
18305
+ return labels.series || scheduler2.locale.labels.button_edit_series;
18306
+ }
18307
+ return decision;
18308
+ }
18209
18309
  function clearMilliseconds(date) {
18210
18310
  return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), 0);
18211
18311
  }
@@ -18245,10 +18345,14 @@ function recurring(scheduler2) {
18245
18345
  if (ev.rrule.includes(";UNTIL=")) {
18246
18346
  ev.rrule = ev.rrule.split(";UNTIL=")[0];
18247
18347
  }
18248
- let parsedRRule = rrulestr(`RRULE:${ev.rrule};UNTIL=${toIcalString(setUTCPartsToDate(ev._end_date || ev.end_date))}`, { dtstart: ev.start_date });
18249
- let newRRULE = new RRule(parsedRRule.origOptions).toString().replace("RRULE:", "");
18250
- newRRULE = newRRULE.split("\n")[1];
18251
- ev.rrule = newRRULE;
18348
+ let parsedRRule;
18349
+ if (ev.rrule.includes(";COUNT=")) {
18350
+ parsedRRule = rrulestr(`RRULE:${ev.rrule};UNTIL=${toIcalString(setUTCPartsToDate(ev._shorten_end_date))}`, { dtstart: ev.start_date });
18351
+ delete parsedRRule.origOptions.count;
18352
+ } else {
18353
+ parsedRRule = rrulestr(`RRULE:${ev.rrule};UNTIL=${toIcalString(setUTCPartsToDate(ev._end_date || ev.end_date))}`, { dtstart: ev.start_date });
18354
+ }
18355
+ ev.rrule = new RRule(parsedRRule.origOptions).toString().replace("RRULE:", "").split("\n")[1];
18252
18356
  }
18253
18357
  function updateFollowingRRULE(id, ev) {
18254
18358
  if (!ev) {
@@ -18256,6 +18360,7 @@ function recurring(scheduler2) {
18256
18360
  }
18257
18361
  let rruleStringparts = ev.rrule.split(";");
18258
18362
  let updatedRRULE = [];
18363
+ let interval;
18259
18364
  for (let i = 0; i < rruleStringparts.length; i++) {
18260
18365
  let splited = rruleStringparts[i].split("=");
18261
18366
  let code = splited[0];
@@ -18272,6 +18377,17 @@ function recurring(scheduler2) {
18272
18377
  ev._end_date = ev.end_date;
18273
18378
  }
18274
18379
  }
18380
+ if (code === "INTERVAL") {
18381
+ interval = Number(name);
18382
+ }
18383
+ if (code === "COUNT") {
18384
+ if (ev._shorten_end_date) {
18385
+ const start = scheduler2.date.date_part(new Date(ev._start_date));
18386
+ const end = scheduler2.date.date_part(new Date(ev._shorten_end_date));
18387
+ const days = Math.floor((end - start) / (1e3 * 60 * 60 * 24 * interval)) + 1;
18388
+ name = name - days;
18389
+ }
18390
+ }
18275
18391
  updatedRRULE.push(code);
18276
18392
  updatedRRULE.push("=");
18277
18393
  updatedRRULE.push(name);
@@ -18411,8 +18527,10 @@ function recurring(scheduler2) {
18411
18527
  for (let i in scheduler2._events) {
18412
18528
  let tev = scheduler2._events[i];
18413
18529
  if (tev.recurring_event_id == id || scheduler2._is_virtual_event(tev.id) && tev.id.split("#")[0] == id) {
18414
- tev.text = data.text;
18415
- scheduler2.updateEvent(tev.id);
18530
+ if (tev.start_date.valueOf() >= data.start_date.valueOf()) {
18531
+ tev.text = data.text;
18532
+ scheduler2.updateEvent(tev.id);
18533
+ }
18416
18534
  }
18417
18535
  }
18418
18536
  }
@@ -18530,7 +18648,7 @@ function recurring(scheduler2) {
18530
18648
  scheduler2.attachEvent("onRecurringEventSave", function(id, data, is_new_event) {
18531
18649
  let ev = this.getEvent(id);
18532
18650
  let tempEvent = scheduler2._lame_clone(ev);
18533
- let tempDataRRULE = data.rrule;
18651
+ let tempData = scheduler2._lame_clone(data);
18534
18652
  if (ev && isSeries(ev)) {
18535
18653
  if (!is_new_event && this._isFollowing(id)) {
18536
18654
  if (ev._removeFollowing) {
@@ -18586,10 +18704,8 @@ function recurring(scheduler2) {
18586
18704
  ev._shorten = true;
18587
18705
  updateFollowingRRULEOnSave(ev);
18588
18706
  scheduler2.callEvent("onEventChanged", [ev.id, ev]);
18589
- let followingEv = { ...tempEvent };
18590
- followingEv.text = data.text;
18591
- followingEv.duration = data.duration;
18592
- followingEv.rrule = tempDataRRULE;
18707
+ let followingEv = { ...tempData };
18708
+ followingEv._end_date = tempEvent._end_date;
18593
18709
  followingEv._start_date = null;
18594
18710
  followingEv.id = scheduler2.uid();
18595
18711
  scheduler2.addEvent(followingEv.start_date, followingEv.end_date, followingEv.text, followingEv.id, followingEv);
@@ -18757,43 +18873,28 @@ function recurring(scheduler2) {
18757
18873
  return this.showLightbox_rec(id);
18758
18874
  }
18759
18875
  if (formSetting === "ask") {
18760
- const locale2 = scheduler2.locale;
18761
- showModalbox([{ value: "Occurrence", label: locale2.labels.button_edit_occurrence, checked: true, callback: () => showRequiredLightbox(id, "Occurrence") }, { value: "Following", label: locale2.labels.button_edit_occurrence_and_following, callback: () => showRequiredLightbox(id, "Following") }, { value: "AllEvents", label: locale2.labels.button_edit_series, callback: () => showRequiredLightbox(id, "AllEvents") }]);
18762
- }
18763
- };
18764
- function showModalbox(options, callback) {
18765
- const locale = scheduler2.locale;
18766
- const haveChecked = options.find((o) => o.checked);
18767
- if (!haveChecked) {
18768
- options[0].checked = true;
18876
+ showRecurringScopeConfirmForLightbox(id, pid);
18769
18877
  }
18770
- const callbacks = options.reduce((result, o) => {
18771
- result[o.value] = o.callback;
18772
- return result;
18773
- }, {});
18774
- scheduler2.modalbox({ text: `<div class="dhx_edit_recurrence_options">
18775
- ${options.map((option) => `<label class="dhx_styled_radio">
18776
- <input type="radio" value="${option.value}" name="option" ${option.checked ? "checked" : ""}>
18777
- ${option.label}
18778
- </label>`).join("")}
18779
- </div>`, type: "recurring_mode", title: locale.labels.confirm_recurring, width: "auto", position: "middle", buttons: [{ label: locale.labels.message_ok, value: "ok", css: "rec_ok" }, { label: locale.labels.message_cancel, value: "cancel" }], callback: function(value, e) {
18780
- if (callback) {
18781
- callback(value, e);
18782
- }
18783
- if (value === "cancel") {
18878
+ async function showRecurringScopeConfirmForLightbox(id2, pid2) {
18879
+ const locale2 = scheduler2.locale;
18880
+ const occurrence = scheduler2.getEvent(id2);
18881
+ const seriesEvent = scheduler2.getEvent(pid2);
18882
+ const context = { origin: "lightbox", occurrence, series: seriesEvent, labels: { title: locale2.labels.confirm_recurring, ok: locale2.labels.message_ok, cancel: locale2.labels.message_cancel, occurrence: locale2.labels.button_edit_occurrence, following: locale2.labels.button_edit_occurrence_and_following, series: locale2.labels.button_edit_series }, options: ["occurrence", "following", "series"] };
18883
+ const decision = await scheduler2.ext.recurring._getDecision(context);
18884
+ if (decision === null) {
18784
18885
  return;
18785
18886
  }
18786
- const box = e.target.closest(".scheduler_modal_box");
18787
- const checked = box.querySelector("input[type='radio']:checked");
18788
- let selectedOption;
18789
- if (checked) {
18790
- selectedOption = checked.value;
18887
+ if (decision === "occurrence") {
18888
+ return showRequiredLightbox(id2, "Occurrence");
18791
18889
  }
18792
- if (selectedOption) {
18793
- callbacks[selectedOption]();
18890
+ if (decision === "following") {
18891
+ return showRequiredLightbox(id2, "Following");
18794
18892
  }
18795
- } });
18796
- }
18893
+ if (decision === "series") {
18894
+ return showRequiredLightbox(id2, "AllEvents");
18895
+ }
18896
+ }
18897
+ };
18797
18898
  scheduler2._showRequiredModalBox = function(id, type) {
18798
18899
  let buttons;
18799
18900
  const locale = scheduler2.locale;
@@ -18915,17 +19016,30 @@ function recurring(scheduler2) {
18915
19016
  }
18916
19017
  }
18917
19018
  };
18918
- const btnAll = { value: "AllEvents", label: locale.labels.button_edit_series, callback: () => handleAllEvents(occurrence) };
18919
- const btnFollowing = { value: "Following", label: locale.labels.button_edit_occurrence_and_following, callback: () => handleFollowing(occurrence) };
18920
- const btnOccurrence = { value: "Occurrence", label: locale.labels.button_edit_occurrence, callback: () => handleOccurrence(occurrence), checked: true };
18921
19019
  if (type === "ask") {
18922
- buttons = [btnOccurrence, btnFollowing, btnAll];
19020
+ buttons = ["occurrence", "following", "series"];
18923
19021
  } else {
18924
- buttons = [btnOccurrence, btnFollowing];
19022
+ buttons = ["occurrence", "following"];
18925
19023
  }
18926
- showModalbox(buttons, (result) => {
18927
- if (result === "cancel") {
19024
+ const context = { origin: "dnd", occurrence, series: event2, labels: { title: locale.labels.confirm_recurring, ok: locale.labels.message_ok, cancel: locale.labels.message_cancel, occurrence: locale.labels.button_edit_occurrence, following: locale.labels.button_edit_occurrence_and_following, series: locale.labels.button_edit_series }, options: buttons };
19025
+ Promise.resolve(scheduler2.ext.recurring._getDecision(context)).then((decision) => {
19026
+ if (!decision) {
18928
19027
  removeTempDraggedEvent();
19028
+ return;
19029
+ }
19030
+ switch (decision) {
19031
+ case "occurrence":
19032
+ handleOccurrence(occurrence);
19033
+ break;
19034
+ case "following":
19035
+ handleFollowing(occurrence);
19036
+ break;
19037
+ case "series":
19038
+ handleAllEvents(occurrence);
19039
+ break;
19040
+ default:
19041
+ removeTempDraggedEvent();
19042
+ return;
18929
19043
  }
18930
19044
  });
18931
19045
  };
@@ -20977,73 +21091,103 @@ function units_restricted(scheduler2) {
20977
21091
  notImplemented.alert("Units", scheduler2.assert);
20978
21092
  }
20979
21093
  function url(scheduler2) {
20980
- scheduler2._get_url_nav = function() {
20981
- var p = {};
20982
- var data = (document.location.hash || "").replace("#", "").split(",");
20983
- for (var i = 0; i < data.length; i++) {
20984
- var s = data[i].split("=");
20985
- if (s.length == 2)
20986
- p[s[0]] = s[1];
21094
+ function parseHashParameters() {
21095
+ const parameters = {};
21096
+ const raw = (document.location.hash || "").replace("#", "");
21097
+ if (!raw) {
21098
+ return parameters;
21099
+ }
21100
+ const pairs = raw.split(",");
21101
+ for (let i = 0; i < pairs.length; i++) {
21102
+ const parts = pairs[i].split("=");
21103
+ if (parts.length === 2) {
21104
+ parameters[parts[0]] = parts[1];
21105
+ }
20987
21106
  }
20988
- return p;
21107
+ return parameters;
21108
+ }
21109
+ scheduler2._get_url_nav = function() {
21110
+ return parseHashParameters();
20989
21111
  };
20990
- scheduler2.attachEvent("onTemplatesReady", function() {
20991
- var first = true;
20992
- var s2d = scheduler2.date.str_to_date("%Y-%m-%d");
20993
- var d2s = scheduler2.date.date_to_str("%Y-%m-%d");
20994
- var select_event = scheduler2._get_url_nav().event || null;
20995
- scheduler2.attachEvent("onAfterEventDisplay", function(ev) {
20996
- select_event = null;
20997
- return true;
20998
- });
20999
- scheduler2.attachEvent("onBeforeViewChange", function(om, od, m, d) {
21000
- if (first) {
21001
- first = false;
21002
- var p = scheduler2._get_url_nav();
21003
- if (p.event) {
21004
- try {
21005
- if (scheduler2.getEvent(p.event)) {
21006
- setTimeout(function() {
21007
- showEvent(p.event);
21008
- });
21009
- return false;
21010
- } else {
21011
- var handler = scheduler2.attachEvent("onXLE", function() {
21012
- setTimeout(function() {
21013
- showEvent(p.event);
21014
- });
21015
- scheduler2.detachEvent(handler);
21016
- });
21017
- }
21018
- } catch (e) {
21019
- }
21020
- }
21021
- if (p.date || p.mode) {
21022
- try {
21023
- this.setCurrentView(p.date ? s2d(p.date) : null, p.mode || null);
21024
- } catch (e) {
21025
- this.setCurrentView(p.date ? s2d(p.date) : null, m);
21026
- }
21027
- return false;
21112
+ const dateToString = scheduler2.date.date_to_str("%Y-%m-%d");
21113
+ const originalGetInitialState = scheduler2._getInitialState;
21114
+ scheduler2._getInitialState = function(provided) {
21115
+ const baseState = originalGetInitialState.call(this, provided);
21116
+ const url2 = scheduler2._get_url_nav ? scheduler2._get_url_nav() : null;
21117
+ if (!url2) {
21118
+ return baseState;
21119
+ }
21120
+ const nextState = { date: baseState.date, mode: baseState.mode };
21121
+ if (url2.date) {
21122
+ const stringToDate = scheduler2.date.str_to_date("%Y-%m-%d");
21123
+ try {
21124
+ const parsed = stringToDate(url2.date);
21125
+ if (!isNaN(+parsed)) {
21126
+ nextState.date = parsed;
21028
21127
  }
21128
+ } catch (e) {
21029
21129
  }
21030
- var values = ["date=" + d2s(d || od), "mode=" + (m || om)];
21031
- if (select_event) {
21032
- values.push("event=" + select_event);
21130
+ }
21131
+ if (url2.mode) {
21132
+ try {
21133
+ if (this.isViewExists(url2.mode)) {
21134
+ nextState.mode = url2.mode;
21135
+ }
21136
+ } catch (e) {
21033
21137
  }
21034
- var text = "#" + values.join(",");
21035
- document.location.hash = text;
21036
- return true;
21037
- });
21038
- function showEvent(e) {
21138
+ }
21139
+ return nextState;
21140
+ };
21141
+ function updateHashFromState(optionalSelectedEventId) {
21142
+ const currentDate = scheduler2._date || scheduler2.getState().date;
21143
+ const currentMode = scheduler2.getState().mode;
21144
+ const values = ["date=" + dateToString(currentDate), "mode=" + currentMode];
21145
+ if (optionalSelectedEventId) {
21146
+ values.push("event=" + optionalSelectedEventId);
21147
+ }
21148
+ document.location.hash = "#" + values.join(",");
21149
+ }
21150
+ function showEventWhenPossible(eventId) {
21151
+ if (!eventId) {
21152
+ return;
21153
+ }
21154
+ const tryShowNow = function() {
21039
21155
  if (scheduler2.$destroyed) {
21040
- return true;
21156
+ return;
21041
21157
  }
21042
- select_event = e;
21043
- if (scheduler2.getEvent(e)) {
21044
- scheduler2.showEvent(e);
21158
+ if (scheduler2.getEvent(eventId)) {
21159
+ scheduler2.showEvent(eventId);
21160
+ return true;
21045
21161
  }
21162
+ return false;
21163
+ };
21164
+ if (tryShowNow()) {
21165
+ return;
21046
21166
  }
21167
+ const onLoadedId = scheduler2.attachEvent("onParse", function() {
21168
+ tryShowNow();
21169
+ scheduler2.detachEvent(onLoadedId);
21170
+ return true;
21171
+ });
21172
+ }
21173
+ let pendingSelectedEventId = null;
21174
+ scheduler2.attachEvent("onSchedulerReady", function() {
21175
+ const initialState = scheduler2._get_url_nav();
21176
+ if (initialState.event) {
21177
+ pendingSelectedEventId = initialState.event;
21178
+ showEventWhenPossible(initialState.event);
21179
+ }
21180
+ updateHashFromState(pendingSelectedEventId);
21181
+ return true;
21182
+ });
21183
+ scheduler2.attachEvent("onAfterEventDisplay", function() {
21184
+ pendingSelectedEventId = null;
21185
+ updateHashFromState(null);
21186
+ return true;
21187
+ });
21188
+ scheduler2.attachEvent("onViewChange", function() {
21189
+ updateHashFromState(pendingSelectedEventId);
21190
+ return true;
21047
21191
  });
21048
21192
  }
21049
21193
  function week_agenda_restricted(scheduler2) {