* Calendar: Create new events by dragging on empty space

This commit is contained in:
nathangray 2016-06-30 13:21:13 -06:00
parent 482cf970a8
commit b7919b1fe0
5 changed files with 333 additions and 14 deletions

View File

@ -203,12 +203,14 @@ class calendar_uiforms extends calendar_ui
'id' => 1,
);
}
$duration = isset($_GET['duration']) ? (int)$_GET['duration'] : (int) $this->bo->cal_prefs['defaultlength']*60;
$end = isset($_GET['end']) ? Api\DateTime::to($_GET['end'], 'ts') : $start + $duration;
return array(
'participant_types' => $participant_types,
'participants' => $participants,
'owner' => $owner,
'start' => $start,
'end' => $start + (int) $this->bo->cal_prefs['defaultlength']*60,
'end' => $end,
'tzid' => $this->bo->common_prefs['tz'],
'priority' => 2, // normal
'public'=> $this->cal_prefs['default_private'] ? 0 : 1,

View File

@ -65,6 +65,9 @@ app.classes.calendar = (function(){ "use strict"; return AppJS.extend(
owner: egw.user('account_id')
},
/**
* These are the keys we keep to set & remember the status, others are discarded
*/
states_to_save: ['owner','status_filter','filter','cat_id','view','sortby','planner_view','weekend'],
// If you are in one of these views and select a date in the sidebox, the view
@ -527,7 +530,7 @@ app.classes.calendar = (function(){ "use strict"; return AppJS.extend(
if(!sortable.sortable('instance'))
{
sortable.sortable({
cancel: "#divAppboxHeader, .calendar_calWeekNavHeader, .calendar_plannerHeader",
cancel: "#divAppboxHeader, .calendar_calWeekNavHeader, .calendar_calDayColHeader, .calendar_plannerHeader",
handle: '.calendar_calGridHeader',
//placeholder: "srotable_cal_wk_ph",
axis:"y",

View File

@ -129,10 +129,6 @@ var et2_calendar_planner = (function(){ "use strict"; return et2_calendar_view.e
this._drawGrid();
}
// Actions may be set on a parent, so we need to explicitly get in here
// and get ours
this._link_actions(this.options.actions || this._parent.options.actions || []);
// Automatically bind drag and resize for every event using jQuery directly
// - no action system -
var planner = this;
@ -263,13 +259,26 @@ var et2_calendar_planner = (function(){ "use strict"; return et2_calendar_view.e
planner.vertical_bar
.html('<span>'+date(egw.preference('timeformat','calendar') == 12 ? 'h:ia' : 'H:i',formatDate)+'</span>')
.show();
if(planner.drag_create.event && planner.drag_create.parent && planner.drag_create.end)
{
planner.drag_create.end.date = time.toJSON()
planner._drag_update_event();
}
}
else
{
// No (valid) time, just hide
planner.vertical_bar.hide();
}
});
})
.on('mousedown', jQuery.proxy(this._mouse_down, this))
.on('mouseup', jQuery.proxy(this._mouse_up, this));
// Actions may be set on a parent, so we need to explicitly get in here
// and get ours
this._link_actions(this.options.actions || this._parent.options.actions || []);
// Customize and override some draggable settings
this.div.on('dragcreate','.calendar_calEvent', function(event, ui) {
@ -694,12 +703,6 @@ var et2_calendar_planner = (function(){ "use strict"; return et2_calendar_view.e
this.widget._drawGrid();
// Update actions
if(this.widget._actionManager)
{
this.widget._link_actions(this.widget._actionManager.children);
}
if(this.trigger)
{
this.widget.change();
@ -1742,6 +1745,9 @@ var et2_calendar_planner = (function(){ "use strict"; return et2_calendar_view.e
{
var result = true;
// Drag to create in progress
if(this.drag_create.start !== null) return;
// Is this click in the event stuff, or in the header?
if(!this.options.readonly && this.gridHeader.has(_ev.target).length === 0 && !jQuery(_ev.target).hasClass('calendar_plannerRowHeader'))
{
@ -1873,6 +1879,59 @@ var et2_calendar_planner = (function(){ "use strict"; return et2_calendar_view.e
return new Date(this.date_helper.getValue());
},
/**
* Mousedown handler to support drag to create
*
* @param {jQuery.Event} event
*/
_mouse_down: function(event)
{
// Get time at mouse
if(this.options.group_by === 'month')
{
var time = this._get_time_from_position(event.clientX, event.clientY);
}
else
{
var time = this._get_time_from_position(event.offsetX, event.offsetY);
}
this.div.css('cursor', 'ew-resize');
// Find the correct row so we know the parent
var row = event.target.closest('.calendar_plannerRowWidget');
var row_widget = null;
for(var i = 0; i < this._children.length && row; i++)
{
if(this._children[i].div[0] === row)
{
this.drag_create.parent = this._children[i];
break;
}
}
return this._drag_create_start({date: time.toJSON()});
},
/**
* Mouseup handler to support drag to create
*
* @param {jQuery.Event} event
*/
_mouse_up: function(event)
{
// Get time at mouse
if(this.options.group_by === 'month')
{
var time = this._get_time_from_position(event.clientX, event.clientY);
}
else
{
var time = this._get_time_from_position(event.offsetX, event.offsetY);
}
return this._drag_create_end({date: time.toJSON()});
},
/**
* Code for implementing et2_IDetachedDOM
*

View File

@ -306,16 +306,43 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view.
.css('top', '').css('left','')
.appendTo(ui.helper);
ui.helper.width(jQuery(this).width());
// Cancel drag to create, we're dragging an existing event
timegrid.drag_create.start = null;
})
.on('mousemove', function(event) {
timegrid._get_time_from_position(event.clientX, event.clientY);
if(timegrid.drag_create.event && timegrid.drag_create.parent && timegrid.drag_create.end)
{
var end = jQuery.extend({}, timegrid.gridHover[0].dataset);
if(end.date)
{
timegrid.date_helper.set_year(end.date.substring(0,4));
timegrid.date_helper.set_month(end.date.substring(4,6));
timegrid.date_helper.set_date(end.date.substring(6,8));
if(end.hour)
{
timegrid.date_helper.set_hours(end.hour);
}
if(end.minute)
{
timegrid.date_helper.set_minutes(end.minute);
}
timegrid.drag_create.end.date = timegrid.date_helper.get_value();
}
timegrid._drag_update_event();
}
})
.on('mouseout', function(event) {
if(timegrid.div.has(event.relatedTarget).length === 0)
{
timegrid.gridHover.hide();
}
});
})
.on('mousedown', jQuery.proxy(this._mouse_down, this))
.on('mouseup', jQuery.proxy(this._mouse_up, this));
return true;
},
@ -1751,6 +1778,9 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view.
click: function(_ev)
{
var result = true;
// Drag to create in progress
if(this.drag_create.start !== null) return;
// Is this click in the event stuff, or in the header?
if(_ev.target.dataset.id || jQuery(_ev.target).parents('.calendar_calEvent').length)
@ -1830,6 +1860,67 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view.
}
},
/**
* Mousedown handler to support drag to create
*
* @param {jQuery.Event} event
*/
_mouse_down: function(event)
{
var start = jQuery.extend({},this.gridHover[0].dataset);
if(start.date)
{
// Set parent for event
this.drag_create.parent = this.getWidgetById(start.date);
// Format date
this.date_helper.set_year(start.date.substring(0,4));
this.date_helper.set_month(start.date.substring(4,6));
this.date_helper.set_date(start.date.substring(6,8));
if(start.hour)
{
this.date_helper.set_hours(start.hour);
}
if(start.minute)
{
this.date_helper.set_minutes(start.minute);
}
start.date = this.date_helper.get_value();
this.gridHover.css('cursor', 'ns-resize');
}
return this._drag_create_start(start);
},
/**
* Mouseup handler to support drag to create
*
* @param {jQuery.Event} event
*/
_mouse_up: function(event)
{
var end = jQuery.extend({}, this.gridHover[0].dataset);
if(end.date)
{
this.date_helper.set_year(end.date.substring(0,4));
this.date_helper.set_month(end.date.substring(4,6));
this.date_helper.set_date(end.date.substring(6,8));
if(end.hour)
{
this.date_helper.set_hours(end.hour);
}
if(end.minute)
{
this.date_helper.set_minutes(end.minute);
}
end.date = this.date_helper.get_value();
}
this.gridHover.css('cursor', '');
return this._drag_create_end(end);
},
/**
* Get time from position for drag and drop
*
@ -1878,6 +1969,8 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view.
height: $node.css('padding-bottom')
});
day = node;
this.gridHover
.attr('data-non_blocking','true');
break;
}
if($node.hasClass('calendar_calDayCol'))

View File

@ -57,6 +57,14 @@ var et2_calendar_view = (function(){ "use strict"; return et2_valueWidget.extend
this.loader = jQuery('<div class="egw-loading-prompt-container ui-front loading"></div>');
this.update_timer = null;
// Used to support dragging on empty space to create an event
this.drag_create = {
start: null,
end: null,
parent: null,
event: null
};
},
destroy: function destroy() {
@ -383,6 +391,160 @@ var et2_calendar_view = (function(){ "use strict"; return et2_valueWidget.extend
result.widget_id = 'event_' + widget_id.join('');
}
return result;
},
/**
* Starting (mousedown) handler to support drag to create
*
* Extending classes need to set this.drag_create.parent, which is the
* parent container (child of extending class) that will directly hold the
* event.
*
* @param {String} start Date string (JSON format)
*/
_drag_create_start: function(start)
{
this.drag_create.start = jQuery.extend({},start);
if(!this.drag_create.start.date)
{
this.drag_create.start = null;
}
this.drag_create.end = start;
// Clear some stuff, if last time did not complete
if(this.drag_create.event)
{
this.drag_create.event.destroy();
this.drag_create.event = null;
}
// Wait a bit before adding an "event", it may be just a click
window.setTimeout(jQuery.proxy(function() {
// Create event
this._drag_create_event();
}, this), 250);
},
/**
* Create or update an event used for feedback while dragging on empty space,
* so user can see something is happening
*
* @param {type} start
*/
_drag_create_event: function()
{
if(!this.drag_create.parent || !this.drag_create.start)
{
return;
}
if(!this.drag_create.event)
{
this.date_helper.set_value(this.drag_create.start.date);
var value = jQuery.extend({},
this.drag_create.start,
this.drag_create.end,
{
start: this.drag_create.start.date,
end: this.drag_create.end && this.drag_create.end.date || this.drag_create.start.date,
date: ""+this.date_helper.get_year()+
sprintf("%02d",this.date_helper.get_month())+
sprintf("%02d",this.date_helper.get_date()),
title: '',
description: '',
owner: this.options.owner,
participants: this.options.owner,
app: 'calendar',
whole_day_on_top: this.drag_create.start.whole_day
}
);
this.drag_create.event = et2_createWidget('calendar-event',{
id:'event_drag',
value: value
},this.drag_create.parent);
this.drag_create.event._values_check(value);
this.drag_create.event.doLoadingFinished();
}
},
_drag_update_event: function()
{
if(!this.drag_create.event || !this.drag_create.start || !this.drag_create.end
|| !this.drag_create.parent)
{
return;
}
else if (this.drag_create.end)
{
this.drag_create.event.options.value.end = this.drag_create.end.date;
this.drag_create.event._values_check(this.drag_create.event.options.value);
}
this.drag_create.event._update()
this.drag_create.parent.position_event(this.drag_create.event);
},
/**
* Ending (mouseup) handler to support drag to create
*
* @param {String} end Date string (JSON format)
*/
_drag_create_end: function(end)
{
this.div.css('cursor','');
if(this.drag_create.start && end.date &&
JSON.stringify(this.drag_create.start.date) !== JSON.stringify(end.date))
{
// Drag from start to end, open dialog
var options = {
start: this.drag_create.start.date < end.date ? this.drag_create.start.date : end.date,
end: this.drag_create.start.date < end.date ? end.date : this.drag_create.start.date
};
// Whole day needs to go from 00:00 to 23:59
if(end.whole_day || this.drag_create.start.whole_day)
{
var start = new Date(options.start);
start.setUTCHours(0);
start.setUTCMinutes(0);
options.start = start.toJSON();
var end = new Date(options.end);
end.setUTCHours(23);
end.setUTCMinutes(59);
options.end = end.toJSON();
}
// Add anything else that was set, but not date
jQuery.extend(options,this.drag_create.start, end);
delete(options.date);
if (this.options.owner !== app.calendar.state.owner && !options.owner)
{
options.owner = this.options.owner;
}
this.egw().open(null, 'calendar', 'add', options, '_blank');
// Wait a bit, having these stops the click
window.setTimeout(jQuery.proxy(function() {
this.drag_create.start = null;
this.drag_create.end = null;
this.drag_create.parent = null;
if(this.drag_create.event)
{
this.drag_create.event.destroy();
this.drag_create.event = null;
}
},this),100);
return false;
}
this.drag_create.start = null;
this.drag_create.end = null;
this.drag_create.parent = null;
this.drag_create.event.destroy();
this.drag_create.event = null;
return false;
}
});}).call(this);