Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / examples / calendar / src / widgets / DateRangeField.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  * @class Ext.calendar.DateRangeField
9  * @extends Ext.form.Field
10  * <p>A combination field that includes start and end dates and times, as well as an optional all-day checkbox.</p>
11  * @constructor
12  * @param {Object} config The config object
13  */
14 Ext.calendar.DateRangeField = Ext.extend(Ext.form.Field, {
15     /**
16      * @cfg {String} toText
17      * The text to display in between the date/time fields (defaults to 'to')
18      */
19     toText: 'to',
20     /**
21      * @cfg {String} toText
22      * The text to display as the label for the all day checkbox (defaults to 'All day')
23      */
24     allDayText: 'All day',
25
26     // private
27     onRender: function(ct, position) {
28         if (!this.el) {
29             this.startDate = new Ext.form.DateField({
30                 id: this.id + '-start-date',
31                 format: 'n/j/Y',
32                 width: 100,
33                 listeners: {
34                     'change': {
35                         fn: function() {
36                             this.checkDates('date', 'start');
37                         },
38                         scope: this
39                     }
40                 }
41             });
42             this.startTime = new Ext.form.TimeField({
43                 id: this.id + '-start-time',
44                 hidden: this.showTimes === false,
45                 labelWidth: 0,
46                 hideLabel: true,
47                 width: 90,
48                 listeners: {
49                     'select': {
50                         fn: function() {
51                             this.checkDates('time', 'start');
52                         },
53                         scope: this
54                     }
55                 }
56             });
57             this.endTime = new Ext.form.TimeField({
58                 id: this.id + '-end-time',
59                 hidden: this.showTimes === false,
60                 labelWidth: 0,
61                 hideLabel: true,
62                 width: 90,
63                 listeners: {
64                     'select': {
65                         fn: function() {
66                             this.checkDates('time', 'end');
67                         },
68                         scope: this
69                     }
70                 }
71             });
72             this.endDate = new Ext.form.DateField({
73                 id: this.id + '-end-date',
74                 format: 'n/j/Y',
75                 hideLabel: true,
76                 width: 100,
77                 listeners: {
78                     'change': {
79                         fn: function() {
80                             this.checkDates('date', 'end');
81                         },
82                         scope: this
83                     }
84                 }
85             });
86             this.allDay = new Ext.form.Checkbox({
87                 id: this.id + '-allday',
88                 hidden: this.showTimes === false || this.showAllDay === false,
89                 boxLabel: this.allDayText,
90                 handler: function(chk, checked) {
91                     this.startTime.setVisible(!checked);
92                     this.endTime.setVisible(!checked);
93                 },
94                 scope: this
95             });
96             this.toLabel = new Ext.form.Label({
97                 xtype: 'label',
98                 id: this.id + '-to-label',
99                 text: this.toText
100             });
101
102             this.fieldCt = new Ext.Container({
103                 autoEl: {
104                     id: this.id
105                 },
106                 //make sure the container el has the field's id
107                 cls: 'ext-dt-range',
108                 renderTo: ct,
109                 layout: 'table',
110                 layoutConfig: {
111                     columns: 6
112                 },
113                 defaults: {
114                     hideParent: true
115                 },
116                 items: [
117                 this.startDate,
118                 this.startTime,
119                 this.toLabel,
120                 this.endTime,
121                 this.endDate,
122                 this.allDay
123                 ]
124             });
125
126             this.fieldCt.ownerCt = this;
127             this.el = this.fieldCt.getEl();
128             this.items = new Ext.util.MixedCollection();
129             this.items.addAll([this.startDate, this.endDate, this.toLabel, this.startTime, this.endTime, this.allDay]);
130         }
131         Ext.calendar.DateRangeField.superclass.onRender.call(this, ct, position);
132     },
133
134     // private
135     checkDates: function(type, startend) {
136         var startField = Ext.getCmp(this.id + '-start-' + type),
137         endField = Ext.getCmp(this.id + '-end-' + type),
138         startValue = this.getDT('start'),
139         endValue = this.getDT('end');
140
141         if (startValue > endValue) {
142             if (startend == 'start') {
143                 endField.setValue(startValue);
144             } else {
145                 startField.setValue(endValue);
146                 this.checkDates(type, 'start');
147             }
148         }
149         if (type == 'date') {
150             this.checkDates('time', startend);
151         }
152     },
153
154     /**
155      * Returns an array containing the following values in order:<div class="mdetail-params"><ul>
156      * <li><b><code>DateTime</code></b> : <div class="sub-desc">The start date/time</div></li>
157      * <li><b><code>DateTime</code></b> : <div class="sub-desc">The end date/time</div></li>
158      * <li><b><code>Boolean</code></b> : <div class="sub-desc">True if the dates are all-day, false 
159      * if the time values should be used</div></li><ul></div>
160      * @return {Array} The array of return values
161      */
162     getValue: function() {
163         return [
164         this.getDT('start'),
165         this.getDT('end'),
166         this.allDay.getValue()
167         ];
168     },
169
170     // private getValue helper
171     getDT: function(startend) {
172         var time = this[startend + 'Time'].getValue(),
173         dt = this[startend + 'Date'].getValue();
174
175         if (Ext.isDate(dt)) {
176             dt = dt.format(this[startend + 'Date'].format);
177         }
178         else {
179             return null;
180         };
181         if (time != '' && this[startend + 'Time'].isVisible()) {
182             return Date.parseDate(dt + ' ' + time, this[startend + 'Date'].format + ' ' + this[startend + 'Time'].format);
183         }
184         return Date.parseDate(dt, this[startend + 'Date'].format);
185
186     },
187
188     /**
189      * Sets the values to use in the date range.
190      * @param {Array/Date/Object} v The value(s) to set into the field. Valid types are as follows:<div class="mdetail-params"><ul>
191      * <li><b><code>Array</code></b> : <div class="sub-desc">An array containing, in order, a start date, end date and all-day flag.
192      * This array should exactly match the return type as specified by {@link #getValue}.</div></li>
193      * <li><b><code>DateTime</code></b> : <div class="sub-desc">A single Date object, which will be used for both the start and
194      * end dates in the range.  The all-day flag will be defaulted to false.</div></li>
195      * <li><b><code>Object</code></b> : <div class="sub-desc">An object containing properties for StartDate, EndDate and IsAllDay
196      * as defined in {@link Ext.calendar.EventMappings}.</div></li><ul></div>
197      */
198     setValue: function(v) {
199         if (Ext.isArray(v)) {
200             this.setDT(v[0], 'start');
201             this.setDT(v[1], 'end');
202             this.allDay.setValue( !! v[2]);
203         }
204         else if (Ext.isDate(v)) {
205             this.setDT(v, 'start');
206             this.setDT(v, 'end');
207             this.allDay.setValue(false);
208         }
209         else if (v[Ext.calendar.EventMappings.StartDate.name]) {
210             //object
211             this.setDT(v[Ext.calendar.EventMappings.StartDate.name], 'start');
212             if (!this.setDT(v[Ext.calendar.EventMappings.EndDate.name], 'end')) {
213                 this.setDT(v[Ext.calendar.EventMappings.StartDate.name], 'end');
214             }
215             this.allDay.setValue( !! v[Ext.calendar.EventMappings.IsAllDay.name]);
216         }
217     },
218
219     // private setValue helper
220     setDT: function(dt, startend) {
221         if (dt && Ext.isDate(dt)) {
222             this[startend + 'Date'].setValue(dt);
223             this[startend + 'Time'].setValue(dt.format(this[startend + 'Time'].format));
224             return true;
225         }
226     },
227
228     // inherited docs
229     isDirty: function() {
230         var dirty = false;
231         if (this.rendered && !this.disabled) {
232             this.items.each(function(item) {
233                 if (item.isDirty()) {
234                     dirty = true;
235                     return false;
236                 }
237             });
238         }
239         return dirty;
240     },
241
242     // private
243     onDisable: function() {
244         this.delegateFn('disable');
245     },
246
247     // private
248     onEnable: function() {
249         this.delegateFn('enable');
250     },
251
252     // inherited docs
253     reset: function() {
254         this.delegateFn('reset');
255     },
256
257     // private
258     delegateFn: function(fn) {
259         this.items.each(function(item) {
260             if (item[fn]) {
261                 item[fn]();
262             }
263         });
264     },
265
266     // private
267     beforeDestroy: function() {
268         Ext.destroy(this.fieldCt);
269         Ext.calendar.DateRangeField.superclass.beforeDestroy.call(this);
270     },
271
272     /**
273      * @method getRawValue
274      * @hide
275      */
276     getRawValue: Ext.emptyFn,
277     /**
278      * @method setRawValue
279      * @hide
280      */
281     setRawValue: Ext.emptyFn
282 });
283
284 Ext.reg('daterangefield', Ext.calendar.DateRangeField);