Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / examples / calendar / src / dd / DayViewDD.js
1 /*!
2  * Ext JS Library 3.3.1
3  * Copyright(c) 2006-2010 Sencha Inc.
4  * licensing@sencha.com
5  * http://www.sencha.com/license
6  */
7 /*
8  * Internal drag zone implementation for the calendar day and week views.
9  */
10 Ext.calendar.DayViewDragZone = Ext.extend(Ext.calendar.DragZone, {
11     ddGroup: 'DayViewDD',
12     resizeSelector: '.ext-evt-rsz',
13
14     getDragData: function(e) {
15         var t = e.getTarget(this.resizeSelector, 2, true),
16             p,
17             rec;
18         if (t) {
19             p = t.parent(this.eventSelector);
20             rec = this.view.getEventRecordFromEl(p);
21
22             return {
23                 type: 'eventresize',
24                 ddel: p.dom,
25                 eventStart: rec.data[Ext.calendar.EventMappings.StartDate.name],
26                 eventEnd: rec.data[Ext.calendar.EventMappings.EndDate.name],
27                 proxy: this.proxy
28             };
29         }
30         t = e.getTarget(this.eventSelector, 3);
31         if (t) {
32             rec = this.view.getEventRecordFromEl(t);
33             return {
34                 type: 'eventdrag',
35                 ddel: t,
36                 eventStart: rec.data[Ext.calendar.EventMappings.StartDate.name],
37                 eventEnd: rec.data[Ext.calendar.EventMappings.EndDate.name],
38                 proxy: this.proxy
39             };
40         }
41
42         // If not dragging/resizing an event then we are dragging on
43         // the calendar to add a new event
44         t = this.view.getDayAt(e.getPageX(), e.getPageY());
45         if (t.el) {
46             return {
47                 type: 'caldrag',
48                 dayInfo: t,
49                 proxy: this.proxy
50             };
51         }
52         return null;
53     }
54 });
55
56 /*
57  * Internal drop zone implementation for the calendar day and week views.
58  */
59 Ext.calendar.DayViewDropZone = Ext.extend(Ext.calendar.DropZone, {
60     ddGroup: 'DayViewDD',
61
62     onNodeOver: function(n, dd, e, data) {
63         var dt,
64             box,
65             endDt,
66             text = this.createText,
67             curr,
68             start,
69             end,
70             evtEl,
71             dayCol;
72         if (data.type == 'caldrag') {
73             if (!this.dragStartMarker) {
74                 // Since the container can scroll, this gets a little tricky.
75                 // There is no el in the DOM that we can measure by default since
76                 // the box is simply calculated from the original drag start (as opposed
77                 // to dragging or resizing the event where the orig event box is present).
78                 // To work around this we add a placeholder el into the DOM and give it
79                 // the original starting time's box so that we can grab its updated
80                 // box measurements as the underlying container scrolls up or down.
81                 // This placeholder is removed in onNodeDrop.
82                 this.dragStartMarker = n.el.parent().createChild({
83                     style: 'position:absolute;'
84                 });
85                 this.dragStartMarker.setBox(n.timeBox);
86                 this.dragCreateDt = n.date;
87             }
88             box = this.dragStartMarker.getBox();
89             box.height = Math.ceil(Math.abs(e.xy[1] - box.y) / n.timeBox.height) * n.timeBox.height;
90
91             if (e.xy[1] < box.y) {
92                 box.height += n.timeBox.height;
93                 box.y = box.y - box.height + n.timeBox.height;
94                 endDt = this.dragCreateDt.add(Date.MINUTE, 30);
95             }
96             else {
97                 n.date = n.date.add(Date.MINUTE, 30);
98             }
99             this.shim(this.dragCreateDt, box);
100
101             curr = Ext.calendar.Date.copyTime(n.date, this.dragCreateDt);
102             this.dragStartDate = Ext.calendar.Date.min(this.dragCreateDt, curr);
103             this.dragEndDate = endDt || Ext.calendar.Date.max(this.dragCreateDt, curr);
104
105             dt = this.dragStartDate.format('g:ia-') + this.dragEndDate.format('g:ia');
106         }
107         else {
108             evtEl = Ext.get(data.ddel);
109             dayCol = evtEl.parent().parent();
110             box = evtEl.getBox();
111
112             box.width = dayCol.getWidth();
113
114             if (data.type == 'eventdrag') {
115                 if (this.dragOffset === undefined) {
116                     this.dragOffset = n.timeBox.y - box.y;
117                     box.y = n.timeBox.y - this.dragOffset;
118                 }
119                 else {
120                     box.y = n.timeBox.y;
121                 }
122                 dt = n.date.format('n/j g:ia');
123                 box.x = n.el.getLeft();
124
125                 this.shim(n.date, box);
126                 text = this.moveText;
127             }
128             if (data.type == 'eventresize') {
129                 if (!this.resizeDt) {
130                     this.resizeDt = n.date;
131                 }
132                 box.x = dayCol.getLeft();
133                 box.height = Math.ceil(Math.abs(e.xy[1] - box.y) / n.timeBox.height) * n.timeBox.height;
134                 if (e.xy[1] < box.y) {
135                     box.y -= box.height;
136                 }
137                 else {
138                     n.date = n.date.add(Date.MINUTE, 30);
139                 }
140                 this.shim(this.resizeDt, box);
141
142                 curr = Ext.calendar.Date.copyTime(n.date, this.resizeDt);
143                 start = Ext.calendar.Date.min(data.eventStart, curr);
144                 end = Ext.calendar.Date.max(data.eventStart, curr);
145
146                 data.resizeDates = {
147                     StartDate: start,
148                     EndDate: end
149                 };
150                 dt = start.format('g:ia-') + end.format('g:ia');
151                 text = this.resizeText;
152             }
153         }
154
155         data.proxy.updateMsg(String.format(text, dt));
156         return this.dropAllowed;
157     },
158
159     shim: function(dt, box) {
160         Ext.each(this.shims,
161         function(shim) {
162             if (shim) {
163                 shim.isActive = false;
164                 shim.hide();
165             }
166         });
167
168         var shim = this.shims[0];
169         if (!shim) {
170             shim = this.createShim();
171             this.shims[0] = shim;
172         }
173
174         shim.isActive = true;
175         shim.show();
176         shim.setBox(box);
177     },
178
179     onNodeDrop: function(n, dd, e, data) {
180         var rec;
181         if (n && data) {
182             if (data.type == 'eventdrag') {
183                 rec = this.view.getEventRecordFromEl(data.ddel);
184                 this.view.onEventDrop(rec, n.date);
185                 this.onCalendarDragComplete();
186                 delete this.dragOffset;
187                 return true;
188             }
189             if (data.type == 'eventresize') {
190                 rec = this.view.getEventRecordFromEl(data.ddel);
191                 this.view.onEventResize(rec, data.resizeDates);
192                 this.onCalendarDragComplete();
193                 delete this.resizeDt;
194                 return true;
195             }
196             if (data.type == 'caldrag') {
197                 Ext.destroy(this.dragStartMarker);
198                 delete this.dragStartMarker;
199                 delete this.dragCreateDt;
200                 this.view.onCalendarEndDrag(this.dragStartDate, this.dragEndDate,
201                 this.onCalendarDragComplete.createDelegate(this));
202                 //shims are NOT cleared here -- they stay visible until the handling
203                 //code calls the onCalendarDragComplete callback which hides them.
204                 return true;
205             }
206         }
207         this.onCalendarDragComplete();
208         return false;
209     }
210 });