How to embed ColorPicker in JavaScript Gantt for changing the color of tasks


Hi, my name is Zhenya, and I'm just one of the inhabitants of the JavaScript universe who wants to share with you interesting experience in frontend development, namely how to customize the Gantt chart.


, . , :



. .


, . β€” . , , JavaScript .


, . :


  • , ,

JavaScript DHTMLX Gantt. , , β€” .


β€” :


  • GPL v2 ;
  • 700$ 3000$ .

β€” .


, GPL GPLv2 , (TLDRlegal). , β€” / front-end/ , . , , . - , .


DHTMLX JavaScript . , , .


.



DHTMLX Gantt :



, . DHTMLX Gantt, β€” color picker, . .



HTML5 JavaScript, .


. JS CSS , , ( ):


<!DOCTYPE html>
<html>
<head>
   <script src="codebase/dhtmlxgantt.js"></script>
   <link href="codebase/dhtmlxgantt.css" rel="stylesheet">
</head>
<body>
    <div id="gantt_here" style='width:100vw; height:100vh;'></div>
    <script>
      window.addEventListener("DOMContentLoaded",() => {
       gantt.init("gantt_here");
      });
   </script>
</body>
</html>

HTML js , , , . 1 ( ) 2 ( ). , , ( ):


gantt.parse({
    data: [
      {
        id: 1, text: "  ", start_date: "01-05-2020", duration: 18, open: true
      },
      {
        id: 2, text: "  ", start_date: "02-05-2020", duration: 4, parent: 1
      },
      {
        id: 3, text: "  ", start_date: "07-05-2020", duration: 5, parent: 1
      }
    ],
    links: [
      {id: 1, source: 1, target: 2, type: "1"},
      {id: 2, source: 2, target: 3, type: "0"}
    ]
  });
});


.


Inline Editors


: , , .


, editor:


gantt.config.columns = [
      {name: "text", tree: true, width: '*', resize: true, editor: textEditor},
      {name: "start_date", align: "center", resize: true, editor: dateEditor},
      {name: "duration", align: "center", editor: durationEditor},
      {name: "add", width: 44}
];

type, , map_to, , . , , :


const textEditor = {type: "text", map_to: "text"};
const dateEditor = {type: "date", map_to: "start_date", min: new Date(2020, 0, 1), 
    max: new Date(2021, 0, 1)};
const durationEditor = {type: "number", map_to: "duration", min:0, max: 100};

.



, .


, : (select) (color picker). , -colorpicker.


, HTML5 input color, .


. :


gantt.config.editor_types.custom_editor = {
  show: (id, column, config, placeholder) => {
    // called when input is displayed, put html markup of the editor into placeholder

    // and initialize your editor if needed:
        placeholder.innerHTML `<div><input type='text' name='${column.name}'></div>`;
  },

  hide: () => {
    // called when input is hidden 
    // destroy any complex editors or detach event listeners from here
  },

  set_value: (value, id, column, node) => {
    // set input value
  },

  get_value: (id, column, node) => {
    // return input value
  }, 

  is_changed: (value, id, column, node) => {
    // called before save/close. Return true if new value differs from the original one
    // returning true will trigger saving changes, returning false will skip saving 
  },

  is_valid: (value, id, column, node) => {
    // validate, changes will be discarded if the method returns false
    return true/false;
  },

  save: (id, column, node) => {
     // only for inputs with map_to:auto. complex save behavior goes here
  },

  focus: (node) => {                                                 
  }
}

, :


  1. show, color:


    gantt.config.editor_types.color = {
      show: (id, column, config, placeholder) => {
        placeholder.innerHTML = `<div><input type='color' name='${column.name}'></div>`;
      },

  2. hide , , , :


    hide: () => {},

  3. β€” set_value get_value:


    set_value: (value, id, column, node) => {
      const input = node.querySelector("input");
      input.value = value   
    },
    get_value: (id, column, node) => {
      const input = node.querySelector("input");
      return input.value;
    },

    , task. , , .


  4. is_changed. , , :


    is_changed: (value, id, column, node) => {
      const input = node.querySelector("input");
      return input.value !== value;
    },

    , , true, . true , false .


  5. is_valid , false, , :


    is_valid: (value, id, column, node) => {
      const input = node.querySelector("input");
      return !!input.value;
    },

  6. save , , , .


  7. focus :


    focus: node => {
      const input = node.querySelector("input");
      input.focus();
    },

    .




.
. type , ( type: β€œcolor”).


  const textEditor = {type: "text", map_to: "text"};
  const dateEditor = {type: "date", map_to: "start_date", min: new Date(2020, 0, 1), 
      max: new Date(2021, 0, 1)};
  const durationEditor = {type: "number", map_to: "duration", min:0, max: 100};
  const colorEditor = {type: "color", map_to: "color"};
  gantt.config.columns = [
      {name: "text", tree: true, width: '*', resize: true, editor: textEditor},
      {name: "start_date", align: "center", resize: true, editor: dateEditor},
      {name: "duration", align: "center", editor: durationEditor},
      {name: "color", align: "center", editor: colorEditor},
      {name: "add", width: 44}
  ];

color, . , , β€” , color:"#FF0000":


{
    id: 2, text: "  ", start_date: "02-05-2020", duration: 4, parent: 1, color:"#FF0000"
},


, , β€œcolor” . :


gantt.config.columns = [
      {name: "text", tree: true, width: '*', resize: true, editor: textEditor},
      {name: "start_date", align: "center", resize: true, editor: dateEditor},
      {name: "duration", align: "center", editor: durationEditor},
      {name: "color", align: "center", label:"Color", editor: colorEditor, template:
       (task) => {
          return `<div class='task-color-cell' style='background:${task.color}'></div>`
        }
       },
      {name: "add", width: 44}
];

, div . css , :


 .task-color-cell{
    margin:10%;
    width:20px;
    height:20px;
    border:1px solid #cecece;
    display:inline-block;
    border-radius:20px;
}


: https://plnkr.co/edit/yGWtLzoELPrhJV2K?preview


Color Picker


DHTMLX Gantt , , jquery Spectrum.


:


<!DOCTYPE html>
<html>
  <head>
     <script src="https://docs.dhtmlx.com/gantt/codebase/dhtmlxgantt.js"></script>   
     <link rel="stylesheet"href="https://docs.dhtmlx.com/gantt/codebase/dhtmlxgantt.css">
     <script
    src="http://code.jquery.com/jquery-3.3.1.min.js"
    integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
    crossorigin="anonymous"></script>
     <script src="http://bgrins.imtqy.com/spectrum/spectrum.js"></script>
     <link rel="stylesheet" href="http://bgrins.imtqy.com/spectrum/spectrum.css">
     <script src="script.js"></script>
     <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div id="gantt_here"></div>
  </body>
</html>

. let editor, . , , input .
show. , .


: editor.spectrum("show") show, . , show placeholder- . -, color picker , placeholder .


document.addEventListener("DOMContentLoaded", function(event) {
  let editor;
  gantt.config.editor_types.color = {
    show: (id, column, config, placeholder) => {
          placeholder.innerHTML = `<div><input type='color' name='${column.name}'></div>`;

          editor = $(placeholder).find("input").spectrum({
            change:() => {
              gantt.ext.inlineEditors.save();
            }
          });
          setTimeout(() => {
            editor.spectrum("show");
          })
    }

Next, I defined the β€œhide” method - the destructor will be called when the editor is closed:


hide: () => {
    if(editor){
      editor.spectrum("destroy");
      editor = null;
    }

The remaining methods are not too different from the original implementation. You just need to change the way you get the values ​​from the control:


 set_value: (value, id, column, node) => {
    editor.spectrum("set", value);
  },
  get_value: (id, column, node) => {
    return editor.spectrum("get").toHexString();
  },
  is_changed: function (value, id, column, node) {
    const newValue = this.get_value(id, column, node);
    return newValue !== value;
  },
  is_valid: function (value, id, column, node) {
    const newValue = this.get_value(id, column, node);
    return !!newValue;
  },
  focus:(node) => {
    editor.spectrum("show");
  }


After that, everything should work as expected!


And this is a link to my example with the built-in Color Picker .


I hope this article helps you in adjusting the color of tasks in the Gantt chart.


All Articles