I’m getting close to having a working context menu on my scheduler.
Here’s code which almost works:[code] var modified_event_id = null;
scheduler.templates.event_class = function(start, end, event) {
if (event.id == modified_event_id)
return “copied_event”;
return “”; // default
};
scheduler.attachEvent("onEventCopied", function(ev) {
dhtmlx.message("Event '<b>"+ev.TaskID+"</b>' copied");
modified_event_id = ev.id;
scheduler.updateEvent(ev.id);
});
scheduler.attachEvent("onEventCut", function(ev) {
dhtmlx.message("Event '<b>"+ev.TaskID+"</b>' cut");
modified_event_id = ev.id;
scheduler.updateEvent(ev.id);
});
scheduler.attachEvent("onEventPasted", function(isCopy, modified_ev, original_ev) {
modified_event_id = null;
scheduler.updateEvent(modified_ev.id);
var evs = scheduler.getEvents(modified_ev.start_date, modified_ev.end_date);
if (evs.length > 1) {
dhtmlx.modalbox({
text: "There is already an event here. What do you want to do?",
width: "500px",
position: "middle",
buttons:["Cancel", "Edit the event", "Save changes"],
callback: function(index) {
switch(+index) {
case 0:
if (isCopy) {
// This is a copy operation, delete new event
scheduler.deleteEvent(modified_ev.id);
} else {
// This is a cut operation, restore previous dates
modified_ev.start_date = original_ev.start_date;
modified_ev.end_date = original_ev.end_date;
scheduler.setCurrentView();
}
break;
case 1:
scheduler.showLightbox(modified_ev.id);
break;
case 2:
return;
}
}
});
}
});
var menu = new dhtmlXMenuObject();
menu.setSkin("dhx_terrace");
menu.setIconsPath("scheduler/ContextMenu/images/");
menu.renderAsContextMenu();
menu.loadStruct("scheduler/ContextMenu/dhxmenu.xml?e=" + new Date().getTime());
menu.attachEvent("onClick", function(id, e) {
var obj = scheduler.getActionData(e);
if(id == 'cut'){ // Check the ID of the clicked menu item
scheduler.callEvent("onEventCut", [e]);
}else if(id == 'copy'){
scheduler.callEvent("onEventCopied", [e]);
}else if(id == 'paste'){
var ev = scheduler.getEvent(scheduler._buffer_id);
if (ev) {
var event_duration = ev.end_date-ev.start_date;
if (isCopy) {
var new_ev = scheduler._lame_clone(ev);
// clear_event_after(new_ev);
new_ev.id = scheduler.uid();
new_ev.start_date = new Date(date);
new_ev.end_date = new Date(new_ev.start_date.valueOf() + event_duration);
scheduler.addEvent(new_ev);
scheduler.callEvent("onEventPasted", [isCopy, new_ev, ev]);
}else { // Cut operation
var copy = scheduler._lame_copy({}, ev);
//clear_event_after(copy);
copy.start_date = new Date(date);
copy.end_date = new Date(copy.start_date.valueOf() + event_duration);
var res = scheduler.callEvent("onBeforeEventChanged",[copy, e, false]);
if (res) {
ev.start_date = new Date(copy.start_date);
ev.end_date = new Date(copy.end_date);
scheduler.render_view_data(); // Redraw all events
scheduler.callEvent("onEventPasted", [isCopy, ev, copy]);
isCopy = true; // Switch to copy after first paste operation
}
}
}
}
return false;
});
scheduler.attachEvent("onContextMenu", function(event_id, native_event_object) {
if (event_id) {
var posx = 0;
var posy = 0;
if (native_event_object.pageX || native_event_object.pageY) {
posx = native_event_object.pageX;
posy = native_event_object.pageY;
} else if (native_event_object.clientX || native_event_object.clientY) {
posx = native_event_object.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = native_event_object.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
menu.showContextMenu(posx, posy);
return false; // Prevent default action and propagation
}
return true;
});[/code] What I've tried to do here is to call existing, working functions to avoid duplicating the code which is in the 'Cut/Copy/Paste' in dhtmlxscheduler_key_nav.js. However, when I right-click the event with ID '1', then select one of the menu items - say, 'Copy' - the message box displays "Event 'undefined' copied, whereas using the keyboard shortcut, it displays, correctly, "Event '1' copied". I'm obviously lost in how to pass the correct event details to these functions.
I then tried some code I found in this forum and substituted what I had with that, as in:[code] scheduler.attachEvent(“onEventCopied”, function(ev) {
dhtmlx.message(“Event '”+ev.TaskID+"’ copied");
modified_event_id = ev.id;
scheduler.updateEvent(ev.id);
});
scheduler.attachEvent("onEventCut", function(ev) {
dhtmlx.message("Event '<b>"+ev.TaskID+"</b>' cut");
modified_event_id = ev.id;
scheduler.updateEvent(ev.id);
});
scheduler.attachEvent("onEventPasted", function(isCopy, modified_ev, original_ev) {
modified_event_id = null;
scheduler.updateEvent(modified_ev.id);
var evs = scheduler.getEvents(modified_ev.start_date, modified_ev.end_date);
if (evs.length > 1) {
dhtmlx.modalbox({
text: "There is already an event here. What do you want to do?",
width: "500px",
position: "middle",
buttons:["Cancel", "Edit the event", "Save changes"],
callback: function(index) {
switch(+index) {
case 0:
if (isCopy) {
// This is a copy operation, delete new event
scheduler.deleteEvent(modified_ev.id);
} else {
// This is a cut operation, restore previous dates
modified_ev.start_date = original_ev.start_date;
modified_ev.end_date = original_ev.end_date;
scheduler.setCurrentView();
}
break;
case 1:
scheduler.showLightbox(modified_ev.id);
break;
case 2:
return;
}
}
});
}
});
var menu = new dhtmlXMenuObject();
menu.setSkin("dhx_terrace");
menu.setIconsPath("scheduler/ContextMenu/images/");
menu.renderAsContextMenu();
// menu.addContextZone(“scheduler_here”);
// menu.loadStruct(“scheduler/ContextMenu/dhxmenu.xml?e=” + new Date().getTime());
menu.addNewChild(null, 0, "menu_cb_copy", "Copy");
menu.addNewChild(null, 1, "menu_cb_cut", "Cut");
menu.addNewChild(null, 2, "menu_cb_paste", "Paste");
var event_id, cb_date, cb_isCopy, cb_section = null;
menu.attachEvent("onClick", function (id) {
eval(id)();
});
scheduler.attachEvent("onContextMenu", function (event_id_loc, native_event_object) {
event_id = event_id_loc;
//cb_date = scheduler.getActionData(native_event_object).date;
//cb_date = scheduler.getEvent(event_id_loc);
var event_loc = scheduler.getEvent(event_id_loc);
if (event_loc != null)
{
cb_date = event_loc.start_date;
}
else
{
//alert(event_id_loc);
//cb_date = scheduler.getActionData(native_event_object).date;
var pos = scheduler.getActionData(native_event_object);
var date;
var timeline = scheduler.matrix[scheduler.getState().mode];
if (timeline && timeline.days) {
date = new Date(pos.section);
date.setHours(pos.date.getHours());
date.setMinutes(pos.date.getMinutes());
} else {
date = new Date(pos.date);
}
cb_date = date;
}
//alert(cb_date);
cb_section = scheduler.getActionData(native_event_object).section;
//alert(cb_date);
/* Menu position */
var posx = 0;
var posy = 0;
if (native_event_object.pageX || native_event_object.pageY) {
posx = native_event_object.pageX;
posy = native_event_object.pageY;
} else if (native_event_object.clientX || native_event_object.clientY) {
posx = native_event_object.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = native_event_object.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
/* Menu items */
if (event_id) {
menu.showItem("menu_cb_copy");
menu.showItem("menu_cb_cut");
menu.hideItem("menu_cb_paste");
menu.showContextMenu(posx, posy);
}
else {
menu.hideItem("menu_cb_copy");
menu.hideItem("menu_cb_cut");
menu.showItem("menu_cb_paste");
menu.showContextMenu(posx, posy);
}
return false; // prevent default action and propagation
});
function menu_cb_copy() {
scheduler._buffer_id = event_id;
cb_isCopy = true;
scheduler.callEvent("onEventCopied", [scheduler.getEvent(event_id)]);
}
function menu_cb_cut() {
scheduler._buffer_id = event_id;
cb_isCopy = false;
scheduler.callEvent("onEventCut", [scheduler.getEvent(event_id)]);
}
function menu_cb_paste() {
var ev = scheduler.getEvent(scheduler._buffer_id);
if (ev) {
if (cb_isCopy) { // copy-paste
new_ev = _cb_make_paste_event(ev);
new_ev.id = scheduler.uid();
scheduler.addEvent(new_ev);
scheduler.callEvent("onEventPasted", [cb_isCopy, new_ev, ev]);
} else { // cut-paste
new_ev = _cb_make_paste_event(ev);
var a = scheduler.callEvent("onBeforeEventChanged", [new_ev, null, !1, ev]);
a && (scheduler.addEvent(new_ev), scheduler.callEvent("onEventPasted", [cb_isCopy, new_ev, ev]));
}
}
}
function _cb_make_paste_event(ev) {
var event_duration = ev.end_date - ev.start_date;
var new_ev = scheduler._lame_copy({}, ev);
//alert(cb_date);
new_ev.start_date = new Date(cb_date);
new_ev.end_date = new Date(new_ev.start_date.valueOf() + event_duration);
if (cb_section) {
var a = scheduler.getState().mode, d = null;
scheduler.matrix[a] ? d = scheduler.matrix[a].y_property : scheduler._props[a] && (d = scheduler._props[a].property), new_ev[d] = cb_section;
}
return new_ev;
}[/code] With this, I get an error when right-clicking the event: " Object doesn't support property or method 'showItem'" That would seem to suggest that the 'menu' object isn't fully initialised.