Event-Organiser
Event-Organiser copied to clipboard
Mark the "current day" on the widget calendar
Consider:
- A user clicks a date in a calendar widget, and is taken to
/events/on/2013/11/13/
- There is also a calendar widget on the left hand side
- It should be possible to highlight the "current day" on that calendar (e.g. if you are on
/events/on/2013/11/13/
then the 13 Nov 2013 should be highlighted when shown on the calendar).
Separate: possibly when you show a widget calendar on an ondate
URL, the calendar should automatically set to include the ondate
?
I haven't got things setup to easily create a pull request, but here's a diff:
diff --git a/wp-content/plugins/event-organiser/classes/class-eo-calendar-widget.php b/wp-content/plugins/event-organiser/classes/class-eo-calendar-widget.php
index 1de9605..2226047 100644
--- a/wp-content/plugins/event-organiser/classes/class-eo-calendar-widget.php
+++ b/wp-content/plugins/event-organiser/classes/class-eo-calendar-widget.php
@@ -214,6 +214,9 @@ class EO_Calendar_Widget extends WP_Widget
$args['event_start_after'] = $start;
}
$events = eo_get_events( array_merge( $args, $required ) );
+ $today_is = isset( $args['today_is'] ) ? $args['today_is'] : get_query_var( 'ondate' );
+ if ( $today_is )
+ $today_is = str_replace( '/', '-', $today_is );
//Populate events array
$calendar_events = array();
@@ -284,6 +287,8 @@ class EO_Calendar_Widget extends WP_Widget
}else{
$class = array();
+ if ( $formated_date == $today_is )
+ $class[] = 'today';
if( $formated_date < $today->format('Y-m-d') ){
$class[] = 'eo-past-date';
}elseif( $formated_date == $today->format('Y-m-d') ){
diff --git a/wp-content/plugins/event-organiser/includes/event-organiser-ajax.php b/wp-content/plugins/event-organiser/includes/event-organiser-ajax.php
index b1dd322..0949cdd 100644
--- a/wp-content/plugins/event-organiser/includes/event-organiser-ajax.php
+++ b/wp-content/plugins/event-organiser/includes/event-organiser-ajax.php
@@ -432,6 +432,13 @@ function eventorganiser_widget_cal() {
$args['showpastevents'] = (empty($_GET['showpastevents']) ? 0 : 1);
$args['link-to-single'] = (empty($_GET['link-to-single']) ? 0 : 1);
$args['show-long'] = (empty($_GET['show-long']) ? 0 : 1);
+
+ if ( isset( $_SERVER[ 'HTTP_REFERER' ] ) ) {
+ // Same regex as the rewrite rule for the ondate query var
+ $regex = '/([0-9]{4}(?:\/[0-9]{2}(?:\/[0-9]{2})?)?)\/$/';
+ if ( preg_match( $regex, $_SERVER[ 'HTTP_REFERER' ], $matches ) )
+ $args['today_is'] = $matches[1];
+ }
echo json_encode(EO_Calendar_Widget::generate_output($month,$args));
exit;
Here's the function eventorganiser_widget_cal
in full, with the changes:
/**
* Ajax response for the widget calendar
*
* This gets the month being requested and generates the
* html code to view that month and its events.
*
*@since 1.0
*@access private
*@ignore
*/
function eventorganiser_widget_cal() {
/*Retrieve the month we are after. $month must be a
DateTime object of the first of that month*/
if(isset($_GET['eo_month'])){
$month = new DateTime($_GET['eo_month'].'-01');
}else{
$month = new DateTime('now');
$month = date_create($month->format('Y-m-1'));
}
$args = array();
//Restrict by category and/or venue
foreach( array('event-venue','event-category') as $tax ){
if( empty($_GET[$tax]) )
continue;
$terms = explode(',',trim($_GET[$tax]));
$args['tax_query'][] = array(
'taxonomy' => $tax,
'field' => 'slug',
'terms' => $terms,
'operator' => 'IN'
);
}
//Options for the calendar
$args['showpastevents'] = (empty($_GET['showpastevents']) ? 0 : 1);
$args['link-to-single'] = (empty($_GET['link-to-single']) ? 0 : 1);
$args['show-long'] = (empty($_GET['show-long']) ? 0 : 1);
if ( isset( $_SERVER[ 'HTTP_REFERER' ] ) ) {
// Same regex as the rewrite rule for the ondate query var
$regex = '/([0-9]{4}(?:\/[0-9]{2}(?:\/[0-9]{2})?)?)\/$/';
if ( preg_match( $regex, $_SERVER[ 'HTTP_REFERER' ], $matches ) )
$args['today_is'] = $matches[1];
}
echo json_encode(EO_Calendar_Widget::generate_output($month,$args));
exit;
}
Here's the EO_Calendar_Widget::generate_output
method in full, with the changes:
/**
* Generates widget / shortcode calendar html
*
* @param $month - DateTime object for first day of the month (in blog timezone)
*/
static function generate_output( $month, $args = array() ){
//Translations
global $wp_locale;
$today = new DateTime( 'now', eo_get_blog_timezone() );
$key = $month->format('YM') . serialize( $args ).get_locale().$today->format('Y-m-d');
$calendar = get_transient( 'eo_widget_calendar' );
if( ( !defined( 'WP_DEBUG' ) || !WP_DEBUG ) && $calendar && is_array( $calendar ) && isset( $calendar[$key] ) ){
return $calendar[$key];
}
//Month details
$first_day_of_month= intval( $month->format('N') ); //0=sun,...,6=sat
$days_in_month= intval( $month->format('t') ); // 28-31
$last_month = clone $month;
$last_month->modify( 'last month' );
$next_month = clone $month;
$next_month->modify( 'next month' );
//Retrieve the start day of the week from the options.
$start_day=intval( get_option( 'start_of_week' ) );//0=sun,...,6=sat
//How many blank cells before inserting dates
$offset = ( $first_day_of_month - $start_day +7 ) % 7;
//Number of weeks to show in Calendar
$totalweeks = ceil( ( $offset + $days_in_month )/7 );
//Get events for this month
$start = $month->format('Y-m-d');
$end = $month->format('Y-m-t');
//Query events
$required = array(
'numberposts'=>-1,
'showrepeats'=>1,
);
if( $args['show-long'] ){
$args['event_start_before'] = $end;
$args['event_end_after'] = $start;
}else{
$args['event_start_before'] = $end;
$args['event_start_after'] = $start;
}
$events = eo_get_events( array_merge( $args, $required ) );
$today_is = isset( $args['today_is'] ) ? $args['today_is'] : get_query_var( 'ondate' );
if ( $today_is )
$today_is = str_replace( '/', '-', $today_is );
//Populate events array
$calendar_events = array();
foreach( $events as $event ):
if( $args['show-long'] ){
$start = eo_get_the_start( DATETIMEOBJ, $event->ID, null, $event->occurrence_id );
$end = eo_get_the_end( DATETIMEOBJ, $event->ID, null, $event->occurrence_id );
while( $start <= $end ){
$date = eo_format_datetime( $start, 'Y-m-d' );
$calendar_events[ $date ][] = $event;
$start->modify( '+1 day' );
}
}else{
$date = eo_get_the_start( 'Y-m-d', $event->ID, null, $event->occurrence_id );
$calendar_events[$date][]= $event;
}
endforeach;
$before = "<table id='wp-calendar'>";
$title = sprintf("<caption> %s </caption>", esc_html(eo_format_datetime( $month, 'F Y' ) ) );
$head = "<thead><tr>";
for ( $d=0; $d <= 6; $d++ ):
$day = $wp_locale->get_weekday( ($d + $start_day ) % 7 );
$day_abbrev = $wp_locale->get_weekday_initial( $day );
$head .= sprintf( "<th title='%s' scope='col'>%s</th>", esc_attr( $day ), esc_html($day_abbrev ) );
endfor;
$head.="</tr></thead>";
$foot = sprintf(
"<tfoot><tr>
<td id='eo-widget-prev-month' colspan='3'><a title='%s' href='%s'>« %s</a></td>
<td class='pad'> </td>
<td id='eo-widget-next-month' colspan='3'><a title='%s' href='%s'> %s » </a></td>
</tr></tfoot>",
esc_html__( 'Previous month', 'eventorganiser' ),
add_query_arg( 'eo_month', $last_month->format( 'Y-m' ) ),
esc_html( eo_format_datetime( $last_month, 'M' ) ),
esc_html__( 'Next month', 'eventorganiser' ),
add_query_arg( 'eo_month', $next_month->format( 'Y-m' ) ),
esc_html(eo_format_datetime( $next_month, 'M' ) )
);
$body = "<tbody>";
$current_date = clone $month;
//Foreach week in calendar
for( $w = 0; $w <= $totalweeks-1; $w++ ):
$body .= "<tr>";
//For each cell in this week
for( $cell = $w*7 +1; $cell <= ($w+1)*7; $cell++ ):
$formated_date = $current_date->format('Y-m-d');
$data = "data-eo-wc-date='{$formated_date}'";
if( $cell <= $offset ){
$body .= "<td class='pad eo-before-month' colspan='1'> </td>";
}elseif( $cell-$offset > $days_in_month ){
$body .= "<td class='pad eo-after-month' colspan='1'> </td>";
}else{
$class = array();
if ( $formated_date == $today_is )
$class[] = 'current-day';
if( $formated_date < $today->format('Y-m-d') ){
$class[] = 'eo-past-date';
}elseif( $formated_date == $today->format('Y-m-d') ){
$class[] = 'today';
}else{
$class[] = 'eo-future-date';
}
//Does the date have any events
if( isset( $calendar_events[$formated_date] ) ){
$class[] = 'event';
$events = $calendar_events[$formated_date];
if( $events && count( $events ) == 1 && $args['link-to-single'] ){
$only_event = $events[0];
$link = get_permalink( $only_event->ID );
}else{
$link = eo_get_event_archive_link(
$current_date->format('Y'),
$current_date->format('m'),
$current_date->format('d')
);
}
$link = esc_url( $link );
/**
* Filters the the link of a date on the events widget calendar
* @param string $link The link
* @param datetime $current_date The date being filtered
* @param array $events Array of events starting on this day
*/
$link = apply_filters( 'eventorganiser_widget_calendar_date_link', $link, $current_date, $events );
foreach( $events as $event ){
$class = array_merge( $class, eo_get_event_classes( $event->ID, $event->occurrence_id ) );
}
$class = array_unique( array_filter( $class ) );
$classes = implode( ' ', $class );
$titles = implode( ', ', wp_list_pluck( $events, 'post_title' ) );
$body .= sprintf("<td $data class='%s'> <a title='%s' href='%s'> %s </a></td>",
esc_attr( $classes ),
esc_attr( $titles ),
$link,
$cell - $offset
);
}else{
$classes = implode(' ',$class);
$body .= sprintf("<td $data class='%s'> %s </td>", esc_attr( $classes ), $cell-$offset );
}
//Proceed to next day
$current_date->modify( '+1 day' );
}
endfor;//Endfor each day in week
$body .="</tr>";
endfor; //End for each week
$body .="</tbody>";
$after = "</table>";
if( !$calendar || !is_array($calendar) )
$calendar = array();
$calendar[$key] = $before.$title.$head.$foot.$body.$after;
set_transient( 'eo_widget_calendar', $calendar, 60*60*24 );
return $calendar[$key];
}
Hello! I find your idea very well. Had they not better when lifted wordpress calendar widget.
There are two problems here: the current day is typically highlighted (with the class .today
- assuming the theme uses that class). So the calendar may end up having two dates highlighted. That's not really much of any issue if different stylings are used.
The bigger issue is that the calendar is cached. And although its likely to be regularly cleared, it may mean when navigating between days, the incorrect date is highlighted.
However, with 2.3 there's a way around this. Data attributes are added to each cell of the form: data-eo-wc-date="yyyy-mm-dd"
The following code can therefore dynamically style the appropriate cell:
add_action( 'wp_head', 'my_style_currenty_viewed_day' );
function my_style_currenty_viewed_day(){
if( eo_is_event_archive( 'day' ) ){
$date = eo_get_event_archive_date( 'Y-m-d' );
if( $date ){
?>
<style type="text/css">
.eo_widget_calendar [data-eo-wc-date="<?php echo $date;?>"] {
background: red;
}
</style>
<?php
}
}
}
The bigger issue is that the calendar is cached. And although its likely to be regularly cleared, it may mean when navigating between days, the incorrect date is highlighted.
I knew this, and didn't think it entirely through. My code covers two scenarios: getting the current date from the query var (e.g. when rendering the widget the first time) and getting the date via an argument (e.g. for AJAX).
The latter scenario would have no caching issues, because the transient key includes the arguments, serialised, but the latter would have an issue. This could be worked around if the line getting $today_is
from a query var set it on the argument, before the arguments were used in the transient key.