diff --git a/calendar/js/app.js b/calendar/js/app.js
index 8d7a1634dd..90577ffb3b 100644
--- a/calendar/js/app.js
+++ b/calendar/js/app.js
@@ -1947,27 +1947,37 @@ app.classes.calendar = AppJS.extend(
* @param {Object} state
* @param {etemplate2} [instance] If the full calendar app isn't loaded
* (home app), pass a different instance to use it to get the data
+ * @param {number} [start] Result offset. Internal use only
*/
- _fetch_data: function(state, instance)
+ _fetch_data: function(state, instance, start)
{
if(!this.sidebox_et2 && !instance) return;
+ if(typeof start === 'undefined')
+ {
+ start = 0;
+ }
+
+ var query = jQuery.extend({}, {
+ get_rows: 'calendar.calendar_uilist.get_rows',
+ row_id:'row_id',
+ startdate:state.first || state.date,
+ enddate:state.last,
+ // Participant must be an array or it won't work
+ col_filter: {participant: (typeof state.owner == 'string' || typeof state.owner == 'number' ? [state.owner] : state.owner)},
+ filter:'custom', // Must be custom to get start & end dates
+ status_filter: state.filter,
+ cat_id: state.cat_id,
+ search: state.keywords
+ });
+ // Show ajax loader
+ framework.applications.calendar.sidemenuEntry.showAjaxLoader()
+
this.egw.dataFetch(
instance ? instance.etemplate_exec_id :
this.sidebox_et2.getInstanceManager().etemplate_exec_id,
- {start: 0, num_rows:0},
- jQuery.extend({}, {
- get_rows: 'calendar.calendar_uilist.get_rows',
- row_id:'row_id',
- startdate:state.first || state.date,
- enddate:state.last,
- // Participant must be an array or it won't work
- col_filter: {participant: (typeof state.owner == 'string' || typeof state.owner == 'number' ? [state.owner] : state.owner)},
- filter:'custom', // Must be custom to get start & end dates
- status_filter: state.filter,
- cat_id: state.cat_id,
- search: state.keywords
- }),
+ {start: start, num_rows:200},
+ query,
this.id,
function(data) {
console.log(data);
@@ -2017,6 +2027,18 @@ app.classes.calendar = AppJS.extend(
{
this.egw.dataStoreUID(app.classes.calendar._daywise_cache_id(day, state.owner), updated_days[day]);
}
+
+ // More rows?
+ if(data.order.length + start < data.total)
+ {
+ // Wait a bit, let UI do something.
+ window.setTimeout( function() {
+ app.calendar._fetch_data(state, instance, start + data.order.length);
+ }, 100);
+ }
+
+ // Hide AJAX loader
+ framework.applications.calendar.sidemenuEntry.hideAjaxLoader();
}, this,null
);
},
diff --git a/calendar/js/et2_widget_daycol.js b/calendar/js/et2_widget_daycol.js
index 580c3c4377..6581015cf6 100644
--- a/calendar/js/et2_widget_daycol.js
+++ b/calendar/js/et2_widget_daycol.js
@@ -30,7 +30,8 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
date: {
name: "Date",
type: "any",
- description: "What date is this daycol for. YYYYMMDD or Date"
+ description: "What date is this daycol for. YYYYMMDD or Date",
+ default: et2_no_init
},
owner: {
name: "Owner",
@@ -103,6 +104,14 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
destroy: function() {
this._super.apply(this, arguments);
+ this.div.off();
+ this.title.off();
+ this.div = null;
+ this.title = null;
+
+ // date_helper has no parent, so we must explicitly remove it
+ this.date_helper.destroy();
+ this.date_helper = null;
egw.dataUnregisterUID(app.classes.calendar._daywise_cache_id(this.options.date,this.options.owner),false,this);
},
@@ -247,27 +256,34 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
* @param {number|number[]} _owner Account ID
*/
set_owner: function(_owner) {
- if(_owner !== this.options.owner)
+ // Simple comparison, both numbers
+ if(_owner === this.options.owner) return;
+
+ // More complicated comparison, one or the other is an array
+ if((typeof _owner == 'object' || typeof this.options.owner == 'object') &&
+ _owner.toString() == this.options.owner.toString())
{
- egw.dataUnregisterUID(app.classes.calendar._daywise_cache_id+(this.options.date,this.options.owner),false,this);
-
- this.options.owner = _owner;
- this.div.attr('data-sortable-id', this.options.owner);
-
- // Register for updates on events for this day
- egw.dataRegisterUID(app.classes.calendar._daywise_cache_id(this.options.date,this.options.owner), function(event_ids) {
- var events = [];
- for(var i = 0; i < event_ids.length; i++)
- {
- var event = egw.dataGetUIDdata('calendar::'+event_ids[i]).data;
- if(event && event.date && event.date === this.options.date)
- {
- events.push(event);
- }
- }
- this._update_events(events);
- },this,this.getInstanceManager().execId,this.id);
+ return;
}
+
+ egw.dataUnregisterUID(app.classes.calendar._daywise_cache_id+(this.options.date,this.options.owner),false,this);
+
+ this.options.owner = _owner;
+ this.div.attr('data-sortable-id', this.options.owner);
+
+ // Register for updates on events for this day
+ egw.dataRegisterUID(app.classes.calendar._daywise_cache_id(this.options.date,this.options.owner), function(event_ids) {
+ var events = [];
+ for(var i = 0; i < event_ids.length; i++)
+ {
+ var event = egw.dataGetUIDdata('calendar::'+event_ids[i]).data;
+ if(event && event.date && event.date === this.options.date)
+ {
+ events.push(event);
+ }
+ }
+ this._update_events(events);
+ },this,this.getInstanceManager().execId,this.id);
},
/**
@@ -335,7 +351,7 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
var events = _events || this.getArrayMgr('content').getEntry(this.options.date) || [];
// Remove extra events
- while(this._children.length > events.length)
+ while(this._children.length > 0)
{
var node = this._children[this._children.length-1];
this.removeChild(node);
@@ -349,7 +365,7 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
return a.whole_day ? -1 : (start ? start : end);
});
- for(var c = this._children.length; c < events.length; c++)
+ for(var c = 0; c < events.length; c++)
{
// Create event
var event = et2_createWidget('calendar-event',{
diff --git a/calendar/js/et2_widget_event.js b/calendar/js/et2_widget_event.js
index 4505c1fdce..0cac28c955 100644
--- a/calendar/js/et2_widget_event.js
+++ b/calendar/js/et2_widget_event.js
@@ -84,7 +84,23 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
destroy: function() {
this._super.apply(this, arguments);
-
+
+ if(this._actionObject)
+ {
+ this._actionObject.remove();
+ this._actionObject = null;
+ }
+
+ this.div.off();
+ this.title.remove();
+ this.title = null;
+ this.body.remove();
+ this.body = null;
+ this.icons = null;
+ this.div.remove();
+ this.div = null;
+
+
// Unregister, or we'll continue to be notified...
if(this.options.value)
{
@@ -280,7 +296,7 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
''+this.egw().lang('End') + ':' + end
var cat = et2_createWidget('select-cat',{'readonly':true},this);
cat.set_value(this.options.value.category);
- var cat_label = cat.node.innerText;
+ var cat_label = cat.span.text();
cat.destroy();
return '
'+
@@ -477,33 +493,37 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
*/
_link_actions: function(actions)
{
- // Get the top level element - timegrid or so
- var objectManager = this.getParent().getParent()._actionObject ||
- egw_getAppObjectManager(true).getObjectById(this._parent._parent._parent.id) || egw_getAppObjectManager(true);
- var widget_object = objectManager.getObjectById('calendar::'+this.id);
- if (widget_object == null) {
+ if(!this._actionObject)
+ {
+ // Get the top level element - timegrid or so
+ var objectManager = this.getParent().getParent()._actionObject ||
+ egw_getAppObjectManager(true).getObjectById(this._parent._parent._parent.id) || egw_getAppObjectManager(true);
+ this._actionObject = objectManager.getObjectById('calendar::'+this.id);
+ }
+
+ if (this._actionObject == null) {
// Add a new container to the object manager which will hold the widget
// objects
- widget_object = objectManager.insertObject(false, new egwActionObject(
+ this._actionObject = objectManager.insertObject(false, new egwActionObject(
'calendar::'+this.id, objectManager, new et2_event_action_object_impl(this,this.getDOMNode()),
this._actionManager || objectManager.manager.getActionById(this.id) || objectManager.manager
));
}
else
{
- widget_object.setAOI(new et2_event_action_object_impl(this, this.getDOMNode()));
+ this._actionObject.setAOI(new et2_event_action_object_impl(this, this.getDOMNode()));
}
// Delete all old objects
- widget_object.clear();
- widget_object.unregisterActions();
+ this._actionObject.clear();
+ this._actionObject.unregisterActions();
// Go over the widget & add links - this is where we decide which actions are
// 'allowed' for this widget at this time
var action_links = this._get_action_links(actions);
action_links.push('egw_link_drag');
action_links.push('egw_link_drop');
- widget_object.updateActionLinks(action_links);
+ this._actionObject.updateActionLinks(action_links);
},
/**
diff --git a/calendar/js/et2_widget_planner.js b/calendar/js/et2_widget_planner.js
index 8e762fe608..6ed4f3aa44 100644
--- a/calendar/js/et2_widget_planner.js
+++ b/calendar/js/et2_widget_planner.js
@@ -108,6 +108,7 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
// Update timer, to avoid redrawing twice when changing start & end date
this.update_timer = null;
+ this.doInvalidate = true;
this.setDOMNode(this.div[0]);
@@ -549,27 +550,40 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
*/
invalidate: function(trigger) {
+ // Busy
+ if(!this.doInvalidate && this.update_timer) return;
+
// Wait a bit to see if anything else changes, then re-draw the days
- if(this.update_timer === null)
+ if(this.update_timer !== null)
{
- this.update_timer = window.setTimeout(jQuery.proxy(function() {
- this.widget.value = this.widget._fetch_data();
-
- this.widget._drawGrid();
-
- // Update actions
- if(this._actionManager)
- {
- this._link_actions(this._actionManager.children);
- }
-
- if(this.trigger)
- {
- this.widget.change();
- }
- this.widget.update_timer = null;
- },{widget:this,"trigger":trigger}),ET2_GRID_INVALIDATE_TIMEOUT);
+ window.clearTimeout(this.update_timer);
}
+ this.update_timer = window.setTimeout(jQuery.proxy(function() {
+ this.doInvalidate = false;
+
+ this.widget.value = this.widget._fetch_data();
+
+ // Show AJAX loader
+ framework.applications.calendar.sidemenuEntry.showAjaxLoader();
+
+ this.widget._drawGrid();
+
+ // Update actions
+ if(this._actionManager)
+ {
+ this._link_actions(this._actionManager.children);
+ }
+
+ // Hide AJAX loader
+ framework.applications.calendar.sidemenuEntry.hideAjaxLoader();
+
+ if(this.trigger)
+ {
+ this.widget.change();
+ }
+ this.widget.update_timer = null;
+ this.doInvalidate = true;
+ },{widget:this,"trigger":trigger}),ET2_GRID_INVALIDATE_TIMEOUT);
},
detachFromDOM: function() {
@@ -661,6 +675,7 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
grouper.draw_row.call(this,labels[key].id, labels[key].label, events[key] || []);
}
+ this.value = [];
},
/**
@@ -1352,6 +1367,8 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
{
var value = [];
var fetch = false;
+ this.doInvalidate = false;
+
for(var i = 0; i < this.registeredCallbacks.length; i++)
{
egw.dataUnregisterUID(this.registeredCallbacks[i],false,this);
@@ -1412,6 +1429,8 @@ var et2_calendar_planner = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResize
filter: this.options.filter
}, this.getInstanceManager());
}
+
+ this.doInvalidate = true;
return value;
},
diff --git a/calendar/js/et2_widget_planner_row.js b/calendar/js/et2_widget_planner_row.js
index 25ee5101a0..8ce2f9415b 100644
--- a/calendar/js/et2_widget_planner_row.js
+++ b/calendar/js/et2_widget_planner_row.js
@@ -181,6 +181,7 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
this._children[this._children.length-1].free();
this.removeChild(this._children[this._children.length-1]);
}
+ this._cached_rows = [];
for(var c = 0; c < events.length; c++)
{
@@ -249,6 +250,12 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
*/
_spread_events: function()
{
+ // Keep it so we don't have to re-do it when the next event asks
+ if(this._cached_rows.length == this._children.length)
+ {
+ return this._cached_rows;
+ }
+
// sorting the events in non-overlapping rows
var rows = [];
var row_end = [0];
@@ -304,6 +311,7 @@ var et2_calendar_planner_row = et2_valueWidget.extend([et2_IDetachedDOM],
rows[row].push(this._children[n]);
row_end[row] = new Date(event['end']).valueOf();
}
+ this._cached_rows = rows;
return rows;
},
diff --git a/calendar/js/et2_widget_timegrid.js b/calendar/js/et2_widget_timegrid.js
index 5cfbead835..ff878f411b 100644
--- a/calendar/js/et2_widget_timegrid.js
+++ b/calendar/js/et2_widget_timegrid.js
@@ -139,8 +139,26 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
this.setDOMNode(this.div[0]);
},
destroy: function() {
+
+ // Stop the invalidate timer
+ if(this.update_timer)
+ {
+ window.clearTimeout(this.update_timer);
+ }
+
this._super.apply(this, arguments);
+
+ // Delete all old objects
+ this._actionObject.clear();
+ this._actionObject.unregisterActions();
+ this._actionObject.remove();
+ this._actionObject = null;
+
this.div.off();
+ this.div = null;
+ this.gridHeader = null;
+ this.days = null;
+ this._labelContainer = null;
// date_helper has no parent, so we must explicitly remove it
this.date_helper.destroy();
@@ -548,6 +566,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
{
day = this.day_widgets[i];
// Set the date, and pass any data we have
+ /* Not needed due to registered callbacks (?)
if(typeof this.value[this.day_list[i]] === 'undefined')
{
var ids = (egw.dataGetUIDdata(app.classes.calendar._daywise_cache_id(this.day_list[i],this.options.owner))||{data:[]});
@@ -563,6 +582,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
}
}
}
+ */
day.set_date(this.day_list[i], this.value[this.day_list[i]] || false);
day.set_owner(this.options.owner);
@@ -1067,7 +1087,6 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
this.options.label = label;
this.gridHeader.text(label);
-debugger;
// If it's a short label (eg week number), don't give it an extra line
// but is empty, but give extra space for a single owner name
this.div.removeClass('calendar_TimeGridNoLabel');