/* @private
* Internal drag zone implementation for the calendar day and week views.
*/
Ext.ensible.cal.DayViewDragZone = Ext.extend(Ext.ensible.cal.DragZone, {
ddGroup : 'DayViewDD',
resizeSelector : '.ext-evt-rsz',
getDragData : function(e){
var t = e.getTarget(this.resizeSelector, 2, true);
if(t){
var p = t.parent(this.eventSelector),
rec = this.view.getEventRecordFromEl(p);
if(!rec){
// if rec is null here it usually means there was a timing issue between drag
// start and the browser reporting it properly. Simply ignore and it will
// resolve correctly once the browser catches up.
return;
}
return {
type: 'eventresize',
xy: e.xy,
ddel: p.dom,
eventStart: rec.data[Ext.ensible.cal.EventMappings.StartDate.name],
eventEnd: rec.data[Ext.ensible.cal.EventMappings.EndDate.name],
proxy: this.proxy
};
}
var t = e.getTarget(this.eventSelector, 3);
if(t){
var rec = this.view.getEventRecordFromEl(t);
if(!rec){
// if rec is null here it usually means there was a timing issue between drag
// start and the browser reporting it properly. Simply ignore and it will
// resolve correctly once the browser catches up.
return;
}
return {
type: 'eventdrag',
xy: e.xy,
ddel: t,
eventStart: rec.data[Ext.ensible.cal.EventMappings.StartDate.name],
eventEnd: rec.data[Ext.ensible.cal.EventMappings.EndDate.name],
proxy: this.proxy
};
}
// If not dragging/resizing an event then we are dragging on
// the calendar to add a new event
t = this.view.getDayAt(e.xy[0], e.xy[1]);
if(t.el){
return {
type: 'caldrag',
dayInfo: t,
proxy: this.proxy
};
}
return null;
}
});
/* @private
* Internal drop zone implementation for the calendar day and week views.
*/
Ext.ensible.cal.DayViewDropZone = Ext.extend(Ext.ensible.cal.DropZone, {
ddGroup : 'DayViewDD',
dateRangeFormat : '{0}-{1}',
dateFormat : 'n/j',
onNodeOver : function(n, dd, e, data){
var dt, text = this.createText,
timeFormat = Ext.ensible.Date.use24HourTime ? 'G:i' : 'g:ia';
if(data.type == 'caldrag'){
if(!this.dragStartMarker){
// Since the container can scroll, this gets a little tricky.
// There is no el in the DOM that we can measure by default since
// the box is simply calculated from the original drag start (as opposed
// to dragging or resizing the event where the orig event box is present).
// To work around this we add a placeholder el into the DOM and give it
// the original starting time's box so that we can grab its updated
// box measurements as the underlying container scrolls up or down.
// This placeholder is removed in onNodeDrop.
this.dragStartMarker = n.el.parent().createChild({
style: 'position:absolute;'
});
// use the original dayInfo values from the drag start
this.dragStartMarker.setBox(data.dayInfo.timeBox);
this.dragCreateDt = data.dayInfo.date;
}
var endDt, box = this.dragStartMarker.getBox();
box.height = Math.ceil(Math.abs(e.xy[1] - box.y) / n.timeBox.height) * n.timeBox.height;
if(e.xy[1] < box.y){
box.height += n.timeBox.height;
box.y = box.y - box.height + n.timeBox.height;
endDt = this.dragCreateDt.add(Date.MINUTE, this.ddIncrement);
}
else{
n.date = n.date.add(Date.MINUTE, this.ddIncrement);
}
this.shim(this.dragCreateDt, box);
var curr = Ext.ensible.Date.copyTime(n.date, this.dragCreateDt);
this.dragStartDate = Ext.ensible.Date.min(this.dragCreateDt, curr);
this.dragEndDate = endDt || Ext.ensible.Date.max(this.dragCreateDt, curr);
dt = String.format(this.dateRangeFormat, this.dragStartDate.format(timeFormat), this.dragEndDate.format(timeFormat));
}
else{
var evtEl = Ext.get(data.ddel),
dayCol = evtEl.parent().parent(),
box = evtEl.getBox();
box.width = dayCol.getWidth();
if(data.type == 'eventdrag'){
if(this.dragOffset === undefined){
// on fast drags there is a lag between the original drag start xy position and
// that first detected within the drop zone's getTargetFromEvent method (which is
// where n.timeBox comes from). to avoid a bad offset we calculate the
// timeBox based on the initial drag xy, not the current target xy.
var initialTimeBox = this.view.getDayAt(data.xy[0], data.xy[1]).timeBox;
this.dragOffset = initialTimeBox.y - box.y;
}
else{
box.y = n.timeBox.y;
}
dt = n.date.format(this.dateFormat + ' ' + timeFormat);
box.x = n.el.getLeft();
this.shim(n.date, box);
text = this.moveText;
}
if(data.type == 'eventresize'){
if(!this.resizeDt){
this.resizeDt = n.date;
}
box.x = dayCol.getLeft();
box.height = Math.ceil(Math.abs(e.xy[1] - box.y) / n.timeBox.height) * n.timeBox.height;
if(e.xy[1] < box.y){
box.y -= box.height;
}
else{
n.date = n.date.add(Date.MINUTE, this.ddIncrement);
}
this.shim(this.resizeDt, box);
var curr = Ext.ensible.Date.copyTime(n.date, this.resizeDt),
start = Ext.ensible.Date.min(data.eventStart, curr),
end = Ext.ensible.Date.max(data.eventStart, curr);
data.resizeDates = {
StartDate: start,
EndDate: end
}
dt = String.format(this.dateRangeFormat, start.format(timeFormat), end.format(timeFormat));
text = this.resizeText;
}
}
data.proxy.updateMsg(String.format(text, dt));
return this.dropAllowed;
},
shim : function(dt, box){
Ext.each(this.shims, function(shim){
if(shim){
shim.isActive = false;
shim.hide();
}
});
var shim = this.shims[0];
if(!shim){
shim = this.createShim();
this.shims[0] = shim;
}
shim.isActive = true;
shim.show();
shim.setBox(box);
},
onNodeDrop : function(n, dd, e, data){
if(n && data){
if(data.type == 'eventdrag'){
var rec = this.view.getEventRecordFromEl(data.ddel);
this.view.onEventDrop(rec, n.date);
this.onCalendarDragComplete();
delete this.dragOffset;
return true;
}
if(data.type == 'eventresize'){
var rec = this.view.getEventRecordFromEl(data.ddel);
this.view.onEventResize(rec, data.resizeDates);
this.onCalendarDragComplete();
delete this.resizeDt;
return true;
}
if(data.type == 'caldrag'){
Ext.destroy(this.dragStartMarker);
delete this.dragStartMarker;
delete this.dragCreateDt;
this.view.onCalendarEndDrag(this.dragStartDate, this.dragEndDate,
this.onCalendarDragComplete.createDelegate(this));
//shims are NOT cleared here -- they stay visible until the handling
//code calls the onCalendarDragComplete callback which hides them.
return true;
}
}
this.onCalendarDragComplete();
return false;
}
});