Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FullCalendar - Vertical resource order arrangement

I have checked the API and haven't been able to find what I'm looking for, is it possible to drag and re-arrange resources on the screen?

In this example, can I drag and re-order Rooms from A,B,C,D to B,C,A,D for example?

https://fullcalendar.io/js/fullcalendar-scheduler-1.6.2/demos/vertical-resource-view.html

Thank you

like image 874
Deano Avatar asked Jun 30 '17 02:06

Deano


1 Answers

Sure, but not without external drag and drop code. Below, I've used jQueryUI's Sortable functionality and hooked into its events.

To make this work the resource list is populated via a function. This means that we can reorder the resources and then call the Callendar's refetchResources method to have it retrieve & redraw the display. I've added a sorting property to the calendar options - resourceOrder: 'sortOrder' to make sure it orders the Resources correctly.

There are two distinct views with FullCalendar resources - vertical, with Resources as html th cells, and horizontal with the Resources as html td. With the vertical case the jQueryUI Sortable events are lost and must be reapplied after calling refetchResources. I've included the code for both layouts below.

To run, save the html in \fullcalendar-scheduler-1.6.2\demos\ - the paths are relative to that folder.

Vertical View:

<!DOCTYPE html>
<html>

<head>
  <meta charset='utf-8' />
  <link href='../lib/fullcalendar.min.css' rel='stylesheet' />
  <link href='../lib/fullcalendar.print.min.css' rel='stylesheet' media='print' />
  <link href='../scheduler.min.css' rel='stylesheet' />
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <script src='../lib/moment.min.js'></script>
  <script src='../lib/jquery.min.js'></script>
  <script src='../lib/fullcalendar.min.js'></script>
  <script src='../scheduler.min.js'></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

  <script>
    var resources = [
      { id: 'a', sortOrder: 1},
      { id: 'b', sortOrder: 2, eventColor: 'green' },
      { id: 'c', sortOrder: 3, eventColor: 'orange' },
      { id: 'd', sortOrder: 4 },
      { id: 'e', sortOrder: 5 },
      { id: 'f', sortOrder: 6, eventColor: 'red' },
      { id: 'g', sortOrder: 7 }
    ];

    $(function() { // document ready

      $('#calendar').fullCalendar({
        now: '2017-05-07',
        editable: true, // enable draggable events
        aspectRatio: 1.8,
        scrollTime: '00:00', // undo default 6am scrollTime
        header: {
          left: 'today prev,next',
          center: 'title',
          right: ''
        },
        defaultView: 'agendaDay',
        views: {},
        resourceLabelText: 'Rooms',
        resourceText: function(resource) {
          return 'Auditorium ' + ('' + resource.id).toUpperCase();
        },
        resourceOrder: 'sortOrder',
        resources: resourcesFunc,
        events: [
          { id: '1', resourceId: 'b', start: '2017-05-07T02:00:00', end: '2017-05-07T07:00:00', title: 'event 1' },
          { id: '2', resourceId: 'c', start: '2017-05-07T05:00:00', end: '2017-05-07T22:00:00', title: 'event 2' },
          { id: '3', resourceId: 'd', start: '2017-05-06', end: '2017-05-08', title: 'event 3' },
          { id: '4', resourceId: 'e', start: '2017-05-07T03:00:00', end: '2017-05-07T08:00:00', title: 'event 4' },
          { id: '5', resourceId: 'f', start: '2017-05-07T00:30:00', end: '2017-05-07T02:30:00', title: 'event 5' }
        ]
      });

      function resourcesFunc(callback) {
        callback(resources);
      }

    });
  </script>
  <style>
    body {
      margin: 0;
      padding: 0;
      font-family: "Lucida Grande", Helvetica, Arial, Verdana, sans-serif;
      font-size: 14px;
    }

    #calendar {
      max-width: 900px;
      margin: 50px auto;
    }
  </style>
</head>

<body>

  <div id='calendar'></div>

  <script>
    $(function() {

      var initialPos, finalPos;

      $("table thead tr").sortable({
          items: "> th:gt(0)",
          axis: "x"
        })
        .disableSelection()
        .on("sortstart", function(event, ui) {
          initialPos = ui.item.index() - 1; // need to subtract 1 because of the empty first header cell
        })
        .on("sortupdate", function(event, ui) {
          sortUpdate(event, ui);
        });

      function sortUpdate(event, ui) {
        finalPos = ui.item.index() - 1; // need to subtract 1 because of the empty first header cell

        if (finalPos == -1) return; // "sortupdate" gets called twice for an unknown reason. Second time with finalPos == -1

        var tmpResources = [];

        for (var i = 0; i < resources.length; i++) {
          tmpResources.push(resources[i]);
        }

        // reorder sorting to match
        if (finalPos > initialPos) {
          tmpResources[finalPos] = resources[initialPos];
          tmpResources[finalPos].sortOrder = finalPos + 1;

          for (var i = initialPos + 1; i <= finalPos; i++) {
            //resources[i].sortOrder -= 1;
            tmpResources[i - 1] = resources[i];
            tmpResources[i - 1].sortOrder -= 1;
          }
        } else {
          tmpResources[finalPos] = resources[initialPos];
          tmpResources[finalPos].sortOrder = finalPos + 1;

          for (var i = initialPos - 1; i >= finalPos; i--) {
            //resources[i].sortOrder += 1;
            tmpResources[i + 1] = resources[i];
            tmpResources[i + 1].sortOrder += 1;
          }
        }

        for (var i = 0; i < tmpResources.length; i++) {
          resources[i] = tmpResources[i];
        }

        $('#calendar').fullCalendar('refetchResources'); // refresh display

        // sorting is lost after a refetch when in vertical display, so need to reapply:    
        $("table thead tr").sortable({
            items: "> th:gt(0)",
            axis: "x"
          })
          .disableSelection()
          .on("sortstart", function(event, ui) {
            initialPos = ui.item.index() - 1; // need to subtract 1 because of the empty first header cell
          })
          .on("sortupdate", function(event, ui) {
            sortUpdate(event, ui);
          });
      }

    });
  </script>
</body>

</html>

Horizontal View:

<!DOCTYPE html>
<html>

<head>
  <meta charset='utf-8' />
  <link href='../lib/fullcalendar.min.css' rel='stylesheet' />
  <link href='../lib/fullcalendar.print.min.css' rel='stylesheet' media='print' />
  <link href='../scheduler.min.css' rel='stylesheet' />
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <script src='../lib/moment.min.js'></script>
  <script src='../lib/jquery.min.js'></script>
  <script src='../lib/fullcalendar.min.js'></script>
  <script src='../scheduler.min.js'></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

  <script>
    var resources = [
      { id: 'a', sortOrder: 1},
      { id: 'b', sortOrder: 2, eventColor: 'green' },
      { id: 'c', sortOrder: 3, eventColor: 'orange' },
      { id: 'd', sortOrder: 4 },
      { id: 'e', sortOrder: 5 },
      { id: 'f', sortOrder: 6, eventColor: 'red' },
      { id: 'g', sortOrder: 7 }
    ];

    $(function() { // document ready

      $('#calendar').fullCalendar({
        now: '2017-05-07',
        editable: true, // enable draggable events
        aspectRatio: 1.8,
        scrollTime: '00:00', // undo default 6am scrollTime
        header: {
          left: 'today prev,next',
          center: 'title',
          right: ''
        },
        defaultView: 'timelineDay',
        views: {
          timelineThreeDays: {
            type: 'timeline',
            duration: {
              days: 3
            }
          }
        },
        resourceLabelText: 'Rooms',
        resourceText: function(resource) {
          return 'Auditorium ' + ('' + resource.id).toUpperCase();
        },
        resourceOrder: 'sortOrder',
        resources: resourcesFunc,
        events: [
          { id: '1', resourceId: 'b', start: '2017-05-07T02:00:00', end: '2017-05-07T07:00:00', title: 'event 1' },
          { id: '2', resourceId: 'c', start: '2017-05-07T05:00:00', end: '2017-05-07T22:00:00', title: 'event 2' },
          { id: '3', resourceId: 'd', start: '2017-05-06', end: '2017-05-08', title: 'event 3' },
          { id: '4', resourceId: 'e', start: '2017-05-07T03:00:00', end: '2017-05-07T08:00:00', title: 'event 4' },
          { id: '5', resourceId: 'f', start: '2017-05-07T00:30:00', end: '2017-05-07T02:30:00', title: 'event 5' }
        ]
      });

      function resourcesFunc(callback) {
        callback(resources);
      }

    });
  </script>
  <style>
    body {
      margin: 0;
      padding: 0;
      font-family: "Lucida Grande", Helvetica, Arial, Verdana, sans-serif;
      font-size: 14px;
    }

    #calendar {
      max-width: 900px;
      margin: 50px auto;
    }
  </style>
</head>

<body>

  <div id='calendar'></div>

  <script>
    $(function() {

      var initialPos, finalPos;

      $("table tbody").sortable({
          axis: "y"
        })
        .disableSelection()

        .on("sortstart", function(event, ui) {
          initialPos = ui.item.index();
        })
        .on("sortupdate", function(event, ui) {

          finalPos = ui.item.index();

          if (finalPos == -1) return; // "sortupdate" gets called twice for an unknown reason. Second time with finalPos == -1

          var tmpResources = [];

          for (var i = 0; i < resources.length; i++) {
            tmpResources.push(resources[i]);
          }

          // reorder sorting to match
          if (finalPos > initialPos) {
            tmpResources[finalPos] = resources[initialPos];
            tmpResources[finalPos].sortOrder = finalPos + 1;

            for (var i = initialPos + 1; i <= finalPos; i++) {
              //resources[i].sortOrder -= 1;
              tmpResources[i - 1] = resources[i];
              tmpResources[i - 1].sortOrder -= 1;
            }
          } else {
            tmpResources[finalPos] = resources[initialPos];
            tmpResources[finalPos].sortOrder = finalPos + 1;

            for (var i = initialPos - 1; i >= finalPos; i--) {
              //resources[i].sortOrder += 1;
              tmpResources[i + 1] = resources[i];
              tmpResources[i + 1].sortOrder += 1;
            }
          }

          for (var i = 0; i < tmpResources.length; i++) {
            resources[i] = tmpResources[i];
          }

          $('#calendar').fullCalendar('refetchResources'); // refresh display
        })
    });
  </script>
</body>

</html>
like image 90
K Scandrett Avatar answered Sep 28 '22 09:09

K Scandrett