Calendar et2 conversion work in progress.

- Slightly more efficient event positioning
This commit is contained in:
Nathan Gray 2015-07-03 17:56:36 +00:00
parent a5b36d48e0
commit 4562b53b1b
5 changed files with 159 additions and 113 deletions

View File

@ -492,7 +492,7 @@ app.classes.calendar = AppJS.extend(
egw().json(
'calendar.calendar_uiforms.ajax_moveEvent',
[widget.id, widget.options.value.owner, widget.options.value.start, widget.options.value.owner, widget.options.value.duration]
).sendRequest();
).sendRequest(true);
},
/**

View File

@ -290,69 +290,41 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM],
// Remove all events
while(this._children.length)
{
this._children[this._children.length-1].free();
var node = this._children[this._children.length-1];
this.removeChild(node);
node.free();
}
var events = _events || this.getArrayMgr('content').getEntry(this.options.date) || [];
// Sort events into minimally-overlapping columns
var columns = this._spread_events(events);
for(var c = 0; c < columns.length; c++)
for(var c = 0; c < events.length; c++)
{
// Calculate horizontal positioning
var left = Math.ceil(5 + (1.5 * 100 / (this.options.width || 100)));
var width = 98 - left;
if (columns.length !== 1)
// Create event
var event = et2_createWidget('calendar-event',{
id:events[c].app_id||events[c].id,
value: events[c]
},this);
if(this.isInTree())
{
width = !c ? 70 : 50;
left += c * (100.0-left) / columns.length;
event.doLoadingFinished();
}
if (left + width > 100.0) width = 98.0 - left;
var whole_day_counter = 0;
for(var i = 0; i < columns[c].length; i++)
{
// Calculate vertical positioning
var top = 0;
var height = 0;
if(columns[c][i].whole_day_on_top)
{
top = ((this.title.height()/this.div.height())*100) + this.display_settings.rowHeight*whole_day_counter++;
height = this.display_settings.rowHeight;
}
else
{
top = this._time_to_position(columns[c][i].start_m,whole_day_counter);
height = this._time_to_position(columns[c][i].end_m,whole_day_counter)-top;
}
// Create event
var event = et2_createWidget('calendar-event',{id:columns[c][i].app_id||columns[c][i].id},this);
if(this.isInTree())
{
event.doLoadingFinished();
}
event.set_value(columns[c][i]);
event._link_actions(this._parent._parent.options.actions||{});
// Position the event
event.div.css('top', top+'%');
event.div.css('height', height+'%');
event.div.css('left', left.toFixed(1)+'%');
event.div.css('width', width.toFixed(1)+'%');
}
// Copy actions set in parent
event._link_actions(this._parent._parent.options.actions||{});
}
// Seperate loop so column sorting finds all children in the right place
for(var c = 0; c < events.length; c++)
{
this._children[c].set_value(events[c]);
}
},
/**
* Sort a day's events into minimally overlapping columns
*
* @param {Object[]} events
* @returns {Array[]} Events sorted into columns
*/
_spread_events: function(events)
_spread_events: function()
{
var day_start = this.date.valueOf() / 1000;
var dst_check = new Date(this.date);
@ -367,9 +339,11 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM],
}
var eventCols = [], col_ends = [];
for(var i = 0; i < events.length; i++)
for(var i = 0; i < this._children.length; i++)
{
var event = events[i];
var event = this._children[i].options.value || false;
if(!event) continue;
var c = 0;
event['multiday'] = false;
if(typeof event.start !== 'object')
@ -407,11 +381,70 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM],
{
eventCols[c] = [];
}
eventCols[c].push(event);
eventCols[c].push(this._children[i]);
}
return eventCols;
},
/**
* Position the event according to it's time and how this widget is laid
* out.
*
* @param {undefined|Object|et2_calendar_event} event
*/
position_event: function(event)
{
// Sort events into minimally-overlapping columns
var columns = this._spread_events();
for(var c = 0; c < columns.length; c++)
{
// Calculate horizontal positioning
var left = Math.ceil(5 + (1.5 * 100 / (this.options.width || 100)));
var width = 98 - left;
if (columns.length !== 1)
{
width = !c ? 70 : 50;
left += c * (100.0-left) / columns.length;
}
if (left + width > 100.0) width = 98.0 - left;
var whole_day_counter = 0;
for(var i = 0; (columns[c].indexOf(event) >= 0 || !event) && i < columns[c].length; i++)
{
// Calculate vertical positioning
var top = 0;
var height = 0;
if(columns[c][i].options.value.whole_day_on_top)
{
top = ((this.title.height()/this.div.height())*100) + this.display_settings.rowHeight*whole_day_counter++;
height = this.display_settings.rowHeight;
}
else
{
top = this._time_to_position(columns[c][i].options.value.start_m,whole_day_counter);
height = this._time_to_position(columns[c][i].options.value.end_m,whole_day_counter)-top;
}
// Position the event
if(event && columns[c].indexOf(event) >= 0 || !event)
{
columns[c][i].div.css('top', top+'%');
columns[c][i].div.css('height', height+'%');
columns[c][i].div.css('left', left.toFixed(1)+'%');
columns[c][i].div.css('width', width.toFixed(1)+'%');
}
}
// Only wanted to position this event, leave the other columns alone
if(event && columns[c].indexOf(event) >= 0)
{
return;
}
}
},
/**
* Calculates the vertical position based on the time
*

View File

@ -25,6 +25,10 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
{
attributes: {
"value": {
type: "any",
default: et2_no_init
},
"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 " +
@ -76,8 +80,11 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
this._super.apply(this, arguments);
// Unregister, or we'll continue to be notified...
var old_app_id = this.options.value.app_id ? this.options.value.app_id : this.options.value.id + (this.options.value.recur_type ? ':'+this.options.value.recur_date : '');
egw.dataUnregisterUID('calendar::'+old_app_id,false,this);
if(this.options.value)
{
var old_app_id = this.options.value.app_id ? this.options.value.app_id : this.options.value.id + (this.options.value.recur_type ? ':'+this.options.value.recur_date : '');
egw.dataUnregisterUID('calendar::'+old_app_id,false,this);
}
},
set_value: function(_value) {
@ -93,30 +100,13 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
var app_id = this.options.value.app_id ? this.options.value.app_id : this.options.value.id + (this.options.value.recur_type ? ':'+this.options.value.recur_date : '');
egw.dataRegisterUID('calendar::'+app_id, function(event) {
// Copy to avoid changes, which may cause nm problems
event = jQuery.extend({},event);
var list = [event];
// Let parent format any missing data
this._parent._spread_events(list);
this.options.value = jQuery.extend({},event);
// Calculate vertical positioning
// TODO: Maybe move this somewhere common between here & parent?
var top = 0;
var height = 0;
if(event.whole_day_on_top)
{
top = ((this._parent.title.height()/this._parent.div.height())*100) + this._parent.display_settings.rowHeight;
height = this._parent.display_settings.rowHeight;
}
else
{
top = this._parent._time_to_position(event.start_m,0);
height = this._parent._time_to_position(event.end_m,0)-top;
}
// Let parent position
this._parent.position_event(this);
this._update(this.options.value);
// Position the event - horizontal is controlled by parent
this.div.css('top', top+'%');
this.div.css('height', height+'%');
this._update(event);
},this,this.getInstanceManager().execId,this.id);
@ -304,16 +294,18 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
icons.push('<img src="'+this.egw().image('recur','calendar')+'" title="'+this.egw().lang('recurring event')+'"/>');
}
// icons for single user, multiple users or group(s) and resources
var single = '<img src="'+this.egw().image('single','calendar')+'" title="'+'"/>';
var multiple = '<img src="'+this.egw().image('users','calendar')+'" title="'+'"/>';
for(var uid in this.options.value['participants'])
{
if(Object.keys(this.options.value.participants).length == 1 && !isNaN(uid))
{
icons.push('<img src="'+this.egw().image('single','calendar')+'" title="'+'"/>');
icons.push(single);
break;
}
if(!isNaN(uid))
if(!isNaN(uid) && icons.indexOf(multiple) === -1)
{
icons.push('<img src="'+this.egw().image('users','calendar')+'" title="'+'"/>');
icons.push(multiple);
}
/*
* TODO: resource icons

View File

@ -171,9 +171,9 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
*
* If event information is not provided, it will be pulled from the content array.
*
* @param {Object[]} [_events] Array of event information, one per event.
* @param {Object[]} [events] Array of event information, one per event.
*/
_update_events: function(_events)
_update_events: function(events)
{
// Remove all events
while(this._children.length)
@ -182,7 +182,38 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
this.removeChild(this._children[this._children.length-1]);
}
var rows = this._spread_events(_events);
for(var c = 0; c < events.length; c++)
{
// Create event
var event = et2_createWidget('calendar-event',{
id:events[c].app_id||events[c].id,
value: events[c]
},this);
if(this.isInTree())
{
event.doLoadingFinished();
}
// Copy actions set in parent
event._link_actions(this._parent._parent.options.actions||{});
}
// Seperate loop so column sorting finds all children in the right place
for(var c = 0; c < events.length; c++)
{
this._children[c].set_value(events[c]);
}
},
/**
* Position the event according to it's time and how this widget is laid
* out.
*
* @param {undefined|Object|et2_calendar_event} event
*/
position_event: function(event)
{
var rows = this._spread_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();
@ -192,31 +223,17 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
// Calculate vertical positioning
var top = c * (100.0 / rows.length);
for(var i = 0; i < rows[c].length; i++)
for(var i = 0; (rows[c].indexOf(event) >=0 || !event) && 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||{});
var left = this._time_to_position(rows[c][i].options.value.start);
var width = this._time_to_position(rows[c][i].options.value.end)-left;
// 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)+'%');
rows[c][i].div.css('top', top+'%');
rows[c][i].div.css('height', (100/rows.length)+'%');
rows[c][i].div.css('left', left.toFixed(1)+'%');
rows[c][i].div.css('width', width.toFixed(1)+'%');
}
}
if(height)
@ -228,10 +245,9 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
/**
* Sort a day's events into non-overlapping rows
*
* @param {Object[]} events
* @returns {Array[]} Events sorted into rows
*/
_spread_events: function(events)
_spread_events: function()
{
// sorting the events in non-overlapping rows
var rows = [];
@ -240,9 +256,9 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
var start = this.options.start_date;
var end = this.options.end_date;
for(var n = 0; n < events.length; n++)
for(var n = 0; n < this._children.length; n++)
{
var event = events[n];
var event = this._children[n].options.value || false;
if(typeof event.start !== 'object')
{
this.date_helper.set_value(event.start);
@ -282,11 +298,11 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
}
}
var event_start = new Date(events[n].start).valueOf();
var event_start = new Date(event.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();
rows[row].push(this._children[n]);
row_end[row] = new Date(event['end']).valueOf();
}
return rows;
},

View File

@ -245,7 +245,8 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
if(event_widget)
{
event_widget.options.value.end_m = event_widget.options.value.duration = e.data.duration;
event_widget.options.value.end_m = eT;
event_widget.options.value.duration = e.data.duration;
}
$j(this).trigger(e);
@ -253,7 +254,10 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
$j(this).resizable('destroy');
}
// Clear the helper, re-draw
event_widget.set_value(event_widget.options.value);
if(event_widget)
{
event_widget._parent.position_event(event_widget);
}
},
/**
@ -517,6 +521,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
// Create / update day widgets with dates and data, if available
// TODO: need data doesn't take category & other filters into account
// Currently always loading new data, which causes multiple unneeded redraws
var need_data = true;
for(var i = 0; i < this.day_list.length; i++)
{