]>
Commit | Line | Data |
---|---|---|
6527f429 DM |
1 | /**\r |
2 | * @class Ext.form.field.DateRange\r | |
3 | * @extends Ext.form.Field\r | |
4 | * <p>A combination field that includes start and end dates and times, as well as an optional all-day checkbox.</p>\r | |
5 | * @constructor\r | |
6 | * @param {Object} config The config object\r | |
7 | */\r | |
8 | Ext.define('Ext.calendar.form.field.DateRange', {\r | |
9 | extend: 'Ext.form.FieldContainer',\r | |
10 | alias: 'widget.daterangefield',\r | |
11 | \r | |
12 | requires: [\r | |
13 | 'Ext.form.field.Date',\r | |
14 | 'Ext.form.field.Time',\r | |
15 | 'Ext.form.Label',\r | |
16 | 'Ext.form.field.Checkbox',\r | |
17 | 'Ext.layout.container.Column'\r | |
18 | ],\r | |
19 | \r | |
20 | /**\r | |
21 | * @cfg {String} toText\r | |
22 | * The text to display in between the date/time fields (defaults to 'to')\r | |
23 | */\r | |
24 | toText: 'to',\r | |
25 | /**\r | |
26 | * @cfg {String} allDayText\r | |
27 | * The text to display as the label for the all day checkbox (defaults to 'All day')\r | |
28 | */\r | |
29 | allDayText: 'All day',\r | |
30 | /**\r | |
31 | * @cfg {String/Boolean} singleLine\r | |
32 | * `true` to render the fields all on one line, `false` to break the start date/time and end date/time\r | |
33 | * into two stacked rows of fields to preserve horizontal space (defaults to `true`).\r | |
34 | */\r | |
35 | singleLine: true,\r | |
36 | /**\r | |
37 | * @cfg {String} dateFormat\r | |
38 | * The date display format used by the date fields (defaults to 'n/j/Y') \r | |
39 | */\r | |
40 | dateFormat: 'n/j/Y',\r | |
41 | /**\r | |
42 | * @cfg {String} timeFormat\r | |
43 | * The time display format used by the time fields. By default the DateRange uses the\r | |
44 | * {@link Ext.Date.use24HourTime} setting and sets the format to 'g:i A' for 12-hour time (e.g., 1:30 PM) \r | |
45 | * or 'G:i' for 24-hour time (e.g., 13:30). This can also be overridden by a static format string if desired.\r | |
46 | */\r | |
47 | timeFormat: Ext.Date.use24HourTime ? 'G:i' : 'g:i A',\r | |
48 | \r | |
49 | // private\r | |
50 | fieldLayout: 'hbox',\r | |
51 | \r | |
52 | defaults: {\r | |
53 | margin: '0 5 0 0'\r | |
54 | },\r | |
55 | \r | |
56 | // private\r | |
57 | initComponent: function() {\r | |
58 | var me = this;\r | |
59 | \r | |
60 | me.addCls('ext-dt-range');\r | |
61 | \r | |
62 | if (me.singleLine) {\r | |
63 | me.layout = me.fieldLayout;\r | |
64 | me.items = me.getFieldConfigs();\r | |
65 | }\r | |
66 | else {\r | |
67 | me.items = [{\r | |
68 | xtype: 'container',\r | |
69 | layout: me.fieldLayout,\r | |
70 | items: [\r | |
71 | me.getStartDateConfig(),\r | |
72 | me.getStartTimeConfig(),\r | |
73 | me.getDateSeparatorConfig()\r | |
74 | ]\r | |
75 | },{\r | |
76 | xtype: 'container',\r | |
77 | layout: me.fieldLayout,\r | |
78 | items: [\r | |
79 | me.getEndDateConfig(),\r | |
80 | me.getEndTimeConfig(),\r | |
81 | me.getAllDayConfig()\r | |
82 | ]\r | |
83 | }];\r | |
84 | }\r | |
85 | \r | |
86 | me.callParent(arguments);\r | |
87 | me.initRefs();\r | |
88 | },\r | |
89 | \r | |
90 | initRefs: function() {\r | |
91 | var me = this;\r | |
92 | me.startDate = me.down('#' + me.id + '-start-date');\r | |
93 | me.startTime = me.down('#' + me.id + '-start-time');\r | |
94 | me.endTime = me.down('#' + me.id + '-end-time');\r | |
95 | me.endDate = me.down('#' + me.id + '-end-date');\r | |
96 | me.allDay = me.down('#' + me.id + '-allday');\r | |
97 | me.toLabel = me.down('#' + me.id + '-to-label');\r | |
98 | \r | |
99 | me.startDate.validateOnChange = me.endDate.validateOnChange = false;\r | |
100 | \r | |
101 | me.startDate.isValid = me.endDate.isValid = function() {\r | |
102 | var me = this,\r | |
103 | valid = Ext.isDate(me.getValue());\r | |
104 | if (!valid) {\r | |
105 | me.focus();\r | |
106 | }\r | |
107 | return valid;\r | |
108 | };\r | |
109 | },\r | |
110 | \r | |
111 | getFieldConfigs: function() {\r | |
112 | var me = this;\r | |
113 | return [\r | |
114 | me.getStartDateConfig(),\r | |
115 | me.getStartTimeConfig(),\r | |
116 | me.getDateSeparatorConfig(),\r | |
117 | me.getEndTimeConfig(),\r | |
118 | me.getEndDateConfig(),\r | |
119 | me.getAllDayConfig()\r | |
120 | ];\r | |
121 | },\r | |
122 | \r | |
123 | getStartDateConfig: function() {\r | |
124 | return {\r | |
125 | xtype: 'datefield',\r | |
126 | itemId: this.id + '-start-date',\r | |
127 | format: this.dateFormat,\r | |
128 | width: 100,\r | |
129 | listeners: {\r | |
130 | 'blur': {\r | |
131 | fn: function(){\r | |
132 | this.onFieldChange('date', 'start');\r | |
133 | },\r | |
134 | scope: this\r | |
135 | }\r | |
136 | }\r | |
137 | };\r | |
138 | },\r | |
139 | \r | |
140 | getStartTimeConfig: function() {\r | |
141 | return {\r | |
142 | xtype: 'timefield',\r | |
143 | itemId: this.id + '-start-time',\r | |
144 | hidden: this.showTimes === false,\r | |
145 | labelWidth: 0,\r | |
146 | hideLabel: true,\r | |
147 | width: 90,\r | |
148 | format: this.timeFormat,\r | |
149 | listeners: {\r | |
150 | 'select': {\r | |
151 | fn: function(){\r | |
152 | this.onFieldChange('time', 'start');\r | |
153 | },\r | |
154 | scope: this\r | |
155 | }\r | |
156 | }\r | |
157 | };\r | |
158 | },\r | |
159 | \r | |
160 | getEndDateConfig: function() {\r | |
161 | return {\r | |
162 | xtype: 'datefield',\r | |
163 | itemId: this.id + '-end-date',\r | |
164 | format: this.dateFormat,\r | |
165 | hideLabel: true,\r | |
166 | width: 100,\r | |
167 | listeners: {\r | |
168 | 'blur': {\r | |
169 | fn: function(){\r | |
170 | this.onFieldChange('date', 'end');\r | |
171 | },\r | |
172 | scope: this\r | |
173 | }\r | |
174 | }\r | |
175 | };\r | |
176 | },\r | |
177 | \r | |
178 | getEndTimeConfig: function() {\r | |
179 | return {\r | |
180 | xtype: 'timefield',\r | |
181 | itemId: this.id + '-end-time',\r | |
182 | hidden: this.showTimes === false,\r | |
183 | labelWidth: 0,\r | |
184 | hideLabel: true,\r | |
185 | width: 90,\r | |
186 | format: this.timeFormat,\r | |
187 | listeners: {\r | |
188 | 'select': {\r | |
189 | fn: function(){\r | |
190 | this.onFieldChange('time', 'end');\r | |
191 | },\r | |
192 | scope: this\r | |
193 | }\r | |
194 | }\r | |
195 | };\r | |
196 | },\r | |
197 | \r | |
198 | getDuration: function() {\r | |
199 | var me = this,\r | |
200 | start = me.getDT('start'),\r | |
201 | end = me.getDT('end');\r | |
202 | \r | |
203 | return end.getTime() - start.getTime();\r | |
204 | },\r | |
205 | \r | |
206 | getAllDayConfig: function() {\r | |
207 | return {\r | |
208 | xtype: 'checkbox',\r | |
209 | itemId: this.id + '-allday',\r | |
210 | hidden: this.showTimes === false || this.showAllDay === false,\r | |
211 | boxLabel: this.allDayText,\r | |
212 | margin: '2 5 0 0',\r | |
213 | handler: this.onAllDayChange,\r | |
214 | scope: this\r | |
215 | };\r | |
216 | },\r | |
217 | \r | |
218 | onAllDayChange: function(chk, checked) {\r | |
219 | Ext.suspendLayouts();\r | |
220 | this.startTime.setDisabled(checked).setVisible(!checked);\r | |
221 | this.endTime.setDisabled(checked).setVisible(!checked);\r | |
222 | Ext.resumeLayouts(true);\r | |
223 | },\r | |
224 | \r | |
225 | getDateSeparatorConfig: function() {\r | |
226 | return {\r | |
227 | xtype: 'label',\r | |
228 | itemId: this.id + '-to-label',\r | |
229 | text: this.toText,\r | |
230 | margin: '4 5 0 0'\r | |
231 | };\r | |
232 | },\r | |
233 | \r | |
234 | isSingleLine: function() {\r | |
235 | var me = this;\r | |
236 | \r | |
237 | if (me.calculatedSingleLine === undefined) {\r | |
238 | if(me.singleLine == 'auto'){\r | |
239 | var ownerCtEl = me.ownerCt.getEl(),\r | |
240 | w = me.ownerCt.getWidth() - ownerCtEl.getPadding('lr'),\r | |
241 | el = ownerCtEl.down('.x-panel-body');\r | |
242 | \r | |
243 | if(el){\r | |
244 | w -= el.getPadding('lr');\r | |
245 | }\r | |
246 | \r | |
247 | el = ownerCtEl.down('.x-form-item-label');\r | |
248 | if(el){\r | |
249 | w -= el.getWidth() - el.getPadding('lr');\r | |
250 | }\r | |
251 | me.calculatedSingleLine = w <= me.singleLineMinWidth ? false : true;\r | |
252 | }\r | |
253 | else {\r | |
254 | me.calculatedSingleLine = me.singleLine !== undefined ? me.singleLine : true;\r | |
255 | }\r | |
256 | }\r | |
257 | return me.calculatedSingleLine;\r | |
258 | },\r | |
259 | \r | |
260 | // private\r | |
261 | onFieldChange: function(type, startend){\r | |
262 | this.checkDates(type, startend);\r | |
263 | this.fireEvent('change', this, this.getValue());\r | |
264 | },\r | |
265 | \r | |
266 | // private\r | |
267 | checkDates: function(type, startend){\r | |
268 | var me = this,\r | |
269 | startField = me.down('#' + me.id + '-start-' + type),\r | |
270 | endField = me.down('#' + me.id + '-end-' + type),\r | |
271 | startValue = me.getDT('start'),\r | |
272 | endValue = me.getDT('end');\r | |
273 | \r | |
274 | if (!startValue || !endValue) {\r | |
275 | return;\r | |
276 | }\r | |
277 | \r | |
278 | if(startValue > endValue){\r | |
279 | if(startend=='start'){\r | |
280 | endField.setValue(startValue);\r | |
281 | }else{\r | |
282 | startField.setValue(endValue);\r | |
283 | me.checkDates(type, 'start');\r | |
284 | }\r | |
285 | }\r | |
286 | if(type=='date'){\r | |
287 | me.checkDates('time', startend);\r | |
288 | }\r | |
289 | },\r | |
290 | \r | |
291 | /**\r | |
292 | * Returns an array containing the following values in order:<div class="mdetail-params"><ul>\r | |
293 | * <li><b><code>DateTime</code></b> : <div class="sub-desc">The start date/time</div></li>\r | |
294 | * <li><b><code>DateTime</code></b> : <div class="sub-desc">The end date/time</div></li>\r | |
295 | * <li><b><code>Boolean</code></b> : <div class="sub-desc">True if the dates are all-day, false \r | |
296 | * if the time values should be used</div></li><ul></div>\r | |
297 | * @return {Array} The array of return values\r | |
298 | */\r | |
299 | getValue: function(){\r | |
300 | var eDate = Ext.calendar.util.Date,\r | |
301 | start = this.getDT('start'),\r | |
302 | end = this.getDT('end'),\r | |
303 | allDay = this.allDay.getValue();\r | |
304 | \r | |
305 | if (Ext.isDate(start) && Ext.isDate(end) && start.getTime() !== end.getTime()) {\r | |
306 | if (!allDay && eDate.isMidnight(start) && eDate.isMidnight(end)) {\r | |
307 | // 12:00am -> 12:00am over n days, all day event\r | |
308 | allDay = true;\r | |
309 | end = eDate.add(end, {\r | |
310 | days: -1\r | |
311 | });\r | |
312 | }\r | |
313 | }\r | |
314 | \r | |
315 | return [\r | |
316 | start, \r | |
317 | end,\r | |
318 | allDay\r | |
319 | ];\r | |
320 | },\r | |
321 | \r | |
322 | // private getValue helper\r | |
323 | getDT: function(startend){\r | |
324 | var time = this[startend+'Time'].getValue(),\r | |
325 | dt = this[startend+'Date'].getValue();\r | |
326 | \r | |
327 | if(Ext.isDate(dt)){\r | |
328 | dt = Ext.Date.format(dt, this[startend + 'Date'].format);\r | |
329 | }\r | |
330 | else{\r | |
331 | return null;\r | |
332 | }\r | |
333 | if(time && time !== ''){\r | |
334 | time = Ext.Date.format(time, this[startend+'Time'].format);\r | |
335 | var val = Ext.Date.parseDate(dt + ' ' + time, this[startend+'Date'].format + ' ' + this[startend+'Time'].format);\r | |
336 | return val;\r | |
337 | //return Ext.Date.parseDate(dt+' '+time, this[startend+'Date'].format+' '+this[startend+'Time'].format);\r | |
338 | }\r | |
339 | return Ext.Date.parseDate(dt, this[startend+'Date'].format);\r | |
340 | \r | |
341 | },\r | |
342 | \r | |
343 | /**\r | |
344 | * Sets the values to use in the date range.\r | |
345 | * @param {Array/Date/Object} v The value(s) to set into the field. Valid types are as follows:<div class="mdetail-params"><ul>\r | |
346 | * <li><b><code>Array</code></b> : <div class="sub-desc">An array containing, in order, a start date, end date and all-day flag.\r | |
347 | * This array should exactly match the return type as specified by {@link #getValue}.</div></li>\r | |
348 | * <li><b><code>DateTime</code></b> : <div class="sub-desc">A single Date object, which will be used for both the start and\r | |
349 | * end dates in the range. The all-day flag will be defaulted to false.</div></li>\r | |
350 | * <li><b><code>Object</code></b> : <div class="sub-desc">An object containing properties for StartDate, EndDate and IsAllDay\r | |
351 | * as defined in {@link Ext.calendar.data.EventMappings}.</div></li><ul></div>\r | |
352 | */\r | |
353 | setValue: function(v){\r | |
354 | if(!v) {\r | |
355 | return;\r | |
356 | }\r | |
357 | if(Ext.isArray(v)){\r | |
358 | this.setDT(v[0], 'start');\r | |
359 | this.setDT(v[1], 'end');\r | |
360 | this.allDay.setValue(!!v[2]);\r | |
361 | }\r | |
362 | else if(Ext.isDate(v)){\r | |
363 | this.setDT(v, 'start');\r | |
364 | this.setDT(v, 'end');\r | |
365 | this.allDay.setValue(false);\r | |
366 | }\r | |
367 | else if(v[Ext.calendar.data.EventMappings.StartDate.name]){ //object\r | |
368 | this.setDT(v[Ext.calendar.data.EventMappings.StartDate.name], 'start');\r | |
369 | if(!this.setDT(v[Ext.calendar.data.EventMappings.EndDate.name], 'end')){\r | |
370 | this.setDT(v[Ext.calendar.data.EventMappings.StartDate.name], 'end');\r | |
371 | }\r | |
372 | this.allDay.setValue(!!v[Ext.calendar.data.EventMappings.IsAllDay.name]);\r | |
373 | }\r | |
374 | },\r | |
375 | \r | |
376 | // private setValue helper\r | |
377 | setDT: function(dt, startend){\r | |
378 | if(dt && Ext.isDate(dt)){\r | |
379 | this[startend + 'Date'].setValue(dt);\r | |
380 | this[startend + 'Time'].setValue(Ext.Date.format(dt, this[startend + 'Time'].format));\r | |
381 | return true;\r | |
382 | }\r | |
383 | },\r | |
384 | \r | |
385 | // inherited docs\r | |
386 | isDirty: function(){\r | |
387 | var dirty = false;\r | |
388 | if(this.rendered && !this.disabled) {\r | |
389 | this.items.each(function(item){\r | |
390 | if (item.isDirty()) {\r | |
391 | dirty = true;\r | |
392 | return false;\r | |
393 | }\r | |
394 | });\r | |
395 | }\r | |
396 | return dirty;\r | |
397 | },\r | |
398 | \r | |
399 | // private\r | |
400 | onDisable : function(){\r | |
401 | this.delegateFn('disable');\r | |
402 | },\r | |
403 | \r | |
404 | // private\r | |
405 | onEnable : function(){\r | |
406 | this.delegateFn('enable');\r | |
407 | },\r | |
408 | \r | |
409 | // inherited docs\r | |
410 | reset : function(){\r | |
411 | this.delegateFn('reset');\r | |
412 | },\r | |
413 | \r | |
414 | // private\r | |
415 | delegateFn : function(fn){\r | |
416 | this.items.each(function(item){\r | |
417 | if (item[fn]) {\r | |
418 | item[fn]();\r | |
419 | }\r | |
420 | });\r | |
421 | },\r | |
422 | \r | |
423 | // private\r | |
424 | beforeDestroy: function(){\r | |
425 | Ext.destroy(this.fieldCt);\r | |
426 | this.callParent(arguments);\r | |
427 | },\r | |
428 | \r | |
429 | /**\r | |
430 | * @method getRawValue\r | |
431 | * @hide\r | |
432 | */\r | |
433 | getRawValue : Ext.emptyFn,\r | |
434 | /**\r | |
435 | * @method setRawValue\r | |
436 | * @hide\r | |
437 | */\r | |
438 | setRawValue : Ext.emptyFn\r | |
439 | }); |