Implement calendar operations (create/edit/remove)
This commit is contained in:
parent
4d532e9a27
commit
95d7fa7c3a
16 changed files with 366 additions and 35 deletions
|
@ -15,7 +15,7 @@
|
|||
- List (Agenda) view
|
||||
- Individual days selection
|
||||
+ Show list of calendars in a (hideable) drawer
|
||||
- View: 3.1: Folder list
|
||||
+ View: 3.1: Folder list
|
||||
- View: 3.2: Add / Remove / Rename / Share Folders
|
||||
+ View: 3.6: Combined calendar view (Turn calendars on/off)
|
||||
+ View: 3.7: Small month overview calendar
|
||||
|
|
|
@ -36,6 +36,7 @@ function rcube_calendar(settings)
|
|||
|
||||
/*** private vars ***/
|
||||
var me = this;
|
||||
var fcselector = '#calendar';
|
||||
var day_clicked = day_clicked_ts = 0;
|
||||
var ignore_click = false;
|
||||
|
||||
|
@ -158,14 +159,15 @@ function rcube_calendar(settings)
|
|||
minWidth: 320,
|
||||
width: 420
|
||||
}).show();
|
||||
|
||||
/*
|
||||
// add link for "more options" drop-down
|
||||
$('<a>')
|
||||
.attr('href', '#')
|
||||
.html('More Options')
|
||||
.addClass('dropdown-link')
|
||||
.click(function(){ return false; })
|
||||
.insertBefore($dialog.parent().find('.ui-dialog-buttonset').children().first());
|
||||
|
||||
*/
|
||||
};
|
||||
|
||||
// bring up the event dialog (jquery-ui popup)
|
||||
|
@ -461,7 +463,7 @@ function rcube_calendar(settings)
|
|||
],
|
||||
close: function(){
|
||||
$dialog.dialog("destroy").hide();
|
||||
$('#calendar').fullCalendar('refetchEvents');
|
||||
$(fcselector).fullCalendar('refetchEvents');
|
||||
}
|
||||
}).show();
|
||||
|
||||
|
@ -475,7 +477,7 @@ function rcube_calendar(settings)
|
|||
this.add_event = function() {
|
||||
if (this.selected_calendar) {
|
||||
var now = new Date();
|
||||
var date = $('#calendar').fullCalendar('getDate') || now;
|
||||
var date = $(fcselector).fullCalendar('getDate') || now;
|
||||
date.setHours(now.getHours()+1);
|
||||
date.setMinutes(0);
|
||||
var end = new Date(date.getTime());
|
||||
|
@ -601,6 +603,82 @@ function rcube_calendar(settings)
|
|||
this.dismiss_link = null;
|
||||
};
|
||||
|
||||
// opens a jquery UI dialog with event properties (or empty for creating a new calendar)
|
||||
this.calendar_edit_dialog = function(calendar)
|
||||
{
|
||||
// close show dialog first
|
||||
var $dialog = $("#calendarform").dialog('close');
|
||||
|
||||
if (!calendar)
|
||||
calendar = { name:'', color:'cc0000' };
|
||||
|
||||
// reset form first
|
||||
$('#calendarform > form').get(0).reset();
|
||||
|
||||
var name = $('#calendar-name').val(calendar.name);
|
||||
var color = $('#calendar-color').val(calendar.color).miniColors('value', calendar.color);
|
||||
|
||||
// dialog buttons
|
||||
var buttons = {};
|
||||
|
||||
buttons[rcmail.gettext('save', 'calendar')] = function() {
|
||||
// TODO: do some input validation
|
||||
if (!name.val() || name.val().length < 2) {
|
||||
alert(rcmail.gettext('invalidcalendarproperties', 'calendar'));
|
||||
name.select();
|
||||
return;
|
||||
}
|
||||
|
||||
// post data to server
|
||||
var data = {
|
||||
name: name.val(),
|
||||
color: color.val().replace(/^#/, '')
|
||||
};
|
||||
if (calendar.id)
|
||||
data.id = calendar.id;
|
||||
|
||||
rcmail.http_post('plugin.calendar', { action:(calendar.id ? 'edit' : 'new'), c:data });
|
||||
$dialog.dialog("close");
|
||||
};
|
||||
|
||||
buttons[rcmail.gettext('cancel', 'calendar')] = function() {
|
||||
$dialog.dialog("close");
|
||||
};
|
||||
|
||||
// open jquery UI dialog
|
||||
$dialog.dialog({
|
||||
modal: true,
|
||||
resizable: true,
|
||||
title: rcmail.gettext((calendar.id ? 'editcalendar' : 'createcalendar'), 'calendar'),
|
||||
close: function() {
|
||||
$dialog.dialog("destroy").hide();
|
||||
},
|
||||
buttons: buttons,
|
||||
minWidth: 400,
|
||||
width: 420
|
||||
}).show();
|
||||
|
||||
name.select();
|
||||
};
|
||||
|
||||
this.calendar_remove = function(calendar)
|
||||
{
|
||||
if (confirm(rcmail.gettext('deletecalendarconfirm', 'calendar'))) {
|
||||
rcmail.http_post('plugin.calendar', { action:'remove', c:{ id:calendar.id } });
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.calendar_destroy_source = function(id)
|
||||
{
|
||||
if (this.calendars[id]) {
|
||||
$(fcselector).fullCalendar('removeEventSource', this.calendars[id]);
|
||||
$(rcmail.get_folder_li(id, 'rcmlical')).remove();
|
||||
$('#edit-calendar option[value="'+id+'"]').remove();
|
||||
delete this.calendars[id];
|
||||
}
|
||||
};
|
||||
|
||||
/*** startup code ***/
|
||||
|
||||
|
@ -633,7 +711,7 @@ function rcube_calendar(settings)
|
|||
action = 'removeEventSource';
|
||||
settings.hidden_calendars.push(id);
|
||||
}
|
||||
$('#calendar').fullCalendar(action, me.calendars[id]);
|
||||
$(fcselector).fullCalendar(action, me.calendars[id]);
|
||||
rcmail.save_pref({ name:'hidden_calendars', value:settings.hidden_calendars.join(',') });
|
||||
}
|
||||
}).data('id', id).get(0).checked = active;
|
||||
|
@ -641,6 +719,7 @@ function rcube_calendar(settings)
|
|||
$(li).click(function(e){
|
||||
var id = $(this).data('id');
|
||||
rcmail.select_folder(id, me.selected_calendar, 'rcmlical');
|
||||
rcmail.enable_command('plugin.calendar-edit','plugin.calendar-remove', true);
|
||||
me.selected_calendar = id;
|
||||
}).data('id', id);
|
||||
}
|
||||
|
@ -652,7 +731,7 @@ function rcube_calendar(settings)
|
|||
}
|
||||
|
||||
// initalize the fullCalendar plugin
|
||||
$('#calendar').fullCalendar({
|
||||
$(fcselector).fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
|
@ -802,7 +881,7 @@ function rcube_calendar(settings)
|
|||
var diff = (kw - base_kw) * 7 * 86400000;
|
||||
// select monday of the chosen calendar week
|
||||
var date = new Date(base_date.getTime() - day_off * 86400000 + diff);
|
||||
$('#calendar').fullCalendar('gotoDate', date).fullCalendar('setDate', date).fullCalendar('changeView', 'agendaWeek');
|
||||
$(fcselector).fullCalendar('gotoDate', date).fullCalendar('setDate', date).fullCalendar('changeView', 'agendaWeek');
|
||||
$("#datepicker").datepicker('setDate', date);
|
||||
window.setTimeout(init_week_events, 10);
|
||||
}).css('cursor', 'pointer');
|
||||
|
@ -817,7 +896,7 @@ function rcube_calendar(settings)
|
|||
onSelect: function(dateText, inst) {
|
||||
ignore_click = true;
|
||||
var d = $("#datepicker").datepicker('getDate'); //parse_datetime('0:0', dateText);
|
||||
$('#calendar').fullCalendar('gotoDate', d).fullCalendar('select', d, d, true);
|
||||
$(fcselector).fullCalendar('gotoDate', d).fullCalendar('select', d, d, true);
|
||||
window.setTimeout(init_week_events, 10);
|
||||
},
|
||||
onChangeMonthYear: function(year, month, inst) {
|
||||
|
@ -826,14 +905,14 @@ function rcube_calendar(settings)
|
|||
d.setYear(year);
|
||||
d.setMonth(month - 1);
|
||||
$("#datepicker").data('year', year).data('month', month);
|
||||
//$('#calendar').fullCalendar('gotoDate', d).fullCalendar('setDate', d);
|
||||
//$(fcselector).fullCalendar('gotoDate', d).fullCalendar('setDate', d);
|
||||
},
|
||||
}));
|
||||
window.setTimeout(init_week_events, 10);
|
||||
|
||||
// react on fullcalendar buttons
|
||||
var fullcalendar_update = function() {
|
||||
var d = $('#calendar').fullCalendar('getDate');
|
||||
var d = $(fcselector).fullCalendar('getDate');
|
||||
$("#datepicker").datepicker('setDate', d);
|
||||
window.setTimeout(init_week_events, 10);
|
||||
};
|
||||
|
@ -930,6 +1009,8 @@ function rcube_calendar(settings)
|
|||
$('#recurrence-form-'+freq+', #recurrence-form-until').show();
|
||||
});
|
||||
$('#edit-recurrence-enddate').datepicker(datepicker_settings).click(function(){ $("#edit-recurrence-repeat-until").prop('checked', true) });
|
||||
|
||||
$('#calendar-color').miniColors();
|
||||
|
||||
// hide event dialog when clicking somewhere into document
|
||||
$(document).bind('mousedown', dialog_check);
|
||||
|
@ -942,6 +1023,11 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
|
|||
|
||||
// configure toobar buttons
|
||||
rcmail.register_command('plugin.addevent', function(){ cal.add_event(); }, true);
|
||||
|
||||
// configure list operations
|
||||
rcmail.register_command('plugin.calendar-create', function(){ cal.calendar_edit_dialog(null); }, true);
|
||||
rcmail.register_command('plugin.calendar-edit', function(){ cal.calendar_edit_dialog(cal.calendars[cal.selected_calendar]); }, false);
|
||||
rcmail.register_command('plugin.calendar-remove', function(){ cal.calendar_remove(cal.calendars[cal.selected_calendar]); }, false);
|
||||
|
||||
// export events
|
||||
rcmail.register_command('plugin.export', function(){ rcmail.goto_url('plugin.export_events', { source:cal.selected_calendar }); }, true);
|
||||
|
@ -950,6 +1036,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
|
|||
// register callback commands
|
||||
rcmail.addEventListener('plugin.display_alarms', function(alarms){ cal.display_alarms(alarms); });
|
||||
rcmail.addEventListener('plugin.reload_calendar', function(p){ $('#calendar').fullCalendar('refetchEvents', cal.calendars[p.source]); });
|
||||
rcmail.addEventListener('plugin.calendar_destroy_source', function(p){ cal.calendar_destroy_source(p.id); });
|
||||
|
||||
|
||||
// let's go
|
||||
|
|
|
@ -50,7 +50,7 @@ class calendar extends rcube_plugin
|
|||
}
|
||||
|
||||
// load localizations
|
||||
$this->add_texts('localization/', $this->rc->action != 'plugin.event');
|
||||
$this->add_texts('localization/', !$this->rc->action || $this->rc->task != 'calendar');
|
||||
|
||||
// load Calendar user interface which includes jquery-ui
|
||||
$this->require_plugin('jqueryui');
|
||||
|
@ -71,9 +71,9 @@ class calendar extends rcube_plugin
|
|||
|
||||
// register calendar actions
|
||||
$this->register_action('index', array($this, 'calendar_view'));
|
||||
$this->register_action('plugin.calendar', array($this, 'calendar_view'));
|
||||
$this->register_action('plugin.event', array($this, 'event_action'));
|
||||
$this->register_action('plugin.calendar', array($this, 'calendar_action'));
|
||||
$this->register_action('plugin.load_events', array($this, 'load_events'));
|
||||
$this->register_action('plugin.event', array($this, 'event'));
|
||||
$this->register_action('plugin.export_events', array($this, 'export_events'));
|
||||
$this->register_action('plugin.randomdata', array($this, 'generate_randomdata'));
|
||||
$this->add_hook('keep_alive', array($this, 'keep_alive'));
|
||||
|
@ -247,7 +247,7 @@ class calendar extends rcube_plugin
|
|||
$field_class = 'rcmfd_category_' . str_replace(' ', '_', $name);
|
||||
$category_remove = new html_inputfield(array('type' => 'button', 'value' => 'X', 'class' => 'button', 'onclick' => '$(this).parent().remove()', 'title' => $this->gettext('remove_category')));
|
||||
$category_name = new html_inputfield(array('name' => "_categories[$key]", 'class' => $field_class, 'size' => 30));
|
||||
$category_color = new html_inputfield(array('name' => "_colors[$key]", 'class' => $field_class, 'size' => 6));
|
||||
$category_color = new html_inputfield(array('name' => "_colors[$key]", 'class' => "$field_class colors", 'size' => 6));
|
||||
$categories_list .= html::div(null, $category_name->show($name) . ' ' . $category_color->show($color) . ' ' . $category_remove->show());
|
||||
}
|
||||
|
||||
|
@ -261,16 +261,22 @@ class calendar extends rcube_plugin
|
|||
$p['blocks']['categories']['options']['categories'] = array(
|
||||
'content' => $new_category->show('') . ' ' . $add_category->show(),
|
||||
);
|
||||
|
||||
|
||||
$this->rc->output->add_script('function rcube_calendar_add_category(){
|
||||
var name = $("#rcmfd_new_category").val();
|
||||
if (name.length) {
|
||||
var input = $("<input>").attr("type", "text").attr("name", "_categories[]").attr("size", 30).val(name);
|
||||
var color = $("<input>").attr("type", "text").attr("name", "_colors[]").attr("size", 6).val("000000");
|
||||
var color = $("<input>").attr("type", "text").attr("name", "_colors[]").attr("size", 6).addClass("colors").val("000000");
|
||||
var button = $("<input>").attr("type", "button").attr("value", "X").addClass("button").click(function(){ $(this).parent().remove() });
|
||||
$("<div>").append(input).append(" ").append(color).append(" ").append(button).appendTo("#calendarcategories");
|
||||
color.miniColors();
|
||||
}
|
||||
}');
|
||||
|
||||
// include color picker
|
||||
$this->include_script('lib/js/jquery.miniColors.min.js');
|
||||
$this->include_stylesheet('skins/' .$this->rc->config->get('skin') . '/jquery.miniColors.css');
|
||||
$this->rc->output->add_script('$("input.colors").miniColors()', 'docready');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,10 +340,43 @@ class calendar extends rcube_plugin
|
|||
return $p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatcher for calendar actions initiated by the client
|
||||
*/
|
||||
function calendar_action()
|
||||
{
|
||||
$action = get_input_value('action', RCUBE_INPUT_POST);
|
||||
$cal = get_input_value('c', RCUBE_INPUT_POST);
|
||||
$success = $reload = false;
|
||||
|
||||
switch ($action) {
|
||||
case "new":
|
||||
$success = $this->driver->create_calendar($cal);
|
||||
$reload = true;
|
||||
break;
|
||||
case "edit":
|
||||
$success = $this->driver->edit_calendar($cal);
|
||||
$reload = true;
|
||||
break;
|
||||
case "remove":
|
||||
if ($success = $this->driver->remove_calendar($cal))
|
||||
$this->rc->output->command('plugin.calendar_destroy_source', array('id' => $cal['id']));
|
||||
break;
|
||||
}
|
||||
|
||||
if ($success)
|
||||
$this->rc->output->show_message('successfullysaved', 'confirmation');
|
||||
else
|
||||
$this->rc->output->show_message('calendar.errorsaving', 'error');
|
||||
|
||||
if ($success && $reload)
|
||||
$this->rc->output->redirect('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatcher for event actions initiated by the client
|
||||
*/
|
||||
function event()
|
||||
function event_action()
|
||||
{
|
||||
$action = get_input_value('action', RCUBE_INPUT_POST);
|
||||
$event = get_input_value('e', RCUBE_INPUT_POST);
|
||||
|
|
|
@ -81,6 +81,24 @@ abstract class calendar_driver
|
|||
*/
|
||||
abstract function create_calendar($prop);
|
||||
|
||||
/**
|
||||
* Update properties of an existing calendar
|
||||
*
|
||||
* @param array Hash array with calendar properties
|
||||
* id: Calendar Identifier
|
||||
* name: Calendar name
|
||||
* color: The color of the calendar
|
||||
* @return boolean True on success, Fales on failure
|
||||
*/
|
||||
abstract function edit_calendar($prop);
|
||||
|
||||
/**
|
||||
* Delete the given calendar with all its contents
|
||||
*
|
||||
* @return boolean True on success, Fales on failure
|
||||
*/
|
||||
abstract function remove_calendar($prop);
|
||||
|
||||
/**
|
||||
* Add a single event to the database
|
||||
*
|
||||
|
|
|
@ -75,7 +75,7 @@ class database_driver extends calendar_driver
|
|||
if (!empty($this->rc->user->ID)) {
|
||||
$calendar_ids = array();
|
||||
$result = $this->rc->db->query(
|
||||
"SELECT * FROM " . $this->db_calendars . "
|
||||
"SELECT *, calendar_id AS id FROM " . $this->db_calendars . "
|
||||
WHERE user_id=?",
|
||||
$this->rc->user->ID
|
||||
);
|
||||
|
@ -121,10 +121,59 @@ class database_driver extends calendar_driver
|
|||
);
|
||||
|
||||
if ($result)
|
||||
return $this->rc->db->insert_id($this->$sequence_calendars);
|
||||
return $this->rc->db->insert_id($this->sequence_calendars);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update properties of an existing calendar
|
||||
*
|
||||
* @see calendar_driver::edit_calendar()
|
||||
*/
|
||||
public function edit_calendar($prop)
|
||||
{
|
||||
$query = $this->rc->db->query(
|
||||
"UPDATE " . $this->db_calendars . "
|
||||
SET name=?, color=?
|
||||
WHERE calendar_id=?
|
||||
AND user_id=?",
|
||||
$prop['name'],
|
||||
$prop['color'],
|
||||
$prop['id'],
|
||||
$this->rc->user->ID
|
||||
);
|
||||
|
||||
return $this->rc->db->affected_rows($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given calendar with all its contents
|
||||
*
|
||||
* @see calendar_driver::remove_calendar()
|
||||
*/
|
||||
public function remove_calendar($prop)
|
||||
{
|
||||
if (!$this->calendars[$prop['id']])
|
||||
return false;
|
||||
|
||||
// delete all events of this calendar
|
||||
$query = $this->rc->db->query(
|
||||
"DELETE FROM " . $this->db_events . "
|
||||
WHERE calendar_id=?",
|
||||
$prop['id']
|
||||
);
|
||||
|
||||
// TODO: also delete linked attachments
|
||||
|
||||
$query = $this->rc->db->query(
|
||||
"DELETE FROM " . $this->db_calendars . "
|
||||
WHERE calendar_id=?",
|
||||
$prop['id']
|
||||
);
|
||||
|
||||
return $this->rc->db->affected_rows($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single event to the database
|
||||
|
@ -699,8 +748,15 @@ class database_driver extends calendar_driver
|
|||
*/
|
||||
public function remove_category($name)
|
||||
{
|
||||
// TBD. alter events accordingly
|
||||
return false;
|
||||
$query = $this->rc->db->query(
|
||||
"UPDATE " . $this->db_events . "
|
||||
SET categories=''
|
||||
WHERE categories=?
|
||||
AND calendar_id IN (" . $this->calendar_ids . ")",
|
||||
$name
|
||||
);
|
||||
|
||||
return $this->rc->db->affected_rows($query);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -708,8 +764,16 @@ class database_driver extends calendar_driver
|
|||
*/
|
||||
public function replace_category($oldname, $name, $color)
|
||||
{
|
||||
// TBD. alter events accordingly
|
||||
return false;
|
||||
$query = $this->rc->db->query(
|
||||
"UPDATE " . $this->db_events . "
|
||||
SET categories=?
|
||||
WHERE categories=?
|
||||
AND calendar_id IN (" . $this->calendar_ids . ")",
|
||||
$name,
|
||||
$oldname
|
||||
);
|
||||
|
||||
return $this->rc->db->affected_rows($query);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ class calendar_ui
|
|||
{
|
||||
$skin = $this->rc->config->get('skin');
|
||||
$this->calendar->include_stylesheet('skins/' . $skin . '/fullcalendar.css');
|
||||
$this->calendar->include_stylesheet('skins/' . $skin . '/jquery.miniColors.css');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,6 +63,7 @@ class calendar_ui
|
|||
public function addJS()
|
||||
{
|
||||
$this->calendar->include_script('lib/js/fullcalendar.js');
|
||||
$this->calendar->include_script('lib/js/jquery.miniColors.min.js');
|
||||
$this->calendar->include_script('calendar.js');
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
--- js/fullcalendar.js.orig 2011-06-04 15:45:44.000000000 -0400
|
||||
+++ js/fullcalendar.js 2011-06-04 15:46:38.000000000 -0400
|
||||
--- js/fullcalendar.js.orig 2011-06-04 13:45:44.000000000 -0600
|
||||
+++ js/fullcalendar.js 2011-06-05 18:58:59.000000000 -0600
|
||||
@@ -500,8 +500,8 @@
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
|||
}
|
||||
|
||||
|
||||
@@ -897,7 +897,7 @@
|
||||
@@ -897,15 +897,16 @@
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,9 +20,10 @@
|
|||
rangeStart = start;
|
||||
rangeEnd = end;
|
||||
cache = [];
|
||||
@@ -905,7 +905,8 @@
|
||||
var fetchID = ++currentFetchID;
|
||||
var len = sources.length;
|
||||
pendingSourceCnt = len;
|
||||
- pendingSourceCnt = len;
|
||||
+ pendingSourceCnt = typeof src == 'undefined' ? len : 1;
|
||||
for (var i=0; i<len; i++) {
|
||||
- fetchEventSource(sources[i], fetchID);
|
||||
+ if (typeof src == 'undefined' || src == sources[i])
|
||||
|
|
|
@ -903,7 +903,7 @@ function EventManager(options, _sources) {
|
|||
cache = [];
|
||||
var fetchID = ++currentFetchID;
|
||||
var len = sources.length;
|
||||
pendingSourceCnt = len;
|
||||
pendingSourceCnt = typeof src == 'undefined' ? len : 1;
|
||||
for (var i=0; i<len; i++) {
|
||||
if (typeof src == 'undefined' || src == sources[i])
|
||||
fetchEventSource(sources[i], fetchID);
|
||||
|
|
17
plugins/calendar/lib/js/jquery.miniColors.min.js
vendored
Normal file
17
plugins/calendar/lib/js/jquery.miniColors.min.js
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
// http://plugins.jquery.com/project/jQueryMiniColors
|
||||
if(jQuery)(function($){$.extend($.fn,{miniColors:function(o,data){var create=function(input,o,data){var color=cleanHex(input.val());if(!color)color='FFFFFF';var hsb=hex2hsb(color);var trigger=$('<a class="miniColors-trigger" style="background-color: #'+color+'" href="#"></a>');trigger.insertAfter(input);input.addClass('miniColors').attr('maxlength',7).attr('autocomplete','off');input.data('trigger',trigger);input.data('hsb',hsb);if(o.change)input.data('change',o.change);if(o.readonly)input.attr('readonly',true);if(o.disabled)disable(input);trigger.bind('click.miniColors',function(event){event.preventDefault();input.trigger('focus');});input.bind('focus.miniColors',function(event){show(input);});input.bind('blur.miniColors',function(event){var hex=cleanHex(input.val());input.val(hex?'#'+hex:'');});input.bind('keydown.miniColors',function(event){if(event.keyCode===9)hide(input);});input.bind('keyup.miniColors',function(event){var filteredHex=input.val().replace(/[^A-F0-9#]/ig,'');input.val(filteredHex);if(!setColorFromInput(input)){input.data('trigger').css('backgroundColor','#FFF');}});input.bind('paste.miniColors',function(event){setTimeout(function(){input.trigger('keyup');},5);});};var destroy=function(input){hide();input=$(input);input.data('trigger').remove();input.removeAttr('autocomplete');input.removeData('trigger');input.removeData('selector');input.removeData('hsb');input.removeData('huePicker');input.removeData('colorPicker');input.removeData('mousebutton');input.removeData('moving');input.unbind('click.miniColors');input.unbind('focus.miniColors');input.unbind('blur.miniColors');input.unbind('keyup.miniColors');input.unbind('keydown.miniColors');input.unbind('paste.miniColors');$(document).unbind('mousedown.miniColors');$(document).unbind('mousemove.miniColors');};var enable=function(input){input.attr('disabled',false);input.data('trigger').css('opacity',1);};var disable=function(input){hide(input);input.attr('disabled',true);input.data('trigger').css('opacity',.5);};var show=function(input){if(input.attr('disabled'))return false;hide();var selector=$('<div class="miniColors-selector"></div>');selector.append('<div class="miniColors-colors" style="background-color: #FFF;"><div class="miniColors-colorPicker"></div></div>');selector.append('<div class="miniColors-hues"><div class="miniColors-huePicker"></div></div>');selector.css({top:input.is(':visible')?input.offset().top+input.outerHeight():input.data('trigger').offset().top+input.data('trigger').outerHeight(),left:input.is(':visible')?input.offset().left:input.data('trigger').offset().left,display:'none'}).addClass(input.attr('class'));var hsb=input.data('hsb');selector.find('.miniColors-colors').css('backgroundColor','#'+hsb2hex({h:hsb.h,s:100,b:100}));var colorPosition=input.data('colorPosition');if(!colorPosition)colorPosition=getColorPositionFromHSB(hsb);selector.find('.miniColors-colorPicker').css('top',colorPosition.y+'px').css('left',colorPosition.x+'px');var huePosition=input.data('huePosition');if(!huePosition)huePosition=getHuePositionFromHSB(hsb);selector.find('.miniColors-huePicker').css('top',huePosition.y+'px');input.data('selector',selector);input.data('huePicker',selector.find('.miniColors-huePicker'));input.data('colorPicker',selector.find('.miniColors-colorPicker'));input.data('mousebutton',0);$('BODY').append(selector);selector.fadeIn(100);selector.bind('selectstart',function(){return false;});$(document).bind('mousedown.miniColors',function(event){input.data('mousebutton',1);if($(event.target).parents().andSelf().hasClass('miniColors-colors')){event.preventDefault();input.data('moving','colors');moveColor(input,event);}
|
||||
if($(event.target).parents().andSelf().hasClass('miniColors-hues')){event.preventDefault();input.data('moving','hues');moveHue(input,event);}
|
||||
if($(event.target).parents().andSelf().hasClass('miniColors-selector')){event.preventDefault();return;}
|
||||
if($(event.target).parents().andSelf().hasClass('miniColors'))return;hide(input);});$(document).bind('mouseup.miniColors',function(event){input.data('mousebutton',0);input.removeData('moving');});$(document).bind('mousemove.miniColors',function(event){if(input.data('mousebutton')===1){if(input.data('moving')==='colors')moveColor(input,event);if(input.data('moving')==='hues')moveHue(input,event);}});};var hide=function(input){if(!input)input='.miniColors';$(input).each(function(){var selector=$(this).data('selector');$(this).removeData('selector');$(selector).fadeOut(100,function(){$(this).remove();});});$(document).unbind('mousedown.miniColors');$(document).unbind('mousemove.miniColors');};var moveColor=function(input,event){var colorPicker=input.data('colorPicker');colorPicker.hide();var position={x:event.clientX-input.data('selector').find('.miniColors-colors').offset().left+$(document).scrollLeft()-5,y:event.clientY-input.data('selector').find('.miniColors-colors').offset().top+$(document).scrollTop()-5};if(position.x<=-5)position.x=-5;if(position.x>=144)position.x=144;if(position.y<=-5)position.y=-5;if(position.y>=144)position.y=144;input.data('colorPosition',position);colorPicker.css('left',position.x).css('top',position.y).show();var s=Math.round((position.x+5)*.67);if(s<0)s=0;if(s>100)s=100;var b=100-Math.round((position.y+5)*.67);if(b<0)b=0;if(b>100)b=100;var hsb=input.data('hsb');hsb.s=s;hsb.b=b;setColor(input,hsb,true);};var moveHue=function(input,event){var huePicker=input.data('huePicker');huePicker.hide();var position={y:event.clientY-input.data('selector').find('.miniColors-colors').offset().top+$(document).scrollTop()-1};if(position.y<=-1)position.y=-1;if(position.y>=149)position.y=149;input.data('huePosition',position);huePicker.css('top',position.y).show();var h=Math.round((150-position.y-1)*2.4);if(h<0)h=0;if(h>360)h=360;var hsb=input.data('hsb');hsb.h=h;setColor(input,hsb,true);};var setColor=function(input,hsb,updateInputValue){input.data('hsb',hsb);var hex=hsb2hex(hsb);if(updateInputValue)input.val('#'+hex);input.data('trigger').css('backgroundColor','#'+hex);if(input.data('selector'))input.data('selector').find('.miniColors-colors').css('backgroundColor','#'+hsb2hex({h:hsb.h,s:100,b:100}));if(input.data('change')){input.data('change').call(input,'#'+hex,hsb2rgb(hsb));}};var setColorFromInput=function(input){var hex=cleanHex(input.val());if(!hex)return false;var hsb=hex2hsb(hex);var currentHSB=input.data('hsb');if(hsb.h===currentHSB.h&&hsb.s===currentHSB.s&&hsb.b===currentHSB.b)return true;var colorPosition=getColorPositionFromHSB(hsb);var colorPicker=$(input.data('colorPicker'));colorPicker.css('top',colorPosition.y+'px').css('left',colorPosition.x+'px');var huePosition=getHuePositionFromHSB(hsb);var huePicker=$(input.data('huePicker'));huePicker.css('top',huePosition.y+'px');setColor(input,hsb,false);return true;};var getColorPositionFromHSB=function(hsb){var x=Math.ceil(hsb.s/.67);if(x<0)x=0;if(x>150)x=150;var y=150-Math.ceil(hsb.b/.67);if(y<0)y=0;if(y>150)y=150;return{x:x-5,y:y-5};}
|
||||
var getHuePositionFromHSB=function(hsb){var y=150-(hsb.h/2.4);if(y<0)h=0;if(y>150)h=150;return{y:y-1};}
|
||||
var cleanHex=function(hex){hex=hex.replace(/[^A-Fa-f0-9]/,'');if(hex.length==3){hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];}
|
||||
return hex.length===6?hex:null;};var hsb2rgb=function(hsb){var rgb={};var h=Math.round(hsb.h);var s=Math.round(hsb.s*255/100);var v=Math.round(hsb.b*255/100);if(s==0){rgb.r=rgb.g=rgb.b=v;}else{var t1=v;var t2=(255-s)*v/255;var t3=(t1-t2)*(h%60)/60;if(h==360)h=0;if(h<60){rgb.r=t1;rgb.b=t2;rgb.g=t2+t3;}
|
||||
else if(h<120){rgb.g=t1;rgb.b=t2;rgb.r=t1-t3;}
|
||||
else if(h<180){rgb.g=t1;rgb.r=t2;rgb.b=t2+t3;}
|
||||
else if(h<240){rgb.b=t1;rgb.r=t2;rgb.g=t1-t3;}
|
||||
else if(h<300){rgb.b=t1;rgb.g=t2;rgb.r=t2+t3;}
|
||||
else if(h<360){rgb.r=t1;rgb.g=t2;rgb.b=t1-t3;}
|
||||
else{rgb.r=0;rgb.g=0;rgb.b=0;}}
|
||||
return{r:Math.round(rgb.r),g:Math.round(rgb.g),b:Math.round(rgb.b)};};var rgb2hex=function(rgb){var hex=[rgb.r.toString(16),rgb.g.toString(16),rgb.b.toString(16)];$.each(hex,function(nr,val){if(val.length==1)hex[nr]='0'+val;});return hex.join('');};var hex2rgb=function(hex){var hex=parseInt(((hex.indexOf('#')>-1)?hex.substring(1):hex),16);return{r:hex>>16,g:(hex&0x00FF00)>>8,b:(hex&0x0000FF)};};var rgb2hsb=function(rgb){var hsb={h:0,s:0,b:0};var min=Math.min(rgb.r,rgb.g,rgb.b);var max=Math.max(rgb.r,rgb.g,rgb.b);var delta=max-min;hsb.b=max;hsb.s=max!=0?255*delta/max:0;if(hsb.s!=0){if(rgb.r==max){hsb.h=(rgb.g-rgb.b)/delta;}else if(rgb.g==max){hsb.h=2+(rgb.b-rgb.r)/delta;}else{hsb.h=4+(rgb.r-rgb.g)/delta;}}else{hsb.h=-1;}
|
||||
hsb.h*=60;if(hsb.h<0){hsb.h+=360;}
|
||||
hsb.s*=100/255;hsb.b*=100/255;return hsb;};var hex2hsb=function(hex){var hsb=rgb2hsb(hex2rgb(hex));if(hsb.s===0)hsb.h=360;return hsb;};var hsb2hex=function(hsb){return rgb2hex(hsb2rgb(hsb));};switch(o){case'readonly':$(this).each(function(){$(this).attr('readonly',data);});return $(this);break;case'disabled':$(this).each(function(){if(data){disable($(this));}else{enable($(this));}});return $(this);case'value':$(this).each(function(){$(this).val(data).trigger('keyup');});return $(this);break;case'destroy':$(this).each(function(){destroy($(this));});return $(this);default:if(!o)o={};$(this).each(function(){if($(this)[0].tagName.toLowerCase()!=='input')return;if($(this).data('trigger'))return;create($(this),o,data);});return $(this);}}});})(jQuery);
|
|
@ -17,7 +17,7 @@ $labels = array();
|
|||
// config
|
||||
$labels['default_view'] = 'Ansicht';
|
||||
$labels['time_format'] = 'Zeitformatierung';
|
||||
$labels['timeslots'] = 'Zeitfenster pro Stunde';
|
||||
$labels['timeslots'] = 'Zeitraster pro Stunde';
|
||||
$labels['first_day'] = 'Erster Wochentag';
|
||||
|
||||
// calendar
|
||||
|
|
|
@ -17,6 +17,9 @@ $labels['calendars'] = 'Calendars';
|
|||
$labels['category'] = 'Category';
|
||||
$labels['categories'] = 'Categories';
|
||||
$labels['createcalendar'] = 'Create new calendar';
|
||||
$labels['editcalendar'] = 'Edit calendar properties';
|
||||
$labels['name'] = 'Name';
|
||||
$labels['color'] = 'Color';
|
||||
$labels['day'] = 'Day';
|
||||
$labels['week'] = 'Week';
|
||||
$labels['month'] = 'Month';
|
||||
|
@ -87,9 +90,11 @@ $labels['tabattachments'] = 'Attachments';
|
|||
|
||||
// messages
|
||||
$labels['deleteventconfirm'] = "Do you really want to delete this event?";
|
||||
$labels['deletecalendarconfirm'] = "Do you really want to delete this calendar with all its events?";
|
||||
$labels['errorsaving'] = "Failed to save changes";
|
||||
$labels['operationfailed'] = "The requested operation failed";
|
||||
$labels['invalideventdates'] = "Invalid dates entered! Please check your input.";
|
||||
$labels['invalidcalendarproperties'] = "Invalid calendar properties! Please set a valid name.";
|
||||
|
||||
// recurrence form
|
||||
$labels['repeat'] = 'Repeat';
|
||||
|
|
|
@ -207,7 +207,8 @@ pre {
|
|||
}
|
||||
|
||||
#eventshow,
|
||||
#eventedit {
|
||||
#eventedit,
|
||||
#calendarform {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -219,6 +220,10 @@ pre {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
a.miniColors-trigger {
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
/* jQuery UI overrides */
|
||||
|
||||
#eventshow h1 {
|
||||
|
@ -256,6 +261,7 @@ pre {
|
|||
border-radius: 0;
|
||||
}
|
||||
|
||||
div.form-section,
|
||||
#eventshow div.event-section,
|
||||
#eventtabs div.event-section {
|
||||
margin-top: 0.2em;
|
||||
|
@ -287,7 +293,8 @@ pre {
|
|||
}
|
||||
|
||||
#eventshow label,
|
||||
#eventedit label {
|
||||
#eventedit label,
|
||||
.form-section label {
|
||||
display: inline-block;
|
||||
min-width: 7em;
|
||||
padding-right: 0.5em;
|
||||
|
|
BIN
plugins/calendar/skins/default/images/minicolors-all.png
Normal file
BIN
plugins/calendar/skins/default/images/minicolors-all.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
plugins/calendar/skins/default/images/minicolors-handles.gif
Normal file
BIN
plugins/calendar/skins/default/images/minicolors-handles.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 421 B |
65
plugins/calendar/skins/default/jquery.miniColors.css
Normal file
65
plugins/calendar/skins/default/jquery.miniColors.css
Normal file
|
@ -0,0 +1,65 @@
|
|||
.miniColors-trigger {
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
background: url('images/minicolors-all.png') -170px 0 no-repeat;
|
||||
vertical-align: middle;
|
||||
margin: 0 .25em;
|
||||
display: inline-block;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.miniColors-selector {
|
||||
position: absolute;
|
||||
width: 175px;
|
||||
height: 150px;
|
||||
background: #FFF;
|
||||
border: solid 1px #BBB;
|
||||
-moz-box-shadow: 0 0 6px rgba(0, 0, 0, .25);
|
||||
-webkit-box-shadow: 0 0 6px rgba(0, 0, 0, .25);
|
||||
box-shadow: 0 0 6px rgba(0, 0, 0, .25);
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
.miniColors-selector.black {
|
||||
background: #000;
|
||||
border-color: #000;
|
||||
}
|
||||
|
||||
.miniColors-colors {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
background: url('images/minicolors-all.png') top left no-repeat;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.miniColors-hues {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 160px;
|
||||
width: 20px;
|
||||
height: 150px;
|
||||
background: url('images/minicolors-all.png') -150px 0 no-repeat;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.miniColors-colorPicker {
|
||||
position: absolute;
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
background: url('images/minicolors-all.png') -170px -28px no-repeat;
|
||||
}
|
||||
|
||||
.miniColors-huePicker {
|
||||
position: absolute;
|
||||
left: -3px;
|
||||
width: 26px;
|
||||
height: 3px;
|
||||
background: url('images/minicolors-all.png') -170px -24px no-repeat;
|
||||
}
|
|
@ -18,8 +18,8 @@
|
|||
<roundcube:object name="plugin.calendar_list" id="calendarslist" />
|
||||
</div>
|
||||
<div class="boxfooter">
|
||||
<roundcube:button command="plugin.createcalendar" type="link" title="calendar.createcalendar" class="buttonPas addgroup" classAct="button addgroup" content=" " />
|
||||
<roundcube:button name="calendarmenulink" id="calendarmenulink" type="link" title="calendaractions" class="button groupactions" onclick="return false" content=" " />
|
||||
<roundcube:button command="plugin.calendar-create" type="link" title="calendar.createcalendar" class="buttonPas addgroup" classAct="button addgroup" content=" " />
|
||||
<roundcube:button name="calendaroptionslink" id="calendaroptionslink" type="link" title="calendaractions" class="button groupactions" onclick="rcmail_ui.show_popup('calendaroptions');return false" content=" " />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -27,6 +27,13 @@
|
|||
<div id="calendar"></div>
|
||||
</div>
|
||||
|
||||
<div id="calendaroptionsmenu" class="popupmenu">
|
||||
<ul>
|
||||
<li><roundcube:button command="plugin.calendar-edit" label="calendar.edit" classAct="active" /></li>
|
||||
<li><roundcube:button command="plugin.calendar-remove" label="calendar.remove" classAct="active" /></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="eventshow">
|
||||
<h1 id="event-title">Event Title</h1>
|
||||
<div class="event-section" id="event-location">Location</div>
|
||||
|
@ -163,9 +170,24 @@
|
|||
|
||||
<roundcube:object name="plugin.edit_recurring_warning" class="edit-recurring-warning" style="display:none" />
|
||||
</div>
|
||||
|
||||
<div id="calendarform">
|
||||
<form action="#">
|
||||
<div class="form-section">
|
||||
<label for="calendar-name"><roundcube:label name="calendar.name" /></label>
|
||||
<input type="text" name="name" size="20" id="calendar-name" />
|
||||
</div>
|
||||
<div class="form-section">
|
||||
<label for="calendar-color"><roundcube:label name="calendar.color" /></label>
|
||||
<input type="text" name="color" size="6" id="calendar-color" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="alarm-snooze-dropdown" class="popupmenu">
|
||||
<roundcube:object name="plugin.snooze_select" type="ul" />
|
||||
</div>
|
||||
|
||||
<div id="calendartoolbar">
|
||||
<roundcube:button command="plugin.addevent" type="link" class="buttonPas addevent" classAct="button addevent" classSel="button addeventSel" title="calendar.new_event" content=" " />
|
||||
<roundcube:button command="plugin.print" type="link" class="buttonPas print" classAct="button print" classSel="button printSel" title="calendar.print" content=" " />
|
||||
|
@ -183,6 +205,10 @@
|
|||
|
||||
<script type="text/javascript">
|
||||
|
||||
// use skin functions to handle popup-menus
|
||||
rcube_init_mail_ui();
|
||||
rcmail_ui.popups.calendaroptions = { id:'calendaroptionsmenu', above:1, obj:$('#calendaroptionsmenu') };
|
||||
|
||||
$(document).ready(function(e){
|
||||
// initialize sidebar toggle
|
||||
$('#sidebartoggle').click(function() {
|
||||
|
|
Loading…
Add table
Reference in a new issue