mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-20 21:50:49 +01:00
284 lines
7.6 KiB
JavaScript
284 lines
7.6 KiB
JavaScript
|
/*
|
||
|
* Egroupware Calendar event widget
|
||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||
|
* @package etemplate
|
||
|
* @subpackage api
|
||
|
* @link http://www.egroupware.org
|
||
|
* @author Nathan Gray
|
||
|
* @version $Id$
|
||
|
*/
|
||
|
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
/*egw:uses
|
||
|
/etemplate/js/et2_core_valueWidget;
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Class for a single event, displayed in a timegrid
|
||
|
*
|
||
|
*
|
||
|
* @augments et2_valueWidget
|
||
|
*/
|
||
|
var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
|
||
|
{
|
||
|
|
||
|
attributes: {
|
||
|
"onclick": {
|
||
|
"description": "JS code which is executed when the element is clicked. " +
|
||
|
"If no handler is provided, or the handler returns true and the event is not read-only, the " +
|
||
|
"event will be opened according to calendar settings."
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Constructor
|
||
|
*
|
||
|
* @memberOf et2_calendar_daycol
|
||
|
*/
|
||
|
init: function() {
|
||
|
this._super.apply(this, arguments);
|
||
|
|
||
|
// Main container
|
||
|
this.div = $j(document.createElement("div"))
|
||
|
.addClass("calendar_calEvent")
|
||
|
.css('width',this.options.width);
|
||
|
this.title = $j(document.createElement('div'))
|
||
|
.addClass("calendar_calEventHeader")
|
||
|
.appendTo(this.div);
|
||
|
this.body = $j(document.createElement('div'))
|
||
|
.addClass("calendar_calEventBody")
|
||
|
.appendTo(this.div);
|
||
|
|
||
|
this.setDOMNode(this.div[0]);
|
||
|
},
|
||
|
|
||
|
doLoadingFinished: function() {
|
||
|
this._super.apply(this, arguments);
|
||
|
|
||
|
// Parent will have everything we need, just load it from there
|
||
|
if(this.title.text() == '' && this.options.date &&
|
||
|
this._parent && this._parent.instanceOf(et2_calendar_timegrid))
|
||
|
{
|
||
|
// Forces an update
|
||
|
var date = this.options.date;
|
||
|
this.options.date = '';
|
||
|
this.set_date(date);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
destroy: function() {
|
||
|
this._super.apply(this, arguments);
|
||
|
},
|
||
|
|
||
|
set_value: function(_value) {
|
||
|
this.options.value = _value;
|
||
|
this._update(this.options.value);
|
||
|
},
|
||
|
|
||
|
_update: function(event) {
|
||
|
|
||
|
var eventId = event.id.match(/-?\d+\.?\d*/g)[0];
|
||
|
var appName = event.id.replace(/-?\d+\.?\d*/g,'');
|
||
|
var app_id = event.app_id ? event.app_id : event.id + (event.recur_type ? ':'+event.recur_date : '')
|
||
|
|
||
|
this.div
|
||
|
.attr('data-draggable-id',event['id']+'_O'+event.owner+'_C'+(event.owner<0?'group'+Math.abs(event.owner):event.owner))
|
||
|
|
||
|
// Put everything we need for basic interaction here, so it's available immediately
|
||
|
.attr('data-id', eventId || event.id)
|
||
|
.attr('data-app', appName || 'calendar')
|
||
|
.attr('data-app_id', app_id)
|
||
|
.attr('data-start', event.start)
|
||
|
.attr('data-recur_type', event.recur_type)
|
||
|
|
||
|
.toggleClass('calendar_calEventPrivate', event.private)
|
||
|
// Remove any category classes
|
||
|
.removeClass(function(index, css) {
|
||
|
return (css.match (/(^|\s)cat_\S+/g) || []).join(' ');
|
||
|
});
|
||
|
if(event.category)
|
||
|
{
|
||
|
this.div.addClass('cat_' + event.category);
|
||
|
}
|
||
|
this.div.css('border-color', this.div.css('background-color'));
|
||
|
|
||
|
this.div.toggleClass('calendar_calEventUnknown', event.participants[egw.user('account_id')][0] == 'U');
|
||
|
|
||
|
this.title.toggle(!event.whole_day_on_top);
|
||
|
this.body.toggleClass('calendar_calEventBodySmall', event.whole_day_on_top || false);
|
||
|
|
||
|
// Header
|
||
|
var title = !event.is_private ? event['title'] : egw.lang('private');
|
||
|
var small_height = event['end_m']-event['start_m'] < 2*this._parent.display_settings.granularity ||
|
||
|
event['end_m'] <= this._parent.display_settings.wd_start || event['start_m'] >= this._parent.display_settings.wd_end;
|
||
|
|
||
|
this.title.text(small_height ? title : this._get_timespan(event))
|
||
|
// Set title color based on background brightness
|
||
|
.css('color', jQuery.Color(this.div.css('background-color')).lightness() > 0.5 ? 'black':'white');
|
||
|
|
||
|
// Body
|
||
|
if(event.whole_day_on_top)
|
||
|
{
|
||
|
this.body.html(title);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this.body.html('<span class="calendar_calEventTitle">'+title+'</span>')
|
||
|
}
|
||
|
this.body
|
||
|
// Set background color to a lighter version of the header color
|
||
|
.css('background-color',jQuery.Color(this.div.css('background-color')).lightness("+=0.3"));
|
||
|
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Get a text representation of the timespan of the event. Either start
|
||
|
* - end, or 'all day'
|
||
|
*
|
||
|
* @param {Object} event Event to get the timespan for
|
||
|
* @param {number} event.start_m Event start, in minutes from midnight
|
||
|
* @param {number} event.end_m Event end, in minutes from midnight
|
||
|
*
|
||
|
* @return {string} Timespan
|
||
|
*/
|
||
|
_get_timespan: function(event) {
|
||
|
var timespan = '';
|
||
|
if (event['start_m'] === 0 && event['end_m'] >= 24*60-1)
|
||
|
{
|
||
|
if (event['end_m'] > 24*60)
|
||
|
{
|
||
|
timespan = jQuery.datepicker.formatTime(
|
||
|
egw.preference("timeformat") === 12 ? "h:mmtt" : "HH:mm",
|
||
|
{
|
||
|
hour: event.start_m / 60,
|
||
|
minute: event.start_m % 60,
|
||
|
seconds: 0,
|
||
|
timezone: 0
|
||
|
},
|
||
|
{"ampm": (egw.preference("timeformat") === "12")}
|
||
|
).trim()+' - '+jQuery.datepicker.formatTime(
|
||
|
egw.preference("timeformat") === 12 ? "h:mmtt" : "HH:mm",
|
||
|
{
|
||
|
hour: event.end_m / 60,
|
||
|
minute: event.end_m % 60,
|
||
|
seconds: 0,
|
||
|
timezone: 0
|
||
|
},
|
||
|
{"ampm": (egw.preference("timeformat") === "12")}
|
||
|
).trim();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
timespan = egw.lang('all day');
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var duration = event.end_m - event.start_m;
|
||
|
if (event.end_m === 24*60-1) ++duration;
|
||
|
duration = Math.floor(duration/60) + this.egw().lang('h')+(duration%60 ? duration%60 : '');
|
||
|
|
||
|
timespan = jQuery.datepicker.formatTime(
|
||
|
egw.preference("timeformat") === 12 ? "h:mmtt" : "HH:mm",
|
||
|
{
|
||
|
hour: event.start_m / 60,
|
||
|
minute: event.start_m % 60,
|
||
|
seconds: 0,
|
||
|
timezone: 0
|
||
|
},
|
||
|
{"ampm": (egw.preference("timeformat") === "12")}
|
||
|
).trim();
|
||
|
|
||
|
timespan += ' ' + duration;
|
||
|
}
|
||
|
return timespan;
|
||
|
},
|
||
|
|
||
|
attachToDOM: function()
|
||
|
{
|
||
|
this._super.apply(this, arguments);
|
||
|
|
||
|
// Remove the binding for the click handler, unless there's something
|
||
|
// custom here.
|
||
|
if (!this.onclick)
|
||
|
{
|
||
|
$j(this.node).off("click");
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Click handler calling custom handler set via onclick attribute to this.onclick.
|
||
|
* All other handling is done by the timegrid widget.
|
||
|
*
|
||
|
* @param {Event} _ev
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
click: function(_ev) {
|
||
|
var result = true;
|
||
|
if(typeof this.onclick == 'function')
|
||
|
{
|
||
|
// Make sure function gets a reference to the widget, splice it in as 2. argument if not
|
||
|
var args = Array.prototype.slice.call(arguments);
|
||
|
if(args.indexOf(this) == -1) args.splice(1, 0, this);
|
||
|
|
||
|
result = this.onclick.apply(this, args);
|
||
|
}
|
||
|
return result;
|
||
|
},
|
||
|
|
||
|
_edit: function()
|
||
|
{
|
||
|
if(this.options.value.recur_type)
|
||
|
{
|
||
|
var edit_id = this.options.value.id;
|
||
|
var edit_date = this.options.value.start;
|
||
|
var that = this;
|
||
|
var buttons = [
|
||
|
{text: this.egw().lang("Edit exception"), id: "exception", class: "ui-priority-primary", "default": true},
|
||
|
{text: this.egw().lang("Edit series"), id:"series"},
|
||
|
{text: this.egw().lang("Cancel"), id:"cancel"}
|
||
|
];
|
||
|
et2_dialog.show_dialog(function(_button_id)
|
||
|
{
|
||
|
switch(_button_id)
|
||
|
{
|
||
|
case 'exception':
|
||
|
that.egw().open(edit_id, 'calendar', 'edit', {date:edit_date,exception: '1'});
|
||
|
break;
|
||
|
case 'series':
|
||
|
that.egw().open(edit_id, 'calendar', 'edit', {date:edit_date});
|
||
|
break;
|
||
|
case 'cancel':
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
},this.egw().lang("Do you want to edit this event as an exception or the whole series?"),
|
||
|
this.egw().lang("This event is part of a series"), {}, buttons, et2_dialog.WARNING_MESSAGE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this.egw().open(this.options.value.id, 'calendar','edit');
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Code for implementing et2_IDetachedDOM
|
||
|
*
|
||
|
* @param {array} _attrs array to add further attributes to
|
||
|
*/
|
||
|
getDetachedAttributes: function(_attrs) {
|
||
|
|
||
|
},
|
||
|
|
||
|
getDetachedNodes: function() {
|
||
|
return [this.getDOMNode()];
|
||
|
},
|
||
|
|
||
|
setDetachedAttributes: function(_nodes, _values) {
|
||
|
|
||
|
},
|
||
|
});
|
||
|
et2_register_widget(et2_calendar_event, ["calendar-event"]);
|