event_platform-1.0.x-dev/event_platform_scheduler/js/scheduler.js

event_platform_scheduler/js/scheduler.js
(function (Drupal, once) {
  'use strict';

  Drupal.behaviors.eventPlatformScheduler = {
    attach: function (context) {

      const unassign = document.querySelector('.scheduler--unassign');
      const filters = document.querySelectorAll('#scheduler_filters select');
      const filter_values = [];

      // Activate empty slots as drag targets.
      once('eventPlatformScheduler', '#scheduler-table .empty', context).forEach(function (element) {
        makDragTarget(element);
      });

      // Activate filters.
      once('eventPlatformScheduler', '#scheduler_filters select', context).forEach(function (element) {
        element.addEventListener('change', applyFilters);
      });

      // Activate unassign slots as a drag target.
      once('eventPlatformScheduler', '#scheduler--sessions .scheduler--unassign', context).forEach(function (element) {
        element.addEventListener('dragover', dragOver);
        element.addEventListener('dragenter', dragEnter);
        element.addEventListener('dragleave', dragLeave);
        element.addEventListener('drop', dragDropUnassign);
      });

      // Activate sessions as draggable.
      once('eventPlatformScheduler', '.session', context).forEach(function (element) {
        element.addEventListener('dragstart', dragStart);
        element.addEventListener('dragend', dragEnd);
        if (element.dataset.room && element.dataset.timeslot) {
          // If a cell matches the sessions data, move it there.
          const cell = document.querySelector('td[data-room="' + element.dataset.room + '"][data-timeslot="' + element.dataset.timeslot + '"]');
          if (cell) {
            cell.appendChild(element);
            cell.classList.remove("empty");
            cell.classList.add("filled");
            removeDragTarget(cell);
          }
          else {
            // Invalid room or timeslot, so reset values.
            element.dataset.room = '';
            element.dataset.timeslot = '';
          }
        }
      });

      function makDragTarget(element) {
        element.addEventListener('dragover', dragOver);
        element.addEventListener('dragenter', dragEnter);
        element.addEventListener('dragleave', dragLeave);
        element.addEventListener('drop', dragDrop);
      }

      function removeDragTarget(element) {
        element.removeEventListener('dragover', dragOver);
        element.removeEventListener('dragenter', dragEnter);
        element.removeEventListener('dragleave', dragLeave);
        element.removeEventListener('drop', dragDrop);
      }

      function checkForConflicts(element) {
        const user = element.dataset.user;
        const timeslot = element.dataset.timeslot;
        const conflicts = document.querySelectorAll('.session[data-user="' + user + '"]');
        if (conflicts) {
          conflicts.forEach((conflict) => {
            if (!conflict.dataset.timeslot || conflict.dataset.timeslot == timeslot) {
              return;
            }
            createConflict(conflict.dataset.timeslot, user);
          });
        }
      }

      function createConflict(timeslot, user) {
        const cells = document.querySelectorAll('td[data-timeslot="' + timeslot + '"]');
        var session;
        cells.forEach((cell) => {
          cell.classList.add('conflict');
          removeDragTarget(cell);
          if (session = cell.querySelector('.session[data-user="' + user + '"]')) {
            session.classList.add('theconflict');
          }
        });
      }

      function removeConflicts() {
        const cells = document.querySelectorAll('td.conflict');
        cells.forEach((cell) => {
          cell.classList.remove('conflict');
          if (!cell.classList.contains('filled')) {
            makDragTarget(cell);
          }
        });
        const sessions = document.querySelectorAll('.session.theconflict');
        sessions.forEach((session) => {
          session.classList.remove('theconflict');
        });
      }

      // Drag Functions
      function dragStart(e) {
        this.classList.add("dragging");
        e.dataTransfer.setData("text/plain", e.target.id);
        const slot = this.closest(".filled");
        if (slot) {
          makDragTarget(slot);
          slot.classList.remove('filled');
        }
        if (this.dataset.room || this.dataset.timeslot) {
          unassign.classList.remove('hidden');
        }
        checkForConflicts(this);
      }

      function dragEnd() {
        this.classList.remove("dragging");
        unassign.classList.add('hidden');
        removeConflicts();
      }

      function dragOver(e) {
        e.preventDefault();
        e.dataTransfer.dropEffect = "move";
      }

      function dragEnter(e) {
        e.preventDefault();
        this.classList.add("dragover");
      }

      function dragLeave() {
        this.classList.remove("dragover");
      }

      function dragDrop(e) {
        // Get the id of the target and add the moved element to the target's DOM
        const data = e.dataTransfer.getData("text/plain");
        const node = document.getElementById(data)
        // Replace classes.
        this.classList.remove("dragover");
        this.classList.remove("empty");
        this.classList.add("filled");
        removeDragTarget(this);
        // Assemble the data necessary to update the node.
        const nid = node.dataset.nid;
        const room = this.dataset.room;
        const timeslot = this.dataset.timeslot;
        // Only update if the new data is different.
        if (nid && room && timeslot && (room != node.dataset.room || timeslot != node.dataset.timeslot)) {
          e.target.appendChild(node);
          // console.log("Target: " + nid + "-" + room + "-" + timeslot);
          const path = '/admin/event-details/scheduler/assign/' + nid + '/' + room + '/' + timeslot;
          fetch(path)
            .then(response => response.text());
            // .then(text => console.log(text));
          // @todo show feedback to user.
          // Add data attributes to the session.
          node.dataset.room = room;
          node.dataset.timeslot = timeslot;
          // Check if the session should be highlighted as a filters match.
          if (!arrayEmpty(filter_values) && checkFiltersMatch(node)) {
            node.classList.add('scheduler--filters-match');
          }
        }
      }

      function dragDropUnassign(e) {
        // Get the id of the target and return the element to the list.
        const data = e.dataTransfer.getData("text/plain");
        const node = document.getElementById(data)
        e.target.parentElement.appendChild(node);
        const nid = node.dataset.nid;
        if (nid) {
          const path = '/admin/event-details/scheduler/unassign/' + nid;
          fetch(path)
            .then(response => response.text());
            // .then(text => console.log(text));
          // @todo show feedback to user.
        }
        // Reset data attributes on the session.
        node.dataset.room = '';
        node.dataset.timeslot = '';
        node.classList.remove('scheduler--filters-match');
      }

      function applyFilters() {
        // Get all filter values.
        filters.forEach((element) => {
          filter_values[element.name] = element.value;
        });
        // Get all unassigned sessions.
        const sessions = document.querySelectorAll('#scheduler--sessions .session');
        // Make all sessions visible.
        sessions.forEach((session) => {
          session.style.display = "block";
          // Hide any sessions that don't match filter criteria.
          if (!checkFiltersMatch(session)) {
            session.style.display = "none";
          }
        });
        // Selectively add a class to highlight filter matches.
        let filters_empty = arrayEmpty(filter_values);
        const scheduledMatches = document.querySelectorAll('#scheduler-table .session');
        scheduledMatches.forEach((session) => {
          // Reset all existing classes to start.
          session.classList.remove('scheduler--filters-match');
          if (!filters_empty && checkFiltersMatch(session)) {
            session.classList.add('scheduler--filters-match');
          }
        });
      }

      function checkFiltersMatch(session) {
        let is_match = true;
        Object.entries(filter_values).forEach(([index, value]) => {
          if (!value) {
            return;
          }
          if (session.dataset[index] != value) {
            is_match = false;
            return;
          }
        });
        return is_match;
      }

      function arrayEmpty(array) {
        let is_empty = true;
        // We don't use the index value, but wanted approach to be consistent.
        Object.entries(array).forEach(([index, value]) => {
          if (value) {
            is_empty = false;
          }
        });
        return is_empty;
      }

    }
  };
}(Drupal, once));

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc