Calendar et2 conversion work in progress.

- Start of planner view
- Scroll moved to app.js so month works better
This commit is contained in:
Nathan Gray 2015-06-25 17:44:28 +00:00
parent 558589c1eb
commit 4648f91bb7
12 changed files with 2067 additions and 55 deletions

View File

@ -710,17 +710,17 @@ class calendar_ui
),
array(
'text' => lang('planner by category'),
'value' => '{"view":"planner", "menuaction":"calendar.calendar_uiviews.planner","sortby":"category"}',
'value' => '{"view":"planner", "sortby":"category"}',
'selected' => $this->view == 'planner' && $this->sortby != 'user',
),
array(
'text' => lang('planner by user'),
'value' => '{"view":"planner", "menuaction":"calendar.calendar_uiviews.planner","sortby":"user"}',
'value' => '{"view":"planner","sortby":"user"}',
'selected' => $this->view == 'planner' && $this->sortby == 'user',
),
array(
'text' => lang('yearly planner'),
'value' => '{"view":"planner", "menuaction":"calendar.calendar_uiviews.planner","sortby":"month"}',
'value' => '{"view":"planner","sortby":"month"}',
'selected' => $this->view == 'planner' && $this->sortby == 'month',
),
array(

View File

@ -211,8 +211,24 @@ class calendar_uiviews extends calendar_ui
/**
* Show the last view or the default one, if no last
*/
function index()
function index($content)
{
if($content['merge'])
{
// View from sidebox is JSON encoded
$this->manage_states(array_merge($content,json_decode($content['view'],true)));
if($content['first'])
{
$this->first = egw_time::to($content['first'],'ts');
}
if($content['last'])
{
$this->last = egw_time::to($content['last'],'ts');
}
$_GET['merge'] = $content['merge'];
$this->merge();
return;
}
if (!$this->view) $this->view = 'week';
// handle views in other files
@ -240,6 +256,11 @@ class calendar_uiviews extends calendar_ui
// Actually, this takes care of most of it...
$this->week();
$tmpl = new etemplate_new('calendar.planner');
// Get the actions
$tmpl->setElementAttribute('planner','actions',$this->get_actions());
$tmpl->exec('calendar_uiviews::index',array());
// List view in a separate file
$list_ui = new calendar_uilist();

View File

@ -12,6 +12,7 @@
/*egw:uses
/etemplate/js/etemplate2.js;
/calendar/js/et2_widget_timegrid.js;
/calendar/js/et2_widget_planner.js;
*/
/**
@ -119,6 +120,10 @@ app.classes.calendar = AppJS.extend(
set_start_date: function(state) {
var d = state.date ? new Date(state.date) : new Date();
d.setUTCDate(1);
d.setUTCHours(0);
d.setUTCMinutes(0);
d.setUTCSeconds(0);
state.date = d.toJSON();
return app.calendar.date.start_of_week(d);
},
set_end_date: function(state) {
@ -130,7 +135,76 @@ app.classes.calendar = AppJS.extend(
return week_start;
},
},
listview: {etemplates: ['calendar.list']}
planner: {
etemplates: ['calendar.planner'],
set_group_by: function(state) {
return state.cat_id? state.cat_id : (state.sortby ? state.sortby : 0);
},
set_start_date: function(state) {
var d = state.date ? new Date(state.date) : new Date();
if(state.sortby && state.sortby === 'month')
{
d.setUTCDate(1);
}
else if (!state.planner_days)
{
if(d.getUTCDate() < 15)
{
d.setUTCDate(1);
return app.calendar.date.start_of_week(d);
}
else
{
return app.calendar.date.start_of_week(d);
}
}
return d;
},
set_end_date: function(state) {
var d = state.date ? new Date(state.date) : new Date();
if(state.sortby && state.sortby === 'month')
{
d.setUTCDate(0);
d.setUTCFullYear(d.getUTCFullYear() + 1);
}
else if (state.planner_days)
{
d.setUTCDate(d.getUTCDate() + parseInt(state.planner_days)-1);
}
else if (app.calendar.state.last)
{
d = new Date(app.calendar.state.last);
}
else if (!state.planner_days)
{
if (d.getUTCDate() < 15)
{
d.setUTCDate(0);
d.setUTCMonth(d.getUTCMonth()+1);
d = app.calendar.date.end_of_week(d);
}
else
{
d.setUTCMonth(d.getUTCMonth()+1);
d = app.calendar.date.end_of_week(d);
}
}
return d;
},
set_owner: function(state) {
return state.owner || 0;
}
},
listview: {
etemplates: ['calendar.list'],
set_start_date: function(state)
{
var d = state.date ? new Date(state.date) : new Date();
return d;
}
}
},
/**
@ -162,6 +236,9 @@ app.classes.calendar = AppJS.extend(
//Drag_n_Drop (need to wait for DOM ready to init dnd)
jQuery(jQuery.proxy(this.drag_n_drop,this));
// Scroll
jQuery(jQuery.proxy(this._scroll,this));
},
/**
@ -177,6 +254,7 @@ app.classes.calendar = AppJS.extend(
{
delete window.top.app.calendar;
}
jQuery(egw_getFramework().applications.calendar.tab.contentDiv).off();
},
/**
@ -543,6 +621,55 @@ app.classes.calendar = AppJS.extend(
}
},
/**
* Bind scroll event
* When the user scrolls, we'll move enddate - startdate days
*/
_scroll: function() {
// Bind only once, to the whole tab
jQuery(egw_getFramework().applications.calendar.tab.contentDiv)
.on('wheel','.et2_container:not(#calendar-list)',
function(e)
{
e.preventDefault();
var direction = e.originalEvent.deltaY > 0 ? 1 : -1;
var delta = 1;
var start = new Date(app.calendar.state.date);
var end = null;
// Get the view to calculate
if (app.calendar.views && app.calendar.state.view && app.calendar.views[app.calendar.state.view].set_end_date)
{
if(direction > 0)
{
start = app.calendar.views[app.calendar.state.view].set_end_date({date:start});
}
else
{
start = app.calendar.views[app.calendar.state.view].set_start_date({date:start});
}
start.setUTCDate(start.getUTCDate()+direction);
end = app.calendar.views[app.calendar.state.view].set_end_date({date:start});
}
// Calculate the current difference, and move
else if(app.calendar.state.first && app.calendar.state.last)
{
start = new Date(app.calendar.state.first);
end = new Date(app.calendar.state.last);
// Get the number of days
delta = (Math.round(Math.max(1,end - start)/(24*3600*1000)))*24*3600*1000
// Adjust
start = new Date(start.valueOf() + (delta * direction ));
end = new Date(end.valueOf() + (delta * direction));
}
app.calendar.update_state({date: start});
return false;
}
);
},
/**
* Function to help calendar resizable event, to fetch the right droppable cell
*
@ -1390,8 +1517,8 @@ app.classes.calendar = AppJS.extend(
// Show the correct number of grids
var grid_count = state.state.view == 'weekN' ? parseInt(this.egw.preference('multiple_weeks','calendar')) || 3 :
state.state.view == 'month' ? 0 : // Calculate based on weeks in the month
var grid_count = state.state.view === 'weekN' ? parseInt(this.egw.preference('multiple_weeks','calendar')) || 3 :
state.state.view === 'month' ? 0 : // Calculate based on weeks in the month
state.state.owner.length > (this.egw.config('calview_no_consolidate','phpgwapi') || 5) ? 1 : state.state.owner.length;
var grid = this.views[this.state.view] ? this.views[this.state.view].etemplates[0].widgetContainer.getWidgetById('view') : false;
@ -1401,11 +1528,13 @@ app.classes.calendar = AppJS.extend(
If the count is > 1, it's either because there are multiple date spans (weekN, month) and we need the correct span
per row, or there are multiple owners and we need the correct owner per row.
*/
if(state.state.view !== 'listview' && (!grid || grid_count != grid._children.length || grid_count > 1))
if(grid && (grid_count !== grid._children.length || grid_count > 1))
{
// Need to redo the number of grids
var value = [];
var date = state.state.first = view.set_start_date(state.state);
state.state.first = view.set_start_date(state.state).toJSON();
// We'll modify this one, so it needs to be a new object
var date = new Date(state.state.first);
// Determine the different end date
switch(state.state.view)
@ -1427,7 +1556,7 @@ app.classes.calendar = AppJS.extend(
value.push(val);
date.setUTCHours(24*7);
}
state.state.last=val.end_date;
state.state.last=val.end_date.toJSON();
break;
default:
var end = state.state.last = view.set_end_date(state.state);
@ -1442,16 +1571,16 @@ app.classes.calendar = AppJS.extend(
}
break;
}
if(view.etemplates[0].widgetContainer.getWidgetById('view'))
if(grid)
{
view.etemplates[0].widgetContainer.getWidgetById('view').set_value(
grid.set_value(
{content: value}
);
}
}
else
{
// Simple, easy case - just one timegrid.
// Simple, easy case - just one widget for the selected time span.
// Update existing view's special attribute filters, defined in the view list
for(var updater in view)
{
@ -1658,8 +1787,18 @@ app.classes.calendar = AppJS.extend(
if(_selected[i].iface.getWidget() && _selected[i].iface.getWidget().instanceOf(et2_calendar_event))
{
is_widget = true;
break;
}
// Also check classes, usually indicating permission
if(_action.data && _action.data.enableClass)
{
is_widget = is_widget && ($j( _selected[i].iface.getDOMNode()).hasClass(_action.data.enableClass))
}
if(_action.data && _action.data.disableClass)
{
is_widget = is_widget && !($j( _selected[i].iface.getDOMNode()).hasClass(_action.data.disableClass))
}
}
return is_widget;
},

View File

@ -207,7 +207,7 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM],
this.div.attr("data-date", this.options.date);
// Set holiday and today classes
this._day_class_holiday();
this.day_class_holiday();
// Update all the little boxes
this._draw();
@ -228,7 +228,7 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM],
/**
* Applies class for today, and any holidays for current day
*/
_day_class_holiday: function() {
day_class_holiday: function() {
// Remove all classes
this.title.removeClass()
// Except this one...
@ -243,7 +243,7 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM],
);
// Holidays and birthdays
var holidays = et2_calendar_daycol.get_holidays(this);
var holidays = et2_calendar_daycol.get_holidays(this,this.options.date.substring(0,4));
var holiday_list = [];
if(holidays && holidays[this.options.date])
{
@ -295,7 +295,7 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM],
var events = _events || this.getArrayMgr('content').getEntry(this.options.date) || [];
// Sort events into minimally-overlapping columns
var columns = this._event_columns(events);
var columns = this._spread_events(events);
for(var c = 0; c < columns.length; c++)
{
@ -352,7 +352,7 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM],
* @param {Object[]} events
* @returns {Array[]} Events sorted into columns
*/
_event_columns: function(events)
_spread_events: function(events)
{
var day_start = this.date.valueOf() / 1000;
var dst_check = new Date(this.date);
@ -633,36 +633,36 @@ jQuery.extend(et2_calendar_daycol,
* Fetch and cache a list of the year's holidays
*
* @param {et2_calendar_timegrid} widget
* @param {string|numeric} year
* @returns {Array}
*/
get_holidays: function(widget)
get_holidays: function(widget,year)
{
// Loaded in an iframe or something
if(!egw.window.et2_calendar_daycol) return {};
var cache_id = widget.options.date.substring(0,4);
var cache = egw.window.et2_calendar_daycol.holiday_cache[cache_id];
var cache = egw.window.et2_calendar_daycol.holiday_cache[year];
if (typeof cache == 'undefined')
{
// Fetch with json instead of jsonq because there may be more than
// one widget listening for the response by the time it gets back,
// and we can't do that when it's queued.
egw.window.et2_calendar_daycol.holiday_cache[cache_id] = egw.json(
egw.window.et2_calendar_daycol.holiday_cache[year] = egw.json(
'calendar_timegrid_etemplate_widget::ajax_get_holidays',
[cache_id]
[year]
).sendRequest();
}
cache = egw.window.et2_calendar_daycol.holiday_cache[cache_id];
cache = egw.window.et2_calendar_daycol.holiday_cache[year];
if(typeof cache.done == 'function')
{
// pending, wait for it
cache.done(jQuery.proxy(function(response) {
egw.window.et2_calendar_daycol.holiday_cache[this.cache_id] = response.response[0].data||undefined;
egw.window.et2_calendar_daycol.holiday_cache[this.year] = response.response[0].data||undefined;
egw.window.setTimeout(jQuery.proxy(function() {
this.widget._day_class_holiday();
this.widget.day_class_holiday();
},this),1);
},{widget:widget,cache_id:cache_id}));
},{widget:widget,year:year}));
return {};
}
else

View File

@ -43,6 +43,7 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
// Main container
this.div = $j(document.createElement("div"))
.addClass("calendar_calEvent")
.addClass(this.options.class)
.css('width',this.options.width);
this.title = $j(document.createElement('div'))
.addClass("calendar_calEventHeader")
@ -95,7 +96,7 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
event = jQuery.extend({},event);
var list = [event];
// Let parent format any missing data
this._parent._event_columns(list);
this._parent._spread_events(list);
// Calculate vertical positioning
// TODO: Maybe move this somewhere common between here & parent?
@ -176,8 +177,12 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
// 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;
var small_height = true;
if(this._parent.display_settings)
{
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.div.attr('data-title', title);
this.title.text(small_height ? title : this._get_timespan(event))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,391 @@
/*
* Egroupware
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package
* @subpackage
* @link http://www.egroupware.org
* @author Nathan Gray
* @version $Id$
*/
/**
* Class for one row of a planner
*
* This widget is responsible for the label on the side
*
* @augments et2_valueWidget
*/
var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
{
attributes: {
start_date: {
name: "Start date",
type: "any"
},
end_date: {
name: "End date",
type: "any"
},
value: {
type: "any"
}
},
/**
* Constructor
*
* @memberOf et2_calendar_daycol
*/
init: function() {
this._super.apply(this, arguments);
// Main container
this.div = $j(document.createElement("div"))
.addClass("calendar_plannerRowWidget")
.css('width',this.options.width);
this.title = $j(document.createElement('div'))
.addClass("calendar_plannerRowHeader")
.css('width', '15%')
.appendTo(this.div);
this.rows = $j(document.createElement('div'))
.addClass("calendar_eventRows")
.appendTo(this.div);
this.setDOMNode(this.div[0]);
// Used for its date calculations
this.date_helper = et2_createWidget('date-time',{},null);
this.date_helper.loadingFinished();
},
doLoadingFinished: function() {
this._super.apply(this, arguments);
this.set_label(this.options.label);
this._draw();
return true;
},
destroy: function() {
this._super.apply(this, arguments);
// date_helper has no parent, so we must explicitly remove it
this.date_helper.destroy();
this.date_helper = null;
},
getDOMNode: function(_sender)
{
if(_sender === this || !_sender)
{
return this.div[0];
}
if(_sender._parent === this)
{
return this.rows[0];
}
},
/**
* Draw the individual divs for weekends and events
*/
_draw: function() {
// Remove any existing
this.rows.empty().nextAll().remove();
var days = 31;
var width = 85;
if (this._parent.options.group_by === 'month')
{
days = new Date(this.options.end_date.getUTCFullYear(),this.options.end_date.getUTCMonth()+1,0).getUTCDate();
if(days < 31)
{
width = 85*days/31;
this.rows.css('width',width+'%');
}
}
// mark weekends and other special days in yearly planner
if (this._parent.options.group_by == 'month')
{
this.rows.append(this._yearlyPlannerMarkDays(this.options.start_date, days));
}
if (this._parent.options.group_by === 'month' && days < 31)
{
// add a filler for non existing days in that month
this.rows.after('<div class="calendar_eventRowsFiller"'+
' style="left:'+(15+width)+'%; width:'+(85-width)+'%;" ></div>');
}
},
set_label: function(label)
{
this.options.label = label;
this.title.text(label);
if(this._parent.options.group_by === 'month')
{
this.title.attr('data-date', this.options.start_date.toJSON());
this.title.addClass('et2_clickable');
}
else
{
this.title.attr('data-date','');
this.title.removeClass('et2_clickable');
}
},
/**
* Mark special days (birthdays, holidays) on the planner
*
* @param {Date} start Start of the month
* @param {number} days How many days in the month
*/
_yearlyPlannerMarkDays: function(start,days)
{
var day_width = 100/days;
var t = new Date(start);
var content = '';
for(var left = 0,i = 0; i < days;left += day_width,++i)
{
var holidays = [];
// TODO: implement this, pull / copy data from et2_widget_timegrid
var day_class = this._parent.day_class_holiday(t,holidays);
if (day_class) // no regular weekday
{
content += '<div class="calendar_eventRowsMarkedDay '+day_class+
'" style="left: '+left+'%; width:'+day_width+'%;"'+
(holidays ? ' title="'+holidays.join(',')+'"' : '')+
' ></div>';
}
t.setUTCDate(t.getUTCDate()+1)
}
return content;
},
/**
* Load the event data for this day and create event widgets for each.
*
* If event information is not provided, it will be pulled from the content array.
*
* @param {Object[]} [_events] Array of event information, one per event.
*/
_update_events: function(_events)
{
// Remove all events
while(this._children.length)
{
this._children[this._children.length-1].free();
this.removeChild(this._children[this._children.length-1]);
}
var rows = this._spread_events(_events);
var row = $j('<div class="calendar_plannerEventRowWidget"></div>').appendTo(this.rows);
var height = rows.length * (parseInt(window.getComputedStyle(row[0]).getPropertyValue("height")) || 20);
row.remove();
for(var c = 0; c < rows.length; c++)
{
// Calculate vertical positioning
var top = c * (100.0 / rows.length);
for(var i = 0; i < rows[c].length; i++)
{
// Calculate horizontal positioning
var left = this._time_to_position(rows[c][i].start);
var width = this._time_to_position(rows[c][i].end)-left;
// Create event
var event = et2_createWidget('calendar-event',{
id:rows[c][i].app_id||rows[c][i].id,
class: 'calendar_plannerEvent'
},this);
if(this.isInTree())
{
event.doLoadingFinished();
}
event.set_value(rows[c][i]);
// TODO
event._link_actions(this._parent.options.actions||{});
// Position the event
event.div.css('top', top+'%');
event.div.css('height', (100/rows.length)+'%');
event.div.css('left', left.toFixed(1)+'%');
event.div.css('width', width.toFixed(1)+'%');
}
}
if(height)
{
this.div.height(height+'px');
}
},
/**
* Sort a day's events into non-overlapping rows
*
* @param {Object[]} events
* @returns {Array[]} Events sorted into rows
*/
_spread_events: function(events)
{
// sorting the events in non-overlapping rows
var rows = [];
var row_end = [0];
var start = this.options.start_date;
var end = this.options.end_date;
for(var n = 0; n < events.length; n++)
{
var event = events[n];
if(typeof event.start !== 'object')
{
this.date_helper.set_value(event.start);
event.start = new Date(this.date_helper.getValue());
}
if(typeof event.end !== 'object')
{
this.date_helper.set_value(event.end);
event.end = new Date(this.date_helper.getValue());
}
if(typeof event['start_m'] === 'undefined')
{
var day_start = event.start.valueOf() / 1000;
var dst_check = new Date(event.start);
dst_check.setUTCHours(12);
// if daylight saving is switched on or off, correct $day_start
// gives correct times after 2am, times between 0am and 2am are wrong
var daylight_diff = day_start + 12*60*60 - (dst_check.valueOf()/1000);
if(daylight_diff)
{
day_start -= daylight_diff;
}
event['start_m'] = parseInt((event.start.valueOf()/1000 - day_start) / 60);
if (event['start_m'] < 0)
{
event['start_m'] = 0;
event['multiday'] = true;
}
event['end_m'] = parseInt((event.end.valueOf()/1000 - day_start) / 60);
if (event['end_m'] >= 24*60)
{
event['end_m'] = 24*60-1;
event['multiday'] = true;
}
}
var event_start = new Date(events[n].start).valueOf();
for(var row = 0; row_end[row] > event_start; ++row); // find a "free" row (no other event)
if(typeof rows[row] === 'undefined') rows[row] = [];
rows[row].push(events[n]);
row_end[row] = new Date(events[n]['end']).valueOf();
}
return rows;
},
/**
* Calculates the horizontal position based on the time given, as a percentage
* between the start and end times
*
* @param {int|Date|string} time in minutes from midnight, or a Date in string or object form
* @param {int|Date|string} start Earliest possible time (0%)
* @param {int|Date|string} end Latest possible time (100%)
* @return {float} position in percent
*/
_time_to_position: function(time, start, end)
{
var pos = 0.0;
// Handle the different value types
start = this.options.start_date;
end = this.options.end_date;
if(typeof start === 'string')
{
start = new Date(start);
end = new Date(end);
}
var wd_start = 60 * (parseInt(egw.preference('workdaystarts','calendar')) || 9);
var wd_end = 60 * (parseInt(egw.preference('workdayends','calendar')) || 17);
var t = time;
if(typeof time === 'number' && time < 3600)
{
t = new Date(start.valueOf() + wd_start * 3600*1000);
}
else
{
t = new Date(time);
}
// Limits
if(t <= start) return 0; // We are left of our scale
if(t >= end) return 100; // We are right of our scale
// Basic scaling, doesn't consider working times
pos = (t - start) / (end - start);
// Month view
if(this._parent.options.group_by !== 'month')
{
// Daywise scaling
var start_date = new Date(start.getUTCFullYear(), start.getUTCMonth(),start.getUTCDate());
var end_date = new Date(end.getUTCFullYear(), end.getUTCMonth(),end.getUTCDate());
var t_date = new Date(t.getUTCFullYear(), t.getUTCMonth(),t.getUTCDate());
var days = Math.round((end_date - start_date) / (24 * 3600 * 1000))+1;
pos = 1 / days * Math.round((t_date - start_date) / (24*3600 * 1000));
var time_of_day = typeof t === 'object' ? 60 * t.getUTCHours() + t.getUTCMinutes() : t;
if (time_of_day >= wd_start)
{
var day_percentage = 0.1;
if (time_of_day > wd_end)
{
day_percentage = 1;
}
else
{
var wd_length = wd_end - wd_start;
if (wd_length <= 0) wd_length = 24*60;
day_percentage = (time_of_day-wd_start) / wd_length; // between 0 and 1
}
pos += day_percentage / days;
}
}
pos = 100 * pos;
return pos;
},
/**
* 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_planner_row, ["calendar-planner_row"]);

View File

@ -331,28 +331,6 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
this.dropEnd = drag_helper.call($j('.calendar_calEventHeader',ui.helper)[0],event,ui.helper[0],0);
$j('.calendar_timeDemo',ui.helper).css('bottom','auto');
});
// Bind scroll event
// When the user scrolls, we'll move enddate - startdate days
this.div.on('wheel',jQuery.proxy(function(e) {
var direction = e.originalEvent.deltaY > 0 ? 1 : -1;
this.date_helper.set_value(this.options.end_date || this.options.start_date);
var end = this.date_helper.get_time();
this.date_helper.set_value(this.options.start_date);
var start = this.date_helper.get_time();
var delta = 1000 * 60 * 60 * 24 + Math.max(0,end - start);
// TODO - actually fetch new data
this.set_start_date(new Date(start + (delta * direction )));
this.set_end_date(new Date(end + (delta * direction)));
e.preventDefault();
return false;
},this));
return true;
},

View File

@ -473,6 +473,12 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
border: 1px solid gray;
padding-right: 3px;
}
.calendar_plannerWidget:nth-child(odd) {
background-color: #ffffff;
}
.calendar_plannerWidget:nth-child(even) {
background-color: #f2f2f2;
}
/* calendar_plannerHeader contains a calendar_plannerHeaderTitle and multiple calendar_plannerHeaderRows
*/
@ -481,6 +487,7 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
top: 0px;
left: 0px;
width: 100%;
background-color: #e0e0e0;
}
/* calendar_plannerRowWidget contains a calendar_plannerRowHeader and multiple eventRowWidgets in an calendar_eventRows
@ -490,6 +497,7 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
top: 0px;
left: 0px;
width: 100%;
min-height: 20px;
}
/* calendar_plannerScale represents a scale-row of the calendar_plannerHeader, containing multiple planner{Day|Week|Month}Scales
@ -553,6 +561,8 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
top: 0px;
left: 15%; /* need to be identical for calendar_eventRows and calendar_plannerHeaderRows and match width of calendar_plannerRowHeader/calendar_plannerHeaderTitle */
width: 85%;
min-height: 20px;
height: 100%;
}
/**
@ -576,6 +586,9 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
height: 100%;
z-index: 10;
}
.calendar_eventRowsMarkedDay.calendar_weekend {
background-color: #e0e0e0;
}
/* calendar_eventRowWidget contains non-overlapping events
*/

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Egroupware
@license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
@package
@subpackage
@link http://www.egroupware.org
@author Nathan Gray
@version $Id$
-->
<!DOCTYPE overlay PUBLIC '-//Stylite AG//eTemplate 2//EN' 'http://www.egroupware.org/etemplate2.dtd'>
<overlay>
<template id="calendar.planner">
<calendar-planner id="planner"
onchange="app.calendar.update_state(ev.data);"
onevent_change="app.calendar.event_change"
>
</calendar-planner>
</template>
</overlay>

View File

@ -31,7 +31,7 @@ Egroupware
<buttononly align="center" class="sideboxstar" id="week" image="week" label="Weekview" onclick="app.calendar.update_state({view:'week'});"/>
<buttononly align="center" class="sideboxstar" id="weekN" image="multiweek" label="Multiple week view" onclick="app.calendar.update_state({view:'weekN'});"/>
<buttononly align="center" class="sideboxstar" id="month" image="month" label="Multiple week view" onclick="app.calendar.update_state({view:'month'});"/>
<buttononly align="center" class="sideboxstar" id="planner" image="planner" label="Group planner" onclick="app.calendar.update_state({view:'planner'});"/>
<buttononly align="center" class="sideboxstar" id="planner" image="planner" label="Group planner" onclick="app.calendar.update_state({view:'planner',planner_days:0});"/>
<buttononly align="center" class="sideboxstar" id="listview" image="list" label="Listview" onclick="app.calendar.update_state({view:'listview'});"/>
</row>
</rows>

View File

@ -11,7 +11,7 @@
* @package calendar
* @version $Id$
*/
/* $Id: app.css 52977 2015-06-23 12:32:55Z hnategh $ */
/* $Id: app.css 52979 2015-06-23 14:17:18Z hnategh $ */
/*Media print classes*/
@media print {
.th td,
@ -473,6 +473,12 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
border: 1px solid gray;
padding-right: 3px;
}
.calendar_plannerWidget:nth-child(odd) {
background-color: #ffffff;
}
.calendar_plannerWidget:nth-child(even) {
background-color: #f2f2f2;
}
/* calendar_plannerHeader contains a calendar_plannerHeaderTitle and multiple calendar_plannerHeaderRows
*/
.calendar_plannerHeader {
@ -480,6 +486,7 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
top: 0px;
left: 0px;
width: 100%;
background-color: #e0e0e0;
}
/* calendar_plannerRowWidget contains a calendar_plannerRowHeader and multiple eventRowWidgets in an calendar_eventRows
*/
@ -488,6 +495,7 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
top: 0px;
left: 0px;
width: 100%;
min-height: 20px;
}
/* calendar_plannerScale represents a scale-row of the calendar_plannerHeader, containing multiple planner{Day|Week|Month}Scales
*/
@ -560,6 +568,8 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
left: 15%;
/* need to be identical for calendar_eventRows and calendar_plannerHeaderRows and match width of calendar_plannerRowHeader/calendar_plannerHeaderTitle */
width: 85%;
min-height: 20px;
height: 100%;
}
/**
* Filler for month with less then 31 days in yearly planner
@ -581,6 +591,9 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
height: 100%;
z-index: 10;
}
.calendar_eventRowsMarkedDay.calendar_weekend {
background-color: #e0e0e0;
}
/* calendar_eventRowWidget contains non-overlapping events
*/
.calendar_eventRowWidget {