Add time-slots popup in task dialog (#5441)
This commit is contained in:
parent
a62b33f54d
commit
7ca0e4c7f8
3 changed files with 125 additions and 95 deletions
|
@ -3845,77 +3845,6 @@ function rcube_calendar_ui(settings)
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// format time string
|
|
||||||
var formattime = function(hour, minutes, start) {
|
|
||||||
var time, diff, unit, duration = '', d = new Date();
|
|
||||||
d.setHours(hour);
|
|
||||||
d.setMinutes(minutes);
|
|
||||||
time = $.fullCalendar.formatDate(d, settings['time_format']);
|
|
||||||
if (start) {
|
|
||||||
diff = Math.floor((d.getTime() - start.getTime()) / 60000);
|
|
||||||
if (diff > 0) {
|
|
||||||
unit = 'm';
|
|
||||||
if (diff >= 60) {
|
|
||||||
unit = 'h';
|
|
||||||
diff = Math.round(diff / 3) / 20;
|
|
||||||
}
|
|
||||||
duration = ' (' + diff + unit + ')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [time, duration];
|
|
||||||
};
|
|
||||||
|
|
||||||
var autocomplete_times = function(p, callback) {
|
|
||||||
/* Time completions */
|
|
||||||
var result = [];
|
|
||||||
var now = new Date();
|
|
||||||
var st, start = (String(this.element.attr('id')).indexOf('endtime') > 0
|
|
||||||
&& (st = $('#edit-starttime').val())
|
|
||||||
&& $('#edit-startdate').val() == $('#edit-enddate').val())
|
|
||||||
? parse_datetime(st, '') : null;
|
|
||||||
var full = p.term - 1 > 0 || p.term.length > 1;
|
|
||||||
var hours = start ? start.getHours() :
|
|
||||||
(full ? parse_datetime(p.term, '') : now).getHours();
|
|
||||||
var step = 15;
|
|
||||||
var minutes = hours * 60 + (full ? 0 : now.getMinutes());
|
|
||||||
var min = Math.ceil(minutes / step) * step % 60;
|
|
||||||
var hour = Math.floor(Math.ceil(minutes / step) * step / 60);
|
|
||||||
// list hours from 0:00 till now
|
|
||||||
for (var h = start ? start.getHours() : 0; h < hours; h++)
|
|
||||||
result.push(formattime(h, 0, start));
|
|
||||||
// list 15min steps for the next two hours
|
|
||||||
for (; h < hour + 2 && h < 24; h++) {
|
|
||||||
while (min < 60) {
|
|
||||||
result.push(formattime(h, min, start));
|
|
||||||
min += step;
|
|
||||||
}
|
|
||||||
min = 0;
|
|
||||||
}
|
|
||||||
// list the remaining hours till 23:00
|
|
||||||
while (h < 24)
|
|
||||||
result.push(formattime((h++), 0, start));
|
|
||||||
|
|
||||||
return callback(result);
|
|
||||||
};
|
|
||||||
|
|
||||||
var autocomplete_open = function(event, ui) {
|
|
||||||
// scroll to current time
|
|
||||||
var $this = $(this);
|
|
||||||
var widget = $this.autocomplete('widget');
|
|
||||||
var menu = $this.data('ui-autocomplete').menu;
|
|
||||||
var amregex = /^(.+)(a[.m]*)/i;
|
|
||||||
var pmregex = /^(.+)(a[.m]*)/i;
|
|
||||||
var val = $(this).val().replace(amregex, '0:$1').replace(pmregex, '1:$1');
|
|
||||||
var li, html;
|
|
||||||
widget.css('width', '10em');
|
|
||||||
widget.children().each(function(){
|
|
||||||
li = $(this);
|
|
||||||
html = li.children().first().html().replace(/\s+\(.+\)$/, '').replace(amregex, '0:$1').replace(pmregex, '1:$1');
|
|
||||||
if (html.indexOf(val) == 0)
|
|
||||||
menu._scrollIntoView(li);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// if start date is changed, shift end date according to initial duration
|
// if start date is changed, shift end date according to initial duration
|
||||||
var shift_enddate = function(dateText) {
|
var shift_enddate = function(dateText) {
|
||||||
var newstart = parse_datetime('0', dateText);
|
var newstart = parse_datetime('0', dateText);
|
||||||
|
@ -4016,30 +3945,12 @@ function rcube_calendar_ui(settings)
|
||||||
$('#edit-allday').click(function(){ $('#edit-starttime, #edit-endtime')[(this.checked?'hide':'show')](); event_times_changed(); });
|
$('#edit-allday').click(function(){ $('#edit-starttime, #edit-endtime')[(this.checked?'hide':'show')](); event_times_changed(); });
|
||||||
|
|
||||||
// configure drop-down menu on time input fields based on jquery UI autocomplete
|
// configure drop-down menu on time input fields based on jquery UI autocomplete
|
||||||
$('#edit-starttime, #edit-endtime, #eventedit input.edit-alarm-time')
|
$('#edit-starttime, #edit-endtime, #eventedit input.edit-alarm-time').each(function() {
|
||||||
.attr('autocomplete', "off")
|
me.init_time_autocomplete(this, {
|
||||||
.autocomplete({
|
container: '#eventedit',
|
||||||
delay: 100,
|
change: event_times_changed
|
||||||
minLength: 1,
|
|
||||||
appendTo: '#eventedit',
|
|
||||||
source: autocomplete_times,
|
|
||||||
open: autocomplete_open,
|
|
||||||
change: event_times_changed,
|
|
||||||
select: function(event, ui) {
|
|
||||||
$(this).val(ui.item[0]).change();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.click(function() { // show drop-down upon clicks
|
|
||||||
$(this).autocomplete('search', $(this).val() ? $(this).val().replace(/\D.*/, "") : " ");
|
|
||||||
}).each(function(){
|
|
||||||
$(this).data('ui-autocomplete')._renderItem = function(ul, item) {
|
|
||||||
return $('<li>')
|
|
||||||
.data('ui-autocomplete-item', item)
|
|
||||||
.append('<a>' + item[0] + item[1] + '</a>')
|
|
||||||
.appendTo(ul);
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// adjust end time when changing start
|
// adjust end time when changing start
|
||||||
$('#edit-starttime').change(function(e) {
|
$('#edit-starttime').change(function(e) {
|
||||||
|
|
|
@ -438,6 +438,121 @@ function rcube_libcalendaring(settings)
|
||||||
return valarms;
|
return valarms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// format time string
|
||||||
|
var time_autocomplete_format = function(hour, minutes, start) {
|
||||||
|
var time, diff, unit, duration = '', d = new Date();
|
||||||
|
|
||||||
|
d.setHours(hour);
|
||||||
|
d.setMinutes(minutes);
|
||||||
|
time = me.format_time(d);
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
diff = Math.floor((d.getTime() - start.getTime()) / 60000);
|
||||||
|
if (diff > 0) {
|
||||||
|
unit = 'm';
|
||||||
|
if (diff >= 60) {
|
||||||
|
unit = 'h';
|
||||||
|
diff = Math.round(diff / 3) / 20;
|
||||||
|
}
|
||||||
|
duration = ' (' + diff + unit + ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [time, duration];
|
||||||
|
};
|
||||||
|
|
||||||
|
var time_autocomplete_list = function(p, callback) {
|
||||||
|
// Time completions
|
||||||
|
var st, h, step = 15, result = [], now = new Date(),
|
||||||
|
id = String(this.element.attr('id')),
|
||||||
|
m = id.match(/^(.*)-(starttime|endtime)$/),
|
||||||
|
start = (m && m[2] == 'endtime'
|
||||||
|
&& (st = $('#' + m[1] + '-starttime').val())
|
||||||
|
&& $('#' + m[1] + '-startdate').val() == $('#' + m[1] + '-enddate').val())
|
||||||
|
? me.parse_datetime(st, '') : null,
|
||||||
|
full = p.term - 1 > 0 || p.term.length > 1,
|
||||||
|
hours = start ? start.getHours() : (full ? me.parse_datetime(p.term, '') : now).getHours(),
|
||||||
|
minutes = hours * 60 + (full ? 0 : now.getMinutes()),
|
||||||
|
min = Math.ceil(minutes / step) * step % 60,
|
||||||
|
hour = Math.floor(Math.ceil(minutes / step) * step / 60);
|
||||||
|
|
||||||
|
// list hours from 0:00 till now
|
||||||
|
for (h = start ? start.getHours() : 0; h < hours; h++)
|
||||||
|
result.push(time_autocomplete_format(h, 0, start));
|
||||||
|
|
||||||
|
// list 15min steps for the next two hours
|
||||||
|
for (; h < hour + 2 && h < 24; h++) {
|
||||||
|
while (min < 60) {
|
||||||
|
result.push(time_autocomplete_format(h, min, start));
|
||||||
|
min += step;
|
||||||
|
}
|
||||||
|
min = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// list the remaining hours till 23:00
|
||||||
|
while (h < 24)
|
||||||
|
result.push(time_autocomplete_format((h++), 0, start));
|
||||||
|
|
||||||
|
return callback(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
var time_autocomplete_open = function(event, ui) {
|
||||||
|
// scroll to current time
|
||||||
|
var $this = $(this),
|
||||||
|
widget = $this.autocomplete('widget')
|
||||||
|
menu = $this.data('ui-autocomplete').menu,
|
||||||
|
amregex = /^(.+)(a[.m]*)/i,
|
||||||
|
pmregex = /^(.+)(a[.m]*)/i,
|
||||||
|
val = $(this).val().replace(amregex, '0:$1').replace(pmregex, '1:$1');
|
||||||
|
|
||||||
|
widget.css('width', '10em');
|
||||||
|
|
||||||
|
if (val === '')
|
||||||
|
menu._scrollIntoView(widget.children('li:first'));
|
||||||
|
else
|
||||||
|
widget.children().each(function() {
|
||||||
|
var li = $(this),
|
||||||
|
html = li.children().first().html()
|
||||||
|
.replace(/\s+\(.+\)$/, '')
|
||||||
|
.replace(amregex, '0:$1')
|
||||||
|
.replace(pmregex, '1:$1');
|
||||||
|
|
||||||
|
if (html.indexOf(val) == 0)
|
||||||
|
menu._scrollIntoView(li);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes time autocompletion
|
||||||
|
*/
|
||||||
|
this.init_time_autocomplete = function(elem, props)
|
||||||
|
{
|
||||||
|
var default_props = {
|
||||||
|
delay: 100,
|
||||||
|
minLength: 1,
|
||||||
|
appendTo: props.container,
|
||||||
|
source: time_autocomplete_list,
|
||||||
|
open: time_autocomplete_open,
|
||||||
|
// change: time_autocomplete_change,
|
||||||
|
select: function(event, ui) {
|
||||||
|
$(this).val(ui.item[0]).change();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(elem).attr('autocomplete', "off")
|
||||||
|
.autocomplete($.extend(default_props, props))
|
||||||
|
.click(function() { // show drop-down upon clicks
|
||||||
|
$(this).autocomplete('search', $(this).val() ? $(this).val().replace(/\D.*/, "") : " ");
|
||||||
|
});
|
||||||
|
|
||||||
|
$(elem).data('ui-autocomplete')._renderItem = function(ul, item) {
|
||||||
|
return $('<li>')
|
||||||
|
.data('ui-autocomplete-item', item)
|
||||||
|
.append('<a>' + item[0] + item[1] + '</a>')
|
||||||
|
.appendTo(ul);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/***** Alarms handling *****/
|
/***** Alarms handling *****/
|
||||||
|
|
||||||
|
@ -1201,5 +1316,4 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
|
||||||
rcmail.location_href(rcmail.env.attachment_download_url, window);
|
rcmail.location_href(rcmail.env.attachment_download_url, window);
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -723,6 +723,11 @@ function rcube_tasklist_ui(settings)
|
||||||
$('#edit-attendees-invite').click();
|
$('#edit-attendees-invite').click();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// configure drop-down menu on time input fields based on jquery UI autocomplete
|
||||||
|
$('#taskedit-starttime, #taskedit-time, #taskedit input.edit-alarm-time').each(function() {
|
||||||
|
me.init_time_autocomplete(this, {container: '#taskedit'});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue