4 * @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
5 * @author Cornelius Weiss <c.weiss@metaways.de>
6 * @copyright Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
8 * @note: lot to do here, i just started to move stuff from views here
11 Ext.ns('Tine.Calendar');
13 Tine.Calendar.EventUI = function(event) {
16 this.app = Tine.Tinebase.appMgr.get('Calendar');
20 Tine.Calendar.EventUI.prototype = {
21 addClass: function(cls) {
22 Ext.each(this.getEls(), function(el){
28 Ext.each(this.getEls(), function(el){
33 clearDirty: function() {
34 Ext.each(this.getEls(), function(el) {
40 Ext.each(this.getEls(), function(el){
47 * @return {Array} of Ext.Element
51 for (var i=0; i<this.domIds.length; i++) {
52 var el = Ext.get(this.domIds[i]);
62 //this.colMgr = Tine.Calendar.colorMgr;
65 markDirty: function() {
66 Ext.each(this.getEls(), function(el) {
67 el.setOpacity(0.5, 1);
71 markOutOfFilter: function() {
72 Ext.each(this.getEls(), function(el) {
73 el.setOpacity(0.5, 0);
74 el.setStyle({'background-color': '#aaa', 'border-color': '#888'});
75 Ext.DomHelper.applyStyles(el.dom.firstChild, {'background-color': '#888'});
76 if (el.dom.firstChild.hasOwnProperty('firstChild')) {
77 Ext.DomHelper.applyStyles(el.dom.firstChild.firstChild, {'background-color': '#888'});
82 onSelectedChange: function(state){
85 this.addClass('cal-event-active');
86 this.setStyle({'z-index': 1000});
90 this.removeClass('cal-event-active');
91 this.setStyle({'z-index': 100});
96 * removes a event from the dom
99 var eventEls = this.getEls();
100 for (var i=0; i<eventEls.length; i++) {
101 if (eventEls[i] && typeof eventEls[i].remove == 'function') {
102 eventEls[i].remove();
105 if (this.resizeable) {
106 this.resizeable.destroy();
107 this.resizeable = null;
112 removeClass: function(cls) {
113 Ext.each(this.getEls(), function(el){
122 setOpacity: function(v) {
123 Ext.each(this.getEls(), function(el){
128 setStyle: function(style) {
129 Ext.each(this.getEls(), function(el){
138 Tine.Calendar.DaysViewEventUI = Ext.extend(Tine.Calendar.EventUI, {
140 clearDirty: function() {
141 Tine.Calendar.DaysViewEventUI.superclass.clearDirty.call(this);
143 Ext.each(this.getEls(), function(el) {
144 el.setStyle({'border-style': 'solid'});
148 * get diff of resizeable
150 * @param {Ext.Resizeable} rz
152 getRzInfo: function(rz, width, height) {
155 var event = rz.event;
156 var view = event.view;
158 // NOTE proxy might be gone after resize
159 var box = rz.proxy.getBox();
160 var width = width ? width: box.width;
161 var height = height? height : box.height;
163 var originalDuration = (event.get('dtend').getTime() - event.get('dtstart').getTime()) / Date.msMINUTE;
165 if(event.get('is_all_day_event')) {
166 var dayWidth = Ext.fly(view.wholeDayArea).getWidth() / view.numOfDays;
167 rzInfo.diff = Math.round((width - rz.originalWidth) / dayWidth);
170 rzInfo.diff = Math.round((height - rz.originalHeight) * (view.timeGranularity / view.granularityUnitHeights));
171 // neglegt diffs due to borders etc.
172 rzInfo.diff = Math.round(rzInfo.diff/15) * 15;
174 rzInfo.duration = originalDuration + rzInfo.diff;
176 if(event.get('is_all_day_event')) {
177 rzInfo.dtend = event.get('dtend').add(Date.DAY, rzInfo.diff);
179 rzInfo.dtend = event.get('dtstart').add(Date.MINUTE, rzInfo.duration);
185 markDirty: function() {
186 Tine.Calendar.DaysViewEventUI.superclass.markDirty.call(this);
188 Ext.each(this.getEls(), function(el) {
189 el.setStyle({'border-style': 'dashed'});
193 onSelectedChange: function(state){
194 Tine.Calendar.DaysViewEventUI.superclass.onSelectedChange.call(this, state);
196 this.addClass('cal-daysviewpanel-event-active');
199 this.removeClass('cal-daysviewpanel-event-active');
203 render: function(view) {
204 this.event.view = view;
206 this.colorSet = Tine.Calendar.colorMgr.getColor(this.event);
207 this.event.colorSet = this.colorSet;
209 this.dtStart = this.event.get('dtstart');
210 this.startColNum = view.getColumnNumber(this.dtStart);
212 this.dtEnd = this.event.get('dtend');
214 if (this.event.get('editGrant')) {
215 this.extraCls = 'cal-daysviewpanel-event-editgrant';
218 this.extraCls += ' cal-status-' + this.event.get('status');
220 // 00:00 in users timezone is a spechial case where the user expects
221 // something like 24:00 and not 00:00
222 if (this.dtEnd.format('H:i') == '00:00') {
223 this.dtEnd = this.dtEnd.add(Date.MINUTE, -1);
225 this.endColNum = view.getColumnNumber(this.dtEnd);
227 // skip dates not in our diplay range
228 if (this.endColNum < 0 || this.startColNum > view.numOfDays-1) {
232 // compute status icons
233 this.statusIcons = [];
234 if (this.event.get('class') === 'PRIVATE') {
235 this.statusIcons.push({
237 text: this.app.i18n._('private classification')
241 if (this.event.get('rrule')) {
242 this.statusIcons.push({
244 text: this.app.i18n._('recurring event')
246 } else if (this.event.isRecurException()) {
247 this.statusIcons.push({
249 text: this.app.i18n._('recurring event exception')
255 if (! Ext.isEmpty(this.event.get('alarms'))) {
256 this.statusIcons.push({
258 text: this.app.i18n._('has alarm')
262 if (! Ext.isEmpty(this.event.get('attachments'))) {
263 this.statusIcons.push({
264 status: 'attachment',
265 text: this.app.i18n._('has attachments')
269 var myAttenderRecord = this.event.getMyAttenderRecord(),
270 myAttenderStatusRecord = myAttenderRecord ? Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'attendeeStatus').getById(myAttenderRecord.get('status')) : null;
272 if (myAttenderStatusRecord && myAttenderStatusRecord.get('system')) {
273 this.statusIcons.push({
274 status: myAttenderRecord.get('status'),
275 text: myAttenderStatusRecord.get('i18nValue')
279 var registry = this.event.get('is_all_day_event') ? view.parallelWholeDayEventsRegistry : view.parallelScrollerEventsRegistry;
281 var position = registry.getPosition(this.event);
282 var maxParallels = registry.getMaxParalles(this.dtStart, this.dtEnd);
284 if (this.event.get('is_all_day_event')) {
285 this.renderAllDayEvent(view, maxParallels, position);
287 this.renderScrollerEvent(view, maxParallels, position);
290 if (this.event.dirty) {
291 // the event was selected before
292 this.onSelectedChange(true);
295 if (this.event.outOfFilter) {
296 this.markOutOfFilter();
299 this.rendered = true;
302 renderAllDayEvent: function(view, parallels, pos) {
304 var extraCls = this.extraCls;
306 var offsetWidth = Ext.fly(view.wholeDayArea).getWidth();
308 var width = Math.round(offsetWidth * (this.dtEnd.getTime() - this.dtStart.getTime()) / (view.numOfDays * Date.msDAY)) -5;
309 var left = Math.round(offsetWidth * (this.dtStart.getTime() - view.startDate.getTime()) / (view.numOfDays * Date.msDAY));
312 width = width + left;
314 extraCls = extraCls + ' cal-daysviewpanel-event-cropleft';
317 if (left + width > offsetWidth) {
318 width = offsetWidth - left;
319 extraCls = extraCls + ' cal-daysviewpanel-event-cropright';
322 var domId = Ext.id() + '-event:' + this.event.get('id');
323 this.domIds.push(domId);
325 var eventEl = view.templates.wholeDayEvent.insertFirst(view.wholeDayArea, {
327 tagsHtml: Tine.Tinebase.common.tagsRenderer(this.event.get('tags')),
328 summary: this.event.get('summary'),
329 startTime: this.dtStart.format('H:i'),
331 color: this.colorSet.color,
332 bgColor: this.colorSet.light,
333 textColor: this.colorSet.text,
338 top: pos * 18 + 'px',//'1px'
339 statusIcons: this.statusIcons
342 if (this.event.dirty) {
343 eventEl.setStyle({'border-style': 'dashed'});
344 eventEl.setOpacity(0.5);
347 if (! (this.endColNum > view.numOfDays) && this.event.get('editGrant')) {
348 this.resizeable = new Ext.Resizable(eventEl, {
350 disableTrackOver: true,
352 //dynamic: !!this.event.isRangeAdd,
353 widthIncrement: Math.round(offsetWidth / view.numOfDays),
354 minWidth: Math.round(offsetWidth / view.numOfDays),
357 resize: view.onEventResize,
358 beforeresize: view.onBeforeEventResize
362 //console.log([eventEl.dom, parallels, pos])
365 renderScrollerEvent: function(view, parallels, pos) {
366 var scrollerHeight = view.granularityUnitHeights * ((24 * 60)/view.timeGranularity);
368 for (var currColNum=this.startColNum; currColNum<=this.endColNum; currColNum++) {
371 var extraCls = this.extraCls;
373 if (currColNum < 0 || currColNum >= view.numOfDays) {
377 var top = view.getTimeOffset(this.dtStart, false);
378 var height = this.startColNum == this.endColNum ? view.getTimeHeight(this.dtStart, this.dtEnd) : view.getTimeOffset(this.dtEnd, true);
380 if (currColNum != this.startColNum) {
382 extraCls = extraCls + ' cal-daysviewpanel-event-croptop';
385 if (this.endColNum != currColNum) {
386 height = view.getTimeHeight(this.dtStart, this.dtStart.add(Date.DAY, 1));
387 extraCls = extraCls + ' cal-daysviewpanel-event-cropbottom';
390 var domId = Ext.id() + '-event:' + this.event.get('id');
391 this.domIds.push(domId);
399 if (top > scrollerHeight -12) {
400 top = scrollerHeight -12;
403 var eventEl = view.templates.event.append(view.getDateColumnEl(currColNum), {
405 summary: height >= 24 ? this.event.get('summary') : '',
406 tagsHtml: height >= 24 ? Tine.Tinebase.common.tagsRenderer(this.event.get('tags')) : '',
407 startTime: (height >= 24 && top <= scrollerHeight-24) ? this.dtStart.format('H:i') : this.dtStart.format('H:i') + ' ' + this.event.get('summary'),
409 color: this.colorSet.color,
410 bgColor: this.colorSet.light,
411 textColor: this.colorSet.text,
413 height: height + 'px',
414 left: Math.round(pos * 90 * 1/parallels) + '%',
415 width: Math.round(90 * 1/parallels) + '%',
416 // max shift to 20+gap
417 //left: 80 - 80/Math.sqrt(pos+1) + 10*Math.sqrt(pos) + '%',
418 //width: 80/Math.sqrt(pos+1) + '%',
420 statusIcons: this.statusIcons
423 if (this.event.dirty) {
424 eventEl.setStyle({'border-style': 'dashed'});
425 eventEl.setOpacity(0.5);
428 if (currColNum == this.endColNum && this.event.get('editGrant')) {
429 var maxHeight = 10000;
431 if (view.cropDayTime) {
432 maxHeight = view.dayEndPx - top;
435 this.resizeable = new Ext.Resizable(eventEl, {
437 disableTrackOver: true,
439 //dynamic: !!this.event.isRangeAdd,
440 heightIncrement: view.granularityUnitHeights/2,
441 maxHeight: maxHeight,
444 resize: view.onEventResize,
445 beforeresize: view.onBeforeEventResize
453 Tine.Calendar.MonthViewEventUI = Ext.extend(Tine.Calendar.EventUI, {
454 onSelectedChange: function(state){
455 Tine.Calendar.MonthViewEventUI.superclass.onSelectedChange.call(this, state);
457 this.addClass('cal-monthview-active');
459 'background-color': this.color,
460 'color': (this.colorSet) ? this.colorSet.text : '#000000'
464 this.removeClass('cal-monthview-active');
466 'background-color': this.is_all_day_event ? this.bgColor : '',
467 'color': this.is_all_day_event ? '#000000' : this.color