/* @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; } });