Event multiselect on altKey


#1

I have a section with multiple events and would like to move 2 or more events at a time, by holding the altKey for selecting multiple events.

I haven’t found any solution on the documents, so I was wondering what could you or some one suggest to make it possible.
thanks


#2

Hi!

there is no built-in support for moving multiple events,
however, such functionality can be implemented using public API.

TLDR: here is a live example http://snippet.dhtmlx.com/5/aa031a9db

The first part is multiple selection. This is fairly simple - you define a variable when you store ids of selected events and manage selected ids using onClick and onEmptyClick events:

function getSelectedIds(){
	var res = [];
	for(var i in selectedEvents){
		res.push(i);
	}
	return res;
}

function repaintEvents(ids){
	ids.forEach(function(eventId){
		scheduler.updateEvent(eventId);
	});
}

var selectedEvents = {};
scheduler.attachEvent("onClick", function (id, e){
	if(e.altKey) {
		// add event to selection on alt+click
		selectedEvents[id] = true;
	}else{
		// select single event on click
		var previousSelection = getSelectedIds();
		selectedEvents = {};
		selectedEvents[id] = true;
		// repaint unselected events
		repaintEvents(previousSelection);
	}
	return true;
});

scheduler.attachEvent("onEmptyClick", function (id, e){
	// clear selection and repaint unselected events
	var previousSelection = getSelectedIds();
	selectedEvents = {};
	repaintEvents(previousSelection);
	return true;
});

After that you’ll be able to select multiple events and highlight them using event_class template:

scheduler.templates.event_class = function(start, end, event){
	var css = [];
	if(selectedEvents[event.id]){
		css.push("selected-event");
	}
	return css.join(" ");
};

Demo:http://snippet.dhtmlx.com/5/c9eb70158

Then, for moving events together, you can detect drag and drop using onEventDrag and manually update dates of all selected events.
In short, the code might look like the following:

// store the initial date of the moved event
// we'll need it to know the date difference between the original date and the current dnd date,
// in order to apply the same date shift to start/end dates of all selected events
var dragStartDate = null;

// and store initial dates of all moved events, so we could revert drag and drop if it's canceled from "onBeforeEventChange" 
var initialDates = {};

scheduler.attachEvent("onBeforeDrag", function (id, mode, e){
	// store all initial dates
	if(mode == "move"){
		dragStartDate = new Date(scheduler.getEvent(id).start_date);
		var selectedEvents = getSelectedIds();
		selectedEvents.forEach(function(id){
			var event = scheduler.getEvent(id);
			initialDates[id] = {
				start_date: new Date(event.start_date),
				end_date: new Date(event.end_date)
			};
		});
	}
	return true;
});


scheduler.attachEvent("onEventDrag", function (id, mode, e){
	if(mode == "move"){
		// calculate the date change so far
		var shift = scheduler.getEvent(id).start_date - dragStartDate;
		var selectedEvents = getSelectedIds();
		selectedEvents.forEach(function(selectedId){
			if(selectedId == id){
				return;
			}
			// and move all selected events by the same value
			var event = scheduler.getEvent(selectedId);
			event.start_date = new Date(initialDates[selectedId].start_date.valueOf() + shift);
			event.end_date = new Date(initialDates[selectedId].end_date.valueOf() + shift);
			// call udpateEvent in order to repaint connected events
			scheduler.updateEvent(selectedId);
		});
	}
	return true;
});


scheduler.attachEvent("onDragEnd", function(id, mode, e){
	if(mode == "move"){
		var selectedEvents = getSelectedIds();
		
		if(scheduler.getEvent(id).start_date.valueOf() == dragStartDate.valueOf()){
			// if the main event position hasn't changed after drag and drop,
			// it may mean that dnd was canceled and we must revert changes to the selected events
			var selectedEvents = getSelectedIds();
			selectedEvents.forEach(function(selectedId){
				if(selectedId == id){
					return;
				}
				var event = scheduler.getEvent(selectedId);
				event.start_date = new Date(initialDates[selectedId].start_date);
				event.end_date = new Date(initialDates[selectedId].end_date);
				scheduler.updateEvent(selectedId);
			});
		}else{
			// changes were applied, trigger data save for all dragged events
			selectedEvents.forEach(function(selectedId){
				if(selectedId == id){
					return;
				}
				scheduler.addEvent(scheduler.getEvent(id));
			});
		}
	}
	return true;
});

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