GanttChart Window Editor

Task Editor

Smart.GanttChart's tasks can be edited via the window editor. The editor represents a Window component that appears when the user double clicks on a task or a connection inside the Timeline.

  • Task Editing - the window editor allows the user to quickly edit the clicked task. The taskColumns property is used to display the value of the properties of the tasks and determines how they are going to be edited. By default each column that represents a task property has it's own editor that appears inside the window when oepened. However property editors can be replaced with a custom editors. In order to do that the user has to define three callback function for the target task property in the taskColumns array:
    • customEditor - a callback that accepts a function which must return an HTML element that represents the custom editor for the column. The callback has two arguments:
      • label - the name of the property that is being edited (e.g. 'duration')
      • value - the current value of the property that is being edited (e.g. 8)

      In the example below we want to display the 'duration' of the tasks and set a custom editor for that property:

      window.onload = function () {
          const gantt = document.querySelector('smart-gantt-chart');
      
          gantt.taskColumns = [
              {
                  label: 'Duration (Hours)',
                  value: 'duration',
                  formatFunction: (date) => parseInt(date),
                  customEditor: function (label, value) {
                      let fragment = document.createDocumentFragment(),
                          customEditorLabel = document.createElement('label'),
                          dropDownList = document.createElement('smart-drop-down-list');
      
                      customEditorLabel.innerHTML = 'Duration';
                      dropDownList.dropDownAppendTo = 'body';
                      dropDownList.dataSource = [4, 8, 12];
      
                      fragment.appendChild(customEditorLabel);
                      fragment.appendChild(dropDownList);
      
                      return fragment;
                  }
              }];
      })
      

      NOTE: If the callback is not defined the default editor will be used instead. The default editor for 'duration' is a numeric input.

    • setCustomEditorValue - a callback that accepts a function which sets the value of the custom editor. It accepts three arguments:
      • editor - the actual editor that was created from the customEditor callback.
      • label - the name of the task property that is being edited (e.g. 'duration')
      • value - the current value of the property that is being edited (e.g. '8')
                  ...
                  setCustomEditorValue: function (editor, label, value) {
                      const dropDownList = editor.querySelector('smart-drop-down-list');
      
                      dropDownList.select(value.toString());
                  }
      

      NOTE: If the callback is not defined the editor will be remain unset.

    • getCustomEditorValue - a callback that should return the value of the editor in the appropriate format which in the case of 'duration' is number. It accepts one argument:
      • editor - the actual editor that was created from the customEditor callback.
                  ...
                  getCustomEditorValue: function (editor) {
                      const dropDownList = editor.querySelector('smart-drop-down-list');
      
                      return dropDownList.selectedValues[0];
                  }
      

      NOTE: If the callback is not defined editing will not be successful because the element does not know what the value of the custom editor is.

The editor will appear in the Window when it's opened. In the example a DropDownList component is created in order to set a specific duration of the edited task.

Note: The demo used in this section is available on the website: gantt chart custom task editor

Connection Editor

The window editor is also used to delete connections between tasks. When the user double clicks on a connection the window editor opens and allows to delete the connection.

Custom Window Editor

The window editor can be completely customized using the element's popupWindowCustomizationFunction property. The property accepts a callback with three arguments:
  • target - the window instance that is going to be customized.
  • type - the type of window that is going to be customized (e.g. 'task', 'connection')
  • index - the index of the task or the id of a connection. ( depending on the target that was clicked )
Here is an example where the window is completely customzied to use specific editors and the editing process is done via the official API of the element. First we define the structure of the window and add event listeners to the footer buttons that are going to be used for the actions
 const gantt = document.querySelector('smart-gantt-chart');
 let editedTaskIndex,
        taskLabel,
        description,
        dayPicker,
        monthPicker,
        yearPicker,
        dayIncrementBtn,
        dayDecrementBtn,
        dayInput,
        totalDate,
        deleteBtn,
        cancelBtn,
        saveBtn;

 gantt.popupWindowCustomizationFunction = function (target, type, taskIndex) {
        const targetTask = gantt.tasks[taskIndex];

        if (type === 'task' && targetTask) {
            let addListeners;

            editedTaskIndex = taskIndex;

            //Hide the header
            target.headerPosition = 'none';
            target.footerPosition = 'none';

            //Create the content
            if (!document.getElementById('taskLabel')) {
                addListeners = true;

                target.clear();
                target.appendChild(document.getElementById('myTemplate').content);
            }

            taskLabel = document.getElementById('taskLabel');
            description = document.getElementById('description');
            dayPicker = document.getElementById('dayPicker');
            monthPicker = document.getElementById('monthPicker');
            yearPicker = document.getElementById('yearPicker');
            dayIncrementBtn = document.getElementById('dayIncrementBtn');
            dayDecrementBtn = document.getElementById('dayDecrementBtn');
            dayInput = document.getElementById('dayInput');
            totalDate = document.getElementById('totalDate');
            deleteBtn = document.getElementById('deleteBtn');
            cancelBtn = document.getElementById('cancelBtn');
            saveBtn = document.getElementById('saveBtn');

            //Configure the content
            const dateStart = targetTask.dateStart,
                dateEnd = targetTask.dateEnd;

            if (!dateStart || !dateEnd) {
                taskLabel.innerHTML = '';
            }
            else {
                const dayFormat = ['2-digit', 'numeric'][gantt.dayFormat] || 'numeric';

                taskLabel.innerHTML = dateStart.toLocaleDateString(gantt.locale, { day: dayFormat, month: gantt.monthFormat, year: gantt.yearFormat }) + ' - ' +
                    dateEnd.toLocaleDateString(gantt.locale, { day: dayFormat, month: gantt.monthFormat, year: gantt.yearFormat });
            }

            description.value = targetTask.label;
            dayPicker.value = dateStart.getDate();
            monthPicker.value = dateStart.getMonth();
            yearPicker.value = dateStart.getFullYear();
            dayInput.value = targetTask.duration.toString();
            totalDate.innerHTML = targetTask.dateEnd.toDateString();

            if (addListeners) {
                dayIncrementBtn.addEventListener('click', function () {
                    dayInput.value = (Math.min(31, (parseInt(dayInput.value) || 0) + 1)).toString();
                    updateTotalDate();
                });

                dayDecrementBtn.addEventListener('click', function () {
                    dayInput.value = Math.max(1, (parseInt(dayInput.value) || 0) - 1).toString();
                    updateTotalDate();
                });

                deleteBtn.addEventListener('click', deleteTask);
                cancelBtn.addEventListener('click', cancelTask);
                saveBtn.addEventListener('click', saveTask);
            }
        }
    };

The popupWindowCustomizationFunction function is called every time the window is opened.

Then we define the functions that will apply the different actions that corresponding to the clicked button

    ...

    function updateTotalDate() {
        let newDateEnd = new Date(parseInt(yearPicker.value), parseInt(monthPicker.value), parseInt(dayPicker.value));

        newDateEnd.setDate(newDateEnd.getDate() + parseInt(dayInput.value));

        if (isNaN(newDateEnd.getTime())) {
            totalDate.innerHTML = '';
            return;
        }

        totalDate.innerHTML = newDateEnd.toDateString();
    }

    function deleteTask() {
        gantt.removeTask(editedTaskIndex);
        gantt.closeWindow();
        editedTaskIndex = undefined;
    };

    function cancelTask() {
        gantt.closeWindow();
    };

    function saveTask() {
        let dateStart = new Date(parseInt(yearPicker.value), parseInt(monthPicker.value), parseInt(dayPicker.value)),
            duration = parseInt(dayInput.value);

        gantt.updateTask(editedTaskIndex, { label: description.value, dateStart: dateStart, duration: duration });
        gantt.closeWindow();
        editedTaskIndex = undefined;
    };

In the current example three buttons are used to save the changed to the clicked task via the updateTask method, remove the task via the removeTask method and cancel which cancels the changes and closes the window via the closeWindow method.

Note: The demo used in this section is available on the website: Link

Editor Window Methods

There are two methods that are documented in the API of the GanttChart element
  • openWindow - opens the editing window. The method accepts one argument - the id/index/path of a task or the id of a connection. If the argument is correct the corresponding editor window will open.
    const gantt = document.querySelector('smart-gantt-chart');
    
    gantt.openWindow(0);
    

    Calling the openWindow with argument '0' will open the Window to edit the Task with index 0 ( the first task ).

  • closeWindow - closes all opened editor windows.
    const gantt = document.querySelector('smart-gantt-chart');
    
    gantt.closeWindow();
    

Editor Window Events

  • opening - the opening action of the editor window can be prevented by adding an event listener to the opening event of the GanttChart element which is fired when the editor window is about to open.
       ganttChart.addEventListener('opening', function (event) {
            event.preventDefault();
        })
    
  • open - fired when the editor window is opened.
       ganttChart.addEventListener('open', function (event) {
            //Do something here...
        })
    
  • close - fired when the editor window is closed.
       ganttChart.addEventListener('open', function (event) {
            //Do something here...
        })
    
  • closing - simiral to the opening event, closing is fired before the window is closed and the action can also be prevented.
       ganttChart.addEventListener('closing', function (event) {
            event.preventDefault();
        })
    

Keyboard Navigation

Keyboard navigation inside the Window is enabled by default when the window is focused.
Key Action
Escape Pressing the 'Escape' key will close the window.
Tab Pressing Tab will change the focus of the different elements inside the window.
Control + Arrow Up/Down/Left/Right Pressing an Arrow key while Control is pressed allows to drag the window in the direction of the arrow.