$(document).ready(function() {
- var today = new Date();
+ // get current time from server
+ var today = new Date($('now').val());
$("#event-startdate").datepicker({
- // Don't let the user set a crazy start date
+ // Don't let the user set a start date < before today
minDate: today,
- onClose: function(dateText, picker) {
- // Don't let the user set a crazy end date
- var newStartDate = new Date(dateText);
- var endDate = new Date($("#event-startdate").val());
- if (endDate < newStartDate) {
- $("#event-enddate").val(dateText);
- }
- if (dateText !== null) {
- $("#event-enddate").datepicker('option', 'minDate', new Date(dateText));
- }
- },
- onSelect: function() {
- var startd = $("#event-startdate").val();
- var endd = $("#event-enddate").val();
- var sdate = new Date(startd);
- var edate = new Date(endd);
- if (sdate !== edate) {
- updateTimes();
- }
- }
+ onClose: onStartDateSelected
});
$("#event-enddate").datepicker({
minDate: today,
- onSelect: function() {
- var startd = $("#event-startdate").val();
- var endd = $("#event-enddate").val();
- var sdate = new Date(startd);
- var edate = new Date(endd);
- if (sdate !== edate) {
- updateTimes();
+ onClose: onEndDateSelected
+ });
+
+ $("#event-starttime").change(function(e) {
+ var tz = $("#tz").val();
+
+ var startDate = $("#event-startdate").val();
+ var startTime = $("#event-starttime option:selected").val().replace(/(pm|am)/, ' $1');
+ var startStr = startDate + ' ' + startTime + ' ' + tz;
+
+ var endDate = $("#event-enddate").val();
+ var endTime = $("#event-endtime option:selected").val();
+ var endStr = endDate + ' ' + endTime.replace(/(pm|am)/, ' $1') + ' ' + tz;
+
+ // just need to compare hours
+ var start = new Date(startStr);
+ var end = new Date(endStr);
+
+ updateTimes(startStr, (startDate === endDate), function (data) {
+ var times = [];
+ $.each(data, function(key, val) {
+ times.push('<option value="' + key + '">' + val + '</option>');
+ });
+ $("#event-endtime").html(times.join(''));
+
+ if (start > end) {
+ $("#event-endtime").val(startTime).attr("selected", "selected");
+ } else {
+ $("#event-endtime").val(endTime).attr("selected", "selected");
+ }
+ });
+
+ });
+
+ $("#event-endtime").change(function(e) {
+ var HOUR = 60 * 60 * 1000;
+ var tz = $("#tz").val();
+ var startDate = $("#event-startdate").val();
+ var endDate = $("#event-enddate").val();
+ var starttime = $("#event-starttime option:selected").val();
+ var endtime = $("#event-endtime option:selected").val();
+ var endtimeText = $("#event-endtime option:selected").text();
+
+ // If the end time is in the next day then update the start date
+ if (startDate === endDate) {
+ var startstr = startDate + ' ' + starttime.replace(/(pm|am)/, ' $1') + ' ' + tz;
+ var start = new Date(startstr);
+ var matches = endtimeText.match(/\(.*\)/);
+ var hours;
+ if (matches) {
+ hours = matches[0].substr(1).split(' ')[0]; // get x from (x hours)
+ if (hours) {
+ if (hours == 30) {
+ hours = .5; // special case: x == 30 from (30 mins)
+ }
+ var end = new Date(start.getTime() + (hours * HOUR));
+ if (end.getDate() > start.getDate()) {
+ $("#event-enddate").datepicker('setDate', end);
+ var endstr = endDate + ' 12:00 am ' + tz;
+ updateTimes(endstr, false, function(data) {
+ var times = [];
+ $.each(data, function(key, val) {
+ times.push('<option value="' + key + '">' + val + '</option>');
+ });
+ $("#event-endtime").html(times.join(''));
+
+ if (start > end) {
+ $("#event-endtime").val(starttime).attr("selected", "selected");
+ } else {
+ $("#event-endtime").val(endtime).attr("selected", "selected");
+ }
+ });
+ }
+ }
}
}
});
- function updateTimes() {
- var startd = $("#event-startdate").val();
- var endd = $("#event-enddate").val();
+ function onStartDateSelected(dateText, inst) {
+ var tz = $("#tz").val();
+ var startTime = $("#event-starttime option:selected").val();
+ var startDateTime = new Date(dateText + ' ' + startTime.replace(/(pm|am)/, ' $1') + ' ' + tz);
+
+ // When we update the start date and time, we need to update the end date and time
+ // to make sure they are equal or in the future
+ $("#event-enddate").datepicker('option', 'minDate', startDateTime);
+
+ recalculateTimes();
+ }
+
+ function onEndDateSelected(dateText, inst) {
+ recalculateTimes();
+ }
+
+ function recalculateTimes(showDuration) {
+ var tz = $("#tz").val();
- var startt = $("#event-starttime option:selected").val();
- var endt = $("#event-endtime option:selected").val();
+ var startDate = $("#event-startdate").val();
+ var startTime = $("#event-starttime option:selected").val();
+ var startStr = startDate + ' ' + startTime.replace(/(pm|am)/, ' $1') + ' ' + tz;
+ var startDateTime = new Date(startStr);
- var sdate = new Date(startd + " " + startt);
- var edate = new Date(endd + " " + endt);
- var duration = (startd === endd);
+ var endDate = $("#event-enddate").val();
+ var endTime = $("#event-endtime option:selected").val();
+ var endDateTime = new Date(endDate + ' ' + endTime.replace(/(pm|am)/, ' $1') + ' ' + tz);
+ var showDuration = true;
+
+ if (endDateTime.getDate() !== startDateTime.getDate()) {
+ starStr = endDate + ' 12:00 am ' + tz;
+ showDuration = false;
+ }
- $.getJSON($('#timelist_action_url').val(),
- { start: startt, ajax: true, duration: duration },
- function(data) {
- var times = [];
- $.each(data, function(key, val) {
+ updateTimes(startStr, showDuration, function(data) {
+ var times = [];
+ $.each(data, function(key, val) {
times.push('<option value="' + key + '">' + val + '</option>');
});
-
$("#event-endtime").html(times.join(''));
- if (startt < endt) {
- $("#event-endtime").val(endt).attr("selected", "selected");
+ if (startDateTime > endDateTime) {
+ $("#event-endtime").val(startTime).attr("selected", "selected");
+ } else {
+ $("#event-endtime").val(endTime).attr("selected", "selected");
}
- })
+ });
}
- $("#event-starttime").change(function(e) {
- updateTimes();
- });
+ function updateTimes(start, duration, onSuccess) {
+ $.getJSON($('#timelist_action_url').val(), {start: start, ajax: true, duration: duration}, onSuccess);
+ }
});
$this->li();
- $times = EventTimeList::getTimes();
+ $times = EventTimeList::getTimes($today->format('m/d/Y 12:00') . ' am ' . $today->format('T'));
+
+ common_debug(var_export($times, true));
+
+ $start = EventTimeList::nearestHalfHour('@' . $today->getTimestamp());
+ $start->setTimezone(new DateTimeZone(common_timezone()));
$this->out->dropdown(
'event-starttime',
_m('LABEL','Start time'),
$times,
// TRANS: Field title on event form. %s is the abbreviated timezone
- sprintf(_m("Time the event starts (%s)."), $today->format("T")),
+ sprintf(_m("Time the event starts (%s)."), $today->format('T')),
false,
- null
+ $start->format('g:ia')
);
+ // Need to keep JavaScript TZ in sync with PHP TZ
+ $this->out->hidden('tz', $today->format('T'));
+ $this->out->hidden('now', $today->format('F d, Y H:i:s T'));
+
$this->unli();
$this->li();
$this->li();
- // XXX: Initial end time should be at least 30 mins out? We could do
- // every 15 minute instead -z
- $keys = array_keys($times);
- $endStr = date('m/d/y', strtotime('now')) . " {$keys[0]}";
- $end = new DateTime($endStr);
- $end->modify('+30');
-
$this->out->dropdown(
'event-endtime',
// TRANS: Field label on event form.
_m('LABEL','End time'),
- EventTimeList::getTimes($end->format('c'), true),
+ EventTimeList::getTimes('@' . $start->getTimestamp(), true),
// TRANS: Field title on event form.
_m('Time the event ends.'),
false,
*/
public static function nearestHalfHour($time)
{
- $start = strtotime($time);
+ $startd = new DateTime($time);
- $minutes = date('i', $start);
- $hour = date('H', $start);
+ $minutes = $startd->format('i');
+ $hour = $startd->format('H');
if ($minutes >= 30) {
$minutes = '00';
$minutes = '30';
}
- $newTimeStr = date('m/d/y', $start) . " {$hour}:{$minutes}:00";
- return new DateTime($newTimeStr);
+ $startd->setTime($hour, $minutes, 0);
+
+ return $startd;
}
/**
* Output a list of times in half-hour intervals
*
- * @param string $start Time to start with (date/time string)
+ * @param string $start Time to start with (date string, usually a ts)
* @param boolean $duration Whether to include the duration of the event
* (from the start)
- * @return array $times (UTC time string => localized time string)
+ * @return array $times (localized 24 hour time string => fancy time string)
*/
public static function getTimes($start = 'now', $duration = false)
{
- $newTime = self::nearestHalfHour($start);
+ $newTime = new DateTime($start);
+ $times = array();
+ $len = 0;
$newTime->setTimezone(new DateTimeZone(common_timezone()));
- $times = array();
- $len = 0;
- for ($i = 0; $i < 48; $i++) {
- // make sure we store the time as UTC
- $newTime->setTimezone(new DateTimeZone('UTC'));
- $utcTime = $newTime->format('H:i:s');
+ for ($i = 0; $i < 47; $i++) {
- // localize time for user
- $newTime->setTimezone(new DateTimeZone(common_timezone()));
- $localTime = $newTime->format('g:ia');
+ $localTime = $newTime->format("g:ia");
// pretty up the end-time option list a bit
if ($duration) {
- $len += 30;
- $hours = $len / 60;
+ $hours = $len / 60;
switch ($hours) {
case 0:
// TRANS: 0 minutes abbreviated. Used in a list.
$total = ' ' . _m('(1 hour)');
break;
default:
- // TRANS: Number of hours (%d). Used in a list.
- $total = ' ' . sprintf(_m('(%d hour)','(%d hours)',$hours), $hours);
+ // TRANS: Number of hours (%.1f and %d). Used in a list.
+ $format = is_float($hours)
+ ? _m('(%.1f hours)')
+ : _m('(%d hours)');
+ $total = ' ' . sprintf($format, $hours);
break;
}
$localTime .= $total;
+ $len += 30;
}
- $times[$utcTime] = $localTime;
+ $times[$newTime->format('g:ia')] = $localTime;
$newTime->modify('+30min'); // 30 min intervals
}