/* @private * Internal drag zone implementation for the calendar components. This provides base functionality * and is primarily for the month view -- DayViewDD adds day/week view-specific functionality. */ Ext.ensible.cal.DragZone = Ext.extend(Ext.dd.DragZone, { ddGroup : 'CalendarDD', eventSelector : '.ext-cal-evt', constructor : function(el, config){ if(!Ext.ensible.cal._statusProxyInstance){ Ext.ensible.cal._statusProxyInstance = new Ext.ensible.cal.StatusProxy(); } this.proxy = Ext.ensible.cal._statusProxyInstance; Ext.ensible.cal.DragZone.superclass.constructor.call(this, el, config); }, getDragData : function(e){ // Check whether we are dragging on an event first 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', 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 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', start: t.date, proxy: this.proxy }; } return null; }, onInitDrag : function(x, y){ if(this.dragData.ddel){ var ghost = this.dragData.ddel.cloneNode(true), child = Ext.fly(ghost).child('dl'); Ext.fly(ghost).setWidth('auto'); if(child){ // for IE/Opera child.setHeight('auto'); } this.proxy.update(ghost); this.onStartDrag(x, y); } else if(this.dragData.start){ this.onStartDrag(x, y); } this.view.onInitDrag(); return true; }, afterRepair : function(){ if(Ext.enableFx && this.dragData.ddel){ Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || 'c3daf9'); } this.dragging = false; }, getRepairXY : function(e){ if(this.dragData.ddel){ return Ext.Element.fly(this.dragData.ddel).getXY(); } }, afterInvalidDrop : function(e, id){ Ext.select('.ext-dd-shim').hide(); }, destroy : function(){ Ext.ensible.cal.DragZone.superclass.destroy.call(this); delete Ext.ensible.cal._statusProxyInstance; } }); /* @private * Internal drop zone implementation for the calendar components. This provides base functionality * and is primarily for the month view -- DayViewDD adds day/week view-specific functionality. */ Ext.ensible.cal.DropZone = Ext.extend(Ext.dd.DropZone, { ddGroup : 'CalendarDD', eventSelector : '.ext-cal-evt', dateRangeFormat : '{0}-{1}', dateFormat : 'n/j', // private shims : [], getTargetFromEvent : function(e){ var dragOffset = this.dragOffset || 0, y = e.getPageY() - dragOffset, d = this.view.getDayAt(e.getPageX(), y); return d.el ? d : null; }, onNodeOver : function(n, dd, e, data){ var D = Ext.ensible.Date, start = data.type == 'eventdrag' ? n.date : D.min(data.start, n.date), end = data.type == 'eventdrag' ? n.date.add(Date.DAY, D.diffDays(data.eventStart, data.eventEnd)) : D.max(data.start, n.date); if(!this.dragStartDate || !this.dragEndDate || (D.diffDays(start, this.dragStartDate) != 0) || (D.diffDays(end, this.dragEndDate) != 0)){ this.dragStartDate = start; this.dragEndDate = end.clearTime().add(Date.DAY, 1).add(Date.MINUTE, -30); this.shim(start, end); var range = start.format(this.dateFormat); if(D.diffDays(start, end) > 0){ end = end.format(this.dateFormat); range = String.format(this.dateRangeFormat, range, end); } var msg = String.format(data.type == 'eventdrag' ? this.moveText : this.createText, range); data.proxy.updateMsg(msg); } return this.dropAllowed; }, shim : function(start, end){ this.currWeek = -1; var dt = start.clone(), i = 0, shim, box, cnt = Ext.ensible.Date.diffDays(dt, end)+1 Ext.each(this.shims, function(shim){ if(shim){ shim.isActive = false; } }); while(i++ < cnt){ var dayEl = this.view.getDayEl(dt); // if the date is not in the current view ignore it (this // can happen when an event is dragged to the end of the // month so that it ends outside the view) if(dayEl){ var wk = this.view.getWeekIndex(dt), shim = this.shims[wk]; if(!shim){ shim = this.createShim(); this.shims[wk] = shim; } if(wk != this.currWeek){ shim.boxInfo = dayEl.getBox(); this.currWeek = wk; } else{ box = dayEl.getBox(); shim.boxInfo.right = box.right; shim.boxInfo.width = box.right - shim.boxInfo.x; } shim.isActive = true; } dt = dt.add(Date.DAY, 1); } Ext.each(this.shims, function(shim){ if(shim){ if(shim.isActive){ shim.show(); shim.setBox(shim.boxInfo); } else if(shim.isVisible()){ shim.hide(); } } }); }, createShim : function(){ var owner = this.view.ownerCalendarPanel ? this.view.ownerCalendarPanel : this.view; if(!this.shimCt){ this.shimCt = Ext.get('ext-dd-shim-ct-'+owner.id); if(!this.shimCt){ this.shimCt = document.createElement('div'); this.shimCt.id = 'ext-dd-shim-ct-'+owner.id; owner.getEl().parent().appendChild(this.shimCt); } } var el = document.createElement('div'); el.className = 'ext-dd-shim'; this.shimCt.appendChild(el); return new Ext.Layer({ shadow:false, useDisplay:true, constrain:false }, el); }, clearShims : function(){ Ext.each(this.shims, function(shim){ if(shim){ shim.hide(); } }); }, onContainerOver : function(dd, e, data){ return this.dropAllowed; }, onCalendarDragComplete : function(){ delete this.dragStartDate; delete this.dragEndDate; this.clearShims(); }, onNodeDrop : function(n, dd, e, data){ if(n && data){ if(data.type == 'eventdrag'){ var rec = this.view.getEventRecordFromEl(data.ddel), dt = Ext.ensible.Date.copyTime(rec.data[Ext.ensible.cal.EventMappings.StartDate.name], n.date); this.view.onEventDrop(rec, dt); this.onCalendarDragComplete(); return true; } if(data.type == 'caldrag'){ 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; }, onContainerDrop : function(dd, e, data){ this.onCalendarDragComplete(); return false; } });