如何使用DHTMLX Scheduler的拖放功能,在 JS 日程安排日历中创建一组相同的事件

DHTMLX Scheduler 是一个全面的调度解决方案,涵盖了与规划事件相关的广泛需求。假设您在我们的 Scheduler 文档中找不到任何功能,并且希望在我们的 Scheduler 文档中看到您的项目。在这种情况下,很可能可以使用自定义解决方案来实现此类功能。今年,我们将继续探索JavaScript 调度组件的自定义功能。

今天,您将学习如何通过拖放功能在日历的"周"视图中轻松添加一系列类似的事件。

DHTMLX Scheduler 最新版下载

通过用户界面安排一组活动的新方法

DHTMLX Scheduler 在 JavaScript 日历中创建新事件时非常灵活。最终用户可以计划各种类型的事件,从基本的一次性约会到基于各种设置的重复活动。但是,如果您需要介于两者之间的活动怎么办?例如,如果最终用户在一周内有一系列类似格式的会议(或其他活动),该怎么办?可以使用重复事件表单,但它似乎很复杂且耗时,尤其是在不需要额外条件的情况下。幸运的是,我们的 JavaScript 调度组件的广泛 API 允许实现自定义解决方案,如下面的示例所示,我们将更详细地讨论。

查看示例 >

如您所见,此解决方案使创建一组相同的事件变得更容易、更快捷。更具体地说,只需一次拖动操作即可在所需时间段内为每一天创建事件副本。此定制不仅包括创建一周多天具有相同时间范围的新事件(约会)的功能,还包括一些视觉元素,例如为事件副本呈现标记的时间跨度。

从编码角度来看,此解决方案需要使用 Scheduler API(插件、方法和事件)以及一些自定义函数(compareTime、getDatesBetween、getWeekdayNumbers和timeFixer)。这些函数用于将可用数据转换为所需的格式。

现在我们可以继续描述将此功能添加到您的项目所需的具体步骤。

准备步骤

您应该从准备步骤开始,其结果稍后会用到。这包括启用视觉部分所需的插件(限制)、设置可选配置以及创建变量。

复制代码
scheduler.plugins({
   limit: true,
});

scheduler.config.time_step = 10;
scheduler.config.first_hour = 6;
scheduler.config.last_hour = 22;

let marked = null;
let start, end;
let backward;
let dates = [];
let daysToCreate = [];

在继续之前,还应注意,此自定义是专门为"周"视图设计的,而其他视图则以常规模式工作。此限制在以下条件下启用:

复制代码
if(scheduler.getState().mode == "week"){
步骤 1

现在,您应该使用onEventDrag事件。当在日历的 Week 视图中通过拖动创建新事件时,将调用该事件。该事件在拖动操作结束前一直有效。此事件有助于在事件拖动操作期间收集日期,并将它们添加到上一步中声明的变量中:

复制代码
scheduler.attachEvent("onEventDrag", function (id, mode, e){
    ...
    start = scheduler.getEvent(id).start_date;
    end = scheduler.getActionData(e).date;

这样,您将获得创建初始事件副本的日期。

第 2 步

您使用自定义getDatesBetween函数创建事件的副本,该函数获取两个日期之间的天数序列,并使用getWeekdayNumbers函数返回这些天的数字。

这些功能可以合并为一个,但我们的方法似乎更清晰:

复制代码
daysToCreate = getWeekdayNumbers(getDatesBetween(start, end));
daysToCreate = daysToCreate.filter(el => el != start.getDay())
步骤3

此外,您还需要使用自定义compareTime函数通过比较小时和分钟来检查事件创建的方向(时间上向前或向后):

复制代码
backward = compareTime(start, end);

您将需要它来正确呈现事件副本的占位符。

这是本次定制功能部分的基础。整个代码块如下:

复制代码
scheduler.attachEvent("onEventDrag", function (id, mode, e){

    start = scheduler.getEvent(id).start_date;
    end = scheduler.getActionData(e).date;
    backward = compareTime(start, end);

    daysToCreate = getWeekdayNumbers(getDatesBetween(start, end));
    daysToCreate = daysToCreate.filter(el => el != start.getDay())

}};

步骤4

在拖动操作结束时,使用onDragEvent事件确定向前和向后创建事件的开始和结束日期:

复制代码
scheduler.attachEvent("onDragEnd", function(id, mode, e){
    if(scheduler.getState().mode == "week"){
        // store dates for event copies
        if(backward != -1){
            start = scheduler.getActionData(e).date;
            end = scheduler.getEvent(id).end_date;
       
        } else {
            start = scheduler.getEvent(id).start_date;
            end = scheduler.getActionData(e).date;
        }
    }

});
步骤5

拖拽操作完成后,可以通过灯箱添加新事件及其副本的参数。保存包含数据的灯箱时,将触发onEventSave事件。

复制代码
scheduler.attachEvent("onEventSave",function(id,ev,is_new){

onDragEnd事件中更新的getDatesBetween函数的参数(start,end)用于填充用于创建事件副本的日期数组。

如果最终用户通过灯箱更改事件日期,您可以在onEventSave事件中存储新的开始和结束参数:

复制代码
start = ev.start_date;
end = ev.end_date;

如果日期数组包含多个日期,则可以使用addEvent()方法为每天创建事件的副本。

使用自定义的timeFixer函数,您可以单独控制事件副本的日期(分钟/小时),以便它们与初始事件相匹配。

复制代码
if(datesToCreate.length > 1){
        datesToCreate.forEach(el => {
        scheduler.addEvent({
             start_date: timeFixer(el).fixedStart,
             end_date: timeFixer(el).fixedEnd,
             text: ev.text
        })
})

之后,清除日期数组(datesToCreate):

复制代码
datesToCreate = [];

应阻止创建事件的默认方式(它也将被副本替换)并且手动隐藏灯箱。

复制代码
// block default event creation
        scheduler.hideLightbox();
        return false;
    }
    return true;
})

现在,它按预期运行,但事件副本将显示在哪里尚不完全清楚。

查看示例 >

可以通过添加事件副本的占位符渲染来解决此问题。

第 6 步

由于事件副本需要在拖动过程中动态渲染,因此它们是从onEventDrag事件中获取的。

占位符使用markedTimespan()方法呈现。您还需要几个变量(zonesStartTime、zonesEndTime)。这些变量将为markedTimespan()方法存储格式化的时间。

要获取格式化的时间,您必须采用通用格式(小时/分钟)获取事件时间,然后使用自定义convertMinutesToPercentage()方法将分钟转换为小时的百分比。

复制代码
if(backward != -1){
    start = scheduler.getEvent(id).end_date;
    zonesEndTime = `${scheduler.getEvent(id).end_date.getHours()}.${convertMinutesToPercentage(scheduler.getEvent(id).end_date.getMinutes())}`;
    zonesStartTime = `${end.getHours()}.${convertMinutesToPercentage(end.getMinutes())}`;
} else {
    zonesStartTime = `${start.getHours()}.${convertMinutesToPercentage(start.getMinutes())}`;
    zonesEndTime = `${end.getHours()}.${convertMinutesToPercentage(end.getMinutes())}`;
}

现在,您已经有了呈现占位符(daysToCreate)的天数以及所需格式(zoneStartTime和zoneEndTime)的时间。

以下是在事件创建期间动态呈现占位符的方法:

复制代码
if(mode == "new-size"){
// Each time delete old placeholders
    scheduler.unmarkTimespan(marked);
// And render new placeholders for creating events
    if(+start < +end){
        marked = scheduler.markTimespan({
            html: `<div class="marked_placeholder">${scheduler.templates.event_date(start)+" - "+
            scheduler.templates.event_date(end)}
            </br> New Event<div>`,
            days: daysToCreate,
            zones:[zonesStartTime*60,zonesEndTime*60],
            css: "highlighted_timespan"
        });
    }
    if(+start > +end){
        marked = scheduler.markTimespan({
            html: `<div class="marked_placeholder">${scheduler.templates.event_date(end)+" - "+
            scheduler.templates.event_date(start)}
            </br> New Event<div>`,
            days: daysToCreate,
            zones:[zonesStartTime*60,zonesEndTime*60],
            css: "highlighted_timespan"
        });
    }
    }
});

最后要提的是,事件及其副本结束后,所有 markTimespan 都应被删除。该操作在 lightbox 关闭后立即完成。

复制代码
scheduler.attachEvent("onAfterLightbox", function (){
    // remove marked timespan after closing the lightbox
    scheduler.unmarkTimespan(marked);  
});

按照上述说明,您可以像我们的示例一样,通过拖放操作在"周"视图中添加一种方便的创建事件组的方法。

总结

在这篇博文中,我们回顾了一个有用的自定义功能,它有助于更方便地管理事件并增强 Web 项目中 JavaScript 调度解决方案的可用性。我们回顾了实现此类自定义功能的一个示例,该功能可以进一步修改并用于特定的用例场景。DHTMLX Scheduler 丰富且文档齐全的 API 无疑有助于满足您的大部分调度需求,同时我们将继续在 DHTMLX 教程中与您分享解决方案,以满足更具体的需求。

相关推荐
前端之虎陈随易8 分钟前
2年没用Nodejs了,Bun很香
linux·前端·javascript·vue.js·typescript
好运的阿财1 小时前
OpenClaw工具拆解之host_workspace_write+host_workspace_edit
前端·javascript·人工智能·机器学习·ai编程·openclaw·openclaw工具
XiYang-DING1 小时前
JavaScript
开发语言·javascript·ecmascript
空中海2 小时前
02 React Native状态、导航、数据流与设备能力
javascript·react native·react.js
空中海3 小时前
02 状态、Hooks、副作用与数据流
开发语言·javascript·ecmascript
空中海3 小时前
04 React Native工程化、质量、发布与生态选型
javascript·react native·react.js
杨超凡4 小时前
豆包收费了?我特么自己用“意念”搓了一个!
javascript
threelab5 小时前
Three.js 咖啡杯烟雾效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能
Heo5 小时前
14_React 中的更新队列 updateQueue
前端·javascript·面试