Features

  • Drag custom items from an external list to JavaScript Scheduler events (each event is an active HTML5 drop target)
  • Built using standard HTML5 drag and drop API
  • Each event can hold multiple external items
  • Items are removed from the source list after drop
  • Includes a trial version of DayPilot Pro for JavaScript (see License below)

License

Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript. Buy a license.

Live Demo

Dragging Items to Scheduler Events

The JavaScript Scheduler includes built-in support for dragging external items to the Scheduler. These items will be transformed into events and you can use this feature to schedule tasks from a list using drag and drop.

It is also possible to drag items from an external list to existing Scheduler events. This tutorial will show how to implement it using standard HTML5 drag and drop API.

Making External Items Draggable

javascript-scheduler-events-as-drag-and-drop-target-draggable-items.png

Let's have a list of items that we want to drag to the Scheduler events. We will use simple <div> elements with some additional data saved using data attributes (id, name):

HTML:

<div class="draggable" data-id="1" data-name="Item 1">Item 1</div>
<div class="draggable" data-id="2" data-name="Item 2">Item 2</div>

We will add some CSS to style the events:

.draggable {
  border: 1px solid gray;
  background-color: white;
  display: inline-block;
  width: 50px;
  height: 50px;
  cursor: move;
}

Now we need to activate the items to make them draggable. This requires the draggable HTML attribute to be added:

item.setAttribute("draggable", "true");

We will also handle dragstart event and use it to specify the object type (we are using a custom data type to prevent other targets on the page from accepting the items) and pass the source object data to the target using event.dataTransfer property:

item.ondragstart = function(ev) {
 var data = {
   id: item.dataset.id,
   name: item.dataset.name
 };
 ev.dataTransfer.setData("daypilot/external-item", JSON.stringify(data));
};

We will use the dragend event to remove the item from the source list if it was dropped successfully:

item.ondragend = function(ev) {
  if (ev.dataTransfer.dropEffect === "move") {
    item.parentElement.removeChild(item);
  }
};

This is how the full source item initialization code looks like now:

function activateItems() {
  var src = document.getElementsByClassName("draggable");

  for (let item of src) {  // Chrome, Firefox, Edge only
    item.setAttribute("draggable", "true");

    item.ondragstart = function(ev) {
      var data = {
        id: item.dataset.id,
        name: item.dataset.name
      };
      ev.dataTransfer.setData("daypilot/external-item", JSON.stringify(data));
    };

    item.ondragend = function(ev) {
      if (ev.dataTransfer.dropEffect === "move") {
        item.parentElement.removeChild(item);
      }
    };

  }

}

Scheduler Events as Drop Target

javascript-scheduler-events-as-drag-and-drop-target-ondrop.png

In this step, we will activate the Scheduler events as drop targets.

That can be done using dragover and drop HTML5 events. We will set the event handlers using onAfterEventRender event which provides access to the event <div> element:

dp.onAfterEventRender = function(args) {

  args.div.ondragover = function(ev) {
    var hasMyType = ev.dataTransfer.types.some(function(type) { return type === "daypilot/external-item"; });
    if (hasMyType) {
      ev.preventDefault();
      ev.dataTransfer.dropEffect = "move";
    }
    DayPilot.Util.addClass(args.div, "dragging-over");
  };

  args.div.ondragleave = function(ev) {
    DayPilot.Util.removeClass(args.div, "dragging-over");
  };

  args.div.ondrop = function(ev) {

    if (!args.e.data.items) {
      args.e.data.items = [];
    }

    var data = JSON.parse(ev.dataTransfer.getData("daypilot/external-item"));
    args.e.data.items.push(data);

    dp.events.update(args.e);
  };
};

Displaying items inside events:

dp.onBeforeEventRender = function(args) {
  if (args.data.items) {
    args.data.html = args.data.items.map(function(item) { return item.name; }).join(", ");
  }
  else {
    args.data.html = "(empty)";
  }
};

Hover CSS Styling :

.dragging-over {
  outline: 2px solid red;
}