UNPKG

dhtmlx-scheduler

Version:

JavaScript event calendar. Allows to manage events and appointments in different views

1,254 lines (1,249 loc) 958 kB
(function(global2, factory) { typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, factory(global2.dhtmlxscheduler = {})); })(this, function(exports2) { "use strict";/** @license dhtmlxScheduler v.7.2.5 Standard 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 (c) XB Software Ltd. */ function dhtmlxHook() { if (typeof dhtmlx != "undefined" && dhtmlx.attaches) { dhtmlx.attaches.attachScheduler = function(day, mode, tabs, scheduler2) { var tabs = tabs || '<div class="dhx_cal_tab" name="day_tab" data-tab="day" style="right:204px;"></div><div class="dhx_cal_tab" name="week_tab" data-tab="week" style="right:140px;"></div><div class="dhx_cal_tab" name="month_tab" data-tab="month" style="right:76px;"></div>'; var obj = document.createElement("DIV"); obj.id = "dhxSchedObj_" + this._genStr(12); obj.innerHTML = '<div id="' + obj.id + '" class="dhx_cal_container" style="width:100%; height:100%;"><div class="dhx_cal_navline"><div class="dhx_cal_prev_button"></div><div class="dhx_cal_next_button"></div><div class="dhx_cal_today_button"></div><div class="dhx_cal_date"></div>' + tabs + '</div><div class="dhx_cal_header"></div><div class="dhx_cal_data"></div></div>'; document.body.appendChild(obj.firstChild); this.attachObject(obj.id, false, true); this.vs[this.av].sched = scheduler2; this.vs[this.av].schedId = obj.id; scheduler2.setSizes = scheduler2.updateView; scheduler2.destructor = function() { }; scheduler2.init(obj.id, day, mode); return this.vs[this._viewRestore()].sched; }; } } const theme = ""; var globalScope; if (typeof window !== "undefined") { globalScope = window; } else { globalScope = global; } const global$1 = globalScope; function dragHighlightPos(scheduler2) { let dndMarkers = []; let dragStarted = false; let eventNode = null; let event2 = null; function isEnabled2() { return scheduler2.config.drag_highlight && scheduler2.markTimespan; } function checkViewName(viewName) { const viewObj = scheduler2.getView(viewName); if (viewObj) { return viewObj.layout; } return viewName; } function checkSectionPropertyName(viewName) { const viewObj = scheduler2.getView(viewName); if (viewObj.y_property) { return viewObj.y_property; } if (viewObj.map_to) { return viewObj.map_to; } } function setRequiredStylesToMarker(eventNode2, layout) { switch (layout) { case "month": eventNode2.style.top = ""; eventNode2.style.left = ""; break; case "timeline": eventNode2.style.left = ""; eventNode2.style.marginLeft = "1px"; break; default: eventNode2.style.top = ""; break; } } function createMarkerConfig(configSettings) { const { event: event3, layout, viewName, sectionId, eventNode: eventNode2 } = configSettings; setRequiredStylesToMarker(eventNode2, layout); const sections = {}; let markerObject = { start_date: event3.start_date, end_date: event3.end_date, css: "dhx_scheduler_dnd_marker", html: eventNode2 }; if (layout == "timeline") { const viewObj = scheduler2.getView(viewName); if (viewObj.round_position) { const index = scheduler2._get_date_index(viewObj, event3.start_date); const rounded_date = viewObj._trace_x[index]; markerObject.start_date = rounded_date; } } if (layout == "timeline" || layout == "month") { markerObject = { ...markerObject, end_date: scheduler2.date.add(event3.start_date, 1, "minute") }; } if (sectionId) { sections[viewName] = sectionId; markerObject.sections = sections; } return markerObject; } function createViewMarker(settings) { const { layout } = settings; let markerConfigs; switch (layout) { case "month": markerConfigs = getMonthViewMarkers(settings); break; case "timeline": case "units": markerConfigs = getTimelineAndUnitsViewMarkers(settings); break; default: markerConfigs = getColumnViewMarkers(settings); break; } markerConfigs.forEach((cfg) => { dndMarkers.push(scheduler2.markTimespan(cfg)); }); } function getColumnViewMarkers(settings) { const { event: event3, layout, viewName, sectionId } = settings; let columnViewMarkersArray = []; let eventNodes = scheduler2.$container.querySelectorAll(`[${scheduler2.config.event_attribute}='${event3.id}']:not(.dhx_cal_select_menu):not(.dhx_drag_marker)`); if (eventNodes) { for (let i = 0; i < eventNodes.length; i++) { let eventNodeClone = eventNodes[i].cloneNode(true); let startDate = /* @__PURE__ */ new Date(+eventNodeClone.getAttribute("data-bar-start")); let endDate = /* @__PURE__ */ new Date(+eventNodeClone.getAttribute("data-bar-end")); let dates = { start_date: startDate, end_date: endDate }; const configSettings = { event: dates, layout, viewName, sectionId, eventNode: eventNodeClone }; columnViewMarkersArray.push(createMarkerConfig(configSettings)); } } return columnViewMarkersArray; } function getMonthViewMarkers(settings) { let monthViewMarkersArray = []; const { event: event3, layout, viewName, sectionId } = settings; const weekDates = []; let currDate = new Date(event3.start_date); while (currDate.valueOf() < event3.end_date.valueOf()) { let obj = { start_date: currDate }; weekDates.push(obj); currDate = scheduler2.date.week_start(scheduler2.date.add(currDate, 1, "week")); } let cells = scheduler2.$container.querySelectorAll(`[${scheduler2.config.event_attribute}='${event3.id}']`); for (let i = 0; i < cells.length; i++) { const configSettings = { event: weekDates[i], layout, viewName, sectionId, eventNode: cells[i].cloneNode(true) }; monthViewMarkersArray.push(createMarkerConfig(configSettings)); } return monthViewMarkersArray; } function getTimelineAndUnitsViewMarkers(settings) { let unitMarkersArray = []; const { event: event3, layout, viewName, eventNode: eventNode2 } = settings; let sectionPropertyName = checkSectionPropertyName(viewName); if (sectionPropertyName) { const sections = String(event3[sectionPropertyName]).split(scheduler2.config.section_delimiter); const formatedSections = sections.map((element) => String(element)); const elems = []; for (let i = 0; i < formatedSections.length; i++) { elems[i] = eventNode2.cloneNode(true); const configSettings = { event: event3, layout, viewName, sectionId: formatedSections[i], eventNode: elems[i] }; unitMarkersArray.push(createMarkerConfig(configSettings)); } } return unitMarkersArray; } scheduler2.attachEvent("onBeforeDrag", function(id2, mode, e) { if (isEnabled2()) { dragStarted = true; event2 = scheduler2.getEvent(id2); eventNode = e.target.closest(`[${scheduler2.config.event_attribute}]`); const viewName = scheduler2.getState().mode; const layout = checkViewName(viewName); if (layout == "units" && scheduler2.config.cascade_event_display) { scheduler2.unselect(id2); eventNode = e.target.closest(`[${scheduler2.config.event_attribute}]`); } } return true; }); scheduler2.attachEvent("onEventDrag", function(id2, mode, e) { if (dragStarted && isEnabled2()) { dragStarted = false; const viewName = scheduler2.getState().mode; const layout = checkViewName(viewName); const sectionId = scheduler2.getActionData(e).section; if (event2) { const settings = { event: event2, layout, viewName, sectionId, eventNode }; createViewMarker(settings); } } }); scheduler2.attachEvent("onDragEnd", function(id2, mode, e) { for (let i = 0; i < dndMarkers.length; i++) { scheduler2.unmarkTimespan(dndMarkers[i]); } dndMarkers = []; eventNode = null; event2 = null; }); } function undoDelete(scheduler2) { const undoableDeletes = {}; scheduler2.attachEvent("onConfirmedBeforeEventDelete", function(id2) { undoableDeletes[id2] = true; return true; }); scheduler2.attachEvent("onEventDeleted", function(id2, ev) { if (undoableDeletes[id2]) { delete undoableDeletes[id2]; } else { return; } let deletedEvent = scheduler2.copy(ev); if (scheduler2.config.undo_deleted && !scheduler2.getState().new_event) { scheduler2.message({ text: `<div class="dhx_info_message"> <span class="undo_popup_text">Event deleted</span> <button class="undo_button" data-deleted-event-id="${ev.id}">Undo</button> </div>`, expire: 1e4, type: "popup_after_delete", callback: function(e) { let undoBtn = e.target.closest(`[data-deleted-event-id="${ev.id}"]`); if (undoBtn) { if (deletedEvent.rrule && deletedEvent.duration) { deletedEvent.end_date = new Date(deletedEvent.start_date.valueOf() + deletedEvent.duration * 1e3); scheduler2.addEvent(deletedEvent); } scheduler2.addEvent(deletedEvent); scheduler2.render(); } } }); } }); } function limitPlugin(scheduler2) { scheduler2.config.mark_now = true; scheduler2.config.display_marked_timespans = true; scheduler2.config.overwrite_marked_timespans = true; var dhx_time_block = "dhx_time_block"; var default_timespan_type = "default"; var fix_options = function(options, days, zones) { if (days instanceof Date && zones instanceof Date) { options.start_date = days; options.end_date = zones; } else { options.days = days; options.zones = zones; } return options; }; var get_resulting_options = function(days, zones, sections) { var options = typeof days == "object" ? days : { days }; options.type = dhx_time_block; options.css = ""; if (zones) { if (sections) options.sections = sections; options = fix_options(options, days, zones); } return options; }; scheduler2.blockTime = function(days, zones, sections) { var options = get_resulting_options(days, zones, sections); return scheduler2.addMarkedTimespan(options); }; scheduler2.unblockTime = function(days, zones, sections) { zones = zones || "fullday"; var options = get_resulting_options(days, zones, sections); return scheduler2.deleteMarkedTimespan(options); }; scheduler2.checkInMarkedTimespan = function(ev, timespan_type, on_overlap) { timespan_type = timespan_type || default_timespan_type; var res = true; var temp_start_date = new Date(ev.start_date.valueOf()); var temp_end_date = scheduler2.date.add(temp_start_date, 1, "day"); var timespans = scheduler2._marked_timespans; for (; temp_start_date < ev.end_date; temp_start_date = scheduler2.date.date_part(temp_end_date), temp_end_date = scheduler2.date.add(temp_start_date, 1, "day")) { var day_value = +scheduler2.date.date_part(new Date(temp_start_date)); var day_index = temp_start_date.getDay(); var zones = getZones(ev, timespans, day_index, day_value, timespan_type); if (zones) { for (var i = 0; i < zones.length; i += 2) { var eventStart = scheduler2._get_zone_minutes(temp_start_date); var eventEnd = ev.end_date > temp_end_date || ev.end_date.getDate() != temp_start_date.getDate() ? 1440 : scheduler2._get_zone_minutes(ev.end_date); var markerStart = zones[i]; var markerEnd = zones[i + 1]; if (markerStart < eventEnd && markerEnd > eventStart) { if (typeof on_overlap == "function") { res = on_overlap(ev, eventStart, eventEnd, markerStart, markerEnd); } else { res = false; } if (!res) break; } } } } return !res; }; scheduler2.checkLimitViolation = function(event2) { if (!event2) return true; if (!scheduler2.config.check_limits) return true; var s = scheduler2; var c = s.config; var evs = []; if (event2.rec_type && event2._end_date || event2.rrule) { const seriesEnd = event2._end_date || event2.end_date; if (c.limit_start && c.limit_end) { var recEventInLimits = seriesEnd.valueOf() >= c.limit_start.valueOf() && event2.start_date.valueOf() <= c.limit_end.valueOf(); return recEventInLimits; } else return true; } else { evs = [event2]; } var complete_res = true; for (var p = 0; p < evs.length; p++) { var res = true; var ev = evs[p]; ev._timed = scheduler2.isOneDayEvent(ev); res = c.limit_start && c.limit_end ? ev.start_date.valueOf() >= c.limit_start.valueOf() && ev.end_date.valueOf() <= c.limit_end.valueOf() : true; if (res) { res = !scheduler2.checkInMarkedTimespan(ev, dhx_time_block, function(event3, eventStart, eventEnd, markerStart, markerEnd) { var allow = true; if (eventStart <= markerEnd && eventStart >= markerStart) { if (markerEnd == 24 * 60 || eventEnd <= markerEnd) { allow = false; } if (event3._timed && s._drag_id && s._drag_mode == "new-size") { event3.start_date.setHours(0); event3.start_date.setMinutes(markerEnd); } else { allow = false; } } if (eventEnd >= markerStart && eventEnd <= markerEnd || eventStart < markerStart && eventEnd > markerEnd) { if (event3._timed && s._drag_id && s._drag_mode == "new-size") { event3.end_date.setHours(0); event3.end_date.setMinutes(markerStart); } else { allow = false; } } return allow; }); } if (!res) { res = s.checkEvent("onLimitViolation") ? s.callEvent("onLimitViolation", [ev.id, ev]) : res; } complete_res = complete_res && res; } if (!complete_res) { s._drag_id = null; s._drag_mode = null; } return complete_res; }; scheduler2._get_blocked_zones = function(timespans, property, day_index, day_value, timespan_type) { var zones = []; if (timespans && timespans[property]) { var timeline_zones = timespans[property]; var blocked_timeline_zones = this._get_relevant_blocked_zones(day_index, day_value, timeline_zones, timespan_type); for (var i = 0; i < blocked_timeline_zones.length; i++) { zones = this._add_timespan_zones(zones, blocked_timeline_zones[i].zones); } } return zones; }; scheduler2._get_relevant_blocked_zones = function(day_index, day_value, zones, timespan_type) { var resultZones; if (scheduler2.config.overwrite_marked_timespans) { resultZones = zones[day_value] && zones[day_value][timespan_type] ? zones[day_value][timespan_type] : zones[day_index] && zones[day_index][timespan_type] ? zones[day_index][timespan_type] : []; } else { resultZones = []; if (zones[day_value] && zones[day_value][timespan_type]) { resultZones = resultZones.concat(zones[day_value][timespan_type]); } if (zones[day_index] && zones[day_index][timespan_type]) { resultZones = resultZones.concat(zones[day_index][timespan_type]); } } return resultZones; }; function getZones(ev, timespans, day_index, day_value, timespan_type) { var s = scheduler2; var zones = []; var containers = { _props: "map_to", matrix: "y_property" }; for (var container in containers) { var property = containers[container]; if (s[container]) { for (var view in s[container]) { var view_config = s[container][view]; var linker = view_config[property]; if (!ev[linker]) continue; zones = s._add_timespan_zones(zones, scheduler2._get_blocked_zones(timespans[view], ev[linker], day_index, day_value, timespan_type)); } } } zones = s._add_timespan_zones(zones, scheduler2._get_blocked_zones(timespans, "global", day_index, day_value, timespan_type)); return zones; } scheduler2._mark_now = function(hide) { var dhx_now_time = "dhx_now_time"; if (!this._els[dhx_now_time]) { this._els[dhx_now_time] = []; } var now = scheduler2._currentDate(); var cfg = this.config; scheduler2._remove_mark_now(); if (!hide && cfg.mark_now && now < this._max_date && now > this._min_date && now.getHours() >= cfg.first_hour && now.getHours() < cfg.last_hour) { var day_index = this.locate_holder_day(now); this._els[dhx_now_time] = scheduler2._append_mark_now(day_index, now); } }; scheduler2._append_mark_now = function(day_index, now) { var dhx_now_time = "dhx_now_time"; var zone_start = scheduler2._get_zone_minutes(now); var options = { zones: [zone_start, zone_start + 1], css: dhx_now_time, type: dhx_now_time }; if (!this._table_view) { if (this._props && this._props[this._mode]) { var start_index, end_index; var view = this._props[this._mode]; var units_l = view.size || view.options.length; if (view.days > 1) { if (view.size && view.options.length) { day_index = (view.position + day_index) / view.options.length * view.size; } start_index = day_index; end_index = day_index + units_l; } else { start_index = 0; end_index = start_index + units_l; } var r_divs = []; for (var i = start_index; i < end_index; i++) { var t_day = i; options.days = t_day; var t_div = scheduler2._render_marked_timespan(options, null, t_day)[0]; r_divs.push(t_div); } return r_divs; } else { options.days = day_index; return scheduler2._render_marked_timespan(options, null, day_index); } } else { if (this._mode == "month") { options.days = +scheduler2.date.date_part(now); return scheduler2._render_marked_timespan(options, null, null); } } }; scheduler2._remove_mark_now = function() { var dhx_now_time = "dhx_now_time"; var els = this._els[dhx_now_time]; for (var i = 0; i < els.length; i++) { var div = els[i]; var parent = div.parentNode; if (parent) { parent.removeChild(div); } } this._els[dhx_now_time] = []; }; scheduler2._marked_timespans = { global: {} }; scheduler2._get_zone_minutes = function(date) { return date.getHours() * 60 + date.getMinutes(); }; scheduler2._prepare_timespan_options = function(config) { var r_configs = []; var temp_configs = []; if (config.days == "fullweek") config.days = [0, 1, 2, 3, 4, 5, 6]; if (config.days instanceof Array) { var t_days = config.days.slice(); for (var i = 0; i < t_days.length; i++) { var cloned_config = scheduler2._lame_clone(config); cloned_config.days = t_days[i]; r_configs.push.apply(r_configs, scheduler2._prepare_timespan_options(cloned_config)); } return r_configs; } if (!config || !(config.start_date && config.end_date && config.end_date > config.start_date || config.days !== void 0 && config.zones) && !config.type) return r_configs; var min = 0; var max = 24 * 60; if (config.zones == "fullday") config.zones = [min, max]; if (config.zones && config.invert_zones) { config.zones = scheduler2.invertZones(config.zones); } config.id = scheduler2.uid(); config.css = config.css || ""; config.type = config.type || default_timespan_type; var sections = config.sections; if (sections) { for (var view_key in sections) { if (sections.hasOwnProperty(view_key)) { var ids = sections[view_key]; if (!(ids instanceof Array)) ids = [ids]; for (var i = 0; i < ids.length; i++) { var t_config = scheduler2._lame_copy({}, config); t_config.sections = {}; t_config.sections[view_key] = ids[i]; temp_configs.push(t_config); } } } } else { temp_configs.push(config); } for (var k = 0; k < temp_configs.length; k++) { var c_config = temp_configs[k]; var start_date = c_config.start_date; var end_date = c_config.end_date; if (start_date && end_date) { var t_sd = scheduler2.date.date_part(new Date(start_date)); var t_ed = scheduler2.date.add(t_sd, 1, "day"); while (t_sd < end_date) { var t_config = scheduler2._lame_copy({}, c_config); delete t_config.start_date; delete t_config.end_date; t_config.days = t_sd.valueOf(); var zone_start = start_date > t_sd ? scheduler2._get_zone_minutes(start_date) : min; var zone_end = end_date > t_ed || end_date.getDate() != t_sd.getDate() ? max : scheduler2._get_zone_minutes(end_date); t_config.zones = [zone_start, zone_end]; r_configs.push(t_config); t_sd = t_ed; t_ed = scheduler2.date.add(t_ed, 1, "day"); } } else { if (c_config.days instanceof Date) c_config.days = scheduler2.date.date_part(c_config.days).valueOf(); c_config.zones = config.zones.slice(); r_configs.push(c_config); } } return r_configs; }; scheduler2._get_dates_by_index = function(index, start, end) { var dates = []; start = scheduler2.date.date_part(new Date(start || scheduler2._min_date)); end = new Date(end || scheduler2._max_date); var start_day = start.getDay(); var delta = index - start_day >= 0 ? index - start_day : 7 - start.getDay() + index; var t_date = scheduler2.date.add(start, delta, "day"); for (; t_date < end; t_date = scheduler2.date.add(t_date, 1, "week")) { dates.push(t_date); } return dates; }; scheduler2._get_css_classes_by_config = function(config) { var css_classes = []; if (config.type == dhx_time_block) { css_classes.push(dhx_time_block); if (config.css) css_classes.push(dhx_time_block + "_reset"); } css_classes.push("dhx_marked_timespan", config.css); return css_classes.join(" "); }; scheduler2._get_block_by_config = function(config) { var block = document.createElement("div"); if (config.html) { if (typeof config.html == "string") block.innerHTML = config.html; else block.appendChild(config.html); } return block; }; scheduler2._render_marked_timespan = function(options, area, day) { var blocks = []; var c = scheduler2.config; var min_date = this._min_date; var max_date = this._max_date; var day_value = false; if (!c.display_marked_timespans) return blocks; if (!day && day !== 0) { if (options.days < 7) day = options.days; else { var date_to_display = new Date(options.days); day_value = +date_to_display; if (!(+max_date > +date_to_display && +min_date <= +date_to_display)) return blocks; day = date_to_display.getDay(); } var min_day = min_date.getDay(); if (min_day > day) { day = 7 - (min_day - day); } else { day = day - min_day; } } var zones = options.zones; var css_classes = scheduler2._get_css_classes_by_config(options); if (scheduler2._table_view && scheduler2._mode == "month") { var areas = []; var days = []; if (!area) { days = day_value ? [day_value] : scheduler2._get_dates_by_index(day); for (var i = 0; i < days.length; i++) { areas.push(this._scales[days[i]]); } } else { areas.push(area); days.push(day); } for (var i = 0; i < areas.length; i++) { area = areas[i]; day = days[i]; var sday = this.locate_holder_day(day, false) % this._cols.length; if (this._ignores[sday]) continue; var block_proto = scheduler2._get_block_by_config(options); block_proto.className = css_classes; block_proto.style.top = "0px"; block_proto.style.height = "100%"; for (var k = 0; k < zones.length; k += 2) { var start = zones[i]; var end = zones[i + 1]; if (end <= start) return []; var block = block_proto.cloneNode(true); block.style.left = "0px"; block.style.width = "100%"; area.appendChild(block); blocks.push(block); } } } else { var index = day; if (this._ignores[this.locate_holder_day(day, false)]) return blocks; if (this._props && this._props[this._mode] && options.sections && options.sections[this._mode]) { var view = this._props[this._mode]; index = view.order[options.sections[this._mode]]; var inner_index = view.order[options.sections[this._mode]]; if (!(view.days > 1)) { index = inner_index; if (view.size && index > view.position + view.size) { index = 0; } } else { var units_l = view.size || view.options.length; index = index * units_l + inner_index; } } area = area ? area : scheduler2.locate_holder(index); for (var i = 0; i < zones.length; i += 2) { var start = Math.max(zones[i], c.first_hour * 60); var end = Math.min(zones[i + 1], c.last_hour * 60); if (end <= start) { if (i + 2 < zones.length) continue; else return []; } var block = scheduler2._get_block_by_config(options); block.className = css_classes; var all_hours_height = this.config.hour_size_px * 24 + 1; var hour_ms = 60 * 60 * 1e3; block.style.top = Math.round((start * 60 * 1e3 - this.config.first_hour * hour_ms) * this.config.hour_size_px / hour_ms) % all_hours_height + "px"; block.style.height = Math.max(Math.round((end - start) * 60 * 1e3 * this.config.hour_size_px / hour_ms) % all_hours_height, 1) + "px"; area.appendChild(block); blocks.push(block); } } return blocks; }; scheduler2._mark_timespans = function() { var data = this._els["dhx_cal_data"][0]; var divs = []; if (scheduler2._table_view && scheduler2._mode == "month") { for (var day in this._scales) { var date = /* @__PURE__ */ new Date(+day); divs.push.apply(divs, scheduler2._on_scale_add_marker(this._scales[day], date)); } } else { var date = new Date(scheduler2._min_date); for (var i = 0, len = data.childNodes.length; i < len; i++) { var area = data.childNodes[i]; if (area.firstChild && scheduler2._getClassName(area.firstChild).indexOf("dhx_scale_hour") > -1) { continue; } divs.push.apply(divs, scheduler2._on_scale_add_marker(area, date)); date = scheduler2.date.add(date, 1, "day"); } } return divs; }; scheduler2.markTimespan = function(configuration) { if (!this._els) { throw new Error("`scheduler.markTimespan` can't be used before scheduler initialization. Place `scheduler.markTimespan` call after `scheduler.init`."); } var rebuild_els = false; if (!this._els["dhx_cal_data"]) { scheduler2.get_elements(); rebuild_els = true; } var timespans_ids = scheduler2._marked_timespans_ids, timespan_types = scheduler2._marked_timespans_types, timespans = scheduler2._marked_timespans; scheduler2.deleteMarkedTimespan(); scheduler2.addMarkedTimespan(configuration); var divs = scheduler2._mark_timespans(); if (rebuild_els) scheduler2._els = []; scheduler2._marked_timespans_ids = timespans_ids; scheduler2._marked_timespans_types = timespan_types; scheduler2._marked_timespans = timespans; return divs; }; scheduler2.unmarkTimespan = function(divs) { if (!divs) return; for (var i = 0; i < divs.length; i++) { var div = divs[i]; if (div.parentNode) { div.parentNode.removeChild(div); } } }; scheduler2._addMarkerTimespanConfig = function(config) { var global2 = "global"; var timespans = scheduler2._marked_timespans; var id2 = config.id; var ids = scheduler2._marked_timespans_ids; if (!ids[id2]) ids[id2] = []; var day = config.days; var sections = config.sections; var type = config.type; config.id = id2; if (sections) { for (var view_key in sections) { if (sections.hasOwnProperty(view_key)) { if (!timespans[view_key]) timespans[view_key] = {}; var unit_id = sections[view_key]; var timespans_view = timespans[view_key]; if (!timespans_view[unit_id]) timespans_view[unit_id] = {}; if (!timespans_view[unit_id][day]) timespans_view[unit_id][day] = {}; if (!timespans_view[unit_id][day][type]) { timespans_view[unit_id][day][type] = []; if (!scheduler2._marked_timespans_types) scheduler2._marked_timespans_types = {}; if (!scheduler2._marked_timespans_types[type]) scheduler2._marked_timespans_types[type] = true; } var day_configs = timespans_view[unit_id][day][type]; config._array = day_configs; day_configs.push(config); ids[id2].push(config); } } } else { if (!timespans[global2][day]) timespans[global2][day] = {}; if (!timespans[global2][day][type]) timespans[global2][day][type] = []; if (!scheduler2._marked_timespans_types) scheduler2._marked_timespans_types = {}; if (!scheduler2._marked_timespans_types[type]) scheduler2._marked_timespans_types[type] = true; var day_configs = timespans[global2][day][type]; config._array = day_configs; day_configs.push(config); ids[id2].push(config); } }; scheduler2._marked_timespans_ids = {}; scheduler2.addMarkedTimespan = function(configuration) { var configs = scheduler2._prepare_timespan_options(configuration); if (!configs.length) return; var id2 = configs[0].id; for (var i = 0; i < configs.length; i++) { scheduler2._addMarkerTimespanConfig(configs[i]); } return id2; }; scheduler2._add_timespan_zones = function(current_zones, zones) { var resulting_zones = current_zones.slice(); zones = zones.slice(); if (!resulting_zones.length) return zones; for (var i = 0; i < resulting_zones.length; i += 2) { var c_zone_start = resulting_zones[i]; var c_zone_end = resulting_zones[i + 1]; var isLast = i + 2 == resulting_zones.length; for (var k = 0; k < zones.length; k += 2) { var zone_start = zones[k]; var zone_end = zones[k + 1]; if (zone_end > c_zone_end && zone_start <= c_zone_end || zone_start < c_zone_start && zone_end >= c_zone_start) { resulting_zones[i] = Math.min(c_zone_start, zone_start); resulting_zones[i + 1] = Math.max(c_zone_end, zone_end); i -= 2; } else { if (!isLast) continue; var offset = c_zone_start > zone_start ? 0 : 2; resulting_zones.splice(i + offset, 0, zone_start, zone_end); } zones.splice(k--, 2); break; } } return resulting_zones; }; scheduler2._subtract_timespan_zones = function(current_zones, zones) { var resulting_zones = current_zones.slice(); for (var i = 0; i < resulting_zones.length; i += 2) { var c_zone_start = resulting_zones[i]; var c_zone_end = resulting_zones[i + 1]; for (var k = 0; k < zones.length; k += 2) { var zone_start = zones[k]; var zone_end = zones[k + 1]; if (zone_end > c_zone_start && zone_start < c_zone_end) { var is_modified = false; if (c_zone_start >= zone_start && c_zone_end <= zone_end) { resulting_zones.splice(i, 2); } if (c_zone_start < zone_start) { resulting_zones.splice(i, 2, c_zone_start, zone_start); is_modified = true; } if (c_zone_end > zone_end) { resulting_zones.splice(is_modified ? i + 2 : i, is_modified ? 0 : 2, zone_end, c_zone_end); } i -= 2; break; } else { continue; } } } return resulting_zones; }; scheduler2.invertZones = function(zones) { return scheduler2._subtract_timespan_zones([0, 1440], zones.slice()); }; scheduler2._delete_marked_timespan_by_id = function(id2) { var configs = scheduler2._marked_timespans_ids[id2]; if (configs) { for (var i = 0; i < configs.length; i++) { var config = configs[i]; var parent_array = config._array; for (var k = 0; k < parent_array.length; k++) { if (parent_array[k] == config) { parent_array.splice(k, 1); break; } } } } }; scheduler2._delete_marked_timespan_by_config = function(config) { var timespans = scheduler2._marked_timespans; var sections = config.sections; var day = config.days; var type = config.type || default_timespan_type; var viewspans; if (sections) { for (var view_key in sections) { if (sections.hasOwnProperty(view_key) && timespans[view_key]) { var unit_id = sections[view_key]; if (timespans[view_key][unit_id]) { viewspans = timespans[view_key][unit_id]; } } } } else { viewspans = timespans.global; } if (viewspans) { if (day !== void 0) { if (viewspans[day] && viewspans[day][type]) { scheduler2._addMarkerTimespanConfig(config); scheduler2._delete_marked_timespans_list(viewspans[day][type], config); } } else { for (var d in viewspans) { if (viewspans[d][type]) { var dayConfig = scheduler2._lame_clone(config); config.days = d; scheduler2._addMarkerTimespanConfig(dayConfig); scheduler2._delete_marked_timespans_list(viewspans[d][type], config); } } } } }; scheduler2._delete_marked_timespans_list = function(day_timespans, config) { for (var i = 0; i < day_timespans.length; i++) { var d_t = day_timespans[i]; var zones = scheduler2._subtract_timespan_zones(d_t.zones, config.zones); if (zones.length) d_t.zones = zones; else { day_timespans.splice(i, 1); i--; var related_zones = scheduler2._marked_timespans_ids[d_t.id]; for (var k = 0; k < related_zones.length; k++) { if (related_zones[k] == d_t) { related_zones.splice(k, 1); break; } } } } }; scheduler2.deleteMarkedTimespan = function(configuration) { if (!arguments.length) { scheduler2._marked_timespans = { global: {} }; scheduler2._marked_timespans_ids = {}; scheduler2._marked_timespans_types = {}; } if (typeof configuration != "object") { scheduler2._delete_marked_timespan_by_id(configuration); } else { if (!(configuration.start_date && configuration.end_date)) { if (configuration.days === void 0 && !configuration.type) configuration.days = "fullweek"; if (!configuration.zones) configuration.zones = "fullday"; } var types = []; if (!configuration.type) { for (var type in scheduler2._marked_timespans_types) { types.push(type); } } else { types.push(configuration.type); } var configs = scheduler2._prepare_timespan_options(configuration); for (var i = 0; i < configs.length; i++) { var config = configs[i]; for (var t2 = 0; t2 < types.length; t2++) { var typedConfig = scheduler2._lame_clone(config); typedConfig.type = types[t2]; scheduler2._delete_marked_timespan_by_config(typedConfig); } } } }; scheduler2._get_types_to_render = function(common2, specific) { var types_to_render = common2 ? scheduler2._lame_copy({}, common2) : {}; for (var type in specific || {}) { if (specific.hasOwnProperty(type)) { types_to_render[type] = specific[type]; } } return types_to_render; }; scheduler2._get_configs_to_render = function(types) { var configs = []; for (var type in types) { if (types.hasOwnProperty(type)) { configs.push.apply(configs, types[type]); } } return configs; }; scheduler2._on_scale_add_marker = function(area, day) { if (scheduler2._table_view && scheduler2._mode != "month") return; var day_index = day.getDay(); var day_value = day.valueOf(); var mode = this._mode; var timespans = scheduler2._marked_timespans; var r_configs = []; var divs = []; if (this._props && this._props[mode]) { var view = this._props[mode]; var units = view.options; var index = scheduler2._get_unit_index(view, day); var unit = units[index]; if (!(view.days > 1)) { day = scheduler2.date.date_part(new Date(this._date)); } else { var dx = 24 * 60 * 60 * 1e3; var day_ind = Math.round((day - scheduler2._min_date) / dx); var unitsPerDay = view.size || units.length; day = scheduler2.date.add(scheduler2._min_date, Math.floor(day_ind / unitsPerDay), "day"); day = scheduler2.date.date_part(day); } day_index = day.getDay(); day_value = day.valueOf(); if (timespans[mode] && timespans[mode][unit.key]) { var unit_zones = timespans[mode][unit.key]; var unit_types = scheduler2._get_types_to_render(unit_zones[day_index], unit_zones[day_value]); r_configs.push.apply(r_configs, scheduler2._get_configs_to_render(unit_types)); } } var global_data = timespans["global"]; if (scheduler2.config.overwrite_marked_timespans) { var day_types = global_data[day_value] || global_data[day_index]; r_configs.push.apply(r_configs, scheduler2._get_configs_to_render(day_types)); } else { if (global_data[day_value]) { r_configs.push.apply(r_configs, scheduler2._get_configs_to_render(global_data[day_value])); } if (global_data[day_index]) { r_configs.push.apply(r_configs, scheduler2._get_configs_to_render(global_data[day_index])); } } for (var i = 0; i < r_configs.length; i++) { divs.push.apply(divs, scheduler2._render_marked_timespan(r_configs[i], area, day)); } return divs; }; scheduler2.attachEvent("onScaleAdd", function() { scheduler2._on_scale_add_marker.apply(scheduler2, arguments); }); scheduler2.dblclick_dhx_marked_timespan = function(e, src) { scheduler2.callEvent("onScaleDblClick", [scheduler2.getActionData(e).date, src, e]); if (scheduler2.config.dblclick_create) { scheduler2.addEventNow(scheduler2.getActionData(e).date, null, e); } }; } function createMethod(scheduler2) { var methods = {}; var isActive = false; function disableMethod(methodName, dummyMethod) { dummyMethod = typeof dummyMethod == "function" ? dummyMethod : function() { }; if (!methods[methodName]) { methods[methodName] = this[methodName]; this[methodName] = dummyMethod; } } function restoreMethod(methodName) { if (methods[methodName]) { this[methodName] = methods[methodName]; methods[methodName] = null; } } function disableMethods(methodsHash) { for (var i in methodsHash) { disableMethod.call(this, i, methodsHash[i]); } } function restoreMethods() { for (var i in methods) { restoreMethod.call(this, i); } } function batchUpdatePayload(callback) { try { callback(); } catch (e) { window.console.error(e); } } scheduler2.$stateProvider.registerProvider("batchUpdate", function() { return { batch_update: isActive }; }, false); return function batchUpdate2(callback, noRedraw) { if (isActive) { batchUpdatePayload(callback); return; } var call_dp = this._dp && this._dp.updateMode != "off"; var dp_mode; if (call_dp) { dp_mode = this._dp.updateMode; this._dp.setUpdateMode("off"); } const calls = { setModeDate: { date: null, mode: null }, needRender: false, needUpdateView: false, repaintEvents: {} }; const rememberModeDate = (date, mode) => { if (date) { calls.setModeDate.date = date; } if (mode) { calls.setModeDate.mode = mode; } }; var methods2 = { render: (date, mode) => { calls.needRender = true; rememberModeDate(date, mode); }, setCurrentView: (date, mode) => { calls.needRender = true; rememberModeDate(date, mode); }, updateView: (date, mode) => { calls.needUpdateView = true; rememberModeDate(date, mode); }, render_data: () => calls.needRender = true, render_view_data: (evs) => { if (evs && evs.length) { evs.forEach((e) => calls.repaintEvents[e.id] = true); } else { calls.needRender = true; } } }; disableMethods.call(this, methods2); isActive = true; this.callEvent("onBeforeBatchUpdate", []); batchUpdatePayload(callback); this.callEvent("onAfterBatchUpdate", []); restoreMethods.call(this); isActive = false; if (!noRedraw) { if (calls.needRender) { scheduler2.render(calls.setModeDate.date, calls.setModeDate.mode); } else if (calls.needUpdateView) { scheduler2.updateView(calls.setModeDate.date, calls.setModeDate.mode); } else { for (const i in calls.repaintEvents) { scheduler2.updateEvent(i); } } } if (call_dp) { this._dp.setUpdateMode(dp_mode); this._dp.sendData(); } }; } function batchUpdate(scheduler2) { scheduler2.batchUpdate = createMethod(scheduler2); } class t { constructor(t2) { const { url: e, token: s } = t2; this._url = e, this._token = s, this._mode = 1, this._seed = 1, this._queue = [], this.data = {}, this.api = {}, this._events = {}; } headers() { return { Accept: "application/json", "Content-Type": "application/json", "Remote-Token": this._token }; } fetch(t2, e) { const s = { credentials: "include", headers: this.headers() }; return e && (s.method = "POST", s.body = e), fetch(t2, s).then((t3) => t3.json()); } load(t2) { return t2 && (this._url = t2), this.fetch(this._url).then((t3) => this.parse(t3)); } parse(t2) { const { key: e, websocket: s } = t2; e && (this._token = t2.key); for (const e2 in t2.data) this.data[e2] = t2.data[e2]; for (const e2 in t2.api) { const s2 = this.api[e2] = {}, i = t2.api[e2]; for (const t3 in i) s2[t3] = this._wrapper(e2 + "." + t3); } return s && this.connect(), this; } connect() { const t2 = this._socket; t2 && (this._socket = null, t2.onclose = function() { }, t2.close()), this._mode = 2, this._socket = function(t3, e, s, i) { let n = e; "/" === n[0] && (n = document.location.protocol + "//" + document.location.host + e); n = n.replace(/^http(s|):/, "ws$1:"); const o = -1 != n.indexOf("?") ? "&" : "?"; n = `${n}${o}token=${s}&ws=1`; const r = new WebSocket(n); return r.onclose = () => setTimeout(() => t3.connect(), 2e3), r.onmessage = (e2) => { const s2 = JSON.parse(e2.data); switch (s2.action) { case "result": t3.result(s2.body, []); break; case "event": t3.fire(s2.body.name, s2.body.value); break; case "start": i(); break; default: t3.onError(s2.data); } }, r; }(this, this._url, this._token, () => (this._mode = 3, this._send(), this._resubscribe(), this)); } _wrapper(t2) { return (function() { const e = [].slice.call(arguments); let s = null; const i = new Promise((i2, n) => { s = { data: { id: this._uid(), name: t2, args: e }, status: 1, resolve: i2, reject: n }, this._queue.push(s); }); return this.onCall(s, i), 3 === this._mode ? this._send(s) : setTimeout(() => this._send(), 1), i; }).bind(this); } _uid() { return (this._seed++).toString(); } _send(t2) { if (2 == this._mode) return void setTimeout(() => this._send(), 100); const e = t2 ? [t2] : this._queue.filter((t3) => 1 === t3.status); if (!e.length) return; const s = e.map((t3) => (t3.status = 2, t3.data)); 3 !== this._mode ? this.fetch(this._url, JSON.stringify(s)).catch((t3) => this.onError(t3)).then((t3) => this.result(t3, s)) : this._socket.send(JSON.stringify({ action: "call", body: s })); } result(t2, e) { const s = {}; if (t2) for (let e2 = 0; e2 < t2.length; e2++) s[t2[e2].id] = t2[e2]; else for (let t3 = 0; t3 < e.length; t3++) s[e[t3].id] = { id: e[t3].id, error: "Network Error", data: null }; for (let t3 = this._queue.length - 1; t3 >= 0; t3--) { const e2 = this._queue[t3], i = s[e2.data.id]; i && (this.onResponse(e2, i), i.error ? e2.reject(i.error) : e2.resolve(i.data), this._queue.splice(t3, 1)); } } on(t2, e) { const s = this._uid(); let i = this._events[t2]; const n = !!i; return n || (i = this._events[t2] = []), i.push({ id: s, handler: e }), n || 3 != this._mode || this._socket.send(JSON.stringify({ action: "subscribe", name: t2 })), { name: t2, id: s }; } _resubscribe() { if (3 == this._mode) for (const t2 in this._events) this._socket.send(JSON.stringify({ action: "subscribe", name: t2 })); } detach(t2) { if (!t2) { if (3 == this._mode) for (const t3 in this._events) this._socket.send(JSON.stringify({ action: "unsubscribe", key: t3 })); return void (this._events = {}); } const { id: e, name: s } = t2, i = this._events[s]; if (i) { const t3 = i.filter((t4) => t4.id != e); t3.length ? this._events[s] = t3 : (delete this._events[s], 3 == this._mode && this._socket.send(JSON.stringify({ action: "unsubscribe", name: s }))); } } fire(t2, e) { const s = this._events[t2]; if (s) for (let t3 = 0; t3 < s.length; t3++) s[t3].handler(e); } onError(t2) { return null; } onCall(