]> git.proxmox.com Git - extjs.git/blame - extjs/build/examples/classic/calendar/src/view/Month.js
add extjs 6.0.1 sources
[extjs.git] / extjs / build / examples / classic / calendar / src / view / Month.js
CommitLineData
6527f429
DM
1/**\r
2 * @class Ext.calendar.view.Month\r
3 * @extends Ext.calendar.CalendarView\r
4 * <p>Displays a calendar view by month. This class does not usually need ot be used directly as you can\r
5 * use a {@link Ext.calendar.CalendarPanel CalendarPanel} to manage multiple calendar views at once including\r
6 * the month view.</p>\r
7 * @constructor\r
8 * @param {Object} config The config object\r
9 */\r
10Ext.define('Ext.calendar.view.Month', {\r
11 extend: 'Ext.calendar.view.AbstractCalendar',\r
12 alias: 'widget.monthview',\r
13 \r
14 requires: [\r
15 'Ext.XTemplate',\r
16 'Ext.calendar.template.Month',\r
17 'Ext.calendar.util.WeekEventRenderer',\r
18 'Ext.calendar.view.MonthDayDetail'\r
19 ],\r
20 \r
21 /**\r
22 * @cfg {Boolean} showTime\r
23 * True to display the current time in today's box in the calendar, false to not display it (defautls to true)\r
24 */\r
25 showTime: true,\r
26 /**\r
27 * @cfg {Boolean} showTodayText\r
28 * True to display the {@link #todayText} string in today's box in the calendar, false to not display it (defautls to true)\r
29 */\r
30 showTodayText: true,\r
31 /**\r
32 * @cfg {String} todayText\r
33 * The text to display in the current day's box in the calendar when {@link #showTodayText} is true (defaults to 'Today')\r
34 */\r
35 todayText: 'Today',\r
36 /**\r
37 * @cfg {Boolean} showHeader\r
38 * True to display a header beneath the navigation bar containing the week names above each week's column, false not to \r
39 * show it and instead display the week names in the first row of days in the calendar (defaults to false).\r
40 */\r
41 showHeader: false,\r
42 /**\r
43 * @cfg {Boolean} showWeekLinks\r
44 * True to display an extra column before the first day in the calendar that links to the {@link Ext.calendar.WeekView view}\r
45 * for each individual week, false to not show it (defaults to false). If true, the week links can also contain the week \r
46 * number depending on the value of {@link #showWeekNumbers}.\r
47 */\r
48 showWeekLinks: false,\r
49 /**\r
50 * @cfg {Boolean} showWeekNumbers\r
51 * True to show the week number for each week in the calendar in the week link column, false to show nothing (defaults to false).\r
52 * Note that if {@link #showWeekLinks} is false this config will have no affect even if true.\r
53 */\r
54 showWeekNumbers: false,\r
55 /**\r
56 * @cfg {String} weekLinkOverClass\r
57 * The CSS class name applied when the mouse moves over a week link element (only applies when {@link #showWeekLinks} is true,\r
58 * defaults to 'ext-week-link-over').\r
59 */\r
60 weekLinkOverClass: 'ext-week-link-over',\r
61\r
62 //private properties -- do not override:\r
63 daySelector: '.ext-cal-day',\r
64 moreSelector: '.ext-cal-ev-more',\r
65 weekLinkSelector: '.ext-cal-week-link',\r
66 weekCount: -1,\r
67 // defaults to auto by month\r
68 dayCount: 7,\r
69 moreElIdDelimiter: '-more-',\r
70 weekLinkIdDelimiter: 'ext-cal-week-',\r
71\r
72 // See EXTJSIV-11407.\r
73 operaLT11: Ext.isOpera && (parseInt(Ext.operaVersion) < 11),\r
74\r
75 /**\r
76 * @event dayclick\r
77 * Fires after the user clicks within the view container and not on an event element\r
78 * @param {Ext.calendar.view.Month} this\r
79 * @param {Date} dt The date/time that was clicked on\r
80 * @param {Boolean} allday True if the day clicked on represents an all-day box, else false. Clicks within the \r
81 * MonthView always return true for this param.\r
82 * @param {Ext.core.Element} el The Element that was clicked on\r
83 */\r
84\r
85 /**\r
86 * @event weekclick\r
87 * Fires after the user clicks within a week link (when {@link #showWeekLinks is true)\r
88 * @param {Ext.calendar.view.Month} this\r
89 * @param {Date} dt The start date of the week that was clicked on\r
90 */\r
91\r
92 // inherited docs\r
93 //dayover: true,\r
94 // inherited docs\r
95 //dayout: true\r
96\r
97 // private\r
98 initDD: function() {\r
99 var cfg = {\r
100 view: this,\r
101 createText: this.ddCreateEventText,\r
102 moveText: this.ddMoveEventText,\r
103 ddGroup: 'MonthViewDD'\r
104 };\r
105\r
106 this.dragZone = new Ext.calendar.dd.DragZone(this.el, cfg);\r
107 this.dropZone = new Ext.calendar.dd.DropZone(this.el, cfg);\r
108 },\r
109\r
110 // private\r
111 onDestroy: function() {\r
112 Ext.destroy(this.ddSelector);\r
113 Ext.destroy(this.dragZone);\r
114 Ext.destroy(this.dropZone);\r
115 \r
116 this.callParent(arguments);\r
117 },\r
118\r
119 // private\r
120 afterRender: function() {\r
121 if (!this.tpl) {\r
122 this.tpl = new Ext.calendar.template.Month({\r
123 id: this.id,\r
124 showTodayText: this.showTodayText,\r
125 todayText: this.todayText,\r
126 showTime: this.showTime,\r
127 showHeader: this.showHeader,\r
128 showWeekLinks: this.showWeekLinks,\r
129 showWeekNumbers: this.showWeekNumbers\r
130 });\r
131 }\r
132 this.tpl.compile();\r
133 this.addCls('ext-cal-monthview ext-cal-ct');\r
134\r
135 this.callParent(arguments);\r
136 },\r
137\r
138 // private\r
139 onResize: function() {\r
140 var me = this;\r
141 me.callParent(arguments);\r
142 me.maxEventsPerDay = me.getMaxEventsPerDay();\r
143 if (me.monitorResize) {\r
144 me.refresh();\r
145 }\r
146 },\r
147\r
148 // private\r
149 forceSize: function() {\r
150 // Compensate for the week link gutter width if visible\r
151 if(this.showWeekLinks && this.el){\r
152 var hd = this.el.down('.ext-cal-hd-days-tbl'),\r
153 bgTbl = this.el.select('.ext-cal-bg-tbl'),\r
154 evTbl = this.el.select('.ext-cal-evt-tbl'),\r
155 wkLinkW = this.el.down('.ext-cal-week-link').getWidth(),\r
156 w = this.el.getWidth()-wkLinkW;\r
157 \r
158 hd.setWidth(w);\r
159 bgTbl.setWidth(w);\r
160 evTbl.setWidth(w);\r
161 }\r
162 this.callParent(arguments);\r
163 },\r
164\r
165 //private\r
166 initClock: function() {\r
167 if (Ext.fly(this.id + '-clock') !== null) {\r
168 this.prevClockDay = new Date().getDay();\r
169 if (this.clockTask) {\r
170 Ext.TaskManager.stop(this.clockTask);\r
171 }\r
172 this.clockTask = Ext.TaskManager.start({\r
173 run: function() {\r
174 var el = Ext.fly(this.id + '-clock'),\r
175 t = new Date();\r
176\r
177 if (t.getDay() == this.prevClockDay) {\r
178 if (el) {\r
179 el.update(Ext.Date.format(t, 'g:i a'));\r
180 }\r
181 }\r
182 else {\r
183 this.prevClockDay = t.getDay();\r
184 this.moveTo(t);\r
185 }\r
186 },\r
187 scope: this,\r
188 interval: 1000\r
189 });\r
190 }\r
191 },\r
192\r
193 // inherited docs\r
194 getEventBodyMarkup: function() {\r
195 if (!this.eventBodyMarkup) {\r
196 this.eventBodyMarkup = ['{Title}',\r
197 '<tpl if="_isReminder">',\r
198 '<i class="ext-cal-ic ext-cal-ic-rem">&#160;</i>',\r
199 '</tpl>',\r
200 '<tpl if="_isRecurring">',\r
201 '<i class="ext-cal-ic ext-cal-ic-rcr">&#160;</i>',\r
202 '</tpl>',\r
203 '<tpl if="spanLeft">',\r
204 '<i class="ext-cal-spl">&#160;</i>',\r
205 '</tpl>',\r
206 '<tpl if="spanRight">',\r
207 '<i class="ext-cal-spr">&#160;</i>',\r
208 '</tpl>'\r
209 ].join('');\r
210 }\r
211 return this.eventBodyMarkup;\r
212 },\r
213\r
214 // inherited docs\r
215 getEventTemplate: function() {\r
216 if (!this.eventTpl) {\r
217 var tpl,\r
218 body = this.getEventBodyMarkup();\r
219\r
220 tpl = !(Ext.isIE7m || this.operaLT11) ?\r
221 new Ext.XTemplate(\r
222 '<div id="{_elId}" class="{_selectorCls} {_colorCls} {spanCls} ext-cal-evt ext-cal-evr">',\r
223 body,\r
224 '</div>'\r
225 )\r
226 : new Ext.XTemplate(\r
227 '<tpl if="_renderAsAllDay">',\r
228 '<div id="{_elId}" class="{_selectorCls} {spanCls} {_colorCls} {_operaLT11} ext-cal-evo">',\r
229 '<div class="ext-cal-evm">',\r
230 '<div class="ext-cal-evi">',\r
231 '</tpl>',\r
232 '<tpl if="!_renderAsAllDay">',\r
233 '<div id="{_elId}" class="{_selectorCls} {_colorCls} {_operaLT11} ext-cal-evt ext-cal-evr">',\r
234 '</tpl>',\r
235 body,\r
236 '<tpl if="_renderAsAllDay">',\r
237 '</div>',\r
238 '</div>',\r
239 '</tpl>',\r
240 '</div>'\r
241 );\r
242 tpl.compile();\r
243 this.eventTpl = tpl;\r
244 }\r
245 return this.eventTpl;\r
246 },\r
247\r
248 // private\r
249 getTemplateEventData: function(evt) {\r
250 var M = Ext.calendar.data.EventMappings,\r
251 selector = this.getEventSelectorCls(evt[M.EventId.name]),\r
252 title = evt[M.Title.name];\r
253\r
254 return Ext.applyIf({\r
255 _selectorCls: selector,\r
256 _colorCls: 'ext-color-' + (evt[M.CalendarId.name] ?\r
257 evt[M.CalendarId.name] : 'default') + (evt._renderAsAllDay ? '-ad': ''),\r
258 _elId: selector + '-' + evt._weekIndex,\r
259 _isRecurring: evt.Recurrence && evt.Recurrence != '',\r
260 _isReminder: evt[M.Reminder.name] && evt[M.Reminder.name] != '',\r
261 Title: (evt[M.IsAllDay.name] ? '' : Ext.Date.format(evt[M.StartDate.name], 'g:ia ')) + (!title || title.length == 0 ? '(No title)' : title),\r
262 _operaLT11: this.operaLT11 ? 'ext-operaLT11' : ''\r
263 },\r
264 evt);\r
265 },\r
266\r
267 // private\r
268 refresh: function() {\r
269 if (this.detailPanel) {\r
270 this.detailPanel.hide();\r
271 }\r
272 this.callParent(arguments);\r
273\r
274 if (this.showTime !== false) {\r
275 this.initClock();\r
276 }\r
277 },\r
278\r
279 // private\r
280 renderItems: function() {\r
281 Ext.calendar.util.WeekEventRenderer.render({\r
282 eventGrid: this.allDayOnly ? this.allDayGrid: this.eventGrid,\r
283 viewStart: this.viewStart,\r
284 tpl: this.getEventTemplate(),\r
285 maxEventsPerDay: this.getMaxEventsPerDay(),\r
286 id: this.id,\r
287 templateDataFn: Ext.bind(this.getTemplateEventData, this),\r
288 evtMaxCount: this.evtMaxCount,\r
289 weekCount: this.weekCount,\r
290 dayCount: this.dayCount\r
291 });\r
292 this.fireEvent('eventsrendered', this);\r
293 },\r
294\r
295 // private\r
296 getDayEl: function(dt) {\r
297 return Ext.get(this.getDayId(dt));\r
298 },\r
299\r
300 // private\r
301 getDayId: function(dt) {\r
302 if (Ext.isDate(dt)) {\r
303 dt = Ext.Date.format(dt, 'Ymd');\r
304 }\r
305 return this.id + this.dayElIdDelimiter + dt;\r
306 },\r
307\r
308 // private\r
309 getWeekIndex: function(dt) {\r
310 var el = this.getDayEl(dt).up('.ext-cal-wk-ct');\r
311 return parseInt(el.id.split('-wk-')[1], 10);\r
312 },\r
313\r
314 // private\r
315 getDaySize : function(contentOnly){\r
316 var box = this.el.getBox(),\r
317 padding = this.getViewPadding(),\r
318 w = (box.width - padding.width) / this.dayCount,\r
319 h = (box.height - padding.height) / this.getWeekCount();\r
320 \r
321 if(contentOnly){\r
322 // measure last row instead of first in case text wraps in first row\r
323 var hd = this.el.select('.ext-cal-dtitle').last().parent('tr');\r
324 h = hd ? h-hd.getHeight(true) : h;\r
325 }\r
326 return {height: h, width: w};\r
327 },\r
328 \r
329 // private\r
330 getEventHeight : function() {\r
331 if (!this.eventHeight) {\r
332 var evt = this.el.select('.ext-cal-evt').first();\r
333 if(evt){\r
334 this.eventHeight = evt.parent('td').getHeight();\r
335 }\r
336 else {\r
337 return 16; // no events rendered, so try setting this.eventHeight again later\r
338 }\r
339 }\r
340 return this.eventHeight;\r
341 },\r
342 \r
343 // private\r
344 getMaxEventsPerDay : function(){\r
345 var dayHeight = this.getDaySize(true).height,\r
346 eventHeight = this.getEventHeight(),\r
347 max = Math.max(Math.floor((dayHeight - eventHeight) / eventHeight), 0);\r
348 \r
349 return max;\r
350 },\r
351 \r
352 // private\r
353 getViewPadding: function(sides) {\r
354 var sides = sides || 'tlbr',\r
355 top = sides.indexOf('t') > -1,\r
356 left = sides.indexOf('l') > -1,\r
357 right = sides.indexOf('r') > -1,\r
358 height = this.showHeader && top ? this.el.select('.ext-cal-hd-days-tbl').first().getHeight() : 0,\r
359 width = 0;\r
360 \r
361 if (this.isHeaderView) {\r
362 if (left) {\r
363 width = this.el.select('.ext-cal-gutter').first().getWidth();\r
364 }\r
365 if (right) {\r
366 width += this.el.select('.ext-cal-gutter-rt').first().getWidth();\r
367 }\r
368 }\r
369 else if (this.showWeekLinks && left) {\r
370 width = this.el.select('.ext-cal-week-link').first().getWidth();\r
371 }\r
372 \r
373 return {\r
374 height: height,\r
375 width: width\r
376 }\r
377 },\r
378\r
379 // private\r
380 getDayAt: function(x, y) {\r
381 var box = this.el.getBox(),\r
382 daySize = this.getDaySize(),\r
383 dayL = Math.floor(((x - box.x) / daySize.width)),\r
384 dayT = Math.floor(((y - box.y) / daySize.height)),\r
385 days = (dayT * 7) + dayL,\r
386 dt = Ext.calendar.util.Date.add(this.viewStart, {days: days});\r
387 return {\r
388 date: dt,\r
389 el: this.getDayEl(dt)\r
390 };\r
391 },\r
392\r
393 // inherited docs\r
394 moveNext: function() {\r
395 return this.moveMonths(1);\r
396 },\r
397\r
398 // inherited docs\r
399 movePrev: function() {\r
400 return this.moveMonths( - 1);\r
401 },\r
402\r
403 // private\r
404 onInitDrag: function() {\r
405 this.callParent(arguments);\r
406 \r
407 if (this.dayOverClass) {\r
408 Ext.select(this.daySelector).removeCls(this.dayOverClass);\r
409 }\r
410 if (this.detailPanel) {\r
411 this.detailPanel.hide();\r
412 }\r
413 },\r
414\r
415 // private\r
416 onMoreClick: function(dt) {\r
417 if (!this.detailPanel) {\r
418 this.detailPanel = Ext.create('Ext.Panel', {\r
419 id: this.id + '-details-panel',\r
420 title: Ext.Date.format(dt, 'F j'),\r
421 layout: 'fit',\r
422 floating: true,\r
423 renderTo: Ext.getBody(),\r
424 tools: [{\r
425 type: 'close',\r
426 handler: function(e, t, p) {\r
427 p.ownerCt.hide();\r
428 }\r
429 }],\r
430 items: {\r
431 xtype: 'monthdaydetailview',\r
432 id: this.id + '-details-view',\r
433 date: dt,\r
434 view: this,\r
435 store: this.store,\r
436 listeners: {\r
437 'eventsrendered': Ext.bind(this.onDetailViewUpdated, this)\r
438 }\r
439 }\r
440 });\r
441 }\r
442 else {\r
443 this.detailPanel.setTitle(Ext.Date.format(dt, 'F j'));\r
444 }\r
445 this.detailPanel.getComponent(this.id + '-details-view').update(dt);\r
446 },\r
447\r
448 // private\r
449 onDetailViewUpdated : function(view, dt, numEvents){\r
450 var p = this.detailPanel,\r
451 dayEl = this.getDayEl(dt),\r
452 box = dayEl.getBox();\r
453 \r
454 p.setWidth(Math.max(box.width, 220));\r
455 p.show();\r
456 p.getEl().alignTo(dayEl, 't-t?');\r
457 },\r
458\r
459 // private\r
460 onHide: function() {\r
461 this.callParent(arguments);\r
462 \r
463 if (this.detailPanel) {\r
464 this.detailPanel.hide();\r
465 }\r
466 },\r
467\r
468 // private\r
469 onClick: function(e, t) {\r
470 if (this.detailPanel) {\r
471 this.detailPanel.hide();\r
472 }\r
473 if (Ext.calendar.view.Month.superclass.onClick.apply(this, arguments)) {\r
474 // The superclass handled the click already so exit\r
475 return;\r
476 }\r
477 if (this.dropZone) {\r
478 this.dropZone.clearShims();\r
479 }\r
480 var el = e.getTarget(this.weekLinkSelector, 3),\r
481 dt,\r
482 parts;\r
483 if (el) {\r
484 dt = el.id.split(this.weekLinkIdDelimiter)[1];\r
485 this.fireEvent('weekclick', this, Ext.Date.parseDate(dt, 'Ymd'));\r
486 return;\r
487 }\r
488 el = e.getTarget(this.moreSelector, 3);\r
489 if (el) {\r
490 dt = el.id.split(this.moreElIdDelimiter)[1];\r
491 this.onMoreClick(Ext.Date.parseDate(dt, 'Ymd'));\r
492 return;\r
493 }\r
494 el = e.getTarget('td', 3);\r
495 if (el) {\r
496 if (el.id && el.id.indexOf(this.dayElIdDelimiter) > -1) {\r
497 parts = el.id.split(this.dayElIdDelimiter);\r
498 dt = parts[parts.length - 1];\r
499\r
500 this.fireEvent('dayclick', this, Ext.Date.parseDate(dt, 'Ymd'), false, Ext.get(this.getDayId(dt)));\r
501 return;\r
502 }\r
503 }\r
504 },\r
505\r
506 // private\r
507 handleDayMouseEvent: function(e, t, type) {\r
508 var el = e.getTarget(this.weekLinkSelector, 3, true);\r
509 if (el && this.weekLinkOverClass) {\r
510 el[type == 'over' ? 'addCls': 'removeCls'](this.weekLinkOverClass);\r
511 return;\r
512 }\r
513 this.callParent(arguments);\r
514 }\r
515});\r