Multiple sequent events per single item - place on own row

I’m setting up the timeline scheduler, where each source item can have multiple timeline ranges. In case if ranges per item overlap each other, they’re placed on its own row, which is fine. When they do not overlap (say, March 1-15 and March 16-18), they’re placed on the same row. How can I force them to take separate rows?


I would like to have something to docs.dhtmlx.com/scheduler/api__ … onfig.html, but in a timeline view.

Hello,

Unfortunately by default the task takes the first available free place from the top and currently there is no built-on solution to display all tasks in separate row in the Timeline view.

Hi there, wondering if you’ve a solution for above query?

Hi Team,
Is there a fix for this, I need the same behaviour ?

Please suggest some workaround if it is not possible in a straight forward approach, this is very critical please help

Hello,

starting from dhtmlxScheduler v6.0.0 you can override the size and position of the event by redefining getEventTop/getEventHeight/getSectionHeight methods of the timeline,
which allows you to place events into custom subrows.

Please check this example:
https://snippet.dhtmlx.com/017nx1ru

Currently, scheduler can’t automatically adjust the heights of sections to custom positions of bars so you need to manually override the sizes of the sections in order to fit all needed subrows.
It was supposed to be done using getSectionHeight setting, but there appears to be a bug with it, so the example contains a workaround using ‘onBeforeViewChange’ event.

relevant code:

var subrowHeight = 25;
function getSectionEvents(sectionId) {
	var state = scheduler.getState();
	var sectionProperty = scheduler.getView().y_property;
	return scheduler.getEvents(state.min_date, state.max_date).filter(function (ev) {
		return ev[sectionProperty] == sectionId;
	}).sort(function (a, b) {
		if (a.start_date.valueOf() == b.start_date.valueOf())
			return a.id > b.id ? 1 : -1;
		return a.start_date > b.start_date ? 1 : -1;
	});
}

function getSection(sectionId) {
	return scheduler.serverList("rooms").find(function (section) {
		return section.key == sectionId;
	});
}
scheduler.createTimelineView({
	name: "timeline",
	x_unit: "minute",
	x_date: "%H:%i",
	x_step: 30,
	x_size: 24,
	x_start: 16,
	x_length: 48,
	y_unit: scheduler.serverList("rooms"),
	y_property: "room_id",
	render: "bar",
	dx: 200,
	getEventTop: function (event) {
		var sectionEvents = getSectionEvents(event.room_id);
		var index = 0;
		for (var i = 0; i < sectionEvents.length; i++) {
			if (sectionEvents[i].id == event.id) {
				index = i;
				break;
			}
		}

		var eventHeight = index * subrowHeight;
		var section = getSection(event.room_id);
		return Math.min(eventHeight, section.height - subrowHeight - 1);
	},
	getEventHeight: function (event) {
		return subrowHeight - 2;
	},
	getSectionHeight: function (section) {
		var eventCount = getSectionEvents(section.key).length || 1;

		return eventCount * subrowHeight;
	},
});
// as of v6.0.0 `timeline.getSectionHeight` works incorrectly, internal issue code: GS-1862
// need workaround in onBeforeViewChange to set custom dynamic height for sections
scheduler.attachEvent("onBeforeViewChange", function (old_mode, old_date, mode, date) {
	if (scheduler.getView(mode) && scheduler.getView(mode).y_unit) {
		var timeline = scheduler.getView(mode);
		var sections = timeline.y_unit;
		var minDate = new Date(scheduler.date[`${mode}_start`](date));
		var maxDate = scheduler.date.add(minDate, 1, mode);
		sections.forEach(function (section) {
			var sectionProperty = timeline.y_property;
			var sectionEvents = scheduler.getEvents(minDate, maxDate).filter(function (ev) {
				return ev[sectionProperty] == section.key;
			});
			var eventCount = sectionEvents.length || 1;
			section.height = eventCount * subrowHeight + 1;
			console.log(section);
		});
	}
	return true;
});

// redraw scheduler after event modified in order to readjust heights of sections
function repaintOnUpdate() {
	requestAnimationFrame(function () {
		scheduler.render();
	});
}
scheduler.attachEvent("onEventAdded", repaintOnUpdate);
scheduler.attachEvent("onEventChanged", repaintOnUpdate);
scheduler.attachEvent("onEventDeleted", repaintOnUpdate);

// end workaround

Thanks Aliaksandr will check this out

1 Like

Hi Aliaksandr, I tried to apply the above implementation to my treetimeline,

but in my case they are all moved to separated rows as expected but they are not plotted on the right dates,

Let me just share the relevant snippet of it, what am I missing. I am plotting using scheduler.parse()

    ``` getSectionEvents(sectionId) {
        var state = this._schedulerInstance.getState();
        var sectionProperty = this._schedulerInstance.getView().y_property;
        return this._schedulerInstance.getEvents(state.min_date, state.max_date).filter(function (ev) {
            return ev[sectionProperty] == sectionId;
        }).sort(function (a, b) {
            if (a.start_date.valueOf() === b.start_date.valueOf())
                return a.id > b.id ? 1 : -1;
            return a.start_date > b.start_date ? 1 : -1;
        });
    }```
```return {
            section_autoheight: false,
            cell_template: true,
            name: "timeline",
            x_unit: "day",
            x_date: "%D %d",
            x_step: 1,
            x_size: 7,
            x_length: 25,
            y_unit: elements,
            y_property: "section_id",
            render: "tree",
            folder_dy: 92,
            dy: 250,
            dx: 220,
            getEventTop: (event) => {
                let sectionEvents = this.getSectionEvents(event.section_id);
                let index = 0;
                for (let i = 0; i < sectionEvents.length; i++) {
                    if (sectionEvents[i].id === event.id) {
                        index = i;
                        break;
                    }
                }
                let eventHeight = index * SUB_ROW_HEIGHT;
                return eventHeight;
            }
        };

I am not using onBeforeEventAttached in my case.

Hi Chris!

I can’t see any issues in your code, and overriding the top position shouldn’t affect the placement of events on the time axis. So I’m not sure what may be wrong

I’ve modified my snippet in order for it to work with the TreeTimeline, changes were required for the getSection(sectionId) function in order to make it work with a hierarchical list of sections. But otherwise, everything works as expected:
https://snippet.dhtmlx.com/n9qs8c3e

If you continue having this issue, can you pls PM me a complete js/html example that I could run locally to debug the problem?

1 Like

Hey Hi @Aliaksandr, I identified the issue in my case the events are plotted as expected, but the section height is not dynamically increasing so remaning events are hidden below the next section.

In my case I will only have one open section, so I have to increase the height of that section to the number of events in the open section. How will I be able to increase the height of a particular section after scheduler.parse ?

I will know the current section’s Id I just have to increase that section’s id to number of events in that section ?

I was able to achieve this, thank you for your help. Much appreciated.

1 Like

Hi there, wondering if you’ve a solution for above query

Yes @Grace_J the above solution works

Hi,
Please take a look at the solutions above:

I have an issue with this, I am getting a lot of whitespace appended to the last when i try to increase the height please help on this

Hi,
Sorry, but I can’t understand why you’re getting white space in your app. Can you provide access to an application where the issue can be reproduced or send a demo and additional details? Then I might be able to help you.

Hi Maksim thanks for the quick help, It is integrated in a ember application Maksim it is difficult to showcase as a snippet but I can provide the highlights of the implementation.

We are using tree timeline and we are plotting the events. The events will be plotted in the form of lazy loading when the user scrolls to a certain point in the child section.

so whenever the viewport is visible we will trigger a method that will get the list of events that has to be plotted.

Everytime we use scheduler.parse([]) and append the data to it.

After plotting events we can this method, which increases the height of the current section.

		let events = timeline.selectEvents({
			section: this.constructTreeTimelineSectionId(),
		});
		let section = this.dhtmlxScheduler.schedulerInstance.getSection(this.constructTreeTimelineSectionId());
		section.height = Math.max(SUBROW_HEIGHT * events.length + 1, MIN_SECTION_HEIGHT);
		// adding offset height
		section.height += 15;
		this.dhtmlxScheduler.schedulerInstance.render();```

But at the end right I have a lot of empty space

![image|690x291](upload://k1TluKPkYNVqMVjKYNW4Lvv9vEH.png) 


Also after plotting the events in order to make it appear in a single row we use this below approach

```getEventTop: (event) => {
				var sectionEvents = this.getSectionEvents(event.section_id);
				let currentEventPlace = sectionEvents.findIndex(sectionEvent => sectionEvent.id === event.id);
				return currentEventPlace * SUBROW_HEIGHT;
			},
			getEventHeight: () => SUBROW_HEIGHT - 2
		};

Please help on this not sure why this is happening.
This is the element whose height is affecting

![image|668x500](upload://hVPaRSW5tSc2qppe6TGRtAzHBbJ.png)

Hi,
I can see no issues in your code. Maybe you can send me a zip archive with a standalone example or an online link to the page so I could debug it in my browser?
You can send it in private messages if you don’t want to share the link publicly.