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

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.

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

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 (data-id, data-name):

HTML:

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

We will add some CSS to style the draggable items:

.draggable {
  cursor: move;
}

.item {
  display: inline-block;
  padding: 10px 20px;
  margin-right: 5px;
  text-align: center;

  border-radius: 30px;
  background-color: #38761d;
  color: #ffffff;
}

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 the 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.addEventListener("dragstart", (ev) => {
  const 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.addEventListener("dragend", (ev) => {
  if (ev.dataTransfer.dropEffect === "move") {
    item.parentElement.removeChild(item);
  }
});

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

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

  for (let item of src) {
    item.setAttribute("draggable", "true");

    item.addEventListener("dragstart", (ev) => {
      const data = {
        id: item.dataset.id,
        name: item.dataset.name
      };
      ev.dataTransfer.setData("daypilot/external-item", JSON.stringify(data));
    });

    item.addEventListener("dragend", (ev) => {
      if (ev.dataTransfer.dropEffect === "move") {
        item.parentElement.removeChild(item);
      }
    });

  }

}

Scheduler Events as Drop Target

javascript scheduler events as drag and drop target ondrop

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:

onAfterEventRender: (args) => {

  args.div.addEventListener("dragover", (ev) => {
    const hasMyType = ev.dataTransfer.types.some(function(type) { return type === "daypilot/external-item"; });
    if (hasMyType) {
      ev.preventDefault();
      ev.dataTransfer.dropEffect = "move";
    }
    args.div.classList.add("dragging-over");
  });

  args.div.addEventListener("dragleave", (ev) => {
    args.div.classList.remove("dragging-over");
  });

  args.div.addEventListener("drop", (ev) => {

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

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

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

To display items inside events, we check whether the source data object (args.data) has items property. If so, we insert a <div> element for each of the items.

If the items property is not specified, we display an “(empty)” string.

onBeforeEventRender: args => {
  args.data.backColor = "#93c47d";
  args.data.borderColor = "darker";
  args.data.fontColor = "#ffffff";

  if (args.data.items) {
    args.data.html = args.data.items.map(item => {
      const text = DayPilot.Util.escapeHtml(item.name);
      return `<div class="item">${text}</div> `
    }).join("");
  } else {
    args.data.html = "(empty)";
  }
},

To highlight the target event during dragging, we specify dragging-over CSS class:

.dragging-over {
  outline: 2px solid #38761d;
}