Can I show multiple baselines in one row?

Hi
I want the baseline to be the same like the task
(multi-line in one row).
Can I do it?

 gantt.attachEvent("onTaskClosed", function(id) {
	show_hidden_baseline(gantt.getTask(id));
 });


  function show_hidden_baseline (task) {
		if (!task.$open && gantt.hasChild(task.id)) {
			var sub_tasks = gantt.getChildren(task.id);
			substasks = [];

			for (var i = 0; i < sub_tasks.length; i++) {
				var child = gantt.getTask(sub_tasks[i]);
				var child_sizes = gantt.getTaskPosition(child, child.planned_start, child.planned_end);

				var left_position = child_sizes.left - gantt.getTaskPosition(task).left;
				var task_width = child_sizes.width;
				var task_top = child_sizes.top - 12;
				var task_height = child_sizes.height - 6;

				current_subtask = "<span class='subtask_base' style='position: absolute; left: "+left_position+"px; height: "+task_height+"px; width: "+task_width+"px; '></span >"

				substasks.push(current_subtask)
			}
			var baselineString = '';
			for (var i = 0; i < substasks.length; i++) {
				baselineString += substasks[i];
			}
			document.getElementById('baseline_'+task.id).innerHTML = baselineString;
		}
		return false;
	};

I succeeded with innerHTML.
However, if you do something different, the baseline disappears.
Can’t it be frozen until I open it?

Hi @chang,

the usual approach for adding extra elements into the chart is using gantt.addTaskLayer method.

Similarly to what is done in our baselines example, you can add additional lines into the chart:
https://docs.dhtmlx.com/gantt/samples/04_customization/15_baselines.html

If you want parent tasks to show the summary baseline for all nested tasks, it’s done the same way:

// get start/end dates of the baseline for a specific task

function getBaselineRange(task){
   // use tasks own baseline dates
   var range = { start_date: task.planned_start, 
                       end_date: task.planned_end};
  
   // but if it's closed parent task - get min/max dates of all nested baselines
   if(!task.$open && gantt.hasChild(task.id)){
     range.start_date = null;
     range.end_date = null;

     gantt.eachTask(function(child){
       if(child.planned_start && child.planned_end){
         if(!range.start_date || child.planned_start.valueOf() < range.start_date.valueOf()){
           range.start_date = child.planned_start; 
         }
         if(!range.end_date || child.planned_end.valueOf() > range.end_date.valueOf()){
           range.end_date = child.planned_end; 
         }
       }
     }, task.id);

   }else if(gantt.hasChild(task.id)){
     // if it's opened parent task - do not show baseline at all
     range.start_date = null;
     range.end_date = null;
   }
  return range;
}

addTaskLayer function:

gantt.addTaskLayer({
  renderer: {
    render: function draw_planned(task) {
      var range = getBaselineRange(task);
      if (range.start_date && range.end_date) {
        var sizes = gantt.getTaskPosition(task, range.start_date, range.end_date);
        var el = document.createElement('div');
        el.className = 'baseline';
        el.style.left = sizes.left + 'px';
        el.style.width = sizes.width + 'px';
        el.style.top = sizes.top + gantt.config.task_height + 13 + 'px';
        return el;
      }
      return false;
    },
    // define getRectangle in order to hook layer with the smart rendering
    getRectangle: function(task, view){
      var range = getBaselineRange(task);
      if (range.start_date && range.end_date) {
        return gantt.getTaskPosition(task, range.start_date, range.end_date);
      }
      return null;
    }
  }
});

Live demo: http://snippet.dhtmlx.com/5/eacb4acbd

hi:)
I want the child information to be shown in each parent, not a summary.
With the example given, can the child information be shown in one row each?

And does addTaskLayer work even if I specify multiple??

Do you mean you want to display baselines of each individual child in the parent row? I.e. not one element which goes from the start of the earliest baseline to the end of the latest baseline, but multiple individual baselines?

If you want gantt.addTaskLayer to make multiple visible elements, you need to create one parent node, append all visible elements to that parent node and return it from the render function.

Here is the modified example:
http://snippet.dhtmlx.com/5/618f4cd89

I’ve moved code that creates absolutely positioned item into a separate function:

// adding baseline display
function renderElement(row, start, end){
  // row - a task at which row the element will be displayed
  // start/end - dates 

  var sizes = gantt.getTaskPosition(row, start, end);
  var el = document.createElement('div');
  el.className = 'baseline';
  el.style.left = sizes.left + 'px';
  el.style.width = sizes.width + 'px';
  el.style.top = sizes.top + gantt.config.task_height + 13 + 'px';
  return el;
}

And here is how gantt.addTaskLayer can look after the changes:

gantt.addTaskLayer({
  renderer: {
    render: function draw_planned(task) {
      var result = null;
      if(gantt.hasChild(task.id)){

        // create a node element that will be returned from the function
        result = document.createElement("div");
        gantt.eachTask(function(child){
          if(child.planned_start && child.planned_end){
            // where you need to display multiple elements - you append them to the node you've created before
            // since element we create uses absolute positioning, they all will be visible		
            var childEl = renderElement(task, child.planned_start, child.planned_end);
            result.appendChild(childEl);
          }
           
        }, task.id);

      } else if (task.planned_start && task.planned_end) {
        result = renderElement(task, task.planned_start, task.planned_end);
      }

      // return the DOM element
      return result; 
    },
    // define getRectangle in order to hook layer with the smart rendering
    getRectangle: function(task, view){
      return true;
      var range = getBaselineRange(task);
      if (range.start_date && range.end_date) {
        return gantt.getTaskPosition(task, range.start_date, range.end_date);
      }
      return null;
    }
  }
});

HI!

The way I want is like a picture.
We completed the desired method using Aliaksandr’s function!
Here’s how I used it :slight_smile:

	gantt.addTaskLayer(function draw_planned(task) {
		if(!task.$open && gantt.hasChild(task.id) && task.planned_start && task.planned_end){
			var el = document.createElement('div');
				gantt.eachTask(function(child){
		          if(child.planned_start && child.planned_end){
		            // where you need to display multiple elements - you append them to the node you've created before
		            // since element we create uses absolute positioning, they all will be visible		
		            var childEl = renderElement(task, child.planned_start, child.planned_end);
		            el.appendChild(childEl);
		          }
		        }, task.id);
			return el;
		} else if (task.$open && task.planned_start && task.planned_end) {
			var el = renderElement(task, task.planned_start, task.planned_end);
			return el;
		}
		return false;
	});

Thank you.

2 Likes