Version Description
- Prevent new row being created on single event save
Download this release
Release Info
Developer | stephenharris |
Plugin | Event Organiser |
Version | 2.0.2 |
Comparing to | |
See all releases |
Version 2.0.2
- .gitignore +10 -0
- classes/class-eo-agenda-widget.php +112 -0
- classes/class-eo-calendar-widget.php +278 -0
- classes/class-eo-event-list-widget.php +217 -0
- classes/class-eo-venue-list-table.php +193 -0
- classes/class-eo-widget-categories.php +103 -0
- classes/class-eo-widget-venues.php +98 -0
- classes/class-eventorganiser-admin-page.php +65 -0
- classes/class-eventorganiser-shortcodes.php +407 -0
- css/eventorganiser-admin-classic.css +576 -0
- css/eventorganiser-admin-fresh.css +591 -0
- css/eventorganiser-admin-style.css +364 -0
- css/eventorganiser-front-end.css +251 -0
- css/fullcalendar.css +208 -0
- css/images/eo-pro-event-search.png +0 -0
- css/images/eo-pro-ticket-picker.png +0 -0
- css/images/eo-pro-venue-cf.png +0 -0
- css/images/eobadge.png +0 -0
- css/images/eoicon-16.png +0 -0
- css/images/eoicon-32.png +0 -0
- css/images/eoicon-32.xcf +0 -0
- css/images/eoicon-64.png +0 -0
- css/images/help-14.png +0 -0
- css/images/info-14.png +0 -0
- css/images/loading-image.gif +0 -0
- css/images/ui-bg_flat_100_f5f5f5_40x100.png +0 -0
- css/images/ui-bg_flat_100_ffffff_40x100.png +0 -0
- css/images/ui-bg_flat_10_ffebe8_40x100.png +0 -0
- css/images/ui-bg_flat_10_ffffff_40x100.png +0 -0
- css/images/ui-bg_flat_15_f9f9f9_40x100.png +0 -0
- css/images/ui-bg_flat_15_ffffe0_40x100.png +0 -0
- css/images/ui-bg_flat_20_000000_40x100.png +0 -0
- css/images/ui-bg_flat_70_000000_40x100.png +0 -0
- css/images/ui-bg_highlight-soft_100_ececec_1x100.png +0 -0
- css/images/ui-icons_21759b_256x240.png +0 -0
- css/images/ui-icons_222222_256x240.png +0 -0
- css/images/ui-icons_333333_256x240.png +0 -0
- css/images/ui-icons_3572ac_256x240.png +0 -0
- css/images/ui-icons_999999_256x240.png +0 -0
- css/images/ui-icons_cc0000_256x240.png +0 -0
- css/images/ui-icons_d54e21_256x240.png +0 -0
- event-organiser-calendar.php +306 -0
- event-organiser-debug.php +387 -0
- event-organiser-edit.php +389 -0
- event-organiser-go-pro.php +115 -0
- event-organiser-manage.php +240 -0
- event-organiser-settings.php +562 -0
- event-organiser-venues.php +433 -0
- event-organiser.php +234 -0
- includes/class-event-organiser-im-export.php +852 -0
- includes/debug.php +57 -0
- includes/deprecated.php +151 -0
- includes/event-organiser-ajax.php +596 -0
- includes/event-organiser-archives.php +517 -0
- includes/event-organiser-cpt.php +1057 -0
- includes/event-organiser-event-functions.php +1231 -0
- includes/event-organiser-install.php +388 -0
- includes/event-organiser-register.php +780 -0
- includes/event-organiser-templates.php +269 -0
- includes/event-organiser-utility-functions.php +910 -0
- includes/event-organiser-venue-functions.php +867 -0
- includes/event.php +715 -0
- js/admin-calendar.js +1199 -0
- js/admin-calendar.min.js +45 -0
- js/event-manager.js +234 -0
- js/event-manager.min.js +5 -0
- js/event.js +2219 -0
- js/event.min.js +73 -0
- js/eventorganiser-pointer.js +16 -0
- js/frontend.js +467 -0
- js/frontend.min.js +19 -0
- js/fullcalendar.js +5236 -0
- js/fullcalendar.min.js +117 -0
- js/inline-help.js +25 -0
- js/qtip2.js +2 -0
- js/venues.js +100 -0
- js/venues.min.js +7 -0
- languages/eventorganiser-da_DK.mo +0 -0
- languages/eventorganiser-da_DK.po +866 -0
.gitignore
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*~
|
2 |
+
.project
|
3 |
+
.settings
|
4 |
+
.buildpath
|
5 |
+
.metadata
|
6 |
+
compiler.jar
|
7 |
+
dist
|
8 |
+
externs.js
|
9 |
+
externs-venue.js
|
10 |
+
Makefile
|
classes/class-eo-agenda-widget.php
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class used to create the event calendar widget
|
4 |
+
*/
|
5 |
+
class EO_Events_Agenda_Widget extends WP_Widget{
|
6 |
+
var $w_arg = array(
|
7 |
+
'title'=> '',
|
8 |
+
'mode'=> 'day',
|
9 |
+
'group_format'=>'l, jS F',
|
10 |
+
'item_format'=>'g:i a',
|
11 |
+
'add_to_google' => 1,
|
12 |
+
);
|
13 |
+
|
14 |
+
static $agendas=array();
|
15 |
+
|
16 |
+
function __construct() {
|
17 |
+
$widget_ops = array('classname' => 'widget_events', 'description' => __('Displays a list of events, grouped by date','eventorganiser'));
|
18 |
+
parent::__construct('EO_Events_Agenda_Widget', __('Events Agenda','eventorganiser'), $widget_ops);
|
19 |
+
}
|
20 |
+
|
21 |
+
|
22 |
+
function form($instance) {
|
23 |
+
$instance = wp_parse_args( (array) $instance, $this->w_arg );
|
24 |
+
?>
|
25 |
+
<p>
|
26 |
+
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title', 'eventorganiser'); ?>: </label>
|
27 |
+
<input id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($instance['title']);?>" />
|
28 |
+
</p>
|
29 |
+
<p>
|
30 |
+
<label for="<?php echo $this->get_field_id('mode'); ?>"><?php _e('Group by', 'eventorganiser'); ?>: </label>
|
31 |
+
<select id="<?php echo $this->get_field_id('mode'); ?>" name="<?php echo $this->get_field_name('mode'); ?>" type="text">
|
32 |
+
<option value="day" <?php selected($instance['mode'], ''); ?>><?php _e('Day','eventorganiser'); ?> </option>
|
33 |
+
<option value="week" <?php selected($instance['mode'], 'week'); ?>><?php _e('Week','eventorganiser'); ?> </option>
|
34 |
+
<option value="month" <?php selected($instance['mode'], 'month'); ?>><?php _e('Month','eventorganiser'); ?> </option>
|
35 |
+
</select>
|
36 |
+
</p>
|
37 |
+
<p>
|
38 |
+
<label for="<?php echo $this->get_field_id('group_format'); ?>"><?php _e('Group date format', 'eventorganiser'); ?>: </label>
|
39 |
+
<input id="<?php echo $this->get_field_id('group_format'); ?>" name="<?php echo $this->get_field_name('group_format'); ?>" type="text" value="<?php echo esc_attr($instance['group_format']);?>" />
|
40 |
+
</p>
|
41 |
+
<p>
|
42 |
+
<label for="<?php echo $this->get_field_id('item_format'); ?>"><?php _e('Event date/time format', 'eventorganiser'); ?>: </label>
|
43 |
+
<input id="<?php echo $this->get_field_id('item_format'); ?>" name="<?php echo $this->get_field_name('item_format'); ?>" type="text" value="<?php echo esc_attr($instance['item_format']);?>" />
|
44 |
+
</p>
|
45 |
+
<p>
|
46 |
+
<label for="<?php echo $this->get_field_id('add_to_google'); ?>"><?php _e('Include \'Add To Google\' link','eventorganiser'); ?>: </label>
|
47 |
+
<input id="<?php echo $this->get_field_id('add_to_google'); ?>" name="<?php echo $this->get_field_name('add_to_google'); ?>" type="checkbox" value="1" <?php checked($instance['add_to_google'],1);?>" />
|
48 |
+
</p>
|
49 |
+
|
50 |
+
<?php
|
51 |
+
}
|
52 |
+
|
53 |
+
|
54 |
+
function update($new_instance, $old_instance){
|
55 |
+
$validated=array();
|
56 |
+
delete_transient('eo_widget_agenda');
|
57 |
+
$validated['title'] = sanitize_text_field( $new_instance['title'] );
|
58 |
+
$validated['mode'] = sanitize_text_field( $new_instance['mode'] );
|
59 |
+
$validated['group_format'] = sanitize_text_field( $new_instance['group_format'] );
|
60 |
+
$validated['item_format'] = sanitize_text_field( $new_instance['item_format'] );
|
61 |
+
$validated['add_to_google'] = intval( $new_instance['add_to_google']);
|
62 |
+
return $validated;
|
63 |
+
}
|
64 |
+
|
65 |
+
|
66 |
+
|
67 |
+
function widget($args, $instance){
|
68 |
+
global $wp_locale;
|
69 |
+
wp_enqueue_script( 'eo_front');
|
70 |
+
wp_enqueue_style( 'eo_front');
|
71 |
+
extract($args, EXTR_SKIP);
|
72 |
+
|
73 |
+
add_action('wp_footer', array(__CLASS__, 'add_options_to_script'));
|
74 |
+
$id = esc_attr($args['widget_id']).'_container';
|
75 |
+
self::$agendas[$id] = array(
|
76 |
+
'id'=>esc_attr($args['widget_id']),
|
77 |
+
'number'=>$this->number,
|
78 |
+
'mode'=> isset($instance['mode']) ? $instance['mode'] : 'day',
|
79 |
+
'add_to_google'=>$instance['add_to_google']
|
80 |
+
);
|
81 |
+
|
82 |
+
//Echo widget
|
83 |
+
echo $before_widget;
|
84 |
+
|
85 |
+
$widget_title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
|
86 |
+
|
87 |
+
if ( $widget_title )
|
88 |
+
echo $before_title.esc_html($widget_title).$after_title;
|
89 |
+
|
90 |
+
echo "<div style='width:100%' id='{$id}' class='eo-agenda-widget'>";
|
91 |
+
?>
|
92 |
+
<div class='agenda-nav'>
|
93 |
+
<span class="next button ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only" role="button" title="">
|
94 |
+
<span class="ui-button-icon-primary ui-icon ui-icon-carat-1-e"></span><span class="ui-button-text"></span>
|
95 |
+
</span>
|
96 |
+
<span class="prev button ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only" role="button" title="">
|
97 |
+
<span class="ui-button-icon-primary ui-icon ui-icon-carat-1-w"></span><span class="ui-button-text"></span>
|
98 |
+
</span>
|
99 |
+
</div>
|
100 |
+
<?php
|
101 |
+
echo "<ul class='dates'>";
|
102 |
+
echo '</ul>';//End dates
|
103 |
+
echo "</div>";
|
104 |
+
echo $after_widget;
|
105 |
+
}
|
106 |
+
|
107 |
+
function add_options_to_script() {
|
108 |
+
if(!empty(self::$agendas))
|
109 |
+
wp_localize_script( 'eo_front', 'eo_widget_agenda', self::$agendas);
|
110 |
+
}
|
111 |
+
|
112 |
+
}
|
classes/class-eo-calendar-widget.php
ADDED
@@ -0,0 +1,278 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class used to create the event calendar widget
|
4 |
+
*/
|
5 |
+
class EO_Calendar_Widget extends WP_Widget
|
6 |
+
{
|
7 |
+
|
8 |
+
var $w_arg = array(
|
9 |
+
'title'=> '',
|
10 |
+
'showpastevents'=>1,
|
11 |
+
'event-category'=>'',
|
12 |
+
'event-venue'=>'',
|
13 |
+
);
|
14 |
+
static $widget_cal =array();
|
15 |
+
|
16 |
+
function __construct() {
|
17 |
+
$widget_ops = array('classname' => 'widget_calendar eo_widget_calendar', 'description' => __('Displays a calendar of your events','eventorganiser') );
|
18 |
+
parent::__construct('EO_Calendar_Widget', __('Events Calendar','eventorganiser'), $widget_ops);
|
19 |
+
}
|
20 |
+
|
21 |
+
function form($instance) {
|
22 |
+
|
23 |
+
$instance = wp_parse_args( (array) $instance, $this->w_arg );
|
24 |
+
|
25 |
+
printf('<p>
|
26 |
+
<label for="%1$s"> %2$s: </label>
|
27 |
+
<input type="text" id="%1$s" name="%3$s" value="%4$s">
|
28 |
+
</p>',
|
29 |
+
esc_attr( $this->get_field_id('title') ),
|
30 |
+
esc_html__('Title', 'eventorganiser'),
|
31 |
+
esc_attr( $this->get_field_name('title') ),
|
32 |
+
esc_attr($instance['title'])
|
33 |
+
);
|
34 |
+
|
35 |
+
printf('<p>
|
36 |
+
<label for="%1$s"> %2$s: </label>
|
37 |
+
<input type="checkbox" id="%1$s" name="%3$s" value="1" %4$s>
|
38 |
+
</p>',
|
39 |
+
esc_attr( $this->get_field_id('showpastevents') ),
|
40 |
+
esc_html__('Include past events', 'eventorganiser'),
|
41 |
+
esc_attr( $this->get_field_name('showpastevents') ),
|
42 |
+
checked($instance['showpastevents'], 1, false)
|
43 |
+
);
|
44 |
+
|
45 |
+
printf('<p>
|
46 |
+
<label for="%1$s"> %2$s: </label>
|
47 |
+
<input type="text" id="%1$s" name="%3$s" value="%4$s" class="widefat">
|
48 |
+
<em> %5$s </em>
|
49 |
+
</p>',
|
50 |
+
esc_attr( $this->get_field_id('event-category') ),
|
51 |
+
esc_html__('Event categories', 'eventorganiser'),
|
52 |
+
esc_attr( $this->get_field_name('event-category') ),
|
53 |
+
esc_attr($instance['event-category']),
|
54 |
+
esc_html__('List category slug(s), seperate by comma. Leave blank for all', 'eventorganiser')
|
55 |
+
);
|
56 |
+
|
57 |
+
printf('<p>
|
58 |
+
<label for="%1$s"> %2$s: </label>
|
59 |
+
%3$s
|
60 |
+
</p>',
|
61 |
+
esc_attr( $this->get_field_id('event-venue') ),
|
62 |
+
esc_html__('Event venue', 'eventorganiser'),
|
63 |
+
eo_event_venue_dropdown(array('echo'=>0,'show_option_all'=>esc_html__('All Venues','eventorganiser'),'id'=>$this->get_field_id('event-venue'),'selected'=>$instance['event-venue'], 'name'=>$this->get_field_name('event-venue'),'hide_empty'=>false))
|
64 |
+
);
|
65 |
+
|
66 |
+
}
|
67 |
+
|
68 |
+
|
69 |
+
function update($new_instance, $old_instance){
|
70 |
+
$validated=array();
|
71 |
+
$validated['title'] = sanitize_text_field( $new_instance['title'] );
|
72 |
+
$validated['event-category'] = sanitize_text_field( $new_instance['event-category'] );
|
73 |
+
$validated['event-venue'] = sanitize_text_field( $new_instance['event-venue'] );
|
74 |
+
$validated['showpastevents'] = ( !empty($new_instance['showpastevents']) ? 1: 0);
|
75 |
+
delete_transient( 'eo_widget_calendar' );
|
76 |
+
return $validated;
|
77 |
+
}
|
78 |
+
|
79 |
+
|
80 |
+
|
81 |
+
function widget($args, $instance){
|
82 |
+
wp_enqueue_script( 'eo_front');
|
83 |
+
extract($args, EXTR_SKIP);
|
84 |
+
|
85 |
+
//Set the month to display (DateTime must be 1st of that month)
|
86 |
+
$tz = eo_get_blog_timezone();
|
87 |
+
$date = get_query_var('ondate') ? str_replace('/','-',get_query_var('ondate')) : 'now';
|
88 |
+
try{
|
89 |
+
$month = new DateTime($date,$tz);
|
90 |
+
}catch( Exception $e){
|
91 |
+
$month = new DateTime('now',$tz);
|
92 |
+
}
|
93 |
+
$month = date_create($month->format('Y-m-1'),$tz);
|
94 |
+
|
95 |
+
/* Set up the event query */
|
96 |
+
$calendar = array(
|
97 |
+
'showpastevents'=> (empty($instance['showpastevents']) ? 0 : 1),
|
98 |
+
'event-venue'=> (!empty($instance['event-venue']) ? $instance['event-venue'] : 0),
|
99 |
+
'event-category'=> (!empty($instance['event-category']) ? $instance['event-category'] : 0),
|
100 |
+
);
|
101 |
+
|
102 |
+
add_action('wp_footer', array(__CLASS__, 'add_options_to_script'));
|
103 |
+
|
104 |
+
$id = esc_attr($args['widget_id']);
|
105 |
+
self::$widget_cal[$id] = $calendar;
|
106 |
+
|
107 |
+
//Echo widget
|
108 |
+
echo $before_widget;
|
109 |
+
|
110 |
+
$widget_title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
|
111 |
+
|
112 |
+
if ( $widget_title )
|
113 |
+
echo $before_title.esc_html($widget_title).$after_title;
|
114 |
+
|
115 |
+
echo "<div id='{$id}_content' >";
|
116 |
+
echo $this->generate_output($month,$calendar);
|
117 |
+
|
118 |
+
echo "</div>";
|
119 |
+
echo $after_widget;
|
120 |
+
}
|
121 |
+
|
122 |
+
function add_options_to_script() {
|
123 |
+
wp_enqueue_script( 'eo_front');
|
124 |
+
if(!empty(self::$widget_cal))
|
125 |
+
wp_localize_script( 'eo_front', 'eo_widget_cal', self::$widget_cal);
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Generates widget / shortcode calendar html
|
130 |
+
*
|
131 |
+
* param $month - DateTime object for first day of the month (in blog timezone)
|
132 |
+
*/
|
133 |
+
function generate_output( $month, $args=array() ){
|
134 |
+
|
135 |
+
//Translations
|
136 |
+
global $wp_locale;
|
137 |
+
|
138 |
+
$today = new DateTime('now',eo_get_blog_timezone());
|
139 |
+
|
140 |
+
$key= $month->format('YM').serialize($args).get_locale().$today->format('Y-m-d');
|
141 |
+
$calendar = get_transient('eo_widget_calendar');
|
142 |
+
if( ( !defined( 'WP_DEBUG' ) || !WP_DEBUG ) && $calendar && is_array( $calendar ) && isset( $calendar[$key] ) ){
|
143 |
+
return $calendar[$key];
|
144 |
+
}
|
145 |
+
|
146 |
+
//Month details
|
147 |
+
$first_day_of_month= intval($month->format('N')); //0=sun,...,6=sat
|
148 |
+
$days_in_month= intval($month->format('t')); // 28-31
|
149 |
+
$last_month = clone $month;
|
150 |
+
$last_month->modify('last month');
|
151 |
+
$next_month = clone $month;
|
152 |
+
$next_month->modify('next month');
|
153 |
+
|
154 |
+
//Retrieve the start day of the week from the options.
|
155 |
+
$start_day=intval(get_option('start_of_week'));//0=sun,...,6=sat
|
156 |
+
|
157 |
+
//How many blank cells before inserting dates
|
158 |
+
$offset = ($first_day_of_month-$start_day +7)%7;
|
159 |
+
|
160 |
+
//Number of weeks to show in Calendar
|
161 |
+
$totalweeks = ceil(($offset + $days_in_month)/7);
|
162 |
+
|
163 |
+
//Get events for this month
|
164 |
+
$start = $month->format('Y-m-d');
|
165 |
+
$end = $month->format('Y-m-t');
|
166 |
+
|
167 |
+
//Query events
|
168 |
+
$required = array( 'numberposts'=>-1, 'showrepeats'=>1, 'event_start_before'=>$end, 'event_start_after'=>$start );
|
169 |
+
$events= eo_get_events(array_merge($args,$required));
|
170 |
+
|
171 |
+
//Populate events array
|
172 |
+
$calendar_events =array();
|
173 |
+
foreach($events as $event):
|
174 |
+
$date = eo_get_the_start('Y-m-d', $event->ID, null, $event->occurrence_id);
|
175 |
+
$calendar_events[$date][]= $event;
|
176 |
+
endforeach;
|
177 |
+
|
178 |
+
$before = "<table id='wp-calendar'>";
|
179 |
+
|
180 |
+
$title = sprintf("<caption> %s </caption>", esc_html(eo_format_datetime($month, 'F Y')) );
|
181 |
+
|
182 |
+
$head="<thead><tr>";
|
183 |
+
for ($d=0; $d <= 6; $d++):
|
184 |
+
$day = $wp_locale->get_weekday( ($d+$start_day)%7 );
|
185 |
+
$day_abbrev =$wp_locale->get_weekday_initial( $day );
|
186 |
+
$head .= sprintf("<th title='%s' scope='col'>%s</th>", esc_attr($day), esc_html($day_abbrev) );
|
187 |
+
endfor;
|
188 |
+
$head.="</tr></thead>";
|
189 |
+
|
190 |
+
$foot = sprintf( "<tfoot><tr>
|
191 |
+
<td id='eo-widget-prev-month' colspan='3'><a title='%s' href='%s'>« %s</a></td>
|
192 |
+
<td class='pad'> </td>
|
193 |
+
<td id='eo-widget-next-month' colspan='3'><a title='%s' href='%s'> %s » </a></td>
|
194 |
+
</tr></tfoot>",
|
195 |
+
esc_html__('Previous month','eventorganiser'),
|
196 |
+
add_query_arg('eo_month',$last_month->format('Y-m')),
|
197 |
+
esc_html(eo_format_datetime($last_month, 'M')),
|
198 |
+
esc_html__('Next month','eventorganiser'),
|
199 |
+
add_query_arg('eo_month',$next_month->format('Y-m')),
|
200 |
+
esc_html(eo_format_datetime($next_month, 'M'))
|
201 |
+
);
|
202 |
+
|
203 |
+
|
204 |
+
$body ="<tbody>";
|
205 |
+
$current_date = clone $month;
|
206 |
+
$event_archive_link = get_post_type_archive_link('event');
|
207 |
+
|
208 |
+
//Foreach week in calendar
|
209 |
+
for( $w = 0; $w <= $totalweeks-1; $w++ ):
|
210 |
+
$body .="<tr>";
|
211 |
+
|
212 |
+
//For each cell in this week
|
213 |
+
for( $cell = $w*7 +1; $cell <= ($w+1)*7; $cell++ ):
|
214 |
+
|
215 |
+
$formated_date = $current_date->format('Y-m-d');
|
216 |
+
|
217 |
+
if( $cell<=$offset || $cell-$offset > $days_in_month ){
|
218 |
+
$body .="<td class='pad' colspan='1'> </td>";
|
219 |
+
|
220 |
+
}else{
|
221 |
+
$class=array();
|
222 |
+
|
223 |
+
//Is the date 'today'?
|
224 |
+
if( $formated_date == $today->format('Y-m-d') )
|
225 |
+
$class[] ='today';
|
226 |
+
|
227 |
+
//Does the date have any events
|
228 |
+
if( isset($calendar_events[$formated_date]) ){
|
229 |
+
$class[] ='event';
|
230 |
+
$events = $calendar_events[$formated_date];
|
231 |
+
|
232 |
+
$link = esc_url(eo_get_event_archive_link($current_date->format('Y'),$current_date->format('m'),$current_date->format('d')));
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Filters the the link of a date on the events widget calendar
|
236 |
+
*@param string $link The link
|
237 |
+
*@param datetime $current_date The date being filtered
|
238 |
+
*@param array $events Array of events starting on this day
|
239 |
+
*/
|
240 |
+
$link = apply_filters('eventorganiser_widget_calendar_date_link', $link, $current_date, $events );
|
241 |
+
|
242 |
+
$classes = implode(' ',$class);
|
243 |
+
$titles = implode(', ',wp_list_pluck( $events, 'post_title') );
|
244 |
+
|
245 |
+
$body .= sprintf("<td class='%s'> <a title='%s' href='%s'> %s </a></td>",
|
246 |
+
esc_attr($classes),
|
247 |
+
esc_attr($titles),
|
248 |
+
$link,
|
249 |
+
($cell-$offset)
|
250 |
+
);
|
251 |
+
}else{
|
252 |
+
$classes = implode(' ',$class);
|
253 |
+
$body .= sprintf("<td class='%s'> %s </td>", esc_attr($classes), ($cell-$offset) );
|
254 |
+
}
|
255 |
+
|
256 |
+
//Proceed to next day
|
257 |
+
$current_date->modify('+1 day');
|
258 |
+
}
|
259 |
+
|
260 |
+
endfor;//Endfor each day in week
|
261 |
+
$body .="</tr>";
|
262 |
+
|
263 |
+
endfor; //End for each week
|
264 |
+
|
265 |
+
$body .="</tbody>";
|
266 |
+
$after = "</table>";
|
267 |
+
|
268 |
+
if( !$calendar || !is_array($calendar) )
|
269 |
+
$calendar = array();
|
270 |
+
|
271 |
+
$calendar[$key] = $before.$title.$head.$foot.$body.$after;
|
272 |
+
|
273 |
+
set_transient('eo_widget_calendar',$calendar, 60*60*24);
|
274 |
+
return $calendar[$key];
|
275 |
+
}
|
276 |
+
}
|
277 |
+
|
278 |
+
?>
|
classes/class-eo-event-list-widget.php
ADDED
@@ -0,0 +1,217 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class used to create the event list widget
|
4 |
+
*/
|
5 |
+
class EO_Event_List_Widget extends WP_Widget{
|
6 |
+
|
7 |
+
var $w_arg = array(
|
8 |
+
'title'=> 'Events',
|
9 |
+
'numberposts'=> 5,
|
10 |
+
'event-category'=> '',
|
11 |
+
'venue_id'=> NULL,
|
12 |
+
'venue'=> '',
|
13 |
+
'orderby'=> 'eventstart',
|
14 |
+
'showpastevents'=> 0,
|
15 |
+
'group_events_by'=>'',
|
16 |
+
'order'=> 'ASC',
|
17 |
+
'template'=>'',
|
18 |
+
'no_events'=>'No Events'
|
19 |
+
);
|
20 |
+
|
21 |
+
function __construct() {
|
22 |
+
$widget_ops = array('classname' => 'EO_Event_List_Widget', 'description' => __('Displays a list of events','eventorganiser') );
|
23 |
+
parent::__construct('EO_Event_List_Widget', __('Events','eventorganiser'), $widget_ops);
|
24 |
+
}
|
25 |
+
|
26 |
+
|
27 |
+
function form($instance){
|
28 |
+
$instance = wp_parse_args( (array) $instance, $this->w_arg );
|
29 |
+
?>
|
30 |
+
<p>
|
31 |
+
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title', 'eventorganiser'); ?>: </label>
|
32 |
+
<input type="text" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" value="<?php echo esc_attr($instance['title']); ?>" />
|
33 |
+
</p>
|
34 |
+
<p>
|
35 |
+
<label for="<?php echo $this->get_field_id('numberposts'); ?>"><?php _e('Number of events','eventorganiser');?>: </label>
|
36 |
+
<input id="<?php echo $this->get_field_id('numberposts'); ?>" name="<?php echo $this->get_field_name('numberposts'); ?>" type="number" size="3" value="<?php echo intval($instance['numberposts']);?>" />
|
37 |
+
</p>
|
38 |
+
<p>
|
39 |
+
<label for="<?php echo $this->get_field_id('event-category'); ?>"><?php _e('Event categories', 'eventorganiser'); ?>: </label>
|
40 |
+
<input id="<?php echo $this->get_field_id('event-category'); ?>" class="widefat" name="<?php echo $this->get_field_name('event-category'); ?>" type="text" value="<?php echo esc_attr($instance['event-category']);?>" />
|
41 |
+
<em><?php _e('List category slug(s), seperate by comma. Leave blank for all', 'eventorganiser'); ?> </em>
|
42 |
+
</p>
|
43 |
+
<p>
|
44 |
+
<label for="<?php echo $this->get_field_id('venue'); ?>"><?php _e('Venue', 'eventorganiser'); ?>: </label>
|
45 |
+
<?php $venues = get_terms('event-venue', array('hide_empty'=>false));?>
|
46 |
+
<select id="<?php echo $this->get_field_id('venue'); ?>" name="<?php echo $this->get_field_name('venue'); ?>" type="text">
|
47 |
+
<option value="" <?php selected($instance['venue'], ''); ?>><?php _e('All Venues','eventorganiser'); ?> </option>
|
48 |
+
<?php foreach ($venues as $venue):?>
|
49 |
+
<option <?php selected($instance['venue'],$venue->slug);?> value="<?php echo esc_attr($venue->slug);?>"><?php echo esc_html($venue->name); ?></option>
|
50 |
+
<?php endforeach;?>
|
51 |
+
</select>
|
52 |
+
</p>
|
53 |
+
|
54 |
+
<p>
|
55 |
+
<label for="<?php echo $this->get_field_id('orderby'); ?>"><?php _e('Order by', 'eventorganiser'); ?></label>
|
56 |
+
<select id="<?php echo $this->get_field_id('orderby'); ?>" name="<?php echo $this->get_field_name('orderby'); ?>" type="text">
|
57 |
+
<option value="eventstart" <?php selected($instance['orderby'], 'eventstart'); ?>><?php _e('Start date', 'eventorganiser'); ?></option>
|
58 |
+
<option value="title" <?php selected($instance['orderby'], 'title');?>><?php _e('Title', 'eventorganiser'); ?> </option>
|
59 |
+
</select>
|
60 |
+
<select id="<?php echo $this->get_field_id('order'); ?>" name="<?php echo $this->get_field_name('order'); ?>" type="text">
|
61 |
+
<option value="asc" <?php selected($instance['order'], 'asc'); ?>><?php _e('ASC', 'eventorganiser'); ?> </option>
|
62 |
+
<option value="desc" <?php selected($instance['order'], 'desc');?>><?php _e('DESC', 'eventorganiser'); ?> </option>
|
63 |
+
</select>
|
64 |
+
</p>
|
65 |
+
<p>
|
66 |
+
<label for="<?php echo $this->get_field_id('showpastevents'); ?>"><?php _e('Include past events', 'eventorganiser'); ?> </label>
|
67 |
+
<input type="checkbox" id="<?php echo $this->get_field_id('showpastevents'); ?>" name="<?php echo $this->get_field_name('showpastevents'); ?>" <?php checked($instance['showpastevents'],1);?> value="1" />
|
68 |
+
</p>
|
69 |
+
<p>
|
70 |
+
<label for="<?php echo $this->get_field_id('group_events_by'); ?>"><?php _e('Group occurrences', 'eventorganiser'); ?> </label>
|
71 |
+
<input type="checkbox" id="<?php echo $this->get_field_id('group_events_by'); ?>" value="series" name="<?php echo $this->get_field_name('group_events_by'); ?>" <?php checked($instance['group_events_by'],'series');?> />
|
72 |
+
</p>
|
73 |
+
<p>
|
74 |
+
<label for="<?php echo $this->get_field_id('template'); ?>">
|
75 |
+
<?php
|
76 |
+
_e('Template (leave blank for default)', 'eventorganiser');
|
77 |
+
echo eventorganiser_inline_help(
|
78 |
+
__( 'Event list widget placeholders', 'eventorganiser' ),
|
79 |
+
sprintf(
|
80 |
+
__( 'You can use specified tags as placeholders for event information which you want to appear in the widget. <a href="%s" target="_blank"> Find out more</a>.', 'eventorganiser' ),
|
81 |
+
'http://wp-event-organiser.com/documentation/widgets/#whatistemplate'
|
82 |
+
)
|
83 |
+
);
|
84 |
+
?>
|
85 |
+
</label>
|
86 |
+
<input id="<?php echo $this->get_field_id('template'); ?>" class="widefat" name="<?php echo $this->get_field_name('template'); ?>" type="text" value="<?php echo esc_attr($instance['template']);?>" />
|
87 |
+
|
88 |
+
</p>
|
89 |
+
<p>
|
90 |
+
<label for="<?php echo $this->get_field_id('no_events'); ?>"><?php _e("'No events' message", 'eventorganiser'); ?> </label>
|
91 |
+
<input id="<?php echo $this->get_field_id('no_events'); ?>" class="widefat" name="<?php echo $this->get_field_name('no_events'); ?>" type="text" value="<?php echo esc_attr($instance['no_events']);?>" />
|
92 |
+
</p>
|
93 |
+
|
94 |
+
<?php
|
95 |
+
}
|
96 |
+
|
97 |
+
function update($new_instance, $old_instance){
|
98 |
+
$validated=array();
|
99 |
+
$validated['title'] = sanitize_text_field( $new_instance['title'] );
|
100 |
+
$validated['numberposts'] = intval($new_instance['numberposts']);
|
101 |
+
$event_cats = array_map('sanitize_text_field', explode(',',$new_instance['event-category']));
|
102 |
+
$validated['event-category'] = implode(',',$event_cats);
|
103 |
+
$validated['venue'] = sanitize_text_field( $new_instance['venue'] );
|
104 |
+
$validated['order'] = ($new_instance['order'] == 'asc' ? 'asc' : 'desc');
|
105 |
+
$validated['orderby'] = ($new_instance['order'] == 'title' ? 'title' : 'eventstart');
|
106 |
+
$validated['showpastevents'] = ( !empty($new_instance['showpastevents']) ? 1: 0);
|
107 |
+
$validated['group_events_by'] = ( isset($new_instance['group_events_by']) && $new_instance['group_events_by']=='series' ? 'series': '');
|
108 |
+
$validated['template'] = $new_instance['template'];
|
109 |
+
$validated['no_events'] = $new_instance['no_events'];
|
110 |
+
return $validated;
|
111 |
+
}
|
112 |
+
|
113 |
+
|
114 |
+
function widget($args, $instance){
|
115 |
+
extract($args, EXTR_SKIP);
|
116 |
+
|
117 |
+
$template = $instance['template'];
|
118 |
+
$no_events = isset($instance['no_events']) ? $instance['no_events'] :'';
|
119 |
+
unset($instance['template']);
|
120 |
+
unset($instance['no_events']);
|
121 |
+
|
122 |
+
echo $before_widget;
|
123 |
+
|
124 |
+
$widget_title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);
|
125 |
+
|
126 |
+
if ( $widget_title )
|
127 |
+
echo $before_title.esc_html($widget_title).$after_title;
|
128 |
+
|
129 |
+
eventorganiser_list_events($instance, array('type'=>'widget','class'=>'eo-events eo-events-widget','template'=>$template, 'no_events'=>$no_events));
|
130 |
+
|
131 |
+
echo $after_widget;
|
132 |
+
}
|
133 |
+
|
134 |
+
}
|
135 |
+
|
136 |
+
function eventorganiser_list_events( $query, $args=array(), $echo=1 ){
|
137 |
+
|
138 |
+
$args = array_merge(array(
|
139 |
+
'id'=>'',
|
140 |
+
'class'=>'eo-event-list',
|
141 |
+
'type'=>'shortcode',
|
142 |
+
'no_events' => '',
|
143 |
+
),$args);
|
144 |
+
|
145 |
+
/* Pass these defaults - backwards compat with using eo_get_events()*/
|
146 |
+
$query = wp_parse_args($query, array(
|
147 |
+
'posts_per_page'=>-1,
|
148 |
+
'post_type'=>'event',
|
149 |
+
'supress_filters'=>false,
|
150 |
+
'orderby'=> 'eventstart',
|
151 |
+
'order'=> 'ASC',
|
152 |
+
'showrepeats'=>1,
|
153 |
+
'group_events_by'=>'',
|
154 |
+
'showpastevents'=>true,
|
155 |
+
));
|
156 |
+
|
157 |
+
//Make sure false and 'False' etc actually get parsed as 0/false (input from shortcodes, for instance, can be varied).
|
158 |
+
//This maybe moved to the shortcode handler if this function is made public.
|
159 |
+
if( strtolower($query['showpastevents']) === 'false' )
|
160 |
+
$query['showpastevents'] = 0;
|
161 |
+
|
162 |
+
if( !empty($query['numberposts']) ){
|
163 |
+
$query['posts_per_page'] = (int) $query['numberposts'];
|
164 |
+
}
|
165 |
+
|
166 |
+
$template = isset($args['template']) ? $args['template'] :'';
|
167 |
+
|
168 |
+
global $eo_event_loop,$eo_event_loop_args;
|
169 |
+
$eo_event_loop_args = $args;
|
170 |
+
$eo_event_loop = new WP_Query($query);
|
171 |
+
|
172 |
+
/* Try to find template - backwards compat. Don't use this filter. Will be removed! */
|
173 |
+
$template_file = locate_template(apply_filters('eventorganiser_event_list_loop',false));
|
174 |
+
if( $template_file || empty($template) ){
|
175 |
+
ob_start();
|
176 |
+
if( empty($template_file) )
|
177 |
+
$template_file = eo_locate_template( array($eo_event_loop_args['type'].'-event-list.php', 'event-list.php'), true, false );
|
178 |
+
else
|
179 |
+
require( $template_file );
|
180 |
+
|
181 |
+
$html = ob_get_contents();
|
182 |
+
ob_end_clean();
|
183 |
+
|
184 |
+
|
185 |
+
}else{
|
186 |
+
//Using the 'placeholder' template
|
187 |
+
$no_events = isset($args['no_events']) ? $args['no_events'] :'';
|
188 |
+
|
189 |
+
|
190 |
+
$line_wrap = '<li class="%2$s">%1$s</li>';
|
191 |
+
$id = (!empty($args['id']) ? 'id="'.esc_attr($args['id']).'"' : '');
|
192 |
+
$container = '<ul '.$id.' class="%2$s">%1$s</ul>';
|
193 |
+
|
194 |
+
$html='';
|
195 |
+
if( $eo_event_loop->have_posts() ):
|
196 |
+
while( $eo_event_loop->have_posts() ): $eo_event_loop->the_post();
|
197 |
+
|
198 |
+
$event_classes = eo_get_event_classes();
|
199 |
+
$html .= sprintf($line_wrap, EventOrganiser_Shortcodes::read_template($template), esc_attr(implode(' ',$event_classes)) );
|
200 |
+
|
201 |
+
endwhile;
|
202 |
+
|
203 |
+
elseif( $no_events ):
|
204 |
+
$html .= sprintf($line_wrap, $no_events, 'eo-no-events');
|
205 |
+
endif;
|
206 |
+
|
207 |
+
$html = sprintf($container, $html, esc_attr($args['class']) );
|
208 |
+
}
|
209 |
+
|
210 |
+
wp_reset_postdata();
|
211 |
+
|
212 |
+
if( $echo )
|
213 |
+
echo $html;
|
214 |
+
|
215 |
+
return $html;
|
216 |
+
}
|
217 |
+
?>
|
classes/class-eo-venue-list-table.php
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class used for displaying venue table and handling interations
|
4 |
+
*/
|
5 |
+
|
6 |
+
/*
|
7 |
+
*The WP_List_Table class isn't automatically available to plugins, so we need
|
8 |
+
* to check if it's available and load it if necessary.
|
9 |
+
*/
|
10 |
+
if(!class_exists('WP_List_Table')){
|
11 |
+
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
|
12 |
+
}
|
13 |
+
|
14 |
+
class EO_Venue_List_Table extends WP_List_Table {
|
15 |
+
|
16 |
+
/*
|
17 |
+
* Constructor. Set some default configs.
|
18 |
+
*/
|
19 |
+
function __construct(){
|
20 |
+
global $status, $page;
|
21 |
+
//Set parent defaults
|
22 |
+
parent::__construct( array(
|
23 |
+
'singular' => __('venue','eventorganiser'), //singular name of the listed records
|
24 |
+
'plural' => __('venues','eventorganiser'), //plural name of the listed records
|
25 |
+
'ajax' => true //does this table support ajax?
|
26 |
+
) );
|
27 |
+
}
|
28 |
+
|
29 |
+
/*
|
30 |
+
* For more detailed insight into how columns are handled, take a look at
|
31 |
+
* WP_List_Table::single_row_columns()
|
32 |
+
*
|
33 |
+
* @param array $item A singular item (one full row's worth of data)
|
34 |
+
* @param array $column_name The name/slug of the column to be processed
|
35 |
+
* @return string Text or HTML to be placed inside the column <td>
|
36 |
+
*/
|
37 |
+
function column_default($item, $column_name){
|
38 |
+
$term_id = (int) $item->term_id;
|
39 |
+
$address = eo_get_venue_address($term_id);
|
40 |
+
|
41 |
+
switch($column_name){
|
42 |
+
case 'venue_slug':
|
43 |
+
return esc_html($item->slug);
|
44 |
+
case 'posts':
|
45 |
+
return intval($item->count);
|
46 |
+
default:
|
47 |
+
$address_keys = array_keys($address);
|
48 |
+
foreach( $address_keys as $key ){
|
49 |
+
if( 'venue_'.$key == $column_name ){
|
50 |
+
return esc_html($address[$key]);
|
51 |
+
}
|
52 |
+
}
|
53 |
+
//TODO Hook for extra columns?
|
54 |
+
return print_r($item,true); //Show the whole array for troubleshooting purposes
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
/*
|
60 |
+
* @see WP_List_Table::::single_row_columns()
|
61 |
+
* @param array $item A singular item (one full row's worth of data)
|
62 |
+
* @return string Text to be placed inside the column <td>
|
63 |
+
*/
|
64 |
+
function column_name($item){
|
65 |
+
$term_id = (int) $item->term_id;
|
66 |
+
|
67 |
+
//Build row actions
|
68 |
+
$actions = array(
|
69 |
+
'edit' => sprintf('<a href="?post_type=event&page=%s&action=%s&event-venue=%s">'.__('Edit').'</a>',$_REQUEST['page'],'edit',$item->slug),
|
70 |
+
'delete' => '<a href="'.wp_nonce_url(sprintf('?post_type=event&page=%s&action=%s&event-venue=%s',$_REQUEST['page'],'delete',$item->slug), 'eventorganiser_delete_venue_'.$item->slug).'">'.__('Delete').' </a>',
|
71 |
+
'view' => sprintf('<a href="%s">'.__('View').'</a>', eo_get_venue_link($term_id)),
|
72 |
+
);
|
73 |
+
|
74 |
+
//Return the title contents
|
75 |
+
return sprintf('<a href="?post_type=event&page=%1$s&action=%2$s&event-venue=%3$s" class="row-title">%4$s</a>%5$s',
|
76 |
+
/*$1%s*/ $_REQUEST['page'],
|
77 |
+
/*$2%s*/ 'edit',
|
78 |
+
/*$3%s*/ $item->slug,
|
79 |
+
/*$4%s*/ $item->name,
|
80 |
+
/*$5%s*/ $this->row_actions($actions)
|
81 |
+
);
|
82 |
+
}
|
83 |
+
|
84 |
+
/*
|
85 |
+
* Checkbox column for Bulk Actions.
|
86 |
+
*
|
87 |
+
* @see WP_List_Table::::single_row_columns()
|
88 |
+
* @param array $item A singular item (one full row's worth of data)
|
89 |
+
* @return string Text to be placed inside the column <td> (movie title only)
|
90 |
+
*/
|
91 |
+
function column_cb($item){
|
92 |
+
return sprintf(
|
93 |
+
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
|
94 |
+
/*$1%s*/ 'event-venue',
|
95 |
+
/*$2%s*/ $item->slug //The value of the checkbox should be the record's id
|
96 |
+
);
|
97 |
+
}
|
98 |
+
|
99 |
+
|
100 |
+
/*
|
101 |
+
* Set columns sortable
|
102 |
+
*
|
103 |
+
* @return array An associative array containing all the columns that should be sortable: 'slugs'=>array('data_values',bool)
|
104 |
+
*/
|
105 |
+
function get_sortable_columns() {
|
106 |
+
$sortable_columns = array(
|
107 |
+
'name' => array('name',true), //true means its sorted by default
|
108 |
+
'venue_address' => array('address',false),
|
109 |
+
'venue_city' => array('city',false),
|
110 |
+
'venue_state' => array('state',false),
|
111 |
+
'venue_postcode' => array('postcode',false),
|
112 |
+
'venue_country' => array('country',false),
|
113 |
+
'venue_slug' => array('slug',false),
|
114 |
+
'posts' => array('count',false),
|
115 |
+
);
|
116 |
+
return $sortable_columns;
|
117 |
+
}
|
118 |
+
|
119 |
+
|
120 |
+
/*
|
121 |
+
* Set bulk actions
|
122 |
+
*
|
123 |
+
* @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
|
124 |
+
*/
|
125 |
+
function get_bulk_actions() {
|
126 |
+
$actions = array(
|
127 |
+
'delete' => __('Delete')
|
128 |
+
);
|
129 |
+
return $actions;
|
130 |
+
}
|
131 |
+
|
132 |
+
|
133 |
+
/*
|
134 |
+
* Echos the row, after assigning it an ID based ont eh venue being shown. Assign appropriate class to alternate rows.
|
135 |
+
*/
|
136 |
+
function single_row( $item ) {
|
137 |
+
static $row_class = '';
|
138 |
+
$row_id = 'id="venue-'.$item->term_id.'"';
|
139 |
+
$row_class = ( $row_class == '' ? ' class="alternate"' : '' );
|
140 |
+
echo '<tr' .$row_class.' '.$row_id.'>';
|
141 |
+
echo $this->single_row_columns( $item );
|
142 |
+
echo '</tr>';
|
143 |
+
}
|
144 |
+
|
145 |
+
/*
|
146 |
+
* Prepare venues for display
|
147 |
+
*
|
148 |
+
* @uses $this->_column_headers
|
149 |
+
* @uses $this->items
|
150 |
+
* @uses $this->get_columns()
|
151 |
+
* @uses $this->get_sortable_columns()
|
152 |
+
* @uses $this->get_pagenum()
|
153 |
+
* @uses $this->set_pagination_args()
|
154 |
+
*/
|
155 |
+
function prepare_items() {
|
156 |
+
|
157 |
+
//Retrieve page number for pagination
|
158 |
+
$current_page = (int) $this->get_pagenum();
|
159 |
+
|
160 |
+
//First, lets decide how many records per page to show
|
161 |
+
$screen = get_current_screen();
|
162 |
+
$per_page = $this->get_items_per_page( 'edit_event_venue_per_page' );
|
163 |
+
|
164 |
+
//Get the columns, the hidden columns an sortable columns
|
165 |
+
$columns = get_column_headers('event_page_venues');
|
166 |
+
$hidden = get_hidden_columns('event_page_venues');
|
167 |
+
$sortable = $this->get_sortable_columns();
|
168 |
+
$this->_column_headers = array($columns, $hidden, $sortable);
|
169 |
+
$taxonomy ='event-venue';
|
170 |
+
|
171 |
+
$search = (!empty( $_REQUEST['s'] ) ? trim( stripslashes( $_REQUEST['s'] ) ) : '');
|
172 |
+
$orderby =( !empty( $_REQUEST['orderby'] ) ? trim( stripslashes($_REQUEST['orderby'])) : '');
|
173 |
+
$order =( !empty( $_REQUEST['order'] ) ? trim( stripslashes($_REQUEST['order'])) : '');
|
174 |
+
|
175 |
+
//Display result
|
176 |
+
$this->items = get_terms('event-venue',array(
|
177 |
+
'hide_empty'=>false,
|
178 |
+
'search'=>$search,
|
179 |
+
'offset'=> ($current_page-1)*$per_page,
|
180 |
+
'number'=>$per_page,
|
181 |
+
'orderby'=>$orderby,
|
182 |
+
'order'=>$order
|
183 |
+
)
|
184 |
+
);
|
185 |
+
|
186 |
+
$this->set_pagination_args( array(
|
187 |
+
'total_items' => wp_count_terms('event-venue', compact( 'search', 'orderby' ) ),
|
188 |
+
'per_page' => $per_page,
|
189 |
+
) );
|
190 |
+
|
191 |
+
}
|
192 |
+
|
193 |
+
}?>
|
classes/class-eo-widget-categories.php
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Event categories widget class
|
4 |
+
*
|
5 |
+
* @since 1.8
|
6 |
+
*/
|
7 |
+
class EO_Widget_Categories extends WP_Widget {
|
8 |
+
|
9 |
+
function __construct() {
|
10 |
+
$widget_ops = array( 'classname' => 'eo__event_categories', 'description' => __( "A list or dropdown of event categories" ) );
|
11 |
+
parent::__construct('eo-event-categories', __( 'Event Categories', 'eventorganiser' ), $widget_ops);
|
12 |
+
}
|
13 |
+
|
14 |
+
function widget( $args, $instance ) {
|
15 |
+
extract( $args );
|
16 |
+
|
17 |
+
$taxonomy = 'event-category';
|
18 |
+
|
19 |
+
$title = apply_filters('widget_title', empty( $instance['title'] ) ? __( 'Categories' ) : $instance['title'], $instance, $this->id_base);
|
20 |
+
$h = ! empty( $instance['hierarchical'] ) ? '1' : '0';
|
21 |
+
$d = ! empty( $instance['dropdown'] ) ? '1' : '0';
|
22 |
+
|
23 |
+
echo $before_widget;
|
24 |
+
if ( $title )
|
25 |
+
echo $before_title . $title . $after_title;
|
26 |
+
|
27 |
+
//Select current category by default
|
28 |
+
if( is_tax( $taxonomy ) ){
|
29 |
+
$term = get_term( get_queried_object_id() , $taxonomy );
|
30 |
+
$selected = ( $term && !is_wp_error( $term ) ? $term->slug : false );
|
31 |
+
}else{
|
32 |
+
$selected = false;
|
33 |
+
}
|
34 |
+
|
35 |
+
$cat_args = array(
|
36 |
+
'orderby' => 'name',
|
37 |
+
'hierarchical' => false,
|
38 |
+
'taxonomy' => $taxonomy,
|
39 |
+
'id' => 'eo-event-venue',
|
40 |
+
'selected' => $selected
|
41 |
+
);
|
42 |
+
if ( $d ) {
|
43 |
+
$cat_args['walker'] = new EO_Walker_TaxonomyDropdown();
|
44 |
+
$cat_args['value'] = 'slug';
|
45 |
+
$cat_args['show_option_none'] = __('Select Category');
|
46 |
+
wp_dropdown_categories(apply_filters('eventorganiser_widget_event_venues_dropdown_args', $cat_args));
|
47 |
+
?>
|
48 |
+
|
49 |
+
<script type='text/javascript'>
|
50 |
+
/* <![CDATA[ */
|
51 |
+
var event_dropdown = document.getElementById("eo-event-cat");
|
52 |
+
function eventorganiserDropdownChange() {
|
53 |
+
if ( event_dropdown.options[event_dropdown.selectedIndex].value != -1 ) {
|
54 |
+
location.href = "<?php echo home_url().'/'.$taxonomy.'=';?>"+event_dropdown.options[event_dropdown.selectedIndex].value;
|
55 |
+
}
|
56 |
+
}
|
57 |
+
event_dropdown.onchange = eventorganiserDropdownChange;
|
58 |
+
/* ]]> */
|
59 |
+
</script>
|
60 |
+
|
61 |
+
<?php
|
62 |
+
} else {
|
63 |
+
?>
|
64 |
+
<ul>
|
65 |
+
<?php
|
66 |
+
$cat_args['title_li'] = '';
|
67 |
+
wp_list_categories(apply_filters('eventorganiser_widget_event_categories_args', $cat_args));
|
68 |
+
?>
|
69 |
+
</ul>
|
70 |
+
<?php
|
71 |
+
}
|
72 |
+
|
73 |
+
echo $after_widget;
|
74 |
+
}
|
75 |
+
|
76 |
+
function update( $new_instance, $old_instance ) {
|
77 |
+
$instance = $old_instance;
|
78 |
+
$instance['title'] = strip_tags($new_instance['title']);
|
79 |
+
$instance['hierarchical'] = !empty($new_instance['hierarchical']) ? 1 : 0;
|
80 |
+
$instance['dropdown'] = !empty($new_instance['dropdown']) ? 1 : 0;
|
81 |
+
|
82 |
+
return $instance;
|
83 |
+
}
|
84 |
+
|
85 |
+
function form( $instance ) {
|
86 |
+
//Defaults
|
87 |
+
$instance = wp_parse_args( (array) $instance, array( 'title' => '') );
|
88 |
+
$title = esc_attr( $instance['title'] );
|
89 |
+
$hierarchical = isset( $instance['hierarchical'] ) ? (bool) $instance['hierarchical'] : false;
|
90 |
+
$dropdown = isset( $instance['dropdown'] ) ? (bool) $instance['dropdown'] : false;
|
91 |
+
?>
|
92 |
+
<p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e( 'Title:' ); ?></label>
|
93 |
+
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" /></p>
|
94 |
+
|
95 |
+
<p><input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id('dropdown'); ?>" name="<?php echo $this->get_field_name('dropdown'); ?>"<?php checked( $dropdown ); ?> />
|
96 |
+
<label for="<?php echo $this->get_field_id('dropdown'); ?>"><?php _e( 'Display as dropdown' ); ?></label><br />
|
97 |
+
|
98 |
+
<input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id('hierarchical'); ?>" name="<?php echo $this->get_field_name('hierarchical'); ?>"<?php checked( $hierarchical ); ?> />
|
99 |
+
<label for="<?php echo $this->get_field_id('hierarchical'); ?>"><?php _e( 'Show hierarchy' ); ?></label></p>
|
100 |
+
<?php
|
101 |
+
}
|
102 |
+
|
103 |
+
}
|
classes/class-eo-widget-venues.php
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Event venues widget class
|
4 |
+
*
|
5 |
+
* @since 1.8
|
6 |
+
*/
|
7 |
+
class EO_Widget_Venues extends WP_Widget {
|
8 |
+
|
9 |
+
function __construct() {
|
10 |
+
$widget_ops = array( 'classname' => 'eo__event_venues', 'description' => __( "A list or dropdown of event venues" ) );
|
11 |
+
parent::__construct('eo-event-venues', __( 'Event Venues', 'eventorganiser' ), $widget_ops);
|
12 |
+
}
|
13 |
+
|
14 |
+
function widget( $args, $instance ) {
|
15 |
+
extract( $args );
|
16 |
+
|
17 |
+
$taxonomy = 'event-venue';
|
18 |
+
|
19 |
+
$title = apply_filters('widget_title', empty( $instance['title'] ) ? __( 'Venues' ) : $instance['title'], $instance, $this->id_base);
|
20 |
+
$d = ! empty( $instance['dropdown'] ) ? '1' : '0';
|
21 |
+
|
22 |
+
echo $before_widget;
|
23 |
+
if ( $title )
|
24 |
+
echo $before_title . $title . $after_title;
|
25 |
+
|
26 |
+
//Select current category by default
|
27 |
+
if( is_tax( $taxonomy ) ){
|
28 |
+
$term = get_term( get_queried_object_id() , $taxonomy );
|
29 |
+
$selected = ( $term && !is_wp_error( $term ) ? $term->slug : false );
|
30 |
+
}else{
|
31 |
+
$selected = false;
|
32 |
+
}
|
33 |
+
|
34 |
+
$cat_args = array(
|
35 |
+
'orderby' => 'name',
|
36 |
+
'hierarchical' => false,
|
37 |
+
'taxonomy' => $taxonomy,
|
38 |
+
'id' => 'eo-event-venue',
|
39 |
+
'selected' => $selected
|
40 |
+
);
|
41 |
+
if ( $d ) {
|
42 |
+
$cat_args['walker'] = new EO_Walker_TaxonomyDropdown();
|
43 |
+
$cat_args['value'] = 'slug';
|
44 |
+
$cat_args['show_option_none'] = __('Select Category');
|
45 |
+
wp_dropdown_categories(apply_filters('eventorganiser_widget_event_venues_dropdown_args', $cat_args));
|
46 |
+
?>
|
47 |
+
|
48 |
+
<script type='text/javascript'>
|
49 |
+
/* <![CDATA[ */
|
50 |
+
var event_venue_dropdown = document.getElementById("eo-event-venue");
|
51 |
+
function eventorganiserVenueDropdownChange() {
|
52 |
+
console.log( event_venue_dropdown.options[event_venue_dropdown.selectedIndex].value);
|
53 |
+
if ( event_venue_dropdown.options[event_venue_dropdown.selectedIndex].value != -1 ) {
|
54 |
+
location.href = "<?php echo home_url().'/?'.$taxonomy.'=';?>"+event_venue_dropdown.options[event_venue_dropdown.selectedIndex].value;
|
55 |
+
}
|
56 |
+
}
|
57 |
+
event_venue_dropdown.onchange = eventorganiserVenueDropdownChange;
|
58 |
+
/* ]]> */
|
59 |
+
</script>
|
60 |
+
|
61 |
+
<?php
|
62 |
+
} else {
|
63 |
+
?>
|
64 |
+
<ul>
|
65 |
+
<?php
|
66 |
+
$cat_args['title_li'] = '';
|
67 |
+
wp_list_categories(apply_filters('eventorganiser_widget_event_venues_args', $cat_args));
|
68 |
+
?>
|
69 |
+
</ul>
|
70 |
+
<?php
|
71 |
+
}
|
72 |
+
|
73 |
+
echo $after_widget;
|
74 |
+
}
|
75 |
+
|
76 |
+
function update( $new_instance, $old_instance ) {
|
77 |
+
$instance = $old_instance;
|
78 |
+
$instance['title'] = strip_tags($new_instance['title']);
|
79 |
+
$instance['dropdown'] = !empty($new_instance['dropdown']) ? 1 : 0;
|
80 |
+
|
81 |
+
return $instance;
|
82 |
+
}
|
83 |
+
|
84 |
+
function form( $instance ) {
|
85 |
+
//Defaults
|
86 |
+
$instance = wp_parse_args( (array) $instance, array( 'title' => '') );
|
87 |
+
$title = esc_attr( $instance['title'] );
|
88 |
+
$dropdown = isset( $instance['dropdown'] ) ? (bool) $instance['dropdown'] : false;
|
89 |
+
?>
|
90 |
+
<p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e( 'Title:' ); ?></label>
|
91 |
+
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" /></p>
|
92 |
+
|
93 |
+
<p><input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id('dropdown'); ?>" name="<?php echo $this->get_field_name('dropdown'); ?>"<?php checked( $dropdown ); ?> />
|
94 |
+
<label for="<?php echo $this->get_field_id('dropdown'); ?>"><?php _e( 'Display as dropdown' ); ?></label><br />
|
95 |
+
<?php
|
96 |
+
}
|
97 |
+
|
98 |
+
}
|
classes/class-eventorganiser-admin-page.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class EventOrganiser_Admin_Page{
|
3 |
+
|
4 |
+
static $hook;
|
5 |
+
static $title;
|
6 |
+
static $menu;
|
7 |
+
static $permissions;
|
8 |
+
static $slug;
|
9 |
+
static $page;
|
10 |
+
|
11 |
+
function __construct() {
|
12 |
+
add_action('admin_init', array($this,'admin_init_actions'));
|
13 |
+
add_action('admin_menu', array($this,'add_page'));
|
14 |
+
add_action('init', array($this,'set_constants'));
|
15 |
+
}
|
16 |
+
|
17 |
+
function set_constants(){
|
18 |
+
}
|
19 |
+
|
20 |
+
function add_page(){
|
21 |
+
self::$page = add_submenu_page($this->hook,$this->title, $this->menu, $this->permissions,$this->slug, array($this,'render_page'),10);
|
22 |
+
add_action('load-'.self::$page, array($this,'page_actions'),9);
|
23 |
+
add_action('admin_print_scripts-'.self::$page, array($this,'page_styles'),10);
|
24 |
+
add_action('admin_print_styles-'.self::$page, array($this,'page_scripts'),10);
|
25 |
+
add_action("admin_footer-".self::$page,array($this,'footer_scripts'));
|
26 |
+
}
|
27 |
+
function footer_scripts(){
|
28 |
+
}
|
29 |
+
|
30 |
+
function page_scripts(){
|
31 |
+
}
|
32 |
+
/*
|
33 |
+
* Actions to be taken prior to page loading. This is after headers have been set.
|
34 |
+
* @uses load-$hook
|
35 |
+
*/
|
36 |
+
function page_actions(){
|
37 |
+
}
|
38 |
+
|
39 |
+
function page_styles(){
|
40 |
+
}
|
41 |
+
|
42 |
+
function admin_init_actions(){
|
43 |
+
}
|
44 |
+
|
45 |
+
function current_action(){
|
46 |
+
|
47 |
+
if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] )
|
48 |
+
return $_REQUEST['action'];
|
49 |
+
|
50 |
+
if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] )
|
51 |
+
return $_REQUEST['action2'];
|
52 |
+
|
53 |
+
return false;
|
54 |
+
}
|
55 |
+
|
56 |
+
function init(){
|
57 |
+
}
|
58 |
+
|
59 |
+
function render_page(){
|
60 |
+
$this->init();
|
61 |
+
$this->display();
|
62 |
+
}
|
63 |
+
function display(){
|
64 |
+
}
|
65 |
+
}
|
classes/class-eventorganiser-shortcodes.php
ADDED
@@ -0,0 +1,407 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class used to create the event calendar shortcode
|
4 |
+
*
|
5 |
+
*@uses EO_Calendar Widget class to generate calendar html
|
6 |
+
*/
|
7 |
+
class EventOrganiser_Shortcodes {
|
8 |
+
static $add_script;
|
9 |
+
static $calendars =array();
|
10 |
+
static $widget_calendars =array();
|
11 |
+
static $map = array();
|
12 |
+
static $event;
|
13 |
+
|
14 |
+
function init() {
|
15 |
+
add_shortcode('eo_calendar', array(__CLASS__, 'handle_calendar_shortcode'));
|
16 |
+
add_shortcode('eo_fullcalendar', array(__CLASS__, 'handle_fullcalendar_shortcode'));
|
17 |
+
add_shortcode('eo_venue_map', array(__CLASS__, 'handle_venuemap_shortcode'));
|
18 |
+
add_shortcode('eo_events', array(__CLASS__, 'handle_eventlist_shortcode'));
|
19 |
+
add_shortcode('eo_subscribe', array(__CLASS__, 'handle_subscription_shortcode'));
|
20 |
+
add_action('wp_footer', array(__CLASS__, 'print_script'));
|
21 |
+
}
|
22 |
+
|
23 |
+
function handle_calendar_shortcode($atts=array()) {
|
24 |
+
global $post;
|
25 |
+
|
26 |
+
/* Shortcodes don't accept hyphens, so convert taxonomy names */
|
27 |
+
$taxs = array('category','tag','venue');
|
28 |
+
foreach ($taxs as $tax){
|
29 |
+
if(isset($atts['event_'.$tax])){
|
30 |
+
$atts['event-'.$tax]= $atts['event_'.$tax];
|
31 |
+
unset($atts['event_'.$tax]);
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
/* Backwards compatibility */
|
36 |
+
$atts = wp_parse_args($atts,array(
|
37 |
+
'showpastevents'=>1,
|
38 |
+
));
|
39 |
+
|
40 |
+
self::$add_script = true;
|
41 |
+
|
42 |
+
$id = count(self::$widget_calendars);
|
43 |
+
self::$widget_calendars['eo_shortcode_calendar_'.$id] = $atts;
|
44 |
+
|
45 |
+
$tz = eo_get_blog_timezone();
|
46 |
+
$date = isset($_GET['eo_month']) ? $_GET['eo_month'].'-01' : 'now';
|
47 |
+
$month = new DateTime($date,$tz);
|
48 |
+
$month = date_create($month->format('Y-m-1'),$tz);
|
49 |
+
|
50 |
+
$html = '<div class="widget_calendar eo-calendar eo-calendar-shortcode eo_widget_calendar" id="eo_shortcode_calendar_'.$id.'">';
|
51 |
+
$html .= '<div id="eo_shortcode_calendar_'.$id.'_content">'.EO_Calendar_Widget::generate_output($month,$atts).'</div>';
|
52 |
+
$html .= '</div>';
|
53 |
+
|
54 |
+
return $html;
|
55 |
+
}
|
56 |
+
|
57 |
+
function handle_subscription_shortcode($atts, $content=null) {
|
58 |
+
extract( shortcode_atts( array(
|
59 |
+
'title' => 'Subscribe to calendar',
|
60 |
+
'type' => 'google',
|
61 |
+
'class' => '',
|
62 |
+
'id' => '',
|
63 |
+
), $atts ) );
|
64 |
+
|
65 |
+
$url = eo_get_events_feed();
|
66 |
+
|
67 |
+
$class = esc_attr($class);
|
68 |
+
$title = esc_attr($title);
|
69 |
+
$id = esc_attr($id);
|
70 |
+
|
71 |
+
if(strtolower($type)=='webcal'):
|
72 |
+
$url = str_replace( 'http://', 'webcal://',$url);
|
73 |
+
elseif( strtolower($type)=='ical' ):
|
74 |
+
//Do nothing
|
75 |
+
else:
|
76 |
+
$url = add_query_arg('cid',urlencode($url),'http://www.google.com/calendar/render');
|
77 |
+
endif;
|
78 |
+
|
79 |
+
$html = '<a href="'.$url.'" target="_blank" class="'.$class.'" title="'.$title.'" id="'.$id.'">'.$content.'</a>';
|
80 |
+
return $html;
|
81 |
+
}
|
82 |
+
|
83 |
+
function handle_fullcalendar_shortcode($atts=array()) {
|
84 |
+
|
85 |
+
/* Handle Boolean attributes - this will be passed as strings, we want them as boolean */
|
86 |
+
$bool_atts = array(
|
87 |
+
'key'=>'false',
|
88 |
+
'tooltip'=>'true',
|
89 |
+
'weekends'=>'true',
|
90 |
+
'alldayslot'=>'true',
|
91 |
+
);
|
92 |
+
$atts = wp_parse_args( $atts, $bool_atts );
|
93 |
+
|
94 |
+
foreach( $bool_atts as $att => $value )
|
95 |
+
$atts[$att] = ( strtolower( $atts[$att] ) == 'true' ? true : false );
|
96 |
+
|
97 |
+
if( isset($atts['venue']) && !isset( $atts['event_venue'] ) )
|
98 |
+
$atts['event_venue'] = $atts['venue'];
|
99 |
+
if( isset($atts['category']) && !isset( $atts['event_category'] ) )
|
100 |
+
$atts['event_category'] = $atts['category'];
|
101 |
+
|
102 |
+
return eo_get_event_fullcalendar( $atts );
|
103 |
+
}
|
104 |
+
|
105 |
+
function handle_venuemap_shortcode($atts) {
|
106 |
+
global $post;
|
107 |
+
|
108 |
+
if( !empty($atts['event_venue']) )
|
109 |
+
$atts['venue'] = $atts['event_venue'];
|
110 |
+
|
111 |
+
//If venue is not set get from the venue being quiered or the post being viewed
|
112 |
+
if( empty($atts['venue']) ){
|
113 |
+
if( eo_is_venue() ){
|
114 |
+
$atts['venue']= esc_attr(get_query_var('term'));
|
115 |
+
}else{
|
116 |
+
$atts['venue'] = eo_get_venue_slug(get_the_ID());
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
$venue_slugs = explode(',',$atts['venue']);
|
121 |
+
|
122 |
+
$args = shortcode_atts( array(
|
123 |
+
'zoom' => 15, 'scrollwheel'=>'true','zoomcontrol'=>'true',
|
124 |
+
'rotatecontrol'=>'true','pancontrol'=>'true','overviewmapcontrol'=>'true',
|
125 |
+
'streetviewcontrol'=>'true','maptypecontrol'=>'true','draggable'=>'true',
|
126 |
+
'maptypeid' => 'ROADMAP',
|
127 |
+
'width' => '100%','height' => '200px','class' => '',
|
128 |
+
'tooltip'=>'false'
|
129 |
+
), $atts );
|
130 |
+
|
131 |
+
//Cast options as boolean:
|
132 |
+
$bool_options = array('tooltip','scrollwheel','zoomcontrol','rotatecontrol','pancontrol','overviewmapcontrol','streetviewcontrol','draggable','maptypecontrol');
|
133 |
+
foreach( $bool_options as $option ){
|
134 |
+
$args[$option] = ( $args[$option] == 'false' ? false : true );
|
135 |
+
}
|
136 |
+
|
137 |
+
return eo_get_venue_map($venue_slugs, $args);
|
138 |
+
}
|
139 |
+
|
140 |
+
|
141 |
+
|
142 |
+
function handle_eventlist_shortcode($atts=array(),$content=null) {
|
143 |
+
$taxs = array('category','tag','venue');
|
144 |
+
foreach ($taxs as $tax){
|
145 |
+
if(isset($atts['event_'.$tax])){
|
146 |
+
$atts['event-'.$tax]= $atts['event_'.$tax];
|
147 |
+
unset($atts['event_'.$tax]);
|
148 |
+
}
|
149 |
+
}
|
150 |
+
|
151 |
+
if((isset($atts['venue']) &&$atts['venue']=='%this%') ||( isset($atts['event-venue']) && $atts['event-venue']=='%this%' )){
|
152 |
+
if( eo_get_venue_slug() ){
|
153 |
+
$atts['event-venue']= eo_get_venue_slug();
|
154 |
+
}else{
|
155 |
+
unset($atts['venue']);
|
156 |
+
unset($atts['event-venue']);
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
$args = array(
|
161 |
+
'class'=>'eo-events eo-events-shortcode',
|
162 |
+
'template'=>$content,
|
163 |
+
'no_events'=>'',
|
164 |
+
'type'=>'shortcode',
|
165 |
+
);
|
166 |
+
|
167 |
+
return eventorganiser_list_events( $atts,$args, 0);
|
168 |
+
}
|
169 |
+
|
170 |
+
|
171 |
+
function read_template($template){
|
172 |
+
$patterns = array(
|
173 |
+
'/%(event_title)%/',
|
174 |
+
'/%(start)({([^{}]*)}{([^{}]*)}|{[^{}]*})?%/',
|
175 |
+
'/%(end)({([^{}]*)}{([^{}]*)}|{[^{}]*})?%/',
|
176 |
+
'/%(event_venue)%/',
|
177 |
+
'/%(event_venue_url)%/',
|
178 |
+
'/%(event_cats)%/',
|
179 |
+
'/%(event_tags)%/',
|
180 |
+
'/%(event_venue_address)%/',
|
181 |
+
'/%(event_venue_postcode)%/',
|
182 |
+
'/%(event_venue_city)%/',
|
183 |
+
'/%(event_venue_country)%/',
|
184 |
+
'/%(event_venue_state)%/',
|
185 |
+
'/%(event_venue_city)%/',
|
186 |
+
'/%(schedule_start)({([^{}]*)}{([^{}]*)}|{[^{}]*})?%/',
|
187 |
+
'/%(schedule_last)({([^{}]*)}{([^{}]*)}|{[^{}]*})?%/',
|
188 |
+
'/%(schedule_end)({([^{}]*)}{([^{}]*)}|{[^{}]*})?%/',
|
189 |
+
'/%(event_thumbnail)(?:{([^{}]+)})?(?:{([^{}]+)})?%/',
|
190 |
+
'/%(event_url)%/',
|
191 |
+
'/%(event_custom_field){([^{}]+)}%/',
|
192 |
+
'/%(event_venue_map)({[^{}]+})?%/',
|
193 |
+
'/%(event_excerpt)(?:{(\d+)})?%/',
|
194 |
+
'/%(cat_color)%/',
|
195 |
+
'/%(event_title_attr)%/',
|
196 |
+
'/%(event_duration){([^{}]+)}%/',
|
197 |
+
'/%(event_content)%/',
|
198 |
+
);
|
199 |
+
$template = preg_replace_callback($patterns, array(__CLASS__,'parse_template'), $template);
|
200 |
+
return $template;
|
201 |
+
}
|
202 |
+
|
203 |
+
function parse_template($matches){
|
204 |
+
global $post;
|
205 |
+
$replacement='';
|
206 |
+
|
207 |
+
switch($matches[1]):
|
208 |
+
case 'event_title':
|
209 |
+
$replacement = get_the_title();
|
210 |
+
break;
|
211 |
+
|
212 |
+
case 'start':
|
213 |
+
case 'end':
|
214 |
+
case 'schedule_start':
|
215 |
+
case 'schedule_last':
|
216 |
+
case 'schedule_end':
|
217 |
+
switch(count($matches)):
|
218 |
+
case 2:
|
219 |
+
$dateFormat = get_option('date_format');
|
220 |
+
$dateTime = get_option('time_format');
|
221 |
+
break;
|
222 |
+
case 3:
|
223 |
+
$dateFormat = self::eo_clean_input($matches[2]);
|
224 |
+
$dateTime='';
|
225 |
+
break;
|
226 |
+
case 5:
|
227 |
+
$dateFormat = self::eo_clean_input($matches[3]);
|
228 |
+
$dateTime = self::eo_clean_input($matches[4]);
|
229 |
+
break;
|
230 |
+
endswitch;
|
231 |
+
|
232 |
+
$format = eo_is_all_day(get_the_ID()) ? $dateFormat : $dateFormat . $dateTime;
|
233 |
+
|
234 |
+
switch( $matches[1] ):
|
235 |
+
case 'start':
|
236 |
+
$replacement = eo_get_the_start( $format );
|
237 |
+
break;
|
238 |
+
case 'end':
|
239 |
+
$replacement = eo_get_the_end( $format );
|
240 |
+
break;
|
241 |
+
case 'schedule_start':
|
242 |
+
$replacement = eo_get_schedule_start( $format );
|
243 |
+
break;
|
244 |
+
case 'schedule_last':
|
245 |
+
case 'schedule_end':
|
246 |
+
$replacement = eo_get_schedule_end( $format );
|
247 |
+
break;
|
248 |
+
endswitch;
|
249 |
+
|
250 |
+
break;
|
251 |
+
case 'event_duration':
|
252 |
+
$start = eo_get_the_start(DATETIMEOBJ);
|
253 |
+
$end = eo_get_the_end(DATETIMEOBJ);
|
254 |
+
if( eo_is_all_day() )
|
255 |
+
$end->modify('+1 minute');
|
256 |
+
|
257 |
+
if( !function_exists('date_diff') ){
|
258 |
+
$duration = date_diff($start,$end);
|
259 |
+
$replacement = $duration->format($matches[2]);
|
260 |
+
}else{
|
261 |
+
$replacement = eo_date_interval($start,$end,$matches[2]);
|
262 |
+
}
|
263 |
+
break;
|
264 |
+
|
265 |
+
case 'event_tags':
|
266 |
+
$replacement = get_the_term_list( get_the_ID(), 'event-tag', '', ', ','');
|
267 |
+
break;
|
268 |
+
|
269 |
+
case 'event_cats':
|
270 |
+
$replacement = get_the_term_list( get_the_ID(), 'event-category', '', ', ','');
|
271 |
+
break;
|
272 |
+
|
273 |
+
case 'event_venue':
|
274 |
+
$replacement =eo_get_venue_name();
|
275 |
+
break;
|
276 |
+
|
277 |
+
case 'event_venue_map':
|
278 |
+
if(eo_get_venue()){
|
279 |
+
$class = (isset($matches[2]) ? self::eo_clean_input($matches[2]) : '');
|
280 |
+
$class = (!empty($class) ? 'class='.$class : '');
|
281 |
+
$replacement = eo_get_venue_map( eo_get_venue(), compact('class') );
|
282 |
+
}
|
283 |
+
break;
|
284 |
+
|
285 |
+
case 'event_venue_url':
|
286 |
+
$venue_link =eo_get_venue_link();
|
287 |
+
$replacement = ( !is_wp_error($venue_link) ? $venue_link : '');
|
288 |
+
break;
|
289 |
+
case 'event_venue_address':
|
290 |
+
$address = eo_get_venue_address();
|
291 |
+
$replacement =$address['address'];
|
292 |
+
break;
|
293 |
+
case 'event_venue_postcode':
|
294 |
+
$address = eo_get_venue_address();
|
295 |
+
$replacement =$address['postcode'];
|
296 |
+
break;
|
297 |
+
case 'event_venue_city':
|
298 |
+
$address = eo_get_venue_address();
|
299 |
+
$replacement =$address['city'];
|
300 |
+
break;
|
301 |
+
case 'event_venue_country':
|
302 |
+
$address = eo_get_venue_address();
|
303 |
+
$replacement =$address['country'];
|
304 |
+
break;
|
305 |
+
case 'event_venue_state':
|
306 |
+
$address = eo_get_venue_address();
|
307 |
+
$replacement =$address['state'];
|
308 |
+
break;
|
309 |
+
case 'event_venue_city':
|
310 |
+
$address = eo_get_venue_address();
|
311 |
+
$replacement =$address['city'];
|
312 |
+
break;
|
313 |
+
case 'event_thumbnail':
|
314 |
+
$size = (isset($matches[2]) ? self::eo_clean_input($matches[2]) : '');
|
315 |
+
$size = (!empty($size) ? $size : 'thumbnail');
|
316 |
+
$attr = (isset($matches[3]) ? self::eo_clean_input($matches[3]) : '');
|
317 |
+
|
318 |
+
//Decode HTML entities as shortcode encodes them
|
319 |
+
$attr = html_entity_decode($attr);
|
320 |
+
$replacement = get_the_post_thumbnail(get_the_ID(),$size, $attr);
|
321 |
+
break;
|
322 |
+
case 'event_url':
|
323 |
+
$replacement =get_permalink();
|
324 |
+
break;
|
325 |
+
case 'event_custom_field':
|
326 |
+
$field = $matches[2];
|
327 |
+
$meta = get_post_meta(get_the_ID(), $field);
|
328 |
+
$replacement = implode($meta);
|
329 |
+
break;
|
330 |
+
case 'event_excerpt':
|
331 |
+
$length = ( isset($matches[2]) ? intval($matches[2]) : 55 );
|
332 |
+
//Using get_the_excerpt adds a link....
|
333 |
+
if ( post_password_required($post) ) {
|
334 |
+
$output = __('There is no excerpt because this is a protected post.');
|
335 |
+
}else{
|
336 |
+
$output = $post->post_excerpt;
|
337 |
+
}
|
338 |
+
$replacement = eventorganiser_trim_excerpt( $output, $length);
|
339 |
+
break;
|
340 |
+
case 'event_content':
|
341 |
+
$replacement = get_the_content();
|
342 |
+
break;
|
343 |
+
case 'cat_color':
|
344 |
+
$replacement = eo_get_event_color();
|
345 |
+
break;
|
346 |
+
case 'event_title_attr':
|
347 |
+
$replacement = get_the_title();
|
348 |
+
break;
|
349 |
+
|
350 |
+
endswitch;
|
351 |
+
return $replacement;
|
352 |
+
}
|
353 |
+
|
354 |
+
function eo_clean_input($input){
|
355 |
+
$input = trim($input,"{}"); //remove { }
|
356 |
+
$input = str_replace(array("'",'"',"”","‘", "’"),'',$input); //remove quotations
|
357 |
+
return $input;
|
358 |
+
}
|
359 |
+
|
360 |
+
function print_script() {
|
361 |
+
global $wp_locale;
|
362 |
+
if ( ! self::$add_script ) return;
|
363 |
+
$fullcal = (empty(self::$calendars) ? array() : array(
|
364 |
+
'firstDay'=>intval(get_option('start_of_week')),
|
365 |
+
'venues' => get_terms( 'event-venue', array('hide_empty' => 0)),
|
366 |
+
'categories' => get_terms( 'event-category', array('hide_empty' => 0)),
|
367 |
+
));
|
368 |
+
wp_localize_script( 'eo_front', 'EOAjax',
|
369 |
+
array(
|
370 |
+
'ajaxurl' => admin_url( 'admin-ajax.php'),
|
371 |
+
'calendars' => self::$calendars,
|
372 |
+
'widget_calendars' => self::$widget_calendars,
|
373 |
+
'fullcal' => $fullcal,
|
374 |
+
'map' => self::$map,
|
375 |
+
));
|
376 |
+
|
377 |
+
if( !empty(self::$calendars) || !empty(self::$map) || !empty(self::$widget_calendars) ):
|
378 |
+
wp_enqueue_script( 'eo_qtip2');
|
379 |
+
wp_enqueue_style('eo_calendar-style');
|
380 |
+
wp_enqueue_style('eo_front');
|
381 |
+
wp_enqueue_script( 'eo_front');
|
382 |
+
endif;
|
383 |
+
|
384 |
+
if( !empty( self::$map ) )
|
385 |
+
wp_enqueue_script( 'eo_GoogleMap' );
|
386 |
+
}
|
387 |
+
}
|
388 |
+
|
389 |
+
EventOrganiser_Shortcodes::init();
|
390 |
+
|
391 |
+
function eventorganiser_category_key($args=array(),$id=1){
|
392 |
+
$args['taxonomy'] ='event-category';
|
393 |
+
|
394 |
+
$html ='<div class="eo-fullcalendar-key" id="eo_fullcalendar_key'.$id.'">';
|
395 |
+
$terms = get_terms( 'event-category', $args );
|
396 |
+
$html.= "<ul class='eo_fullcalendar_key'>";
|
397 |
+
foreach ($terms as $term):
|
398 |
+
$slug = esc_attr($term->slug);
|
399 |
+
$color = esc_attr($term->color);
|
400 |
+
$class = "class='eo_fullcalendar_key_cat eo_fullcalendar_key_cat_{$slug}'";
|
401 |
+
$html.= "<li {$class}><span class='eo_fullcalendar_key_colour' style='background:{$color}'> </span>".esc_attr($term->name)."</li>";
|
402 |
+
endforeach;
|
403 |
+
$html.='</ul></div>';
|
404 |
+
|
405 |
+
return $html;
|
406 |
+
}
|
407 |
+
?>
|
css/eventorganiser-admin-classic.css
ADDED
@@ -0,0 +1,576 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* jQuery UI CSS Framework 1.8.16
|
3 |
+
*
|
4 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
5 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
6 |
+
* http://jquery.org/license
|
7 |
+
*
|
8 |
+
* http://docs.jquery.com/UI/Theming/API
|
9 |
+
*/
|
10 |
+
|
11 |
+
/* Layout helpers
|
12 |
+
----------------------------------*/
|
13 |
+
.ui-helper-hidden { display: none; }
|
14 |
+
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
|
15 |
+
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
|
16 |
+
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
|
17 |
+
.ui-helper-clearfix { display: inline-block; }
|
18 |
+
/* required comment for clearfix to work in Opera \*/
|
19 |
+
* html .ui-helper-clearfix { height:1%; }
|
20 |
+
.ui-helper-clearfix { display:block; }
|
21 |
+
/* end clearfix */
|
22 |
+
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
23 |
+
|
24 |
+
|
25 |
+
/* Interaction Cues
|
26 |
+
----------------------------------*/
|
27 |
+
.ui-state-disabled { cursor: default !important; }
|
28 |
+
|
29 |
+
|
30 |
+
/* Icons
|
31 |
+
----------------------------------*/
|
32 |
+
|
33 |
+
/* states and images */
|
34 |
+
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
|
35 |
+
|
36 |
+
|
37 |
+
/* Misc visuals
|
38 |
+
----------------------------------*/
|
39 |
+
|
40 |
+
/* Overlays */
|
41 |
+
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
42 |
+
|
43 |
+
|
44 |
+
/*
|
45 |
+
* jQuery UI CSS Framework 1.8.16
|
46 |
+
*
|
47 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
48 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
49 |
+
* http://jquery.org/license
|
50 |
+
*
|
51 |
+
* http://docs.jquery.com/UI/Theming/API
|
52 |
+
*
|
53 |
+
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=sans-serif&fwDefault=normal&fsDefault=12px&cornerRadius=3px&bgColorHeader=eff8ff&bgTextureHeader=04_highlight_hard.png&bgImgOpacityHeader=75&borderColorHeader=d1e5ee&fcHeader=333333&iconColorHeader=21759b&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=d1e5ee&fcContent=333333&iconColorContent=333333&bgColorDefault=eff8ff&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=75&borderColorDefault=d1e5ee&fcDefault=333333&iconColorDefault=333333&bgColorHover=f7fcfe&bgTextureHover=06_inset_hard.png&bgImgOpacityHover=75&borderColorHover=b8d7e5&fcHover=000000&iconColorHover=333333&bgColorActive=ffffff&bgTextureActive=01_flat.png&bgImgOpacityActive=65&borderColorActive=d1e5ee&fcActive=333333&iconColorActive=333333&bgColorHighlight=ffffe0&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=e6db55&fcHighlight=333333&iconColorHighlight=21759b&bgColorError=ffebe8&bgTextureError=01_flat.png&bgImgOpacityError=95&borderColorError=cc0000&fcError=cc0000&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=3px
|
54 |
+
*/
|
55 |
+
|
56 |
+
|
57 |
+
/* Component containers
|
58 |
+
----------------------------------*/
|
59 |
+
.ui-widget { font-family: sans-serif; font-size: 12px; }
|
60 |
+
.ui-widget .ui-widget { font-size: 1em; }
|
61 |
+
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: sans-serif; font-size: 1em; }
|
62 |
+
.ui-widget-content { border: 1px solid #d1e5ee; background: #ffffff; color: #333333; }
|
63 |
+
.ui-widget-header { border: 1px solid #d1e5ee; background-color: #f5fafd; background-image: -ms-linear-gradient(top, #f7fcfe, #eff8ff); background-image: -moz-linear-gradient(top, #f7fcfe, #eff8ff); background-image: -o-linear-gradient(top, #f7fcfe, #eff8ff); background-image: -webkit-gradient(linear, left top, left bottom, from(#f7fcfe), to(#eff8ff)); background-image: -webkit-linear-gradient(top, #f7fcfe, #eff8ff); background-image: linear-gradient(top, #f7fcfe, #eff8ff); color: #333333; font-weight: bold; }
|
64 |
+
.ui-widget-header a { color: #333333; }
|
65 |
+
|
66 |
+
/* Interaction states
|
67 |
+
----------------------------------*/
|
68 |
+
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d1e5ee; background-color: #f5fafd; background-image: -ms-linear-gradient(top, #f7fcfe, #eff8ff); background-image: -moz-linear-gradient(top, #f7fcfe, #eff8ff); background-image: -o-linear-gradient(top, #f7fcfe, #eff8ff); background-image: -webkit-gradient(linear, left top, left bottom, from(#f7fcfe), to(#eff8ff)); background-image: -webkit-linear-gradient(top, #f7fcfe, #eff8ff); background-image: linear-gradient(top, #f7fcfe, #eff8ff); font-weight: normal; color: #333333; }
|
69 |
+
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #21759b; text-decoration: none; }
|
70 |
+
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #b8d7e5; background-color: #f7fcfe; background-image: -ms-linear-gradient(top, #eff8ff, #f7fcfe); background-image: -moz-linear-gradient(top, #eff8ff, #f7fcfe); background-image: -o-linear-gradient(top, #eff8ff, #f7fcfe); background-image: -webkit-gradient(linear, left top, left bottom, from(#eff8ff), to(#f7fcfe)); background-image: -webkit-linear-gradient(top, #eff8ff, #f7fcfe); background-image: linear-gradient(top, #eff8ff, #f7fcfe);; font-weight: normal; color: #000000; }
|
71 |
+
.ui-state-hover a, .ui-state-hover a:hover { color: #d54e21; text-decoration: none; }
|
72 |
+
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #d1e5ee; background: #ffffff; font-weight: normal; color: #333333; }
|
73 |
+
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #333333; text-decoration: none; }
|
74 |
+
.ui-widget :active { outline: none; }
|
75 |
+
|
76 |
+
/* Interaction Cues
|
77 |
+
----------------------------------*/
|
78 |
+
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #e6db55; background: #ffffe0; color: #333333; }
|
79 |
+
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #333333; }
|
80 |
+
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cc0000; background: #ffebe8; color: #cc0000; }
|
81 |
+
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cc0000; }
|
82 |
+
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cc0000; }
|
83 |
+
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
|
84 |
+
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
85 |
+
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
86 |
+
|
87 |
+
/* Icons
|
88 |
+
----------------------------------*/
|
89 |
+
|
90 |
+
/* states and images */
|
91 |
+
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_21759b_256x240.png); }
|
92 |
+
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_21759b_256x240.png); }
|
93 |
+
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_21759b_256x240.png); }
|
94 |
+
.ui-state-default .ui-icon { background-image: url(images/ui-icons_21759b_256x240.png); }
|
95 |
+
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_d54e21_256x240.png); }
|
96 |
+
.ui-state-active .ui-icon {background-image: url(images/ui-icons_333333_256x240.png); }
|
97 |
+
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_21759b_256x240.png); }
|
98 |
+
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); }
|
99 |
+
|
100 |
+
|
101 |
+
/* positioning */
|
102 |
+
.ui-icon-carat-1-n { background-position: 0 0; }
|
103 |
+
.ui-icon-carat-1-ne { background-position: -16px 0; }
|
104 |
+
.ui-icon-carat-1-e { background-position: -32px 0; }
|
105 |
+
.ui-icon-carat-1-se { background-position: -48px 0; }
|
106 |
+
.ui-icon-carat-1-s { background-position: -64px 0; }
|
107 |
+
.ui-icon-carat-1-sw { background-position: -80px 0; }
|
108 |
+
.ui-icon-carat-1-w { background-position: -96px 0; }
|
109 |
+
.ui-icon-carat-1-nw { background-position: -112px 0; }
|
110 |
+
.ui-icon-carat-2-n-s { background-position: -128px 0; }
|
111 |
+
.ui-icon-carat-2-e-w { background-position: -144px 0; }
|
112 |
+
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
113 |
+
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
114 |
+
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
115 |
+
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
116 |
+
.ui-icon-triangle-1-s { background-position: -64px -16px; }
|
117 |
+
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
118 |
+
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
119 |
+
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
120 |
+
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
121 |
+
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
122 |
+
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
123 |
+
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
124 |
+
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
125 |
+
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
126 |
+
.ui-icon-arrow-1-s { background-position: -64px -32px; }
|
127 |
+
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
128 |
+
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
129 |
+
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
130 |
+
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
131 |
+
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
132 |
+
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
133 |
+
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
134 |
+
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
135 |
+
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
136 |
+
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
137 |
+
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
138 |
+
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
|
139 |
+
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
140 |
+
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
141 |
+
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
142 |
+
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
143 |
+
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
144 |
+
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
145 |
+
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
146 |
+
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
147 |
+
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
148 |
+
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
149 |
+
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
150 |
+
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
151 |
+
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
152 |
+
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
153 |
+
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
154 |
+
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
155 |
+
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
156 |
+
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
157 |
+
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
158 |
+
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
159 |
+
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
160 |
+
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
161 |
+
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
162 |
+
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
163 |
+
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
164 |
+
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
165 |
+
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
166 |
+
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
167 |
+
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
168 |
+
.ui-icon-extlink { background-position: -32px -80px; }
|
169 |
+
.ui-icon-newwin { background-position: -48px -80px; }
|
170 |
+
.ui-icon-refresh { background-position: -64px -80px; }
|
171 |
+
.ui-icon-shuffle { background-position: -80px -80px; }
|
172 |
+
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
173 |
+
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
174 |
+
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
175 |
+
.ui-icon-folder-open { background-position: -16px -96px; }
|
176 |
+
.ui-icon-document { background-position: -32px -96px; }
|
177 |
+
.ui-icon-document-b { background-position: -48px -96px; }
|
178 |
+
.ui-icon-note { background-position: -64px -96px; }
|
179 |
+
.ui-icon-mail-closed { background-position: -80px -96px; }
|
180 |
+
.ui-icon-mail-open { background-position: -96px -96px; }
|
181 |
+
.ui-icon-suitcase { background-position: -112px -96px; }
|
182 |
+
.ui-icon-comment { background-position: -128px -96px; }
|
183 |
+
.ui-icon-person { background-position: -144px -96px; }
|
184 |
+
.ui-icon-print { background-position: -160px -96px; }
|
185 |
+
.ui-icon-trash { background-position: -176px -96px; }
|
186 |
+
.ui-icon-locked { background-position: -192px -96px; }
|
187 |
+
.ui-icon-unlocked { background-position: -208px -96px; }
|
188 |
+
.ui-icon-bookmark { background-position: -224px -96px; }
|
189 |
+
.ui-icon-tag { background-position: -240px -96px; }
|
190 |
+
.ui-icon-home { background-position: 0 -112px; }
|
191 |
+
.ui-icon-flag { background-position: -16px -112px; }
|
192 |
+
.ui-icon-calendar { background-position: -32px -112px; }
|
193 |
+
.ui-icon-cart { background-position: -48px -112px; }
|
194 |
+
.ui-icon-pencil { background-position: -64px -112px; }
|
195 |
+
.ui-icon-clock { background-position: -80px -112px; }
|
196 |
+
.ui-icon-disk { background-position: -96px -112px; }
|
197 |
+
.ui-icon-calculator { background-position: -112px -112px; }
|
198 |
+
.ui-icon-zoomin { background-position: -128px -112px; }
|
199 |
+
.ui-icon-zoomout { background-position: -144px -112px; }
|
200 |
+
.ui-icon-search { background-position: -160px -112px; }
|
201 |
+
.ui-icon-wrench { background-position: -176px -112px; }
|
202 |
+
.ui-icon-gear { background-position: -192px -112px; }
|
203 |
+
.ui-icon-heart { background-position: -208px -112px; }
|
204 |
+
.ui-icon-star { background-position: -224px -112px; }
|
205 |
+
.ui-icon-link { background-position: -240px -112px; }
|
206 |
+
.ui-icon-cancel { background-position: 0 -128px; }
|
207 |
+
.ui-icon-plus { background-position: -16px -128px; }
|
208 |
+
.ui-icon-plusthick { background-position: -32px -128px; }
|
209 |
+
.ui-icon-minus { background-position: -48px -128px; }
|
210 |
+
.ui-icon-minusthick { background-position: -64px -128px; }
|
211 |
+
.ui-icon-close { background-position: -80px -128px; }
|
212 |
+
.ui-icon-closethick { background-position: -96px -128px; }
|
213 |
+
.ui-icon-key { background-position: -112px -128px; }
|
214 |
+
.ui-icon-lightbulb { background-position: -128px -128px; }
|
215 |
+
.ui-icon-scissors { background-position: -144px -128px; }
|
216 |
+
.ui-icon-clipboard { background-position: -160px -128px; }
|
217 |
+
.ui-icon-copy { background-position: -176px -128px; }
|
218 |
+
.ui-icon-contact { background-position: -192px -128px; }
|
219 |
+
.ui-icon-image { background-position: -208px -128px; }
|
220 |
+
.ui-icon-video { background-position: -224px -128px; }
|
221 |
+
.ui-icon-script { background-position: -240px -128px; }
|
222 |
+
.ui-icon-alert { background-position: 0 -144px; }
|
223 |
+
.ui-icon-info { background-position: -16px -144px; }
|
224 |
+
.ui-icon-notice { background-position: -32px -144px; }
|
225 |
+
.ui-icon-help { background-position: -48px -144px; }
|
226 |
+
.ui-icon-check { background-position: -64px -144px; }
|
227 |
+
.ui-icon-bullet { background-position: -80px -144px; }
|
228 |
+
.ui-icon-radio-off { background-position: -96px -144px; }
|
229 |
+
.ui-icon-radio-on { background-position: -112px -144px; }
|
230 |
+
.ui-icon-pin-w { background-position: -128px -144px; }
|
231 |
+
.ui-icon-pin-s { background-position: -144px -144px; }
|
232 |
+
.ui-icon-play { background-position: 0 -160px; }
|
233 |
+
.ui-icon-pause { background-position: -16px -160px; }
|
234 |
+
.ui-icon-seek-next { background-position: -32px -160px; }
|
235 |
+
.ui-icon-seek-prev { background-position: -48px -160px; }
|
236 |
+
.ui-icon-seek-end { background-position: -64px -160px; }
|
237 |
+
.ui-icon-seek-start { background-position: -80px -160px; }
|
238 |
+
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
|
239 |
+
.ui-icon-seek-first { background-position: -80px -160px; }
|
240 |
+
.ui-icon-stop { background-position: -96px -160px; }
|
241 |
+
.ui-icon-eject { background-position: -112px -160px; }
|
242 |
+
.ui-icon-volume-off { background-position: -128px -160px; }
|
243 |
+
.ui-icon-volume-on { background-position: -144px -160px; }
|
244 |
+
.ui-icon-power { background-position: 0 -176px; }
|
245 |
+
.ui-icon-signal-diag { background-position: -16px -176px; }
|
246 |
+
.ui-icon-signal { background-position: -32px -176px; }
|
247 |
+
.ui-icon-battery-0 { background-position: -48px -176px; }
|
248 |
+
.ui-icon-battery-1 { background-position: -64px -176px; }
|
249 |
+
.ui-icon-battery-2 { background-position: -80px -176px; }
|
250 |
+
.ui-icon-battery-3 { background-position: -96px -176px; }
|
251 |
+
.ui-icon-circle-plus { background-position: 0 -192px; }
|
252 |
+
.ui-icon-circle-minus { background-position: -16px -192px; }
|
253 |
+
.ui-icon-circle-close { background-position: -32px -192px; }
|
254 |
+
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
255 |
+
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
256 |
+
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
257 |
+
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
258 |
+
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
259 |
+
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
260 |
+
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
261 |
+
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
262 |
+
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
263 |
+
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
264 |
+
.ui-icon-circle-check { background-position: -208px -192px; }
|
265 |
+
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
266 |
+
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
267 |
+
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
268 |
+
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
269 |
+
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
270 |
+
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
271 |
+
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
272 |
+
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
273 |
+
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
274 |
+
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
275 |
+
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
276 |
+
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
277 |
+
|
278 |
+
|
279 |
+
/* Misc visuals
|
280 |
+
----------------------------------*/
|
281 |
+
|
282 |
+
/* Corner radius */
|
283 |
+
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; -khtml-border-top-left-radius: 3px; border-top-left-radius: 3px; }
|
284 |
+
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; -khtml-border-top-right-radius: 3px; border-top-right-radius: 3px; }
|
285 |
+
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; -khtml-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; }
|
286 |
+
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; -khtml-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; }
|
287 |
+
|
288 |
+
/* Overlays */
|
289 |
+
.ui-widget-overlay { background: #000000; opacity: .6;filter:Alpha(Opacity=60); }
|
290 |
+
.ui-widget-shadow { box-shadow: 0 0 16px rgba(0, 0, 0, 0.3); }/*
|
291 |
+
* jQuery UI Resizable 1.8.16
|
292 |
+
*
|
293 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
294 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
295 |
+
* http://jquery.org/license
|
296 |
+
*
|
297 |
+
* http://docs.jquery.com/UI/Resizable#theming
|
298 |
+
*/
|
299 |
+
.ui-resizable { position: relative;}
|
300 |
+
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
|
301 |
+
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
302 |
+
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
303 |
+
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
304 |
+
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
305 |
+
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
306 |
+
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
307 |
+
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
308 |
+
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
309 |
+
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
|
310 |
+
* jQuery UI Selectable 1.8.16
|
311 |
+
*
|
312 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
313 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
314 |
+
* http://jquery.org/license
|
315 |
+
*
|
316 |
+
* http://docs.jquery.com/UI/Selectable#theming
|
317 |
+
*/
|
318 |
+
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
319 |
+
/*
|
320 |
+
* jQuery UI Accordion 1.8.16
|
321 |
+
*
|
322 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
323 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
324 |
+
* http://jquery.org/license
|
325 |
+
*
|
326 |
+
* http://docs.jquery.com/UI/Accordion#theming
|
327 |
+
*/
|
328 |
+
/* IE/Win - Fix animation bug - #4615 */
|
329 |
+
.ui-accordion { width: 100%; }
|
330 |
+
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
|
331 |
+
.ui-accordion .ui-accordion-li-fix { display: inline; }
|
332 |
+
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
|
333 |
+
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
|
334 |
+
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
|
335 |
+
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
336 |
+
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
|
337 |
+
.ui-accordion .ui-accordion-content-active { display: block; }
|
338 |
+
/*
|
339 |
+
* jQuery UI Autocomplete 1.8.16
|
340 |
+
*
|
341 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
342 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
343 |
+
* http://jquery.org/license
|
344 |
+
*
|
345 |
+
* http://docs.jquery.com/UI/Autocomplete#theming
|
346 |
+
*/
|
347 |
+
.ui-autocomplete { position: absolute; cursor: default; }
|
348 |
+
|
349 |
+
/* workarounds */
|
350 |
+
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
351 |
+
|
352 |
+
/*
|
353 |
+
* jQuery UI Menu 1.8.16
|
354 |
+
*
|
355 |
+
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
|
356 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
357 |
+
* http://jquery.org/license
|
358 |
+
*
|
359 |
+
* http://docs.jquery.com/UI/Menu#theming
|
360 |
+
*/
|
361 |
+
.ui-menu {
|
362 |
+
list-style:none;
|
363 |
+
padding: 2px;
|
364 |
+
margin: 0;
|
365 |
+
display:block;
|
366 |
+
float: left;
|
367 |
+
}
|
368 |
+
.ui-menu .ui-menu {
|
369 |
+
margin-top: -3px;
|
370 |
+
}
|
371 |
+
.ui-menu .ui-menu-item {
|
372 |
+
margin:0;
|
373 |
+
padding: 0;
|
374 |
+
zoom: 1;
|
375 |
+
float: left;
|
376 |
+
clear: left;
|
377 |
+
width: 100%;
|
378 |
+
}
|
379 |
+
.ui-menu .ui-menu-item a {
|
380 |
+
text-decoration:none;
|
381 |
+
display:block;
|
382 |
+
padding:.2em .4em;
|
383 |
+
line-height:1.5;
|
384 |
+
zoom:1;
|
385 |
+
}
|
386 |
+
.ui-menu .ui-menu-item a.ui-state-hover,
|
387 |
+
.ui-menu .ui-menu-item a.ui-state-active {
|
388 |
+
font-weight: normal;
|
389 |
+
margin: -1px;
|
390 |
+
}
|
391 |
+
/*
|
392 |
+
* jQuery UI Button 1.8.16
|
393 |
+
*
|
394 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
395 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
396 |
+
* http://jquery.org/license
|
397 |
+
*
|
398 |
+
* http://docs.jquery.com/UI/Button#theming
|
399 |
+
*/
|
400 |
+
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
|
401 |
+
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
|
402 |
+
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
|
403 |
+
.ui-button-icons-only { width: 3.4em; }
|
404 |
+
button.ui-button-icons-only { width: 3.7em; }
|
405 |
+
|
406 |
+
/*button text element */
|
407 |
+
.ui-button .ui-button-text { display: block; line-height: 1.4; }
|
408 |
+
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
|
409 |
+
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
|
410 |
+
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
|
411 |
+
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
|
412 |
+
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
|
413 |
+
/* no icon support for input elements, provide padding by default */
|
414 |
+
input.ui-button { padding: .4em 1em; }
|
415 |
+
|
416 |
+
/*button icon element(s) */
|
417 |
+
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
|
418 |
+
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
|
419 |
+
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
|
420 |
+
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
421 |
+
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
422 |
+
|
423 |
+
/*button sets*/
|
424 |
+
.ui-buttonset { margin-right: 7px; }
|
425 |
+
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
|
426 |
+
|
427 |
+
/* workarounds */
|
428 |
+
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
429 |
+
/*
|
430 |
+
* jQuery UI Dialog 1.8.16
|
431 |
+
*
|
432 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
433 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
434 |
+
* http://jquery.org/license
|
435 |
+
*
|
436 |
+
* http://docs.jquery.com/UI/Dialog#theming
|
437 |
+
*/
|
438 |
+
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
|
439 |
+
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;color: #333!important; }
|
440 |
+
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
|
441 |
+
.ui-dialog .ui-dialog-titlebar-close { position: absolute!important; right: .3em!important; top: 50%!important; width: 19px!important; margin: -10px 0 0 0!important; padding: 1px!important; height: 18px!important; background:none!important; }
|
442 |
+
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
443 |
+
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0!important; }
|
444 |
+
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
445 |
+
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
446 |
+
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
|
447 |
+
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
|
448 |
+
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
449 |
+
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
450 |
+
/*
|
451 |
+
* jQuery UI Slider 1.8.16
|
452 |
+
*
|
453 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
454 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
455 |
+
* http://jquery.org/license
|
456 |
+
*
|
457 |
+
* http://docs.jquery.com/UI/Slider#theming
|
458 |
+
*/
|
459 |
+
.ui-slider { position: relative; text-align: left; }
|
460 |
+
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
461 |
+
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
|
462 |
+
|
463 |
+
.ui-slider-horizontal { height: .8em; }
|
464 |
+
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
465 |
+
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
466 |
+
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
467 |
+
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
468 |
+
|
469 |
+
.ui-slider-vertical { width: .8em; height: 100px; }
|
470 |
+
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
471 |
+
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
472 |
+
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
473 |
+
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
|
474 |
+
* jQuery UI Tabs 1.8.16
|
475 |
+
*
|
476 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
477 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
478 |
+
* http://jquery.org/license
|
479 |
+
*
|
480 |
+
* http://docs.jquery.com/UI/Tabs#theming
|
481 |
+
*/
|
482 |
+
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
483 |
+
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
|
484 |
+
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
|
485 |
+
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
|
486 |
+
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
|
487 |
+
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
|
488 |
+
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
489 |
+
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
490 |
+
.ui-tabs .ui-tabs-hide { display: none !important; }
|
491 |
+
/*
|
492 |
+
* jQuery UI Datepicker 1.8.16
|
493 |
+
*
|
494 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
495 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
496 |
+
* http://jquery.org/license
|
497 |
+
*
|
498 |
+
* http://docs.jquery.com/UI/Datepicker#theming
|
499 |
+
*/
|
500 |
+
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
501 |
+
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
502 |
+
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
503 |
+
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
504 |
+
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
505 |
+
.ui-datepicker .ui-datepicker-next { right:2px; }
|
506 |
+
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
507 |
+
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
508 |
+
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
509 |
+
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
510 |
+
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
511 |
+
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
512 |
+
.ui-datepicker select.ui-datepicker-month,
|
513 |
+
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
514 |
+
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
515 |
+
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
516 |
+
.ui-datepicker td { border: 0; padding: 1px; }
|
517 |
+
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
518 |
+
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
519 |
+
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
520 |
+
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
521 |
+
|
522 |
+
/* with multiple calendars */
|
523 |
+
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
524 |
+
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
525 |
+
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
526 |
+
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
527 |
+
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
528 |
+
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
529 |
+
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
530 |
+
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
531 |
+
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
532 |
+
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
533 |
+
|
534 |
+
/* RTL support */
|
535 |
+
.ui-datepicker-rtl { direction: rtl; }
|
536 |
+
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
537 |
+
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
538 |
+
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
539 |
+
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
540 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
541 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
542 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
543 |
+
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
544 |
+
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
545 |
+
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
546 |
+
|
547 |
+
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
548 |
+
.ui-datepicker-cover {
|
549 |
+
display: none; /*sorry for IE5*/
|
550 |
+
display/**/: block; /*sorry for IE5*/
|
551 |
+
position: absolute; /*must have*/
|
552 |
+
z-index: -1; /*must have*/
|
553 |
+
filter: mask(); /*must have*/
|
554 |
+
top: -4px; /*must have*/
|
555 |
+
left: -4px; /*must have*/
|
556 |
+
width: 200px; /*must have*/
|
557 |
+
height: 200px; /*must have*/
|
558 |
+
}/*
|
559 |
+
* jQuery UI Progressbar 1.8.16
|
560 |
+
*
|
561 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
562 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
563 |
+
* http://jquery.org/license
|
564 |
+
*
|
565 |
+
* http://docs.jquery.com/UI/Progressbar#theming
|
566 |
+
*/
|
567 |
+
.ui-progressbar { height:2em; text-align: left; }
|
568 |
+
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
|
569 |
+
.ui-progressbar .ui-widget-header {
|
570 |
+
background-color: #83B4D8;
|
571 |
+
background-image: linear-gradient(bottom, rgb(114,167,207) 0%, rgb(144,197,238) 100%);
|
572 |
+
background-image: -o-linear-gradient(bottom, rgb(114,167,207) 0%, rgb(144,197,238) 100%);
|
573 |
+
background-image: -moz-linear-gradient(bottom, rgb(114,167,207) 0%, rgb(144,197,238) 100%);
|
574 |
+
background-image: -webkit-linear-gradient(bottom, rgb(114,167,207) 0%, rgb(144,197,238) 100%);
|
575 |
+
background-image: -ms-linear-gradient(bottom, rgb(114,167,207) 0%, rgb(144,197,238) 100%);
|
576 |
+
}
|
css/eventorganiser-admin-fresh.css
ADDED
@@ -0,0 +1,591 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* jQuery UI CSS Framework 1.8.16
|
3 |
+
*
|
4 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
5 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
6 |
+
* http://jquery.org/license
|
7 |
+
*
|
8 |
+
* http://docs.jquery.com/UI/Theming/API
|
9 |
+
*/
|
10 |
+
|
11 |
+
/* Layout helpers
|
12 |
+
----------------------------------*/
|
13 |
+
.ui-helper-hidden { display: none; }
|
14 |
+
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
|
15 |
+
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
|
16 |
+
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
|
17 |
+
.ui-helper-clearfix { display: inline-block; }
|
18 |
+
/* required comment for clearfix to work in Opera \*/
|
19 |
+
* html .ui-helper-clearfix { height:1%; }
|
20 |
+
.ui-helper-clearfix { display:block; }
|
21 |
+
/* end clearfix */
|
22 |
+
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
23 |
+
|
24 |
+
|
25 |
+
/* Interaction Cues
|
26 |
+
----------------------------------*/
|
27 |
+
.ui-state-disabled { cursor: default !important; }
|
28 |
+
|
29 |
+
|
30 |
+
/* Icons
|
31 |
+
----------------------------------*/
|
32 |
+
|
33 |
+
/* states and images */
|
34 |
+
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
|
35 |
+
|
36 |
+
|
37 |
+
/* Misc visuals
|
38 |
+
----------------------------------*/
|
39 |
+
|
40 |
+
/* Overlays */
|
41 |
+
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
42 |
+
|
43 |
+
|
44 |
+
/*
|
45 |
+
* jQuery UI CSS Framework 1.8.16
|
46 |
+
*
|
47 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
48 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
49 |
+
* http://jquery.org/license
|
50 |
+
*
|
51 |
+
* http://docs.jquery.com/UI/Theming/API
|
52 |
+
*
|
53 |
+
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=sans-serif&fwDefault=normal&fsDefault=12px&cornerRadius=4px&bgColorHeader=ececec&bgTextureHeader=04_highlight_hard.png&bgImgOpacityHeader=75&borderColorHeader=dfdfdf&fcHeader=333333&iconColorHeader=999999&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=dfdfdf&fcContent=333333&iconColorContent=333333&bgColorDefault=ececec&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=75&borderColorDefault=dfdfdf&fcDefault=333333&iconColorDefault=333333&bgColorHover=ececec&bgTextureHover=06_inset_hard.png&bgImgOpacityHover=75&borderColorHover=ccc&fcHover=000000&iconColorHover=333333&bgColorActive=ffffff&bgTextureActive=01_flat.png&bgImgOpacityActive=65&borderColorActive=dfdfdf&fcActive=333333&iconColorActive=333333&bgColorHighlight=ffffe0&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=e6db55&fcHighlight=333333&iconColorHighlight=21759b&bgColorError=ffebe8&bgTextureError=01_flat.png&bgImgOpacityError=95&borderColorError=cc0000&fcError=cc0000&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=3px
|
54 |
+
*/
|
55 |
+
|
56 |
+
|
57 |
+
/* Component containers
|
58 |
+
----------------------------------*/
|
59 |
+
.ui-widget { font-family: sans-serif; font-size: 12px; }
|
60 |
+
.ui-widget .ui-widget { font-size: 1em; }
|
61 |
+
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: sans-serif; font-size: 1em; }
|
62 |
+
.ui-widget-content { border: 1px solid #dfdfdf; background: #ffffff; color: #333333; }
|
63 |
+
.ui-widget-header { border: 1px solid #dfdfdf; color: #333333; font-weight: bold; background-color: #f1f1f1; background-image: -ms-linear-gradient(top, #f9f9f9, #ececec); background-image: -moz-linear-gradient(top, #f9f9f9, #ececec); background-image: -o-linear-gradient(top, #f9f9f9, #ececec); background-image: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec)); background-image: -webkit-linear-gradient(top, #f9f9f9, #ececec); background-image: linear-gradient(top, #f9f9f9, #ececec); }
|
64 |
+
.ui-widget-header a { color: #333333; }
|
65 |
+
|
66 |
+
/* Interaction states
|
67 |
+
----------------------------------*/
|
68 |
+
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #dfdfdf; background-color: #f1f1f1; background-image: -ms-linear-gradient(top, #f9f9f9, #ececec); background-image: -moz-linear-gradient(top, #f9f9f9, #ececec); background-image: -o-linear-gradient(top, #f9f9f9, #ececec); background-image: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec)); background-image: -webkit-linear-gradient(top, #f9f9f9, #ececec); background-image: linear-gradient(top, #f9f9f9, #ececec); font-weight: normal; color: #333333; }
|
69 |
+
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #21759b; text-decoration: none; }
|
70 |
+
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #ccc; background-color: #ececec; background-image: -ms-linear-gradient(top, #ececec, #f9f9f9); background-image: -moz-linear-gradient(top, #ececec, #f9f9f9); background-image: -o-linear-gradient(top, #ececec, #f9f9f9); background-image: -webkit-gradient(linear, left top, left bottom, from(#ececec), to(#f9f9f9)); background-image: -webkit-linear-gradient(top, #ececec, #f9f9f9); background-image: linear-gradient(top, #ececec, #f9f9f9); font-weight: normal; color: #000000; }
|
71 |
+
.ui-state-hover a, .ui-state-hover a:hover { color: #d54e21; text-decoration: none; }
|
72 |
+
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #dfdfdf; background: #ffffff; font-weight: normal; color: #333333; }
|
73 |
+
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #333333; text-decoration: none; }
|
74 |
+
.ui-widget :active { outline: none; }
|
75 |
+
|
76 |
+
/* Interaction Cues
|
77 |
+
----------------------------------*/
|
78 |
+
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #e6db55; background: #ffffe0; color: #333333; }
|
79 |
+
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #333333; }
|
80 |
+
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cc0000; background: #ffebe8; color: #cc0000; }
|
81 |
+
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cc0000; }
|
82 |
+
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cc0000; }
|
83 |
+
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
|
84 |
+
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
85 |
+
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
86 |
+
|
87 |
+
/* Icons
|
88 |
+
----------------------------------*/
|
89 |
+
|
90 |
+
/* states and images */
|
91 |
+
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_21759b_256x240.png); }
|
92 |
+
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_21759b_256x240.png); }
|
93 |
+
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_21759b_256x240.png); }
|
94 |
+
.ui-state-default .ui-icon { background-image: url(images/ui-icons_21759b_256x240.png); }
|
95 |
+
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_d54e21_256x240.png); }
|
96 |
+
.ui-state-active .ui-icon {background-image: url(images/ui-icons_333333_256x240.png); }
|
97 |
+
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_21759b_256x240.png); }
|
98 |
+
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); }
|
99 |
+
|
100 |
+
/* positioning */
|
101 |
+
.ui-icon-carat-1-n { background-position: 0 0; }
|
102 |
+
.ui-icon-carat-1-ne { background-position: -16px 0; }
|
103 |
+
.ui-icon-carat-1-e { background-position: -32px 0; }
|
104 |
+
.ui-icon-carat-1-se { background-position: -48px 0; }
|
105 |
+
.ui-icon-carat-1-s { background-position: -64px 0; }
|
106 |
+
.ui-icon-carat-1-sw { background-position: -80px 0; }
|
107 |
+
.ui-icon-carat-1-w { background-position: -96px 0; }
|
108 |
+
.ui-icon-carat-1-nw { background-position: -112px 0; }
|
109 |
+
.ui-icon-carat-2-n-s { background-position: -128px 0; }
|
110 |
+
.ui-icon-carat-2-e-w { background-position: -144px 0; }
|
111 |
+
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
112 |
+
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
113 |
+
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
114 |
+
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
115 |
+
.ui-icon-triangle-1-s { background-position: -64px -16px; }
|
116 |
+
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
117 |
+
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
118 |
+
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
119 |
+
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
120 |
+
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
121 |
+
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
122 |
+
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
123 |
+
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
124 |
+
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
125 |
+
.ui-icon-arrow-1-s { background-position: -64px -32px; }
|
126 |
+
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
127 |
+
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
128 |
+
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
129 |
+
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
130 |
+
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
131 |
+
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
132 |
+
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
133 |
+
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
134 |
+
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
135 |
+
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
136 |
+
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
137 |
+
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
|
138 |
+
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
139 |
+
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
140 |
+
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
141 |
+
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
142 |
+
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
143 |
+
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
144 |
+
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
145 |
+
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
146 |
+
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
147 |
+
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
148 |
+
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
149 |
+
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
150 |
+
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
151 |
+
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
152 |
+
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
153 |
+
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
154 |
+
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
155 |
+
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
156 |
+
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
157 |
+
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
158 |
+
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
159 |
+
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
160 |
+
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
161 |
+
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
162 |
+
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
163 |
+
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
164 |
+
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
165 |
+
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
166 |
+
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
167 |
+
.ui-icon-extlink { background-position: -32px -80px; }
|
168 |
+
.ui-icon-newwin { background-position: -48px -80px; }
|
169 |
+
.ui-icon-refresh { background-position: -64px -80px; }
|
170 |
+
.ui-icon-shuffle { background-position: -80px -80px; }
|
171 |
+
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
172 |
+
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
173 |
+
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
174 |
+
.ui-icon-folder-open { background-position: -16px -96px; }
|
175 |
+
.ui-icon-document { background-position: -32px -96px; }
|
176 |
+
.ui-icon-document-b { background-position: -48px -96px; }
|
177 |
+
.ui-icon-note { background-position: -64px -96px; }
|
178 |
+
.ui-icon-mail-closed { background-position: -80px -96px; }
|
179 |
+
.ui-icon-mail-open { background-position: -96px -96px; }
|
180 |
+
.ui-icon-suitcase { background-position: -112px -96px; }
|
181 |
+
.ui-icon-comment { background-position: -128px -96px; }
|
182 |
+
.ui-icon-person { background-position: -144px -96px; }
|
183 |
+
.ui-icon-print { background-position: -160px -96px; }
|
184 |
+
.ui-icon-trash { background-position: -176px -96px; }
|
185 |
+
.ui-icon-locked { background-position: -192px -96px; }
|
186 |
+
.ui-icon-unlocked { background-position: -208px -96px; }
|
187 |
+
.ui-icon-bookmark { background-position: -224px -96px; }
|
188 |
+
.ui-icon-tag { background-position: -240px -96px; }
|
189 |
+
.ui-icon-home { background-position: 0 -112px; }
|
190 |
+
.ui-icon-flag { background-position: -16px -112px; }
|
191 |
+
.ui-icon-calendar { background-position: -32px -112px; }
|
192 |
+
.ui-icon-cart { background-position: -48px -112px; }
|
193 |
+
.ui-icon-pencil { background-position: -64px -112px; }
|
194 |
+
.ui-icon-clock { background-position: -80px -112px; }
|
195 |
+
.ui-icon-disk { background-position: -96px -112px; }
|
196 |
+
.ui-icon-calculator { background-position: -112px -112px; }
|
197 |
+
.ui-icon-zoomin { background-position: -128px -112px; }
|
198 |
+
.ui-icon-zoomout { background-position: -144px -112px; }
|
199 |
+
.ui-icon-search { background-position: -160px -112px; }
|
200 |
+
.ui-icon-wrench { background-position: -176px -112px; }
|
201 |
+
.ui-icon-gear { background-position: -192px -112px; }
|
202 |
+
.ui-icon-heart { background-position: -208px -112px; }
|
203 |
+
.ui-icon-star { background-position: -224px -112px; }
|
204 |
+
.ui-icon-link { background-position: -240px -112px; }
|
205 |
+
.ui-icon-cancel { background-position: 0 -128px; }
|
206 |
+
.ui-icon-plus { background-position: -16px -128px; }
|
207 |
+
.ui-icon-plusthick { background-position: -32px -128px; }
|
208 |
+
.ui-icon-minus { background-position: -48px -128px; }
|
209 |
+
.ui-icon-minusthick { background-position: -64px -128px; }
|
210 |
+
.ui-icon-close { background-position: -80px -128px; }
|
211 |
+
.ui-icon-closethick { background-position: -96px -128px; }
|
212 |
+
.ui-icon-key { background-position: -112px -128px; }
|
213 |
+
.ui-icon-lightbulb { background-position: -128px -128px; }
|
214 |
+
.ui-icon-scissors { background-position: -144px -128px; }
|
215 |
+
.ui-icon-clipboard { background-position: -160px -128px; }
|
216 |
+
.ui-icon-copy { background-position: -176px -128px; }
|
217 |
+
.ui-icon-contact { background-position: -192px -128px; }
|
218 |
+
.ui-icon-image { background-position: -208px -128px; }
|
219 |
+
.ui-icon-video { background-position: -224px -128px; }
|
220 |
+
.ui-icon-script { background-position: -240px -128px; }
|
221 |
+
.ui-icon-alert { background-position: 0 -144px; }
|
222 |
+
.ui-icon-info { background-position: -16px -144px; }
|
223 |
+
.ui-icon-notice { background-position: -32px -144px; }
|
224 |
+
.ui-icon-help { background-position: -48px -144px; }
|
225 |
+
.ui-icon-check { background-position: -64px -144px; }
|
226 |
+
.ui-icon-bullet { background-position: -80px -144px; }
|
227 |
+
.ui-icon-radio-off { background-position: -96px -144px; }
|
228 |
+
.ui-icon-radio-on { background-position: -112px -144px; }
|
229 |
+
.ui-icon-pin-w { background-position: -128px -144px; }
|
230 |
+
.ui-icon-pin-s { background-position: -144px -144px; }
|
231 |
+
.ui-icon-play { background-position: 0 -160px; }
|
232 |
+
.ui-icon-pause { background-position: -16px -160px; }
|
233 |
+
.ui-icon-seek-next { background-position: -32px -160px; }
|
234 |
+
.ui-icon-seek-prev { background-position: -48px -160px; }
|
235 |
+
.ui-icon-seek-end { background-position: -64px -160px; }
|
236 |
+
.ui-icon-seek-start { background-position: -80px -160px; }
|
237 |
+
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
|
238 |
+
.ui-icon-seek-first { background-position: -80px -160px; }
|
239 |
+
.ui-icon-stop { background-position: -96px -160px; }
|
240 |
+
.ui-icon-eject { background-position: -112px -160px; }
|
241 |
+
.ui-icon-volume-off { background-position: -128px -160px; }
|
242 |
+
.ui-icon-volume-on { background-position: -144px -160px; }
|
243 |
+
.ui-icon-power { background-position: 0 -176px; }
|
244 |
+
.ui-icon-signal-diag { background-position: -16px -176px; }
|
245 |
+
.ui-icon-signal { background-position: -32px -176px; }
|
246 |
+
.ui-icon-battery-0 { background-position: -48px -176px; }
|
247 |
+
.ui-icon-battery-1 { background-position: -64px -176px; }
|
248 |
+
.ui-icon-battery-2 { background-position: -80px -176px; }
|
249 |
+
.ui-icon-battery-3 { background-position: -96px -176px; }
|
250 |
+
.ui-icon-circle-plus { background-position: 0 -192px; }
|
251 |
+
.ui-icon-circle-minus { background-position: -16px -192px; }
|
252 |
+
.ui-icon-circle-close { background-position: -32px -192px; }
|
253 |
+
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
254 |
+
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
255 |
+
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
256 |
+
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
257 |
+
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
258 |
+
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
259 |
+
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
260 |
+
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
261 |
+
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
262 |
+
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
263 |
+
.ui-icon-circle-check { background-position: -208px -192px; }
|
264 |
+
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
265 |
+
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
266 |
+
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
267 |
+
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
268 |
+
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
269 |
+
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
270 |
+
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
271 |
+
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
272 |
+
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
273 |
+
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
274 |
+
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
275 |
+
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
276 |
+
|
277 |
+
|
278 |
+
/* Misc visuals
|
279 |
+
----------------------------------*/
|
280 |
+
|
281 |
+
/* Corner radius */
|
282 |
+
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; border-top-left-radius: 3px; }
|
283 |
+
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; border-top-right-radius: 3px; }
|
284 |
+
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; }
|
285 |
+
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; }
|
286 |
+
|
287 |
+
/* Overlays */
|
288 |
+
.ui-widget-overlay { background: #000000; opacity: .6;filter:Alpha(Opacity=60); }
|
289 |
+
.ui-widget-shadow { box-shadow: 0 0 16px rgba(0, 0, 0, 0.3); }/*
|
290 |
+
* jQuery UI Resizable 1.8.16
|
291 |
+
*
|
292 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
293 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
294 |
+
* http://jquery.org/license
|
295 |
+
*
|
296 |
+
* http://docs.jquery.com/UI/Resizable#theming
|
297 |
+
*/
|
298 |
+
.ui-resizable { position: relative;}
|
299 |
+
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
|
300 |
+
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
301 |
+
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
302 |
+
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
303 |
+
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
304 |
+
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
305 |
+
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
306 |
+
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
307 |
+
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
308 |
+
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
|
309 |
+
* jQuery UI Selectable 1.8.16
|
310 |
+
*
|
311 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
312 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
313 |
+
* http://jquery.org/license
|
314 |
+
*
|
315 |
+
* http://docs.jquery.com/UI/Selectable#theming
|
316 |
+
*/
|
317 |
+
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
318 |
+
/*
|
319 |
+
* jQuery UI Accordion 1.8.16
|
320 |
+
*
|
321 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
322 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
323 |
+
* http://jquery.org/license
|
324 |
+
*
|
325 |
+
* http://docs.jquery.com/UI/Accordion#theming
|
326 |
+
*/
|
327 |
+
/* IE/Win - Fix animation bug - #4615 */
|
328 |
+
.ui-accordion { width: 100%; }
|
329 |
+
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
|
330 |
+
.ui-accordion .ui-accordion-li-fix { display: inline; }
|
331 |
+
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
|
332 |
+
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
|
333 |
+
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
|
334 |
+
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
335 |
+
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
|
336 |
+
.ui-accordion .ui-accordion-content-active { display: block; }
|
337 |
+
/*
|
338 |
+
* jQuery UI Autocomplete 1.8.16
|
339 |
+
*
|
340 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
341 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
342 |
+
* http://jquery.org/license
|
343 |
+
*
|
344 |
+
* http://docs.jquery.com/UI/Autocomplete#theming
|
345 |
+
*/
|
346 |
+
.ui-autocomplete { position: absolute; cursor: default; }
|
347 |
+
|
348 |
+
/* workarounds */
|
349 |
+
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
350 |
+
|
351 |
+
/*
|
352 |
+
* jQuery UI Menu 1.8.16
|
353 |
+
*
|
354 |
+
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
|
355 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
356 |
+
* http://jquery.org/license
|
357 |
+
*
|
358 |
+
* http://docs.jquery.com/UI/Menu#theming
|
359 |
+
*/
|
360 |
+
.ui-menu {
|
361 |
+
list-style:none;
|
362 |
+
padding: 2px;
|
363 |
+
margin: 0;
|
364 |
+
display:block;
|
365 |
+
float: left;
|
366 |
+
}
|
367 |
+
.ui-menu .ui-menu {
|
368 |
+
margin-top: -3px;
|
369 |
+
}
|
370 |
+
.ui-menu .ui-menu-item {
|
371 |
+
margin:0;
|
372 |
+
padding: 0;
|
373 |
+
zoom: 1;
|
374 |
+
float: left;
|
375 |
+
clear: left;
|
376 |
+
width: 100%;
|
377 |
+
}
|
378 |
+
.ui-menu .ui-menu-item a {
|
379 |
+
text-decoration:none;
|
380 |
+
display:block;
|
381 |
+
padding:.2em .4em;
|
382 |
+
line-height:1.5;
|
383 |
+
zoom:1;
|
384 |
+
}
|
385 |
+
.ui-menu .ui-menu-item a.ui-state-hover,
|
386 |
+
.ui-menu .ui-menu-item a.ui-state-active {
|
387 |
+
font-weight: normal;
|
388 |
+
margin: -1px;
|
389 |
+
}
|
390 |
+
/*
|
391 |
+
* jQuery UI Button 1.8.16
|
392 |
+
*
|
393 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
394 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
395 |
+
* http://jquery.org/license
|
396 |
+
*
|
397 |
+
* http://docs.jquery.com/UI/Button#theming
|
398 |
+
*/
|
399 |
+
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
|
400 |
+
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
|
401 |
+
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
|
402 |
+
.ui-button-icons-only { width: 3.4em; }
|
403 |
+
button.ui-button-icons-only { width: 3.7em; }
|
404 |
+
|
405 |
+
/*button text element */
|
406 |
+
.ui-button .ui-button-text { display: block; line-height: 1.4; }
|
407 |
+
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
|
408 |
+
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
|
409 |
+
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
|
410 |
+
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
|
411 |
+
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
|
412 |
+
/* no icon support for input elements, provide padding by default */
|
413 |
+
input.ui-button { padding: .4em 1em; }
|
414 |
+
|
415 |
+
/*button icon element(s) */
|
416 |
+
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
|
417 |
+
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
|
418 |
+
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
|
419 |
+
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
420 |
+
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
421 |
+
|
422 |
+
/*button sets*/
|
423 |
+
.ui-buttonset { margin-right: 7px; }
|
424 |
+
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
|
425 |
+
|
426 |
+
/* workarounds */
|
427 |
+
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
428 |
+
/*
|
429 |
+
* jQuery UI Dialog 1.8.16
|
430 |
+
*
|
431 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
432 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
433 |
+
* http://jquery.org/license
|
434 |
+
*
|
435 |
+
* http://docs.jquery.com/UI/Dialog#theming
|
436 |
+
*/
|
437 |
+
.ui-dialog { position: fixed; padding: .2em; width: 300px; overflow: hidden; }
|
438 |
+
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;color: #333!important; }
|
439 |
+
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
|
440 |
+
.ui-dialog .ui-dialog-titlebar-close { position: absolute!important; right: .3em!important; top: 50%!important; width: 19px!important; margin: -10px 0 0 0!important; padding: 1px!important; height: 18px!important; background:none!important; }
|
441 |
+
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
442 |
+
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0!important; }
|
443 |
+
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
444 |
+
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
445 |
+
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
|
446 |
+
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
|
447 |
+
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
448 |
+
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
449 |
+
/*
|
450 |
+
* jQuery UI Slider 1.8.16
|
451 |
+
*
|
452 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
453 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
454 |
+
* http://jquery.org/license
|
455 |
+
*
|
456 |
+
* http://docs.jquery.com/UI/Slider#theming
|
457 |
+
*/
|
458 |
+
.ui-slider { position: relative; text-align: left; }
|
459 |
+
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
460 |
+
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
|
461 |
+
|
462 |
+
.ui-slider-horizontal { height: .8em; }
|
463 |
+
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
464 |
+
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
465 |
+
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
466 |
+
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
467 |
+
|
468 |
+
.ui-slider-vertical { width: .8em; height: 100px; }
|
469 |
+
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
470 |
+
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
471 |
+
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
472 |
+
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
|
473 |
+
* jQuery UI Tabs 1.8.16
|
474 |
+
*
|
475 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
476 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
477 |
+
* http://jquery.org/license
|
478 |
+
*
|
479 |
+
* http://docs.jquery.com/UI/Tabs#theming
|
480 |
+
*/
|
481 |
+
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
482 |
+
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
|
483 |
+
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
|
484 |
+
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
|
485 |
+
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
|
486 |
+
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
|
487 |
+
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
488 |
+
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
489 |
+
.ui-tabs .ui-tabs-hide { display: none !important; }
|
490 |
+
/*
|
491 |
+
* jQuery UI Datepicker 1.8.16
|
492 |
+
*
|
493 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
494 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
495 |
+
* http://jquery.org/license
|
496 |
+
*
|
497 |
+
* http://docs.jquery.com/UI/Datepicker#theming
|
498 |
+
*/
|
499 |
+
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
500 |
+
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
501 |
+
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
502 |
+
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
503 |
+
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
504 |
+
.ui-datepicker .ui-datepicker-next { right:2px; }
|
505 |
+
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
506 |
+
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
507 |
+
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
508 |
+
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
509 |
+
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
510 |
+
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
511 |
+
.ui-datepicker select.ui-datepicker-month,
|
512 |
+
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
513 |
+
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
514 |
+
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
515 |
+
.ui-datepicker td { border: 0; padding: 1px; }
|
516 |
+
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
517 |
+
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
518 |
+
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
519 |
+
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
520 |
+
|
521 |
+
/* with multiple calendars */
|
522 |
+
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
523 |
+
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
524 |
+
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
525 |
+
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
526 |
+
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
527 |
+
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
528 |
+
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
529 |
+
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
530 |
+
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
531 |
+
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
532 |
+
|
533 |
+
/* RTL support */
|
534 |
+
.ui-datepicker-rtl { direction: rtl; }
|
535 |
+
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
536 |
+
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
537 |
+
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
538 |
+
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
539 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
540 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
541 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
542 |
+
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
543 |
+
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
544 |
+
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
545 |
+
|
546 |
+
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
547 |
+
.ui-datepicker-cover {
|
548 |
+
display: none; /*sorry for IE5*/
|
549 |
+
display/**/: block; /*sorry for IE5*/
|
550 |
+
position: absolute; /*must have*/
|
551 |
+
z-index: -1; /*must have*/
|
552 |
+
filter: mask(); /*must have*/
|
553 |
+
top: -4px; /*must have*/
|
554 |
+
left: -4px; /*must have*/
|
555 |
+
width: 200px; /*must have*/
|
556 |
+
height: 200px; /*must have*/
|
557 |
+
}/*
|
558 |
+
* jQuery UI Progressbar 1.8.16
|
559 |
+
*
|
560 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
561 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
562 |
+
* http://jquery.org/license
|
563 |
+
*
|
564 |
+
* http://docs.jquery.com/UI/Progressbar#theming
|
565 |
+
*/
|
566 |
+
.ui-progressbar { height:2em; text-align: left; }
|
567 |
+
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
|
568 |
+
.ui-progressbar .ui-widget-header {
|
569 |
+
background-color: #83B4D8;
|
570 |
+
background-image: linear-gradient(bottom, rgb(114,167,207) 0%, rgb(144,197,238) 100%);
|
571 |
+
background-image: -o-linear-gradient(bottom, rgb(114,167,207) 0%, rgb(144,197,238) 100%);
|
572 |
+
background-image: -moz-linear-gradient(bottom, rgb(114,167,207) 0%, rgb(144,197,238) 100%);
|
573 |
+
background-image: -webkit-linear-gradient(bottom, rgb(114,167,207) 0%, rgb(144,197,238) 100%);
|
574 |
+
background-image: -ms-linear-gradient(bottom, rgb(114,167,207) 0%, rgb(144,197,238) 100%);
|
575 |
+
}
|
576 |
+
.wp-tabs, .wp-tabs .ui-tabs-nav, .wp-tabs .ui-state-default {
|
577 |
+
background: none;
|
578 |
+
border: 0px;
|
579 |
+
}
|
580 |
+
|
581 |
+
.wp-tabs .ui-tabs-nav {
|
582 |
+
padding: 0px;
|
583 |
+
}
|
584 |
+
|
585 |
+
.wp-tabs .ui-tabs-selected, .wp-tabs .ui-tabs-panel {
|
586 |
+
background-color: #fff;
|
587 |
+
border-color: #DFDFDF;
|
588 |
+
border-style: solid;
|
589 |
+
border-width: 1px;
|
590 |
+
}
|
591 |
+
|
css/eventorganiser-admin-style.css
ADDED
@@ -0,0 +1,364 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Venue map on event edit page */
|
2 |
+
#venuemap{height:300px; width:100%;float:right;margin: 10px 0 10px -300px}
|
3 |
+
|
4 |
+
/*Hide post date filter*/
|
5 |
+
.tablenav.top .alignleft.actions select[name="m"]{display: none; }
|
6 |
+
|
7 |
+
#eventorganiser_event_detail tr.eo-add-new-venue{
|
8 |
+
display: none;
|
9 |
+
}
|
10 |
+
|
11 |
+
#eventorganiser_event_detail tr .eo-label{
|
12 |
+
width:190px;
|
13 |
+
}
|
14 |
+
/* Venue page address form spacing */
|
15 |
+
#venue_address table tr{line-height: 4em;}
|
16 |
+
|
17 |
+
/* Venue map on venue page*/
|
18 |
+
#venue_address.postbox #venuemap{height: 300px;margin: 0 0 0 -60%;width: 60%;}
|
19 |
+
|
20 |
+
/* Venue address table in metabox*/
|
21 |
+
#eo_venue_form table.address {float:left;text-align:left;margin: 10px;}
|
22 |
+
|
23 |
+
/* Venue address metabox fix */
|
24 |
+
#eo_venue_form #venue_address .inside{padding:0;margin:0;}
|
25 |
+
|
26 |
+
/* Calendar View*/
|
27 |
+
.event.past-event{opacity:0.5;}
|
28 |
+
form.eo_cal .ui-autocomplete-input{width:220px;}
|
29 |
+
/* Table on event details calendar view*/
|
30 |
+
.eo-cal-meta .form-table th {width:50px;}
|
31 |
+
/*Drop down filters*/
|
32 |
+
#eo_admin_calendar select { min-width:180px; width:auto}
|
33 |
+
|
34 |
+
#eo-dialog-tabs, #events-meta {border: none;padding: 0}
|
35 |
+
|
36 |
+
/* Selectmenu
|
37 |
+
----------------------------------*/
|
38 |
+
.ui-selectmenu { display: block; display: inline-block; position: relative; height: 2.2em; vertical-align: middle; text-decoration: none; overflow: hidden; zoom: 1; }
|
39 |
+
.ui-selectmenu-icon { position:absolute; right:6px; margin-top:-8px; top: 50%; }
|
40 |
+
.ui-selectmenu-menu { padding:0; margin:0; position:absolute; top: 0; display: none; z-index: 1005;} /* z-index: 1005 to make selectmenu work with dialog */
|
41 |
+
.ui-selectmenu-menu ul { padding:0; margin:0; list-style:none; position: relative; overflow: auto; overflow-y: auto ; overflow-x: hidden;}
|
42 |
+
.ui-selectmenu-open { display: block; }
|
43 |
+
.ui-selectmenu-menu-popup { margin-top: -1px; }
|
44 |
+
.ui-selectmenu-menu li { padding:0; margin:0; display: block; border-top: 1px dotted transparent; border-bottom: 1px dotted transparent; border-right-width: 0 !important; border-left-width: 0 !important; font-weight: normal !important; }
|
45 |
+
.ui-selectmenu-menu li a,.ui-selectmenu-status { line-height: 1.4em; display: block; padding: .405em 2.1em .405em 1em; outline:none; text-decoration:none; }
|
46 |
+
.ui-selectmenu-menu li.ui-state-disabled a, .ui-state-disabled { cursor: default; }
|
47 |
+
.ui-selectmenu-menu li.ui-selectmenu-hasIcon a,
|
48 |
+
.ui-selectmenu-hasIcon .ui-selectmenu-status { padding-left: 20px; position: relative; margin-left: 5px; }
|
49 |
+
.ui-selectmenu-menu li .ui-icon, .ui-selectmenu-status .ui-icon { position: absolute; top: 1em; margin-top: -8px; left: 0; }
|
50 |
+
.ui-selectmenu-status { line-height: 1.4em; }
|
51 |
+
.ui-selectmenu-menu li span,.ui-selectmenu-status span { display:block; margin-bottom: .2em; }
|
52 |
+
.ui-selectmenu-menu li .ui-selectmenu-item-header { font-weight: bold; }
|
53 |
+
.ui-selectmenu-menu li .ui-selectmenu-item-footer { opacity: .8; }
|
54 |
+
/* for optgroups */
|
55 |
+
.ui-selectmenu-menu .ui-selectmenu-group { font-size: 1em; }
|
56 |
+
.ui-selectmenu-menu .ui-selectmenu-group .ui-selectmenu-group-label { line-height: 1.4em; display:block; padding: .6em .5em 0; font-weight: bold; }
|
57 |
+
.ui-selectmenu-menu .ui-selectmenu-group ul { margin: 0; padding: 0; }
|
58 |
+
/* IE6 workaround (dotted transparent borders) */
|
59 |
+
* html .ui-selectmenu-menu li { border-color: pink; filter:chroma(color=pink); width:100%; }
|
60 |
+
* html .ui-selectmenu-menu li a { position: relative }
|
61 |
+
/* IE7 workaround (opacity disabled) */
|
62 |
+
*+html .ui-state-disabled, *+html .ui-state-disabled a { color: silver; }
|
63 |
+
|
64 |
+
/* Autocomplete / Combobox
|
65 |
+
----------------------------------*/
|
66 |
+
.ui-autocomplete .ui-menu-item{border-top: 1px solid #cbc7bd;}
|
67 |
+
.ui-autocomplete .ui-menu-item:first-child {border-top: none;}
|
68 |
+
.ui-combobox {position: relative;display: inline-block;margin-right:30px;}
|
69 |
+
.ui-combobox-toggle {top: 0;bottom: 0;margin-left: -1px;padding: 0;/* adjust styles for IE 6/7 */*height: 1.7em;*top: 0.1em;}
|
70 |
+
.ui-combobox-input {margin: 0;padding: 0.3em;}
|
71 |
+
.eo-venue-combobox-buttons{position: absolute;width:4.5em;}
|
72 |
+
|
73 |
+
#eo_occurrence_datepicker .ui-datepicker .ui-state-default a,
|
74 |
+
#eo_occurrence_datepicker .ui-datepicker .ui-state-active a{color:#FFF;
|
75 |
+
background: #7eacbf; /* Old browsers */
|
76 |
+
background: -moz-linear-gradient(top, #7eacbf 0%, #21759b 100%); /* FF3.6+ */
|
77 |
+
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#7eacbf), color-stop(100%,#21759b)); /* Chrome,Safari4+ */
|
78 |
+
background: -webkit-linear-gradient(top, #7eacbf 0%,#21759b 100%); /* Chrome10+,Safari5.1+ */
|
79 |
+
background: -o-linear-gradient(top, #7eacbf 0%,#21759b 100%); /* Opera 11.10+ */
|
80 |
+
background: -ms-linear-gradient(top, #7eacbf 0%,#21759b 100%); /* IE10+ */
|
81 |
+
background: linear-gradient(to bottom, #7eacbf 0%,#21759b 100%); /* W3C */
|
82 |
+
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#7eacbf', endColorstr='#21759b',GradientType=0 ); /* IE6-9 */
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
/*
|
87 |
+
* Timepicker stylesheet
|
88 |
+
* Highly inspired from datepicker
|
89 |
+
* FG - Nov 2010 - Web3R
|
90 |
+
*/
|
91 |
+
.ui-timepicker-inline{display:inline}
|
92 |
+
#ui-timepicker-div{background-color:#fff;padding:.2em}
|
93 |
+
.ui-timepicker-table{display:inline-table;width:0}
|
94 |
+
.ui-timepicker-table table{border-collapse:collapse;margin:.15em 0 0}
|
95 |
+
.ui-timepicker-hours,.ui-timepicker-minutes{padding:.2em}
|
96 |
+
.ui-timepicker-table .ui-timepicker-title{line-height:1.8em;text-align:center}
|
97 |
+
.ui-timepicker-table td span{display:block;width:1.2em;text-align:right;text-decoration:none;padding:.2em .3em .2em .5em}
|
98 |
+
.ui-timepicker-table td a{display:block;width:1.2em;cursor:pointer;text-align:right;text-decoration:none;padding:.2em .3em .2em .5em}
|
99 |
+
.ui-timepicker .ui-timepicker-buttonpane{background-image:none;border-left:0;border-right:0;border-bottom:0;margin:.7em 0 0;padding:0 .2em}
|
100 |
+
.ui-timepicker .ui-timepicker-buttonpane button{cursor:pointer;width:auto;overflow:visible;margin:.5em .2em .4em;padding:.2em .6em .3em}
|
101 |
+
.ui-timepicker .ui-timepicker-close{float:right}
|
102 |
+
.ui-timepicker-cover{display:block;position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}
|
103 |
+
.ui-timepicker-table td,.ui-timepicker-table th.periods{width:2.2em;padding:.1em}
|
104 |
+
.ui-timepicker .ui-timepicker-now,.ui-timepicker .ui-timepicker-deselect{float:left}
|
105 |
+
|
106 |
+
/* Debugger */
|
107 |
+
.eo-debug-alert{font-weight:bold;color:orange;}
|
108 |
+
.eo-debug-warning{font-weight:bold;color:red;}
|
109 |
+
.eo-debug-ok{font-weight:bold;color:green;}
|
110 |
+
|
111 |
+
/*! qTip2 - Pretty powerful tooltips - v2.0.0 - 2012-08-14
|
112 |
+
* http://craigsworks.com/projects/qtip2/
|
113 |
+
* Copyright (c) 2012 Craig Michael Thompson; Licensed MIT, GPL */
|
114 |
+
/* Core qTip styles */
|
115 |
+
.ui-tooltip, .qtip{position:absolute; left:-28000px; top:-28000px; display:none; max-width:280px; min-width:50px; font-size:10.5px; line-height:12px; border-width:1px; border-style:solid}
|
116 |
+
|
117 |
+
/*!
|
118 |
+
* qTip2 - Pretty powerful tooltips - v2.0.1-4-g
|
119 |
+
* http://qtip2.com
|
120 |
+
*
|
121 |
+
* Copyright (c) 2013 Craig Michael Thompson
|
122 |
+
* Released under the MIT, GPL licenses
|
123 |
+
* http://jquery.org/license
|
124 |
+
*
|
125 |
+
* Date: Fri Jan 4 2013 04:05 GMT+0000
|
126 |
+
* Plugins: svg ajax tips modal viewport imagemap ie6
|
127 |
+
* Styles: basic css3
|
128 |
+
*/
|
129 |
+
a.eo-inline-help img {
|
130 |
+
width: 16px;
|
131 |
+
height: 16px;
|
132 |
+
display: inline-block;
|
133 |
+
text-decoration: none;
|
134 |
+
margin-left:3px;
|
135 |
+
margin-bottom:-3px;
|
136 |
+
}
|
137 |
+
|
138 |
+
/* Core qTip styles */
|
139 |
+
.qtip, .qtip{
|
140 |
+
position: absolute;
|
141 |
+
left: -28000px;
|
142 |
+
top: -28000px;
|
143 |
+
display: none;
|
144 |
+
|
145 |
+
max-width: 280px;
|
146 |
+
min-width: 50px;
|
147 |
+
|
148 |
+
font-size: 10.5px;
|
149 |
+
line-height: 12px;
|
150 |
+
|
151 |
+
direction: ltr;
|
152 |
+
}
|
153 |
+
|
154 |
+
.qtip-content{
|
155 |
+
position: relative;
|
156 |
+
padding: 5px 9px;
|
157 |
+
overflow: hidden;
|
158 |
+
font-size: 11px;
|
159 |
+
text-align: left;
|
160 |
+
word-wrap: break-word;
|
161 |
+
background-color: rgb(247, 247, 247);
|
162 |
+
}
|
163 |
+
|
164 |
+
.qtip-titlebar{
|
165 |
+
position: relative;
|
166 |
+
padding: 5px 35px 5px 10px;
|
167 |
+
overflow: hidden;
|
168 |
+
|
169 |
+
border-width: 0 0 1px;
|
170 |
+
font-weight: bold;
|
171 |
+
font-weight: bold;
|
172 |
+
font-size: 14px;
|
173 |
+
color: #21759B;
|
174 |
+
}
|
175 |
+
|
176 |
+
.qtip-titlebar + .qtip-content{ border-top-width: 0 !important; }
|
177 |
+
|
178 |
+
/* Default close button class */
|
179 |
+
.qtip-close{
|
180 |
+
position: absolute;
|
181 |
+
right: -9px; top: -9px;
|
182 |
+
|
183 |
+
cursor: pointer;
|
184 |
+
outline: medium none;
|
185 |
+
|
186 |
+
border-width: 1px;
|
187 |
+
border-style: solid;
|
188 |
+
border-color: transparent;
|
189 |
+
}
|
190 |
+
|
191 |
+
.qtip-titlebar .qtip-close{
|
192 |
+
right: 4px; top: 50%;
|
193 |
+
margin-top: -9px;
|
194 |
+
}
|
195 |
+
|
196 |
+
* html .qtip-titlebar .qtip-close{ top: 16px; } /* IE fix */
|
197 |
+
|
198 |
+
.qtip-titlebar .ui-icon,
|
199 |
+
.qtip-icon .ui-icon{
|
200 |
+
display: block;
|
201 |
+
text-indent: -1000em;
|
202 |
+
direction: ltr;
|
203 |
+
vertical-align: middle;
|
204 |
+
}
|
205 |
+
|
206 |
+
.qtip-icon, .qtip-icon .ui-icon{
|
207 |
+
-moz-border-radius: 3px;
|
208 |
+
-webkit-border-radius: 3px;
|
209 |
+
border-radius: 3px;
|
210 |
+
text-decoration: none;
|
211 |
+
}
|
212 |
+
|
213 |
+
.qtip-icon .ui-icon{
|
214 |
+
width: 18px;
|
215 |
+
height: 14px;
|
216 |
+
|
217 |
+
text-align: center;
|
218 |
+
text-indent: 0;
|
219 |
+
font: normal bold 10px/13px Tahoma,sans-serif;
|
220 |
+
|
221 |
+
color: inherit;
|
222 |
+
background: transparent none no-repeat -100em -100em;
|
223 |
+
}
|
224 |
+
|
225 |
+
|
226 |
+
/* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */
|
227 |
+
.qtip-focus{}
|
228 |
+
|
229 |
+
/* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */
|
230 |
+
.qtip-hover{}
|
231 |
+
|
232 |
+
|
233 |
+
|
234 |
+
/* Default tooltip style */
|
235 |
+
.qtip-default{
|
236 |
+
border-width: 1px;
|
237 |
+
border-style: solid;
|
238 |
+
border-color: #F1D031;
|
239 |
+
|
240 |
+
background-color: #FFFFA3;
|
241 |
+
color: #555;
|
242 |
+
}
|
243 |
+
|
244 |
+
.qtip-default .qtip-titlebar{
|
245 |
+
background-color: #FFEF93;
|
246 |
+
}
|
247 |
+
|
248 |
+
.qtip-default .qtip-icon{
|
249 |
+
border-color: #CCC;
|
250 |
+
background: #F1F1F1;
|
251 |
+
color: #777;
|
252 |
+
}
|
253 |
+
|
254 |
+
.qtip-default .qtip-titlebar .qtip-close{
|
255 |
+
border-color: #AAA;
|
256 |
+
color: #111;
|
257 |
+
}
|
258 |
+
|
259 |
+
|
260 |
+
/*! Light tooltip style */
|
261 |
+
.qtip-light{
|
262 |
+
background-color: white;
|
263 |
+
border-color: #E2E2E2;
|
264 |
+
color: #454545;
|
265 |
+
}
|
266 |
+
|
267 |
+
.qtip-light .qtip-titlebar{
|
268 |
+
background-color: rgb(247, 247, 247);
|
269 |
+
}
|
270 |
+
|
271 |
+
|
272 |
+
/*! Dark tooltip style */
|
273 |
+
.qtip-dark{
|
274 |
+
background-color: #505050;
|
275 |
+
border-color: #303030;
|
276 |
+
color: #f3f3f3;
|
277 |
+
}
|
278 |
+
|
279 |
+
.qtip-dark .qtip-titlebar{
|
280 |
+
background-color: #404040;
|
281 |
+
}
|
282 |
+
|
283 |
+
.qtip-dark .qtip-icon{
|
284 |
+
border-color: #444;
|
285 |
+
}
|
286 |
+
|
287 |
+
.qtip-dark .qtip-titlebar .ui-state-hover{
|
288 |
+
border-color: #303030;
|
289 |
+
}
|
290 |
+
|
291 |
+
|
292 |
+
/*! Cream tooltip style */
|
293 |
+
.qtip-cream{
|
294 |
+
background-color: #FBF7AA;
|
295 |
+
border-color: #F9E98E;
|
296 |
+
color: #A27D35;
|
297 |
+
}
|
298 |
+
|
299 |
+
.qtip-cream .qtip-titlebar{
|
300 |
+
background-color: #F0DE7D;
|
301 |
+
}
|
302 |
+
|
303 |
+
.qtip-cream .qtip-close .qtip-icon{
|
304 |
+
background-position: -82px 0;
|
305 |
+
}
|
306 |
+
|
307 |
+
|
308 |
+
/* Fluid class for determining actual width in IE */
|
309 |
+
.ui-tooltip-fluid{display:block; visibility:hidden; position:static !important; float:left !important}
|
310 |
+
.ui-tooltip-content{position:relative; padding:5px 9px; overflow:hidden; text-align:left; word-wrap:break-word}
|
311 |
+
.ui-tooltip-titlebar{position:relative; min-height:14px; padding:5px 35px 5px 10px; overflow:hidden; border-width:0 0 1px; font-weight:bold}
|
312 |
+
.ui-tooltip-titlebar+.ui-tooltip-content{border-top-width:0 !important}
|
313 |
+
|
314 |
+
/* Default close button class */
|
315 |
+
.ui-tooltip-titlebar .ui-state-default{position:absolute; right:4px; top:50%; margin-top:-9px; cursor:pointer; outline:medium none; border-width:1px; border-style:solid}
|
316 |
+
* html .ui-tooltip-titlebar .ui-state-default{top:16px}/* IE fix */
|
317 |
+
.ui-tooltip-titlebar .ui-icon,
|
318 |
+
.ui-tooltip-icon .ui-icon{display:block; text-indent:-1000em; direction:ltr}
|
319 |
+
.ui-tooltip-icon, .ui-tooltip-icon .ui-icon{-moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; text-decoration:none}
|
320 |
+
.ui-tooltip-icon .ui-icon{width:18px; height:14px; text-align:center; text-indent:0; font:normal bold 10px/13px Tahoma,sans-serif; color:inherit; background:transparent none no-repeat -100em -100em}
|
321 |
+
|
322 |
+
/* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */
|
323 |
+
.ui-tooltip-focus{}
|
324 |
+
|
325 |
+
/* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */
|
326 |
+
.ui-tooltip-hover{}
|
327 |
+
|
328 |
+
/* Add shadows to your tooltips in:FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+*/
|
329 |
+
.ui-tooltip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15); -moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15); box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15)}
|
330 |
+
|
331 |
+
/* Add rounded corners to your tooltips in:FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+*/
|
332 |
+
.ui-tooltip-rounded,
|
333 |
+
.ui-tooltip-tipsy,
|
334 |
+
.ui-tooltip-bootstrap{-moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px}
|
335 |
+
|
336 |
+
/* jQuery TOOLS Tooltip style */
|
337 |
+
.ui-tooltip-jtools{background:#232323; background:rgba(0,0,0,0.7); background-image:-webkit-gradient(linear,left top,left bottom,from(#717171),to(#232323)); background-image:-moz-linear-gradient(top,#717171,#232323); background-image:-webkit-linear-gradient(top,#717171,#232323); background-image:-ms-linear-gradient(top,#717171,#232323); background-image:-o-linear-gradient(top,#717171,#232323); border:2px solid #ddd; border:2px solid rgba(241,241,241,1); -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; -webkit-box-shadow:0 0 12px #333; -moz-box-shadow:0 0 12px #333; box-shadow:0 0 12px #333}
|
338 |
+
|
339 |
+
/* IE Specific */
|
340 |
+
.ui-tooltip-jtools .ui-tooltip-titlebar{background-color:transparent; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)"}
|
341 |
+
.ui-tooltip-jtools .ui-tooltip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)"}
|
342 |
+
|
343 |
+
.ui-tooltip-jtools .ui-tooltip-titlebar,
|
344 |
+
.ui-tooltip-jtools .ui-tooltip-content{background:transparent; color:white; border:0 dashed transparent}
|
345 |
+
.ui-tooltip-jtools .ui-tooltip-icon{border-color:#555}
|
346 |
+
.ui-tooltip-jtools .ui-tooltip-titlebar .ui-state-hover{border-color:#333}
|
347 |
+
|
348 |
+
/* Tipped style */
|
349 |
+
.ui-tooltip-tipped{border:3px solid #959FA9; -moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; background-color:#F9F9F9; color:#454545; font-weight:normal; font-family:serif}
|
350 |
+
.ui-tooltip-tipped .ui-tooltip-titlebar{border-bottom-width:0; color:white; background:#3A79B8; background-image:-webkit-gradient(linear,left top,left bottom,from(#3A79B8),to(#2E629D)); background-image:-webkit-linear-gradient(top,#3A79B8,#2E629D); background-image:-moz-linear-gradient(top,#3A79B8,#2E629D); background-image:-ms-linear-gradient(top,#3A79B8,#2E629D); background-image:-o-linear-gradient(top,#3A79B8,#2E629D); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)"}
|
351 |
+
.ui-tooltip-tipped .ui-tooltip-icon{border:2px solid #285589; background:#285589}
|
352 |
+
.ui-tooltip-tipped .ui-tooltip-icon .ui-icon{background-color:#FBFBFB; color:#555}
|
353 |
+
|
354 |
+
/* IE9 fix - removes all filters */
|
355 |
+
.ui-tooltip:not(.ie9haxors) div.ui-tooltip-content,
|
356 |
+
.ui-tooltip:not(.ie9haxors) div.ui-tooltip-titlebar{filter:none; -ms-filter:none}
|
357 |
+
|
358 |
+
/* Tips plugin */
|
359 |
+
.ui-tooltip .ui-tooltip-tip{margin:0 auto; overflow:hidden; z-index:10}
|
360 |
+
.ui-tooltip .ui-tooltip-tip,
|
361 |
+
.ui-tooltip .ui-tooltip-tip *{position:absolute; line-height:0.1px !important; font-size:0.1px !important; color:#123456; background:transparent; border:0 dashed transparent}
|
362 |
+
.ui-tooltip .ui-tooltip-tip canvas{top:0; left:0}
|
363 |
+
|
364 |
+
|
css/eventorganiser-front-end.css
ADDED
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.fc-button .ui-button-text{line-height: 8px!important;}
|
2 |
+
.ui-button-text-only .ui-button-text {padding: .4em .8em;}
|
3 |
+
.ui-button { margin-left: -1px; }
|
4 |
+
.ui-button-icon-only .ui-button-text { padding: 0.14em; }
|
5 |
+
.ui-autocomplete-input { margin: 0; padding: 0.3em 0 0.3em 0.45em; }
|
6 |
+
|
7 |
+
/*Venue Map*/
|
8 |
+
.eo-venue-map{z-index:1000;}
|
9 |
+
|
10 |
+
/* Agenda CSS */
|
11 |
+
.eo-agenda-widget ul{list-style:none; margin:0}
|
12 |
+
.eo-agenda-widget .agenda-nav{overflow:hidden}
|
13 |
+
.eo-agenda-widget .next,
|
14 |
+
.eo-agenda-widget .prev{float:right; padding:5px 0px; background:#ececec; margin:3px}
|
15 |
+
.eo-agenda-widget ul.dates{border-bottom:1px solid #ececec; font-weight:bold}
|
16 |
+
.eo-agenda-widget ul.a-date{margin:0}
|
17 |
+
.eo-agenda-widget li.date{border-top:1px solid #ececec; padding:10px 0px}
|
18 |
+
.eo-agenda-widget li.event{padding:5px 0px 5px 10px; ; font-weight:normal; background:#ececec; border-radius:3px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; cursor:pointer; opacity:0.75; color:#333; margin:1px 0px; position:relative}
|
19 |
+
.eo-agenda-widget li.event:hover{opacity:1; background:#ececec}
|
20 |
+
.eo-agenda-widget li.event .cat{padding:10px 3px; background:none; margin-right:5px; height:100%; position:absolute; top:0; left:0}
|
21 |
+
.eo-agenda-widget li.event .meta{font-size:0.9em}
|
22 |
+
.eo-agenda-widget li.event a.eo-agenda-event-permalink{display:block;text-decoration:none;color:#333;}
|
23 |
+
.eo-agenda-widget li.event a.eo-agenda-event-permalink:hover{text-decoration:none;color:#333;}
|
24 |
+
/*
|
25 |
+
* jQuery UI CSS Framework 1.8.16
|
26 |
+
*
|
27 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
28 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
29 |
+
* http://jquery.org/license
|
30 |
+
* Includes: jquery.ui.core.css, jquery.ui.autocomplete.css, jquery.ui.menu.css, jquery.ui.button.css
|
31 |
+
* @see http://jqueryui.com/themeroller/?ffDefault=sans-serif&fwDefault=normal&fsDefault=12px&cornerRadius=4px&bgColorHeader=ececec&bgTextureHeader=04_highlight_hard.png&bgImgOpacityHeader=75&borderColorHeader=dfdfdf&fcHeader=333333&iconColorHeader=999999&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=dfdfdf&fcContent=333333&iconColorContent=333333&bgColorDefault=ececec&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=75&borderColorDefault=dfdfdf&fcDefault=333333&iconColorDefault=333333&bgColorHover=ececec&bgTextureHover=06_inset_hard.png&bgImgOpacityHover=75&borderColorHover=ccc&fcHover=000000&iconColorHover=333333&bgColorActive=ffffff&bgTextureActive=01_flat.png&bgImgOpacityActive=65&borderColorActive=dfdfdf&fcActive=333333&iconColorActive=333333&bgColorHighlight=ffffe0&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=e6db55&fcHighlight=333333&iconColorHighlight=21759b&bgColorError=ffebe8&bgTextureError=01_flat.png&bgImgOpacityError=95&borderColorError=cc0000&fcError=cc0000&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=3px
|
32 |
+
*/
|
33 |
+
|
34 |
+
/* Layout helpers
|
35 |
+
----------------------------------*/
|
36 |
+
.ui-helper-hidden { display: none; }
|
37 |
+
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
|
38 |
+
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
|
39 |
+
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
|
40 |
+
.ui-helper-clearfix { display: inline-block; }
|
41 |
+
/* required comment for clearfix to work in Opera \*/
|
42 |
+
* html .ui-helper-clearfix { height:1%; }
|
43 |
+
.ui-helper-clearfix { display:block; }
|
44 |
+
/* end clearfix */
|
45 |
+
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
46 |
+
|
47 |
+
|
48 |
+
/* Interaction Cues
|
49 |
+
----------------------------------*/
|
50 |
+
.ui-state-disabled { cursor: default !important; }
|
51 |
+
|
52 |
+
|
53 |
+
/* Icons
|
54 |
+
----------------------------------*/
|
55 |
+
|
56 |
+
/* states and images */
|
57 |
+
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
|
58 |
+
|
59 |
+
|
60 |
+
/* Misc visuals
|
61 |
+
----------------------------------*/
|
62 |
+
|
63 |
+
/* Overlays */
|
64 |
+
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
65 |
+
.ui-autocomplete {position: absolute;top: 0;left: 0;cursor: default;}
|
66 |
+
|
67 |
+
/* workarounds */
|
68 |
+
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
69 |
+
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
70 |
+
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
71 |
+
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
72 |
+
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
73 |
+
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
74 |
+
.ui-datepicker .ui-datepicker-next { right:2px; }
|
75 |
+
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
76 |
+
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
77 |
+
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
78 |
+
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
79 |
+
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
80 |
+
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
81 |
+
.ui-datepicker select.ui-datepicker-month,
|
82 |
+
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
83 |
+
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
84 |
+
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
85 |
+
.ui-datepicker td { border: 0; padding: 1px; }
|
86 |
+
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
87 |
+
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
88 |
+
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
89 |
+
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
90 |
+
|
91 |
+
/* with multiple calendars */
|
92 |
+
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
93 |
+
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
94 |
+
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
95 |
+
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
96 |
+
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
97 |
+
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
98 |
+
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
99 |
+
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
100 |
+
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
101 |
+
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
102 |
+
|
103 |
+
/* RTL support */
|
104 |
+
.ui-datepicker-rtl { direction: rtl; }
|
105 |
+
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
106 |
+
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
107 |
+
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
108 |
+
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
109 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
110 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
111 |
+
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
112 |
+
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
113 |
+
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
114 |
+
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
115 |
+
|
116 |
+
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
117 |
+
.ui-datepicker-cover {
|
118 |
+
position: absolute; /*must have*/
|
119 |
+
z-index: -1; /*must have*/
|
120 |
+
filter: mask(); /*must have*/
|
121 |
+
top: -4px; /*must have*/
|
122 |
+
left: -4px; /*must have*/
|
123 |
+
width: 200px; /*must have*/
|
124 |
+
height: 200px; /*must have*/
|
125 |
+
}.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
|
126 |
+
.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
|
127 |
+
.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; }
|
128 |
+
.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
|
129 |
+
.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
|
130 |
+
.ui-menu .ui-menu-item a.ui-state-focus,
|
131 |
+
.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; }
|
132 |
+
|
133 |
+
.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
|
134 |
+
.ui-menu .ui-state-disabled a { cursor: default; }
|
135 |
+
|
136 |
+
/* icon support */
|
137 |
+
.ui-menu-icons { position: relative; }
|
138 |
+
.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
|
139 |
+
|
140 |
+
/* left-aligned */
|
141 |
+
.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
|
142 |
+
|
143 |
+
/* right-aligned */
|
144 |
+
.ui-menu .ui-menu-icon { position: static; float: right; }
|
145 |
+
|
146 |
+
/* Component containers
|
147 |
+
----------------------------------*/
|
148 |
+
.ui-widget { font-family: sans-serif; font-size: 12px; }
|
149 |
+
.ui-widget .ui-widget { font-size: 1em; }
|
150 |
+
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: sans-serif; font-size: 1em; }
|
151 |
+
.ui-widget-content { border: 1px solid #dfdfdf; background: #ffffff; color: #333333; }
|
152 |
+
.ui-widget-header { border: 1px solid #dfdfdf; color: #333333; font-weight: bold; background-color: #f1f1f1; background-image: -ms-linear-gradient(top, #f9f9f9, #ececec); background-image: -moz-linear-gradient(top, #f9f9f9, #ececec); background-image: -o-linear-gradient(top, #f9f9f9, #ececec); background-image: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec)); background-image: -webkit-linear-gradient(top, #f9f9f9, #ececec); background-image: linear-gradient(top, #f9f9f9, #ececec); }
|
153 |
+
.ui-widget-header a { color: #333333; }
|
154 |
+
|
155 |
+
/* Interaction states
|
156 |
+
----------------------------------*/
|
157 |
+
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #dfdfdf; background-color: #f1f1f1; background-image: -ms-linear-gradient(top, #f9f9f9, #ececec); background-image: -moz-linear-gradient(top, #f9f9f9, #ececec); background-image: -o-linear-gradient(top, #f9f9f9, #ececec); background-image: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec)); background-image: -webkit-linear-gradient(top, #f9f9f9, #ececec); background-image: linear-gradient(top, #f9f9f9, #ececec); font-weight: normal; color: #333333; }
|
158 |
+
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #21759b; text-decoration: none; }
|
159 |
+
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #ccc; background-color: #ececec; background-image: -ms-linear-gradient(top, #ececec, #f9f9f9); background-image: -moz-linear-gradient(top, #ececec, #f9f9f9); background-image: -o-linear-gradient(top, #ececec, #f9f9f9); background-image: -webkit-gradient(linear, left top, left bottom, from(#ececec), to(#f9f9f9)); background-image: -webkit-linear-gradient(top, #ececec, #f9f9f9); background-image: linear-gradient(top, #ececec, #f9f9f9); font-weight: normal; color: #000000; }
|
160 |
+
.ui-state-hover a, .ui-state-hover a:hover { color: #d54e21; text-decoration: none; }
|
161 |
+
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #dfdfdf; background: #ffffff; font-weight: normal; color: #333333; }
|
162 |
+
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #333333; text-decoration: none; }
|
163 |
+
.ui-widget :active { outline: none; }
|
164 |
+
|
165 |
+
/* Interaction Cues
|
166 |
+
----------------------------------*/
|
167 |
+
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #e6db55; background: #ffffe0; color: #333333; }
|
168 |
+
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #333333; }
|
169 |
+
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cc0000; background: #ffebe8; color: #cc0000; }
|
170 |
+
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cc0000; }
|
171 |
+
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cc0000; }
|
172 |
+
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
|
173 |
+
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
174 |
+
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
175 |
+
|
176 |
+
/* Icons
|
177 |
+
----------------------------------*/
|
178 |
+
|
179 |
+
/* states and images */
|
180 |
+
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_21759b_256x240.png); }
|
181 |
+
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_21759b_256x240.png); }
|
182 |
+
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_21759b_256x240.png); }
|
183 |
+
.ui-state-default .ui-icon { background-image: url(images/ui-icons_21759b_256x240.png); }
|
184 |
+
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_d54e21_256x240.png); }
|
185 |
+
.ui-state-active .ui-icon {background-image: url(images/ui-icons_333333_256x240.png); }
|
186 |
+
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_21759b_256x240.png); }
|
187 |
+
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); }
|
188 |
+
|
189 |
+
/* positioning */
|
190 |
+
.ui-icon-carat-1-e { background-position: -32px 0; }
|
191 |
+
.ui-icon-carat-1-w { background-position: -96px 0; }
|
192 |
+
.ui-icon-carat-2-e-w { background-position: -144px 0; }
|
193 |
+
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
194 |
+
.ui-icon-triangle-1-s { background-position: -64px -16px; }
|
195 |
+
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
196 |
+
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
197 |
+
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
198 |
+
.ui-icon-arrow-1-s { background-position: -64px -32px; }
|
199 |
+
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
200 |
+
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
201 |
+
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
202 |
+
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
203 |
+
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
204 |
+
|
205 |
+
/* Misc visuals
|
206 |
+
----------------------------------*/
|
207 |
+
|
208 |
+
/* Corner radius */
|
209 |
+
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; border-top-left-radius: 3px; }
|
210 |
+
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; border-top-right-radius: 3px; }
|
211 |
+
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; }
|
212 |
+
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; }
|
213 |
+
|
214 |
+
/*
|
215 |
+
* jQuery UI Button 1.8.16
|
216 |
+
*
|
217 |
+
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
218 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
219 |
+
* http://jquery.org/license
|
220 |
+
*
|
221 |
+
* http://docs.jquery.com/UI/Button#theming
|
222 |
+
*/
|
223 |
+
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
|
224 |
+
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
|
225 |
+
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
|
226 |
+
.ui-button-icons-only { width: 3.4em; }
|
227 |
+
button.ui-button-icons-only { width: 3.7em; }
|
228 |
+
|
229 |
+
/*button text element */
|
230 |
+
.ui-button .ui-button-text { display: block; line-height: 1.4; }
|
231 |
+
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
|
232 |
+
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
|
233 |
+
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
|
234 |
+
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
|
235 |
+
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
|
236 |
+
/* no icon support for input elements, provide padding by default */
|
237 |
+
input.ui-button { padding: .4em 1em; }
|
238 |
+
|
239 |
+
/*button icon element(s) */
|
240 |
+
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
|
241 |
+
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
|
242 |
+
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
|
243 |
+
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
244 |
+
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
245 |
+
|
246 |
+
/*button sets*/
|
247 |
+
.ui-buttonset { margin-right: 7px; }
|
248 |
+
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
|
249 |
+
|
250 |
+
/* workarounds */
|
251 |
+
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
css/fullcalendar.css
ADDED
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*Front-end full calendar key*/
|
2 |
+
.eo-fullcalendar-key ul.eo_fullcalendar_key{display: inline-block;font-size: 0.8em;}
|
3 |
+
.eo-fullcalendar-key ul.eo_fullcalendar_key li{display: inline-block;margin:0 3px;}
|
4 |
+
.eo-fullcalendar-key span.eo_fullcalendar_key_colour{margin: 4px 2px 4px 5px;border: 1px solid #DFDFDF;border-radius: 4px 4px 4px 4px;font-size: 0.9em;vertical-align: top;padding: 0 6px;}
|
5 |
+
|
6 |
+
|
7 |
+
/*styling for calendar view tabs */
|
8 |
+
.view-button{float:right;background: #FFFFFF;height: 30px;line-height: 28px;margin-top: 3px;padding: 0 11px;}
|
9 |
+
.view-button.active{border-color: #dfdfdf #dfdfdf #FFFFFF;border-style: solid;border-width: 1px;font-size: 120%;}
|
10 |
+
|
11 |
+
/*calendar view conainer */
|
12 |
+
div#calendar-view{clear: both;height: 34px;margin-bottom: 15px;border-bottom: 1px solid #dfdfdf;padding-right: 100px;position: relative;}
|
13 |
+
|
14 |
+
/* loading text */
|
15 |
+
#loading{position:absolute;bottom:0;font-size: 16px;line-height: 16px;margin-bottom: 5px;}
|
16 |
+
#loading:before {content: url("images/loading-image.gif");padding-right: 5px;}
|
17 |
+
|
18 |
+
/*Added to fit with full calendar*/
|
19 |
+
/*button.ui-datepicker-trigger.ui-button.ui-widget{vertical-align: top;}*/
|
20 |
+
.ui-datepicker{z-index: 100 !important}
|
21 |
+
.ui-selectmenu-menu{z-index: 10!important}
|
22 |
+
|
23 |
+
/*For the blocks of colour*/
|
24 |
+
.cat .ui-selectmenu-item-icon { height: 14px; width: 14px; border:1px solid #dfdfdf;border-radius: 4px;}
|
25 |
+
.cat .ui-selectmenu-item-icon{ background-image:none!important; }
|
26 |
+
|
27 |
+
/*
|
28 |
+
* FullCalendar v1.5.2 Stylesheet
|
29 |
+
*
|
30 |
+
* Copyright (c) 2011 Adam Shaw
|
31 |
+
* Dual licensed under the MIT and GPL licenses, located in
|
32 |
+
* MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
33 |
+
*
|
34 |
+
* Date: Sun Aug 21 22:06:09 2011 -0700
|
35 |
+
*/
|
36 |
+
.fc{direction:ltr;text-align:left}
|
37 |
+
.fc table{border-collapse:collapse;border-spacing:0}
|
38 |
+
html .fc,.fc table{font-size:1em}
|
39 |
+
.fc td,.fc th{vertical-align:top;padding:0}
|
40 |
+
.fc-header td{white-space:nowrap;vertical-align:middle}
|
41 |
+
.fc-header-left{width:25%;text-align:left}
|
42 |
+
.fc-header-right{width:25%;text-align:right}
|
43 |
+
.fc-header-title{display:inline-block;vertical-align:top}
|
44 |
+
.fc-header-title h2{margin-top:0;white-space:nowrap}
|
45 |
+
.fc .fc-header-space{padding-left:10px}
|
46 |
+
.fc-header .ui-corner-right{margin-right:0}
|
47 |
+
.fc-header .fc-state-hover,.fc-header .ui-state-hover{z-index:2}
|
48 |
+
.fc-header .fc-state-down{z-index:3}
|
49 |
+
.fc-header .fc-state-active,.fc-header .ui-state-active{z-index:4}
|
50 |
+
.fc-content{clear:both}
|
51 |
+
.fc-view{width:100%;overflow:hidden}
|
52 |
+
.fc-widget-header,/* <th>,usually */
|
53 |
+
.fc-widget-content{border:1px solid #ccc}
|
54 |
+
.fc-state-highlight{background:#ffc}
|
55 |
+
.fc-cell-overlay{background:#9cf;opacity:.2;filter:alpha(opacity=20)}
|
56 |
+
.fc-button{position:relative;display:inline-block;cursor:pointer}
|
57 |
+
.fc-state-default{border-style:solid;border-width:1px 0}
|
58 |
+
.fc-button-inner{position:relative;float:left;overflow:hidden}
|
59 |
+
.fc-state-default .fc-button-inner{border-style:solid;border-width:0 1px}
|
60 |
+
/*.fc-button-content{position:relative;float:left;height:1.9em;line-height:1.9em;white-space:nowrap;padding:0 .6em}*/
|
61 |
+
.fc-button-content{position: relative;float: left;height: 20px;white-space: nowrap;padding: 0 .6em;line-height: 20px;}
|
62 |
+
/*.fc-button-content .fc-icon-wrap{position:relative;float:left;top:50%}*/
|
63 |
+
.fc-button-content .fc-icon-wrap {position: relative;float: left;top: 2px;}
|
64 |
+
.fc-button-content .ui-icon{position:relative;float:left;margin-top:0;top:-50%}
|
65 |
+
.fc-state-default .fc-button-effect{position:absolute;top:50%;left:0}
|
66 |
+
.fc-state-default .fc-button-effect span{position:absolute;top:-100px;left:0;width:500px;height:100px;background:#444;opacity:.09;filter:alpha(opacity=9);border-color:#fff;border-style:solid;border-width:100px 0 0 1px}
|
67 |
+
.fc-state-default,.fc-state-default .fc-button-inner{background:#F3F3F3;color:#000;border-color:#ccc #bbb #aaa;border-style:solid}
|
68 |
+
.fc-state-hover,.fc-state-hover .fc-button-inner{border-color:#999}
|
69 |
+
.fc-state-down,.fc-state-down .fc-button-inner{background:#777;border-color:#555}
|
70 |
+
.fc-state-active,.fc-state-active .fc-button-inner{background:#777;color:#fff;border-color:#555}
|
71 |
+
.fc-state-disabled,.fc-state-disabled .fc-button-inner{color:#999;border-color:#ddd}
|
72 |
+
.fc-state-disabled{cursor:default}
|
73 |
+
.fc-state-disabled .fc-button-effect{display:none}
|
74 |
+
.fc-event{font-size:.85em;cursor:default;border-style:solid;border-width:0}
|
75 |
+
a.fc-event,.fc-event-draggable{cursor:pointer}
|
76 |
+
a.fc-event{text-decoration:none}
|
77 |
+
.fc-rtl .fc-event{text-align:right}
|
78 |
+
.fc-event-skin{background-color:#36c;color:#fff;border-color:#36c}
|
79 |
+
.fc-event-inner{position:relative;width:100%;height:100%;overflow:hidden;border-style:solid;border-width:0}
|
80 |
+
.fc-event-time,.fc-event-title{padding:0 1px}
|
81 |
+
.fc .ui-resizable-handle{display:block;position:absolute;z-index:99999;overflow:hidden;font-size:300%;line-height:50%}
|
82 |
+
.fc-event-hori{margin-bottom:1px;border-width:1px 0}
|
83 |
+
.fc-event-hori .ui-resizable-e{top:0!important;right:-3px!important;width:7px!important;height:100%!important;cursor:e-resize}
|
84 |
+
.fc-event-hori .ui-resizable-w{top:0!important;left:-3px!important;width:7px!important;height:100%!important;cursor:w-resize}
|
85 |
+
.fc-event-hori .ui-resizable-handle{_padding-bottom:14px}
|
86 |
+
.fc-corner-left{margin-left:1px}
|
87 |
+
.fc-corner-left .fc-button-inner,.fc-corner-left .fc-event-inner{margin-left:-1px}
|
88 |
+
.fc-corner-top{margin-top:1px}
|
89 |
+
.fc-corner-top .fc-event-inner{margin-top:-1px;border-top-width:1px}
|
90 |
+
.fc-corner-bottom{margin-bottom:1px}
|
91 |
+
.fc-corner-bottom .fc-event-inner{margin-bottom:-1px;border-bottom-width:1px}
|
92 |
+
.fc-corner-left .fc-event-inner{border-left-width:1px}
|
93 |
+
.fc-border-separate th,.fc-border-separate td{border-width:1px 0 0 1px}
|
94 |
+
.fc-border-separate tr.fc-last th,.fc-border-separate tr.fc-last td{border-bottom-width:1px}
|
95 |
+
.fc-grid .fc-day-number{float:right;padding:0 2px}
|
96 |
+
.fc-grid .fc-other-month .fc-day-number{opacity:0.3;filter:alpha(opacity=30)}
|
97 |
+
.fc-grid .fc-day-content{clear:both;padding:2px 2px 1px}
|
98 |
+
.fc-grid .fc-event-time{font-weight:700}
|
99 |
+
.fc-rtl .fc-grid .fc-day-number{float:left}
|
100 |
+
.fc-rtl .fc-grid .fc-event-time{float:right}
|
101 |
+
.fc-agenda .fc-agenda-axis{width:50px;vertical-align:middle;text-align:right;white-space:nowrap;font-weight:400;padding:0 4px}
|
102 |
+
.fc-agenda .fc-day-content{padding:2px 2px 1px}
|
103 |
+
.fc-agenda-days .fc-col0{border-left-width:0}
|
104 |
+
.fc-agenda-allday .fc-day-content{min-height:34px;_height:34px}
|
105 |
+
.fc-agenda-divider-inner{height:2px;overflow:hidden}
|
106 |
+
.fc-widget-header .fc-agenda-divider-inner{background:#eee}
|
107 |
+
.fc-agenda-slots th{border-width:1px 1px 0}
|
108 |
+
.fc-agenda-slots td{background:none;border-width:1px 0 0}
|
109 |
+
.fc-agenda-slots td div{height:20px}
|
110 |
+
.fc-agenda-slots tr.fc-minor th,.fc-agenda-slots tr.fc-minor td{border-top-style:dotted}
|
111 |
+
.fc-agenda-slots tr.fc-minor th.ui-widget-header{border-top-style:solid}
|
112 |
+
.fc-event-vert .fc-event-head,.fc-event-vert .fc-event-content{position:relative;z-index:2;width:100%;overflow:hidden}
|
113 |
+
.fc-event-vert .fc-event-time{white-space:nowrap;font-size:10px}
|
114 |
+
.fc-event-vert .fc-event-bg{position:absolute;z-index:1;top:0;left:0;width:100%;height:100%;background:#fff;opacity:.3;filter:alpha(opacity=30)}
|
115 |
+
.fc .ui-draggable-dragging .fc-event-bg,/* TODO: something nicer like .fc-opacity */
|
116 |
+
.fc-select-helper .fc-event-bg{display:none\9}
|
117 |
+
.fc-event-vert .ui-resizable-s{bottom:0!important;width:100%!important;height:8px!important;overflow:hidden!important;line-height:8px!important;font-size:11px!important;font-family:monospace;text-align:center;cursor:s-resize}
|
118 |
+
.fc-agenda .ui-resizable-resizing{_overflow:hidden}
|
119 |
+
.fc-header-center,.fc-grid th,.fc-agenda-days th{text-align:center}
|
120 |
+
.fc-header .fc-button,.fc-corner-right .fc-button-inner,.fc-corner-right .fc-event-inner{margin-right:-1px}
|
121 |
+
.fc-header .fc-corner-right,.fc-corner-right{margin-right:1px}
|
122 |
+
.fc-corner-right .fc-event-inner,.fc-border-separate th.fc-last,.fc-border-separate td.fc-last,.fc-agenda-days .fc-agenda-axis{border-right-width:1px}
|
123 |
+
table.fc-border-separate,.fc-agenda table{border-collapse:separate}
|
124 |
+
.fc-border-separate tbody tr.fc-first td,.fc-border-separate tbody tr.fc-first th,.fc-agenda-slots tr.fc-slot0 th,.fc-agenda-slots tr.fc-slot0 td{border-top-width:0}
|
125 |
+
.fc-agenda-allday th,.fc-event-vert{border-width:0 1px}
|
126 |
+
|
127 |
+
|
128 |
+
/*! qTip2 - Pretty powerful tooltips - v2.0.0 - 2012-08-14
|
129 |
+
* http://craigsworks.com/projects/qtip2/
|
130 |
+
* Copyright (c) 2012 Craig Michael Thompson; Licensed MIT, GPL */
|
131 |
+
/* Core qTip styles */
|
132 |
+
.ui-tooltip, .qtip{position:absolute; left:-28000px; top:-28000px; display:none; max-width:280px; min-width:50px; font-size:10.5px; line-height:12px; border-width:1px; border-style:solid}
|
133 |
+
|
134 |
+
/* Fluid class for determining actual width in IE */
|
135 |
+
.ui-tooltip-fluid{display:block; visibility:hidden; position:static !important; float:left !important}
|
136 |
+
.ui-tooltip-content{position:relative; padding:5px 9px; overflow:hidden; text-align:left; word-wrap:break-word}
|
137 |
+
.ui-tooltip-titlebar{position:relative; min-height:14px; padding:5px 35px 5px 10px; overflow:hidden; border-width:0 0 1px; font-weight:bold}
|
138 |
+
.ui-tooltip-titlebar+.ui-tooltip-content{border-top-width:0 !important}
|
139 |
+
|
140 |
+
/* Default close button class */
|
141 |
+
.ui-tooltip-titlebar .ui-state-default{position:absolute; right:4px; top:50%; margin-top:-9px; cursor:pointer; outline:medium none; border-width:1px; border-style:solid}
|
142 |
+
* html .ui-tooltip-titlebar .ui-state-default{top:16px}/* IE fix */
|
143 |
+
.ui-tooltip-titlebar .ui-icon,
|
144 |
+
.ui-tooltip-icon .ui-icon{display:block; text-indent:-1000em; direction:ltr}
|
145 |
+
.ui-tooltip-icon, .ui-tooltip-icon .ui-icon{-moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; text-decoration:none}
|
146 |
+
.ui-tooltip-icon .ui-icon{width:18px; height:14px; text-align:center; text-indent:0; font:normal bold 10px/13px Tahoma,sans-serif; color:inherit; background:transparent none no-repeat -100em -100em}
|
147 |
+
|
148 |
+
/* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */
|
149 |
+
.ui-tooltip-focus{}
|
150 |
+
|
151 |
+
/* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */
|
152 |
+
.ui-tooltip-hover{}
|
153 |
+
|
154 |
+
/* Add shadows to your tooltips in:FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+*/
|
155 |
+
.ui-tooltip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15); -moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15); box-shadow:1px 1px 3px 1px rgba(0,0,0,0.15)}
|
156 |
+
|
157 |
+
/* Add rounded corners to your tooltips in:FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+*/
|
158 |
+
.ui-tooltip-rounded,
|
159 |
+
.ui-tooltip-tipsy,
|
160 |
+
.ui-tooltip-bootstrap{-moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px}
|
161 |
+
|
162 |
+
/* jQuery TOOLS Tooltip style */
|
163 |
+
.ui-tooltip-jtools{background:#232323; background:rgba(0,0,0,0.7); background-image:-webkit-gradient(linear,left top,left bottom,from(#717171),to(#232323)); background-image:-moz-linear-gradient(top,#717171,#232323); background-image:-webkit-linear-gradient(top,#717171,#232323); background-image:-ms-linear-gradient(top,#717171,#232323); background-image:-o-linear-gradient(top,#717171,#232323); border:2px solid #ddd; border:2px solid rgba(241,241,241,1); -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; -webkit-box-shadow:0 0 12px #333; -moz-box-shadow:0 0 12px #333; box-shadow:0 0 12px #333}
|
164 |
+
|
165 |
+
/* IE Specific */
|
166 |
+
.ui-tooltip-jtools .ui-tooltip-titlebar{background-color:transparent; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)"}
|
167 |
+
.ui-tooltip-jtools .ui-tooltip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)"}
|
168 |
+
|
169 |
+
.ui-tooltip-jtools .ui-tooltip-titlebar,
|
170 |
+
.ui-tooltip-jtools .ui-tooltip-content{background:transparent; color:white; border:0 dashed transparent}
|
171 |
+
.ui-tooltip-jtools .ui-tooltip-icon{border-color:#555}
|
172 |
+
.ui-tooltip-jtools .ui-tooltip-titlebar .ui-state-hover{border-color:#333}
|
173 |
+
|
174 |
+
/* Tipped style */
|
175 |
+
.ui-tooltip-tipped{border:3px solid #959FA9; -moz-border-radius:3px; -webkit-border-radius:3px; border-radius:3px; background-color:#F9F9F9; color:#454545; font-weight:normal; font-family:serif}
|
176 |
+
.ui-tooltip-tipped .ui-tooltip-titlebar{border-bottom-width:0; color:white; background:#3A79B8; background-image:-webkit-gradient(linear,left top,left bottom,from(#3A79B8),to(#2E629D)); background-image:-webkit-linear-gradient(top,#3A79B8,#2E629D); background-image:-moz-linear-gradient(top,#3A79B8,#2E629D); background-image:-ms-linear-gradient(top,#3A79B8,#2E629D); background-image:-o-linear-gradient(top,#3A79B8,#2E629D); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)"}
|
177 |
+
.ui-tooltip-tipped .ui-tooltip-icon{border:2px solid #285589; background:#285589}
|
178 |
+
.ui-tooltip-tipped .ui-tooltip-icon .ui-icon{background-color:#FBFBFB; color:#555}
|
179 |
+
|
180 |
+
/* IE9 fix - removes all filters */
|
181 |
+
.ui-tooltip:not(.ie9haxors) div.ui-tooltip-content,
|
182 |
+
.ui-tooltip:not(.ie9haxors) div.ui-tooltip-titlebar{filter:none; -ms-filter:none}
|
183 |
+
|
184 |
+
/* Tips plugin */
|
185 |
+
.ui-tooltip .ui-tooltip-tip{margin:0 auto; overflow:hidden; z-index:10}
|
186 |
+
.ui-tooltip .ui-tooltip-tip,
|
187 |
+
.ui-tooltip .ui-tooltip-tip *{position:absolute; line-height:0.1px !important; font-size:0.1px !important; color:#123456; background:transparent; border:0 dashed transparent}
|
188 |
+
.ui-tooltip .ui-tooltip-tip canvas{top:0; left:0}
|
189 |
+
|
190 |
+
|
191 |
+
/* =Print
|
192 |
+
----------------------------------------------- */
|
193 |
+
@media print {
|
194 |
+
/*.fc-event-skin {background: none !important;color: #000 !important;}*/
|
195 |
+
|
196 |
+
/* horizontal events */
|
197 |
+
.fc-event-hori {padding: 1px 0 0 0 !important;}
|
198 |
+
.fc-event-hori .fc-event-inner {border-width: 0 !important;padding: 0 1px !important}
|
199 |
+
|
200 |
+
/* vertical events */
|
201 |
+
.fc-event-vert {padding: 0 1px 0 0 !important;}
|
202 |
+
.fc-event-vert .fc-event-inner {border-width: 0 !important;padding: 1px 0 !important;}
|
203 |
+
|
204 |
+
/*.fc-event-bg {display: none !important;}*/
|
205 |
+
.fc-event .ui-resizable-handle {display: none !important;}
|
206 |
+
.fc-button{display: none;}
|
207 |
+
.eo-fullcalendar table tr td{width:10%;}
|
208 |
+
}
|
css/images/eo-pro-event-search.png
ADDED
Binary file
|
css/images/eo-pro-ticket-picker.png
ADDED
Binary file
|
css/images/eo-pro-venue-cf.png
ADDED
Binary file
|
css/images/eobadge.png
ADDED
Binary file
|
css/images/eoicon-16.png
ADDED
Binary file
|
css/images/eoicon-32.png
ADDED
Binary file
|
css/images/eoicon-32.xcf
ADDED
Binary file
|
css/images/eoicon-64.png
ADDED
Binary file
|
css/images/help-14.png
ADDED
Binary file
|
css/images/info-14.png
ADDED
Binary file
|
css/images/loading-image.gif
ADDED
Binary file
|
css/images/ui-bg_flat_100_f5f5f5_40x100.png
ADDED
Binary file
|
css/images/ui-bg_flat_100_ffffff_40x100.png
ADDED
Binary file
|
css/images/ui-bg_flat_10_ffebe8_40x100.png
ADDED
Binary file
|
css/images/ui-bg_flat_10_ffffff_40x100.png
ADDED
Binary file
|
css/images/ui-bg_flat_15_f9f9f9_40x100.png
ADDED
Binary file
|
css/images/ui-bg_flat_15_ffffe0_40x100.png
ADDED
Binary file
|
css/images/ui-bg_flat_20_000000_40x100.png
ADDED
Binary file
|
css/images/ui-bg_flat_70_000000_40x100.png
ADDED
Binary file
|
css/images/ui-bg_highlight-soft_100_ececec_1x100.png
ADDED
Binary file
|
css/images/ui-icons_21759b_256x240.png
ADDED
Binary file
|
css/images/ui-icons_222222_256x240.png
ADDED
Binary file
|
css/images/ui-icons_333333_256x240.png
ADDED
Binary file
|
css/images/ui-icons_3572ac_256x240.png
ADDED
Binary file
|
css/images/ui-icons_999999_256x240.png
ADDED
Binary file
|
css/images/ui-icons_cc0000_256x240.png
ADDED
Binary file
|
css/images/ui-icons_d54e21_256x240.png
ADDED
Binary file
|
event-organiser-calendar.php
ADDED
@@ -0,0 +1,306 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Calendar Admin Page
|
4 |
+
*/
|
5 |
+
if ( !class_exists( 'EventOrganiser_Admin_Page' ) ){
|
6 |
+
require_once( EVENT_ORGANISER_DIR.'classes/class-eventorganiser-admin-page.php' );
|
7 |
+
}
|
8 |
+
/**
|
9 |
+
* Calendar Admin Page
|
10 |
+
*
|
11 |
+
* Extends the EentOrganiser_Admin_Page class. Creates the calendar admin page
|
12 |
+
* @version 1.0
|
13 |
+
* @see EventOrganiser_Admin_Page
|
14 |
+
* @package event organiser
|
15 |
+
*/
|
16 |
+
class EventOrganiser_Calendar_Page extends EventOrganiser_Admin_Page
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
* This sets the calendar page variables
|
20 |
+
*/
|
21 |
+
function set_constants(){
|
22 |
+
$this->hook = 'edit.php?post_type=event';
|
23 |
+
$this->title = __( 'Calendar View', 'eventorganiser' );
|
24 |
+
$this->menu = __( 'Calendar View', 'eventorganiser' );
|
25 |
+
$this->permissions = 'edit_events';
|
26 |
+
$this->slug = 'calendar';
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Enqueues the page's scripts and styles, and localises them.
|
31 |
+
*/
|
32 |
+
function page_scripts(){
|
33 |
+
global $wp_locale;
|
34 |
+
|
35 |
+
wp_enqueue_script( 'eo_calendar' );
|
36 |
+
wp_enqueue_script( 'eo_event' );
|
37 |
+
wp_localize_script( 'eo_event', 'EO_Ajax_Event', array(
|
38 |
+
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
39 |
+
'startday' => intval( get_option( 'start_of_week' ) ),
|
40 |
+
'format' => eventorganiser_php2jquerydate( eventorganiser_get_option('dateformat') ),
|
41 |
+
));
|
42 |
+
wp_localize_script( 'eo_calendar', 'EO_Ajax', array(
|
43 |
+
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
44 |
+
'startday' => intval( get_option( 'start_of_week' ) ),
|
45 |
+
'format' => eventorganiser_php2jquerydate( eventorganiser_get_option('dateformat') ),
|
46 |
+
'timeFormat' => ( get_current_screen()->get_option( 'eofc_time_format', 'value' ) ? 'h:mmtt' : 'HH:mm' ),
|
47 |
+
'perm_edit' => current_user_can( 'edit_events' ),
|
48 |
+
'categories' => get_terms( 'event-category', array( 'hide_empty' => 0 ) ),
|
49 |
+
'venues' => get_terms( 'event-venue', array( 'hide_empty' => 0 ) ),
|
50 |
+
'locale' => array(
|
51 |
+
'monthNames' => array_values( $wp_locale->month ),
|
52 |
+
'monthAbbrev' => array_values( $wp_locale->month_abbrev ),
|
53 |
+
'dayNames' => array_values( $wp_locale->weekday ),
|
54 |
+
'dayAbbrev' => array_values( $wp_locale->weekday_abbrev ),
|
55 |
+
'today' => __( 'today', 'eventorganiser' ),
|
56 |
+
'day' => __( 'day', 'eventorganiser' ),
|
57 |
+
'week' => __( 'week', 'eventorganiser' ),
|
58 |
+
'month' => __( 'month', 'eventorganiser' ),
|
59 |
+
'gotodate' => __( 'go to date', 'eventorganiser' ),
|
60 |
+
'cat' => __( 'View all categories', 'eventorganiser' ),
|
61 |
+
'venue' => __( 'View all venues', 'eventorganiser' ),
|
62 |
+
)
|
63 |
+
));
|
64 |
+
wp_enqueue_style( 'eo_calendar-style' );
|
65 |
+
wp_enqueue_style( 'eventorganiser-style' );
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Prints page styles
|
70 |
+
*/
|
71 |
+
function page_styles(){
|
72 |
+
if ( $terms = get_terms( 'event-category', array( 'hide_empty' => 0 ) ) ):
|
73 |
+
$css = '';
|
74 |
+
foreach ( $terms as $term ):
|
75 |
+
$css .= ".cat-slug-{$term->slug} span.ui-selectmenu-item-icon{ background: ".eo_get_category_color( $term ).";}\n";
|
76 |
+
endforeach;
|
77 |
+
wp_add_inline_style( 'eo_calendar-style', $css );
|
78 |
+
endif;
|
79 |
+
}
|
80 |
+
|
81 |
+
function page_actions(){
|
82 |
+
|
83 |
+
//Add screen option
|
84 |
+
$user = wp_get_current_user();
|
85 |
+
$is12hour = get_user_meta( $user->ID, 'eofc_time_format', true );
|
86 |
+
add_screen_option( 'eofc_time_format', array( 'value' => $is12hour ) );
|
87 |
+
add_filter( 'screen_settings', array( $this, 'screen_options' ), 10, 2 );
|
88 |
+
|
89 |
+
//Check action
|
90 |
+
if ( !empty( $_REQUEST['save'] ) || !empty( $_REQUEST['publish'] ) ){
|
91 |
+
//Check nonce
|
92 |
+
check_admin_referer( 'eventorganiser_calendar_save' );
|
93 |
+
|
94 |
+
//authentication checks
|
95 |
+
if ( !current_user_can( 'edit_events' ) )
|
96 |
+
wp_die( __( 'You do not have sufficient permissions to create events', 'eventorganiser' ) );
|
97 |
+
|
98 |
+
$input = $_REQUEST['eo_event']; //Retrieve input from posted data
|
99 |
+
|
100 |
+
//Set the status of the new event
|
101 |
+
if ( !empty( $_REQUEST['save'] ) ):
|
102 |
+
$status = 'draft';
|
103 |
+
else:
|
104 |
+
$status = ( current_user_can( 'publish_events' ) ? 'publish' : 'pending' );
|
105 |
+
endif;
|
106 |
+
|
107 |
+
//Set post and event details
|
108 |
+
$venue = (int) $input['venue_id'];
|
109 |
+
|
110 |
+
$post_input = array(
|
111 |
+
'post_title' => $input['event_title'],
|
112 |
+
'post_status' => $status,
|
113 |
+
'post_content' => $input['event_content'],
|
114 |
+
'post_type' => 'event',
|
115 |
+
'tax_input' => array( 'event-venue' => array( $venue ) ),
|
116 |
+
);
|
117 |
+
$tz = eo_get_blog_timezone();
|
118 |
+
$event_data = array(
|
119 |
+
'schedule' => 'once',
|
120 |
+
'all_day' => $input['allday'],
|
121 |
+
'start' => new DateTime( $input['StartDate'].' '.$input['StartTime'], $tz ),
|
122 |
+
'end' => new DateTime( $input['EndDate'].' '.$input['FinishTime'], $tz ),
|
123 |
+
);
|
124 |
+
|
125 |
+
//Insert event
|
126 |
+
$post_id = eo_insert_event( $post_input, $event_data );
|
127 |
+
|
128 |
+
if ( $post_id ){
|
129 |
+
//If event was successfully inserted, redirect and display appropriate message
|
130 |
+
$redirect = get_edit_post_link( $post_id, '' );
|
131 |
+
|
132 |
+
if( $status == 'publish' )
|
133 |
+
$redirect = add_query_arg( 'message', 6, $redirect );
|
134 |
+
else
|
135 |
+
$redirect = add_query_arg( 'message', 7, $redirect );
|
136 |
+
|
137 |
+
//Redirect to event admin page & exit
|
138 |
+
wp_redirect( $redirect );
|
139 |
+
exit;
|
140 |
+
}
|
141 |
+
}elseif ( isset( $_REQUEST['action'] ) && ( $_REQUEST['action'] == 'delete_occurrence' || $_REQUEST['action'] == 'break_series') && isset( $_REQUEST['series'] ) && isset( $_REQUEST['event'] ) ){
|
142 |
+
$post_id = intval( $_REQUEST['series'] );
|
143 |
+
$event_id = intval( $_REQUEST['event'] );
|
144 |
+
$action = $_REQUEST['action'];
|
145 |
+
|
146 |
+
if ( $action == 'break_series' ):
|
147 |
+
//Check nonce
|
148 |
+
check_admin_referer( 'eventorganiser_break_series_'.$event_id );
|
149 |
+
|
150 |
+
//Check permissions
|
151 |
+
if ( !current_user_can( 'edit_event', $post_id ) || !current_user_can( 'delete_event', $post_id ) )
|
152 |
+
wp_die( __( 'You do not have sufficient permissions to edit this event', 'eventorganiser' ) );
|
153 |
+
|
154 |
+
eo_break_occurrence( $post_id, $event_id );
|
155 |
+
|
156 |
+
//Redirect to prevent resubmisson
|
157 |
+
$redirect = add_query_arg( array( 'post_type' => 'event', 'page' => 'calendar' ), admin_url( 'edit.php' ) );
|
158 |
+
wp_redirect( $redirect );
|
159 |
+
|
160 |
+
elseif( $action == 'delete_occurrence' ):
|
161 |
+
global $EO_Errors;
|
162 |
+
|
163 |
+
//Check nonce
|
164 |
+
check_admin_referer( 'eventorganiser_delete_occurrence_'.$event_id );
|
165 |
+
|
166 |
+
//Check permissions
|
167 |
+
if ( ! current_user_can( 'delete_event', $post_id ) )
|
168 |
+
wp_die( __( 'You do not have sufficient permissions to delete this event', 'eventorganiser' ) );
|
169 |
+
|
170 |
+
$response = _eventorganiser_remove_occurrence( $post_id, $event_id );
|
171 |
+
|
172 |
+
//Break Cache!
|
173 |
+
_eventorganiser_delete_calendar_cache();
|
174 |
+
|
175 |
+
if ( is_wp_error( $response ) ){
|
176 |
+
$EO_Errors = $response;
|
177 |
+
} else {
|
178 |
+
$EO_Errors = new WP_Error( 'eo_notice', '<strong>'.__( 'Occurrence deleted.', 'eventorganiser' ).'</strong>' );
|
179 |
+
}
|
180 |
+
endif;
|
181 |
+
}
|
182 |
+
}
|
183 |
+
|
184 |
+
|
185 |
+
function screen_options( $options, $screen ){
|
186 |
+
$options .= '<h5>'.__( 'Calendar options', 'eventorganiser' ).'</h5>';
|
187 |
+
$options .= sprintf(
|
188 |
+
'<p><label for="%s" style="line-height: 20px;"> <input type="checkbox" name="%s" id="%s" %s> %s </label></p>',
|
189 |
+
'eofc_time_format',
|
190 |
+
'eofc_time_format',
|
191 |
+
'eofc_time_format',
|
192 |
+
checked( $screen->get_option( 'eofc_time_format', 'value' ), 0, false ),
|
193 |
+
__( '24 hour time', 'eventorganiser' )
|
194 |
+
);
|
195 |
+
return $options;
|
196 |
+
}
|
197 |
+
|
198 |
+
|
199 |
+
|
200 |
+
function display(){
|
201 |
+
//Get the time 'now' according to blog's timezone
|
202 |
+
$now = new DateTime( null, eo_get_blog_timezone() );
|
203 |
+
$venues = eo_get_venues();
|
204 |
+
?>
|
205 |
+
|
206 |
+
<div class="wrap">
|
207 |
+
<?php screen_icon( 'edit' );?>
|
208 |
+
<h2><?php _e( 'Events Calendar', 'eventorganiser' ); ?></h2>
|
209 |
+
|
210 |
+
<?php
|
211 |
+
$current = !empty( $_COOKIE['eo_admin_cal_last_view'] ) ? $_COOKIE['eo_admin_cal_last_view'] : 'month';
|
212 |
+
$views = array( 'agendaDay' => __( 'Day', 'eventorganiser' ), 'agendaWeek' => __( 'Week', 'eventorganiser' ), 'month' => __( 'Month', 'eventorganiser' ) );
|
213 |
+
?>
|
214 |
+
<div id="calendar-view">
|
215 |
+
<span id='loading' style='display:none'><?php _e( 'Loading…' );?></span>
|
216 |
+
<?php foreach( $views as $id => $label )
|
217 |
+
printf( '<a href="#" class="view-button %s" id="%s">%s</a>', ( $id == $current ? 'active' : '' ), $id, $label );
|
218 |
+
?>
|
219 |
+
</div>
|
220 |
+
|
221 |
+
<div id='eo_admin_calendar'></div>
|
222 |
+
<span><?php _e( 'Current date/time', 'eventorganiser' );?>: <?php echo $now->format( 'Y-m-d G:i:s \G\M\TP' );?></span>
|
223 |
+
|
224 |
+
<?php eventorganiser_event_detail_dialog(); ?>
|
225 |
+
|
226 |
+
<?php if ( current_user_can( 'publish_events' ) || current_user_can( 'edit_events' ) ):?>
|
227 |
+
<div id='eo_event_create_cal' style="display:none;" class="eo-dialog" title="<?php esc_attr_e( 'Create an event', 'eventorganiser' ); ?>">
|
228 |
+
<form name="eventorganiser_calendar" method="post" class="eo_cal">
|
229 |
+
|
230 |
+
<table class="form-table">
|
231 |
+
<tr>
|
232 |
+
<th><?php _e( 'When', 'eventorganiser' );?>: </th>
|
233 |
+
<td id="date"></td>
|
234 |
+
</tr>
|
235 |
+
<tr>
|
236 |
+
<th><?php _e( 'Event Title', 'eventorganiser' );?>: </th>
|
237 |
+
<td><input name="eo_event[event_title]" class="eo-event-title ui-autocomplete-input ui-widget-content ui-corner-all" ></td>
|
238 |
+
</tr>
|
239 |
+
<tr>
|
240 |
+
<th><?php _e( 'Where', 'eventorganiser' );?>: </th>
|
241 |
+
<td><!-- If javascript is disabed, a simple drop down menu box is displayed to choose venue.
|
242 |
+
Otherwise, the user is able to search the venues by typing in the input box.-->
|
243 |
+
<select size="30" id="venue_select" name="eo_event[venue_id]">
|
244 |
+
<option>Select a venue </option>
|
245 |
+
<?php foreach ( $venues as $venue ):?>
|
246 |
+
<option value="<?php echo intval( $venue->term_id );?>"><?php echo esc_html( $venue->name ); ?></option>
|
247 |
+
<?php endforeach;?>
|
248 |
+
</select>
|
249 |
+
</td>
|
250 |
+
</tr>
|
251 |
+
<tr>
|
252 |
+
<th></th>
|
253 |
+
<td><textarea rows="4" name="eo_event[event_content]" style="width: 220px;"></textarea></td>
|
254 |
+
</tr>
|
255 |
+
</table>
|
256 |
+
<p class="submit">
|
257 |
+
<input type="hidden" name="eo_event[StartDate]">
|
258 |
+
<input type="hidden" name="eo_event[EndDate]">
|
259 |
+
<input type="hidden" name="eo_event[StartTime]">
|
260 |
+
<input type="hidden" name="eo_event[FinishTime]">
|
261 |
+
<input type="hidden" name="eo_event[allday]">
|
262 |
+
<?php wp_nonce_field( 'eventorganiser_calendar_save' ); ?>
|
263 |
+
<?php if ( current_user_can( 'publish_events' ) ):?>
|
264 |
+
<input type="submit" class="button" tabindex="4" value="<?php _e( 'Save Draft', 'eventorganiser' );?>"" id="event-draft" name="save">
|
265 |
+
<input type="reset" class="button" id="reset" value="<?php _e( 'Cancel', 'eventorganiser' );?>">
|
266 |
+
|
267 |
+
<span id="publishing-action">
|
268 |
+
<input type="submit" accesskey="p" tabindex="5" value="<?php _e( 'Publish Event', 'eventorganiser' );?>" class="button-primary" id="publish" name="publish">
|
269 |
+
</span>
|
270 |
+
|
271 |
+
<?php elseif( current_user_can( 'edit_events' ) ):?>
|
272 |
+
<input type="reset" class="button" id="reset" value="<?php _e( 'Cancel', 'eventorganiser' );?>">
|
273 |
+
<span id="publishing-action">
|
274 |
+
<input type="submit" accesskey="p" tabindex="5" value="<?php _e( 'Submit for Review', 'eventorganiser' );?>" class="eo_alignright button-primary" id="submit-for-review" name="publish">
|
275 |
+
</span>
|
276 |
+
<?php endif; ?>
|
277 |
+
|
278 |
+
<br class="clear">
|
279 |
+
</form>
|
280 |
+
</div>
|
281 |
+
<?php endif; ?>
|
282 |
+
</div><!-- .wrap -->
|
283 |
+
<?php
|
284 |
+
}
|
285 |
+
}
|
286 |
+
$calendar_page = new EventOrganiser_Calendar_Page();
|
287 |
+
|
288 |
+
|
289 |
+
function eventorganiser_event_detail_dialog(){
|
290 |
+
|
291 |
+
$tabs = apply_filters( 'eventorganiser_calendar_dialog_tabs', array( 'summary' => __( 'Event Details', 'eventorganiser' ) ) );
|
292 |
+
|
293 |
+
printf( "<div id='events-meta' class='eo-dialog' style='display:none;' title='%s'>", esc_attr__( 'Event Detail', 'eventorganiser' ) );
|
294 |
+
echo "<div id='eo-dialog-tabs'>";
|
295 |
+
echo "<ul style='position: relative;'>";
|
296 |
+
foreach ( $tabs as $id => $label ){
|
297 |
+
printf( '<li id="eo-dialog-tab-%1$s"><a href="#eo-dialog-tab-%1$s-content">%2$s</a></li>', esc_attr( $id ), esc_html( $label ) );
|
298 |
+
}
|
299 |
+
echo '</ul>';
|
300 |
+
foreach ( $tabs as $id => $label ){
|
301 |
+
printf( '<div id="eo-dialog-tab-%s-content"> </div>', esc_attr( $id ) );
|
302 |
+
}
|
303 |
+
echo '</div>';
|
304 |
+
echo '</div>';
|
305 |
+
}
|
306 |
+
?>
|
event-organiser-debug.php
ADDED
@@ -0,0 +1,387 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/****** DEBUG PAGE ******/
|
3 |
+
if ( !class_exists( 'EventOrganiser_Admin_Page' ) ){
|
4 |
+
require_once( EVENT_ORGANISER_DIR.'classes/class-eventorganiser-admin-page.php' );
|
5 |
+
}
|
6 |
+
class EventOrganiser_Debug_Page extends EventOrganiser_Admin_Page
|
7 |
+
{
|
8 |
+
function set_constants(){
|
9 |
+
$this->hook = 'edit.php?post_type=event';
|
10 |
+
$this->title = __( 'System Info', 'eventorganiser' );
|
11 |
+
$this->menu = __( 'System Info', 'eventorganiser' );
|
12 |
+
$this->permissions = 'manage_options';
|
13 |
+
$this->slug = 'debug';
|
14 |
+
}
|
15 |
+
|
16 |
+
function add_page(){
|
17 |
+
self::$page = add_submenu_page($this->hook,$this->title, $this->menu, $this->permissions,$this->slug, array($this,'render_page'),10);
|
18 |
+
add_action('load-'.self::$page, array($this,'page_actions'),9);
|
19 |
+
add_action('admin_print_scripts-'.self::$page, array($this,'page_styles'),10);
|
20 |
+
add_action('admin_print_styles-'.self::$page, array($this,'page_scripts'),10);
|
21 |
+
add_action("admin_footer-".self::$page,array($this,'footer_scripts'));
|
22 |
+
if( !defined( "WP_DEBUG" ) || !WP_DEBUG ){
|
23 |
+
remove_submenu_page('edit.php?post_type=event',$this->slug);
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
function page_actions(){
|
28 |
+
wp_enqueue_style('eventorganiser-style');
|
29 |
+
}
|
30 |
+
|
31 |
+
function display(){
|
32 |
+
?>
|
33 |
+
<div class="wrap">
|
34 |
+
<?php screen_icon( 'edit' );?>
|
35 |
+
|
36 |
+
<h2><?php _e('System Info','eventorganiser');?> </h2>
|
37 |
+
|
38 |
+
<?php
|
39 |
+
$eo_debugger = new EventOrganiser_Debugger();
|
40 |
+
$eo_debugger->set_prequiste( 'WordPress', '3.3', '3.5.1');
|
41 |
+
//$eo_debugger->set_known_plugin_conflicts();
|
42 |
+
//$eo_debugger->set_known_theme_conflicts();
|
43 |
+
$eo_debugger->set_db_tables( 'eo_events', 'eo_venuemeta' );
|
44 |
+
do_action_ref_array( 'eventorganiser_debugger_setup', array( &$eo_debugger ) );
|
45 |
+
?>
|
46 |
+
<p>
|
47 |
+
<?php
|
48 |
+
_e( "This page highlights useful information for debugging. If you're reporting a bug, please include this information.", 'eventorganiser' );
|
49 |
+
echo " ";
|
50 |
+
_e( "The 'system info' link in under the Events admin tab is only visible to admins and only when <code>WP_DEBUG</code> is set to <code>true</code>.", 'eventorganiser' );
|
51 |
+
?>
|
52 |
+
</p>
|
53 |
+
<p class="description">
|
54 |
+
<?php
|
55 |
+
_e( "Most bugs arise from theme or plug-in conflicts. You can check this by disabling all other plug-ins and switching to TwentyTweleve.", 'eventorganiser' );
|
56 |
+
echo " ";
|
57 |
+
_e( "To help speed things along, if you report a bug please indicate if you have done so. Once the plug-in or theme has been identified it is often easy to resolve the issue.", 'eventorganiser' );
|
58 |
+
echo " ";
|
59 |
+
_e( "Below any <strong>known</strong> plug-in and theme conflicts are highlighted in red.", 'eventorganiser' );
|
60 |
+
?>
|
61 |
+
</p>
|
62 |
+
<table class="widefat">
|
63 |
+
<tr>
|
64 |
+
<th><?php esc_html_e('Site url');?></th>
|
65 |
+
<td><?php echo site_url(); ?></td>
|
66 |
+
</tr>
|
67 |
+
<tr>
|
68 |
+
<th><?php esc_html_e('Home url');?></th>
|
69 |
+
<td><?php echo home_url(); ?></td>
|
70 |
+
</tr>
|
71 |
+
<tr>
|
72 |
+
<th><?php esc_html_e('Multisite');?></th>
|
73 |
+
<td><?php echo is_multisite() ? 'Yes' : 'No' ?></td>
|
74 |
+
</tr>
|
75 |
+
<tr>
|
76 |
+
<th><?php esc_html_e('Event Organiser version');?></th>
|
77 |
+
<td><?php global $eventorganiser_db_version; echo $eventorganiser_db_version; ?></td>
|
78 |
+
</tr>
|
79 |
+
<tr>
|
80 |
+
<th><?php esc_html_e('WordPress');?></th>
|
81 |
+
<td>
|
82 |
+
<?php $eo_debugger->verbose_prequiste_check( 'WordPress', get_bloginfo( 'version' ) );?>
|
83 |
+
</td>
|
84 |
+
</tr>
|
85 |
+
<tr>
|
86 |
+
<th><?php esc_html_e('PHP Version');?></th>
|
87 |
+
<td> <?php echo PHP_VERSION; ?></td>
|
88 |
+
</tr>
|
89 |
+
<tr>
|
90 |
+
<th><?php esc_html_e('MySQL Version');?></th>
|
91 |
+
<td> <?php echo mysql_get_server_info(); ?></td>
|
92 |
+
</tr>
|
93 |
+
<tr>
|
94 |
+
<th><?php esc_html_e('Web Server');?></th>
|
95 |
+
<td> <?php echo $_SERVER['SERVER_SOFTWARE']; ?></td>
|
96 |
+
</tr>
|
97 |
+
<tr>
|
98 |
+
<th><?php esc_html_e('PHP Memory Usage');?></th>
|
99 |
+
<th><?php echo $eo_debugger->verbose_memory_check(); ?>
|
100 |
+
</tr>
|
101 |
+
<tr>
|
102 |
+
<th><?php esc_html_e('PHP Post Max Size');?></th>
|
103 |
+
<td><?php echo ini_get('post_max_size'); ?></td>
|
104 |
+
</tr>
|
105 |
+
<tr>
|
106 |
+
<th><?php esc_html_e('PHP Upload Max Size');?></th>
|
107 |
+
<td><?php echo ini_get('upload_max_filesize'); ?></td>
|
108 |
+
</tr>
|
109 |
+
<tr>
|
110 |
+
<th><?php esc_html_e('PHP cURL Support');?></th>
|
111 |
+
<td> <?php echo (function_exists('curl_init')) ? _e('Yes', 'eventorganiser') . "\n" : _e('No', 'eventorganiser') . "\n"; ?></td>
|
112 |
+
</tr>
|
113 |
+
<tr>
|
114 |
+
<th><?php esc_html_e('Plug-ins');?></th>
|
115 |
+
<td>
|
116 |
+
<?php $eo_debugger->verbose_plugin_check();?>
|
117 |
+
</td>
|
118 |
+
</tr>
|
119 |
+
<tr>
|
120 |
+
<th><?php esc_html_e('Theme');?></th>
|
121 |
+
<td>
|
122 |
+
<?php $eo_debugger->verbose_theme_check();?>
|
123 |
+
</td>
|
124 |
+
</tr>
|
125 |
+
<tr>
|
126 |
+
<th><?php esc_html_e('Databse Prefix:');?></th>
|
127 |
+
<td><?php global $wpdb; echo $wpdb->prefix; ?></td>
|
128 |
+
</tr>
|
129 |
+
<tr>
|
130 |
+
<th><?php esc_html_e('Database tables');?></th>
|
131 |
+
<td>
|
132 |
+
<?php $eo_debugger->verbose_database_check();?>
|
133 |
+
</td>
|
134 |
+
</tr>
|
135 |
+
<tr>
|
136 |
+
<th><?php esc_html_e('Database character set');?></th>
|
137 |
+
<td>
|
138 |
+
<?php $eo_debugger->verbose_database_charset_check();?>
|
139 |
+
</td>
|
140 |
+
</tr>
|
141 |
+
<tr>
|
142 |
+
<th><?php esc_html_e('Debug mode');?></th>
|
143 |
+
<td><?php echo defined( 'WP_DEBUG' ) && WP_DEBUG ? 'Enabled' : 'Disabled'; ?></td>
|
144 |
+
</tr>
|
145 |
+
|
146 |
+
<tr>
|
147 |
+
<th><?php printf( esc_html__( '%s present', 'eventorganiser' ), '<code>wp_footer()</code>' );?></th>
|
148 |
+
<td><?php $eo_debugger->verbose_footer_check();?></td>
|
149 |
+
</tr>
|
150 |
+
<tr>
|
151 |
+
<th><?php esc_html_e('Widget Sidebars');?></th>
|
152 |
+
<td><?php $eo_debugger->verbose_sidebar_check();?></td>
|
153 |
+
</tr>
|
154 |
+
<tr>
|
155 |
+
<th><?php esc_html_e('Timezone');?></th>
|
156 |
+
<td><?php echo eo_get_blog_timezone()->getName(); printf( ' ( %s / %s ) ', get_option( 'gmt_offset' ), get_option( 'timezone_string' ) )?></td>
|
157 |
+
</tr>
|
158 |
+
</table>
|
159 |
+
<?php
|
160 |
+
printf(
|
161 |
+
'<p class="description"> <span class="eo-debug-warning">*</span> %s </p>',
|
162 |
+
__( 'Known plug-in & theme conflicts, highlighted in red, may be minor or have a simple resolution. Please contact support.' )
|
163 |
+
);
|
164 |
+
?>
|
165 |
+
</div><!--End .wrap -->
|
166 |
+
<?php
|
167 |
+
}
|
168 |
+
|
169 |
+
}
|
170 |
+
$venues_page = new EventOrganiser_Debug_Page();
|
171 |
+
|
172 |
+
class EventOrganiser_Debugger{
|
173 |
+
|
174 |
+
var $prequiste = array();
|
175 |
+
var $plugins = array();
|
176 |
+
var $themes = array();
|
177 |
+
var $db_tables = array();
|
178 |
+
var $plugin = 'Event Organiser';
|
179 |
+
|
180 |
+
var $ok_class = 'eo-debug-ok';
|
181 |
+
var $warning_class = 'eo-debug-warning';
|
182 |
+
var $alert_class = 'eo-debug-alert';
|
183 |
+
|
184 |
+
function set_plugin( $plugin ){
|
185 |
+
$this->plugin = $plugin;
|
186 |
+
}
|
187 |
+
|
188 |
+
function set_prequiste( $requirement, $min = false, $max = false ){
|
189 |
+
$this->prequiste[$requirement] = compact( 'min', 'max' );
|
190 |
+
}
|
191 |
+
|
192 |
+
function set_known_plugin_conflicts( ){
|
193 |
+
$this->plugins = array_merge( $this->plugins, array_map( 'strtolower', func_get_args() ) );
|
194 |
+
}
|
195 |
+
|
196 |
+
function set_known_theme_conflicts( ){
|
197 |
+
$this->themes = array_merge( $this->themes, func_get_args() );
|
198 |
+
}
|
199 |
+
|
200 |
+
function set_db_tables( ){
|
201 |
+
$this->db_tables = array_merge( $this->db_tables, func_get_args() );
|
202 |
+
}
|
203 |
+
|
204 |
+
function check_prequiste( $requirement, $v ){
|
205 |
+
if( !isset( $this->prequiste[$requirement] ) )
|
206 |
+
return 1;
|
207 |
+
|
208 |
+
$versions = $this->prequiste[$requirement];
|
209 |
+
|
210 |
+
if( $versions['min'] && version_compare( $versions['min'], $v ) > 0 )
|
211 |
+
return -1;
|
212 |
+
|
213 |
+
if( $versions['max'] && version_compare( $versions['max'], $v ) < 0 )
|
214 |
+
return 0;
|
215 |
+
|
216 |
+
return 1;
|
217 |
+
}
|
218 |
+
|
219 |
+
function verbose_plugin_check(){
|
220 |
+
$installed = get_plugins();
|
221 |
+
|
222 |
+
foreach( $installed as $plugin_slug => $plugin_data ){
|
223 |
+
if( ! is_plugin_active( $plugin_slug ) )
|
224 |
+
continue;
|
225 |
+
|
226 |
+
$class = in_array( strtolower( $plugin_slug ), $this->plugins ) ? $this->warning_class : '';
|
227 |
+
|
228 |
+
printf(
|
229 |
+
' <span class="%s"> %s %s </span> </br>',
|
230 |
+
esc_attr( $class ),
|
231 |
+
$plugin_data['Name'],
|
232 |
+
$plugin_data['Version']
|
233 |
+
);
|
234 |
+
}
|
235 |
+
}
|
236 |
+
|
237 |
+
function verbose_theme_check(){
|
238 |
+
if( version_compare( '3.4', get_bloginfo( 'version' ) ) <= 0 ){
|
239 |
+
$theme = wp_get_theme();
|
240 |
+
$class = in_array( strtolower( $theme->stylesheet ), $this->themes ) ? $this->warning_class : '';
|
241 |
+
printf(
|
242 |
+
' <span class="%s"> %s %s </span> </br> %s',
|
243 |
+
esc_attr( $class ),
|
244 |
+
$theme->get('Name'),
|
245 |
+
$theme->get('Version'),
|
246 |
+
$theme->get('ThemeURI')
|
247 |
+
);
|
248 |
+
}else{
|
249 |
+
$theme_name = get_current_theme();
|
250 |
+
$class = in_array( strtolower( $theme_name ), $this->themes ) ? $this->warning_class : '';
|
251 |
+
printf(
|
252 |
+
' <span class="%s"> %s </span> </br>',
|
253 |
+
esc_attr( $class ),
|
254 |
+
$theme_name
|
255 |
+
);
|
256 |
+
}
|
257 |
+
}
|
258 |
+
|
259 |
+
function verbose_database_check(){
|
260 |
+
if( $this->db_tables ){
|
261 |
+
foreach( $this->db_tables as $db_table ){
|
262 |
+
$class = $this->table_exists( $db_table ) ? $this->ok_class : $this->warning_class;
|
263 |
+
printf( '<span class="%s"> %s </span></br>', esc_attr( $class ), esc_attr( $db_table ) );
|
264 |
+
}
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
+
function table_exists( $table ){
|
269 |
+
global $wpdb;
|
270 |
+
return $wpdb->get_var("show tables like '".$wpdb->prefix.$table."'") == $wpdb->prefix.$table;
|
271 |
+
}
|
272 |
+
|
273 |
+
function verbose_database_charset_check(){
|
274 |
+
global $wpdb;
|
275 |
+
|
276 |
+
if( $wpdb->query( $wpdb->prepare( 'SHOW CHARACTER SET WHERE LOWER( Charset ) = LOWER( %s )', DB_CHARSET ) ) )
|
277 |
+
$class = '';
|
278 |
+
else
|
279 |
+
$class = $this->warning_class;
|
280 |
+
|
281 |
+
printf( '<span class="%s"> %s </span></br>', esc_attr( $class ), esc_attr( DB_CHARSET ) );
|
282 |
+
}
|
283 |
+
|
284 |
+
function verbose_prequiste_check( $requirement, $v ){
|
285 |
+
|
286 |
+
$versions = $this->prequiste[$requirement];
|
287 |
+
|
288 |
+
if( 1 == $this->check_prequiste( $requirement, $v ) ){
|
289 |
+
printf( '<span class="%s">%s</span>', esc_attr( $this->ok_class ), $v );
|
290 |
+
}elseif( 0 == $this->check_prequiste( $requirement, $v ) ){
|
291 |
+
printf(
|
292 |
+
'<span class="%s">%s</span>. %s',
|
293 |
+
esc_attr( $this->alert_class ),
|
294 |
+
$v,
|
295 |
+
sprintf( __( '%s has only been tested up to %s %s' ), $this->plugin, $requirement, $versions['max'] )
|
296 |
+
);
|
297 |
+
}elseif( -1 == $this->check_prequiste( $requirement, $v ) ){
|
298 |
+
printf(
|
299 |
+
'<span class="%s">%s</span>. %s',
|
300 |
+
esc_attr( $this->warning_class ),
|
301 |
+
$v,
|
302 |
+
sprintf( __( '%s requires %s version %s or higher' ), $this->plugin, $requirement, $versions['min'] )
|
303 |
+
);
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
function verbose_sidebar_check(){
|
308 |
+
$footer_present = get_option( 'eo_sidebar_correct' );
|
309 |
+
|
310 |
+
if( $footer_present === false ){
|
311 |
+
printf(
|
312 |
+
'<span class="%s">%s</span><br/> %s',
|
313 |
+
esc_attr( $this->alert_class ),
|
314 |
+
__( 'Unknown', 'eventorganiser' ),
|
315 |
+
sprintf( __( 'Turn <a href="%s">WP_Debug mode</a> on and revisit the front-end to check' ), 'http://codex.wordpress.org/WP_DEBUG' )
|
316 |
+
);
|
317 |
+
}elseif( $footer_present == 1 ){
|
318 |
+
printf(
|
319 |
+
'<span class="%s">%s</span><br/> %s',
|
320 |
+
esc_attr( $this->ok_class ),
|
321 |
+
__( 'Correctly registered', 'eventorganiser' ),
|
322 |
+
sprintf( __( 'Turn <a href="%s">WP_Debug mode</a> on and revisit the front-end to check' ), 'http://codex.wordpress.org/WP_DEBUG' )
|
323 |
+
);
|
324 |
+
}else{
|
325 |
+
printf(
|
326 |
+
'<span class="%s">%s</span><br/> %s',
|
327 |
+
esc_attr( $this->warning_class ),
|
328 |
+
__( 'Incorrectly registered', 'eventorganiser' ),
|
329 |
+
sprintf(
|
330 |
+
__( "The widget sidebars are incorrectly registered. See the <a href='%s'>FAQ</a> or contact support to resolve this." ),
|
331 |
+
'http://wp-event-organiser.com/faq#i-cannot-navigate-between-months-on-the-widget-calendar'
|
332 |
+
)
|
333 |
+
);
|
334 |
+
}
|
335 |
+
}
|
336 |
+
|
337 |
+
function verbose_memory_check(){
|
338 |
+
|
339 |
+
if( function_exists( 'memory_get_usage' ) ){
|
340 |
+
$memory_usage = round( memory_get_usage() / 1024 / 1024, 2);
|
341 |
+
$percentage = round( $memory_usage / ini_get( 'memory_limit' ) * 100, 0 );
|
342 |
+
printf( '%d / %d <span class="%s">( %s )</span>',
|
343 |
+
ceil( $memory_usage ),
|
344 |
+
ini_get( 'memory_limit' ),
|
345 |
+
$percentage > 90 ? $this->alert_class : $this->ok_class,
|
346 |
+
$percentage . "%"
|
347 |
+
);
|
348 |
+
}else{
|
349 |
+
printf( ' ? / %d <span class="%s">( %s )</span>',
|
350 |
+
ini_get( 'memory_limit' ),
|
351 |
+
$this->alert_class,
|
352 |
+
__( 'unknown', 'eventorganiser' )
|
353 |
+
);
|
354 |
+
}
|
355 |
+
|
356 |
+
}
|
357 |
+
|
358 |
+
function verbose_footer_check(){
|
359 |
+
$footer_present = get_option( 'eo_wp_footer_present' );
|
360 |
+
|
361 |
+
if( $footer_present === false ){
|
362 |
+
printf(
|
363 |
+
'<span class="%s">%s</span><br/> %s',
|
364 |
+
esc_attr( $this->alert_class ),
|
365 |
+
__( 'Unknown', 'eventorganiser' ),
|
366 |
+
sprintf( __( 'Turn <a href="%s">WP_Debug mode</a> on and revisit the front-end to check' ), 'http://codex.wordpress.org/WP_DEBUG' )
|
367 |
+
);
|
368 |
+
}elseif( $footer_present == 1 ){
|
369 |
+
printf(
|
370 |
+
'<span class="%s">%s</span><br/> %s',
|
371 |
+
esc_attr( $this->ok_class ),
|
372 |
+
__( 'Yes', 'eventorganiser' ),
|
373 |
+
sprintf( __( 'Turn <a href="%s">WP_Debug mode</a> on and revisit the front-end to check' ), 'http://codex.wordpress.org/WP_DEBUG' )
|
374 |
+
);
|
375 |
+
}else{
|
376 |
+
printf(
|
377 |
+
'<span class="%s">%s</span><br/> %s',
|
378 |
+
esc_attr( $this->warning_class ),
|
379 |
+
__( 'No', 'eventorganiser' ),
|
380 |
+
sprintf(
|
381 |
+
__( "The <a href='%s'>wp_footer hook</a> could be not be found. Without, for example, the calendar will not function" ),
|
382 |
+
'http://codex.wordpress.org/Function_Reference/wp_footer'
|
383 |
+
)
|
384 |
+
);
|
385 |
+
}
|
386 |
+
}
|
387 |
+
}
|
event-organiser-edit.php
ADDED
@@ -0,0 +1,389 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Functions for Event CPT editing / creating page
|
4 |
+
* @since 1.0.0
|
5 |
+
*/
|
6 |
+
/**
|
7 |
+
* Initialises the plug-ins metaboxs on Event CPT
|
8 |
+
* @since 1.0.0
|
9 |
+
* @ignore
|
10 |
+
*/
|
11 |
+
function eventorganiser_edit_init(){
|
12 |
+
|
13 |
+
// add a meta box to event post types.
|
14 |
+
add_meta_box( 'eventorganiser_detail', __( 'Event Details', 'eventorganiser' ), '_eventorganiser_details_metabox', 'event', 'normal', 'high' );
|
15 |
+
|
16 |
+
// add a callback function to save any data a user enters in
|
17 |
+
add_action( 'save_post', 'eventorganiser_details_save' );
|
18 |
+
}
|
19 |
+
add_action( 'admin_init', 'eventorganiser_edit_init' );
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Repurposes author metabox as organiser
|
23 |
+
* @since 1.0.0
|
24 |
+
* @ignore
|
25 |
+
*/
|
26 |
+
function _eventorganiser_author_meta_box_title() {
|
27 |
+
remove_meta_box( 'authordiv', 'event', 'core' );
|
28 |
+
add_meta_box( 'authordiv', __( 'Organiser', 'eventorganiser' ), 'post_author_meta_box', 'event', 'core', 'high' );
|
29 |
+
}
|
30 |
+
add_action( 'add_meta_boxes_event', '_eventorganiser_author_meta_box_title' );
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Sets up the event data metabox
|
34 |
+
* This allows user to enter date / time, reoccurrence and venue data for the event
|
35 |
+
* @ignore
|
36 |
+
* @since 1.0.0
|
37 |
+
*/
|
38 |
+
function _eventorganiser_details_metabox( $post ){
|
39 |
+
global $wp_locale;
|
40 |
+
|
41 |
+
//Sets the format as php understands it, and textual.
|
42 |
+
$phpFormat = eventorganiser_get_option( 'dateformat' );
|
43 |
+
if ( 'd-m-Y' == $phpFormat ){
|
44 |
+
$format = 'dd-mm-yyyy'; //Human form
|
45 |
+
} elseif( 'Y-m-d' == $phpFormat ) {
|
46 |
+
$format = 'yyyy-mm-dd'; //Human form
|
47 |
+
}else{
|
48 |
+
$format = 'mm-dd-yyyy'; //Human form
|
49 |
+
}
|
50 |
+
|
51 |
+
//Get the starting day of the week
|
52 |
+
$start_day = intval( get_option( 'start_of_week' ) );
|
53 |
+
$ical_days = array( 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA' );
|
54 |
+
|
55 |
+
//Retrieve event details
|
56 |
+
extract( eo_get_event_schedule( $post->ID ) );
|
57 |
+
$venues = eo_get_venues();
|
58 |
+
$venue_id = (int) eo_get_venue( $post->ID );
|
59 |
+
|
60 |
+
|
61 |
+
//$sche_once is used to disable date editing unless the user specifically requests it.
|
62 |
+
//But a new event might be recurring (via filter), and we don't want to 'lock' new events.
|
63 |
+
//See http://wordpress.org/support/topic/wrong-default-in-input-element
|
64 |
+
$sche_once = ( $schedule == 'once' || !empty(get_current_screen()->action) );
|
65 |
+
|
66 |
+
if ( !$sche_once ){
|
67 |
+
$notices = '<strong>'. __( 'This is a reoccurring event', 'eventorganiser' ).'</strong>. '
|
68 |
+
. __( 'Check to edit this event and its reoccurrences', 'eventorganiser' )
|
69 |
+
.' <input type="checkbox" id="HWSEvent_rec" name="eo_input[AlterRe]" value="yes">';
|
70 |
+
}else{
|
71 |
+
$notices = '';
|
72 |
+
}
|
73 |
+
|
74 |
+
//Start of meta box
|
75 |
+
if( $notices = apply_filters('eventorganiser_event_metabox_notice', $notices, $post ) ){
|
76 |
+
echo '<div class="updated below-h2"><p>'.$notices.'</p></div>';
|
77 |
+
}
|
78 |
+
?>
|
79 |
+
<div class="<?php echo ( $sche_once ? 'onetime': 'reoccurence' );?>">
|
80 |
+
<p><?php printf( __( 'Ensure dates are entered in %1$s format and times in %2$s (24 hour) format', 'eventorganiser' ), '<strong>'.$format.'</strong>', ' <strong>hh:mm</strong>' );?> </p>
|
81 |
+
|
82 |
+
<table id="eventorganiser_event_detail" class="form-table">
|
83 |
+
<tr valign="top" class="event-date">
|
84 |
+
<td class="eo-label"><?php echo __( 'Start Date/Time', 'eventorganiser' ).':'; ?> </td>
|
85 |
+
<td>
|
86 |
+
<input class="ui-widget-content ui-corner-all" name="eo_input[StartDate]" size="10" maxlength="10" id="from_date" <?php disabled( !$sche_once );?> value="<?php echo $start->format( $phpFormat ); ?>"/>
|
87 |
+
|
88 |
+
<input name="eo_input[StartTime]" class="eo_time ui-widget-content ui-corner-all" size="4" maxlength="5" id="HWSEvent_time" <?php disabled( (!$sche_once) || $all_day );?> value="<?php echo $start->format( 'H:i' );?>"/>
|
89 |
+
|
90 |
+
</td>
|
91 |
+
</tr>
|
92 |
+
|
93 |
+
<tr valign="top" class="event-date">
|
94 |
+
<td class="eo-label"><?php echo __( 'End Date/Time', 'eventorganiser' ).':';?> </td>
|
95 |
+
<td>
|
96 |
+
<input class="ui-widget-content ui-corner-all" name="eo_input[EndDate]" size="10" maxlength="10" id="to_date" <?php disabled( !$sche_once );?> value="<?php echo $end->format( $phpFormat ); ?>"/>
|
97 |
+
<input name="eo_input[FinishTime]" class="eo_time ui-widget-content ui-corner-all " size="4" maxlength="5" id="HWSEvent_time2" <?php disabled( (!$sche_once) || $all_day );?> value="<?php echo $end->format( 'H:i' ); ?>"/>
|
98 |
+
|
99 |
+
<label>
|
100 |
+
<input type="checkbox" id="eo_allday" <?php checked( $all_day ); ?> name="eo_input[allday]" <?php disabled( !$sche_once );?> value="1"/>
|
101 |
+
<?php _e( 'All day', 'eventorganiser' );?>
|
102 |
+
</label>
|
103 |
+
|
104 |
+
</td>
|
105 |
+
</tr>
|
106 |
+
|
107 |
+
<tr class="event-date">
|
108 |
+
<td class="eo-label"><?php _e( 'Reoccurence:', 'eventorganiser' );?> </td>
|
109 |
+
<td>
|
110 |
+
<?php $reoccurrence_schedules = array( 'once' => __( 'once', 'eventorganiser' ), 'daily' => __( 'daily', 'eventorganiser' ), 'weekly' => __( 'weekly', 'eventorganiser' ),
|
111 |
+
'monthly' => __( 'monthly', 'eventorganiser' ), 'yearly' => __( 'yearly', 'eventorganiser' ), 'custom' => __( 'custom', 'eventorganiser' ) );?>
|
112 |
+
|
113 |
+
<select id="HWSEventInput_Req" name="eo_input[schedule]">
|
114 |
+
<?php foreach ( $reoccurrence_schedules as $index => $val ): ?>
|
115 |
+
<option value="<?php echo $index;?>" <?php selected( $schedule, $index );?>><?php echo $val;?></option>
|
116 |
+
<?php endforeach; //End foreach $allowed_reoccurs?>
|
117 |
+
</select>
|
118 |
+
</td>
|
119 |
+
</tr>
|
120 |
+
|
121 |
+
<tr valign="top" class="event-date reocurrence_row">
|
122 |
+
<td></td>
|
123 |
+
<td>
|
124 |
+
<p><?php _e( 'Repeat every', 'eventorganiser' );?>
|
125 |
+
<input <?php disabled( !$sche_once || $all_day );?> class="ui-widget-content ui-corner-all" name="eo_input[event_frequency]" id="HWSEvent_freq" type="number" min="1" max="365" maxlength="4" size="4" disabled="disabled" value="<?php echo $frequency;?>" />
|
126 |
+
<span id="recpan" > </span>
|
127 |
+
</p>
|
128 |
+
|
129 |
+
<p id="dayofweekrepeat">
|
130 |
+
<?php _e( 'on', 'eventorganiser' );?>
|
131 |
+
<?php for ($i = 0; $i <= 6; $i++ ):
|
132 |
+
$d = ($start_day + $i) % 7;
|
133 |
+
$ical_d = $ical_days[$d];
|
134 |
+
$day = $wp_locale->weekday_abbrev[$wp_locale->weekday[$d]];
|
135 |
+
$schedule_days = ( is_array( $schedule_meta ) ? $schedule_meta : array() );
|
136 |
+
?>
|
137 |
+
<input type="checkbox" id="day-<?php echo $day;?>" <?php checked( in_array( $ical_d, $schedule_days ), true ); ?> value="<?php echo esc_attr( $ical_d )?>" class="daysofweek" name="eo_input[days][]" disabled="disabled" />
|
138 |
+
<label for="day-<?php echo $day;?>" > <?php echo $day;?></label>
|
139 |
+
<?php endfor; ?>
|
140 |
+
</p>
|
141 |
+
|
142 |
+
<p id="dayofmonthrepeat">
|
143 |
+
<label for="bymonthday" >
|
144 |
+
<input type="radio" id="bymonthday" disabled="disabled" name="eo_input[schedule_meta]" <?php checked( $occurs_by, 'BYMONTHDAY' ); ?> value="BYMONTHDAY=" />
|
145 |
+
<?php _e( 'day of month', 'eventorganiser' );?>
|
146 |
+
</label>
|
147 |
+
<label for="byday" >
|
148 |
+
<input type="radio" id="byday" disabled="disabled" name="eo_input[schedule_meta]" <?php checked( $occurs_by != 'BYMONTHDAY', true ); ?> value="BYDAY=" />
|
149 |
+
<?php _e( 'day of week', 'eventorganiser' );?>
|
150 |
+
</label>
|
151 |
+
</p>
|
152 |
+
|
153 |
+
<p class="reoccurrence_label">
|
154 |
+
<?php _e( 'until', 'eventorganiser' );?>
|
155 |
+
<input <?php disabled( (!$sche_once) || $all_day ); ?> class="ui-widget-content ui-corner-all" name="eo_input[schedule_end]" id="recend" size="10" maxlength="10" disabled="disabled" value="<?php echo $schedule_last->format( $phpFormat ); ?>"/>
|
156 |
+
</p>
|
157 |
+
|
158 |
+
<p id="event_summary"> </p>
|
159 |
+
</td>
|
160 |
+
</tr>
|
161 |
+
|
162 |
+
<tr valign="top" id="eo_occurrence_picker_row" class="event-date">
|
163 |
+
<td class="eo-label">
|
164 |
+
<?php esc_html_e( 'Include/Exclude occurrences', 'eventorganiser' );?>
|
165 |
+
</td>
|
166 |
+
<td>
|
167 |
+
<?php submit_button( __( 'Show dates', 'eventorganiser' ), 'hide-if-no-js eo_occurrence_toogle button small', 'eo_date_toggle', false ); ?>
|
168 |
+
|
169 |
+
<div id="eo_occurrence_datepicker"></div>
|
170 |
+
<?php
|
171 |
+
//var_dump($include);
|
172 |
+
if ( !empty( $include ) ){
|
173 |
+
$include_str = array_map( 'eo_format_datetime', $include, array_fill( 0, count( $include ), 'Y-m-d' ) );
|
174 |
+
$include_str = esc_textarea( sanitize_text_field( implode( ',', $include_str ) ) );
|
175 |
+
} else {
|
176 |
+
$include_str = '';
|
177 |
+
}?>
|
178 |
+
<textarea style="display:none;" name="eo_input[include]" id="eo_occurrence_includes"><?php echo $include_str; ?></textarea>
|
179 |
+
|
180 |
+
<?php
|
181 |
+
if ( !empty($exclude) ){
|
182 |
+
$exclude_str = array_map( 'eo_format_datetime', $exclude, array_fill( 0, count( $exclude ), 'Y-m-d' ) );
|
183 |
+
$exclude_str = esc_textarea( sanitize_text_field( implode( ',', $exclude_str ) ) );
|
184 |
+
} else {
|
185 |
+
$exclude_str = '';
|
186 |
+
}?>
|
187 |
+
<textarea style="display:none;" name="eo_input[exclude]" id="eo_occurrence_excludes"><?php echo $exclude_str; ?></textarea>
|
188 |
+
|
189 |
+
</td>
|
190 |
+
</tr>
|
191 |
+
<tr valign="top"class="eo-venue-combobox-select">
|
192 |
+
<td class="eo-label"> <?php _e( 'Venue', 'eventorganiser' );?>: </td>
|
193 |
+
<td>
|
194 |
+
<select size="50" id="venue_select" name="eo_input[event-venue]">
|
195 |
+
<option><?php _e( 'Select a venue', 'eventorganiser' );?></option>
|
196 |
+
<?php foreach ( $venues as $venue ):?>
|
197 |
+
<option <?php selected( $venue->term_id, $venue_id );?> value="<?php echo intval( $venue->term_id );?>"><?php echo esc_html( $venue->name ); ?></option>
|
198 |
+
<?php endforeach;?>
|
199 |
+
</select>
|
200 |
+
</td>
|
201 |
+
</tr>
|
202 |
+
|
203 |
+
<!-- Add New Venue -->
|
204 |
+
<tr valign="top"class="eo-add-new-venue">
|
205 |
+
<td class="eo-label"><label><?php _e( 'Venue Name', 'eventorganiser' );?>:</label></td>
|
206 |
+
<td><input type="text" name="eo_venue[name]" id="eo_venue_name" value=""/></td>
|
207 |
+
</tr>
|
208 |
+
<?php
|
209 |
+
$address_fields = _eventorganiser_get_venue_address_fields();
|
210 |
+
foreach ( $address_fields as $key => $label ){
|
211 |
+
printf( '<tr valign="top"class="eo-add-new-venue">
|
212 |
+
<th><label>%1$s:</label></th>
|
213 |
+
<td><input type="text" name="eo_venue[%2$s]" class="eo_addressInput" id="eo_venue_add" value=""/></td>
|
214 |
+
</tr>',
|
215 |
+
$label,
|
216 |
+
esc_attr( trim( $key, '_' ) )/* Keys are prefixed by '_' */
|
217 |
+
);
|
218 |
+
}
|
219 |
+
?>
|
220 |
+
<tr valign="top" class="eo-add-new-venue" >
|
221 |
+
<td class="eo-label"></td>
|
222 |
+
<td>
|
223 |
+
<a class="button eo-add-new-venue-cancel" href="#"><?php esc_html_e( 'Cancel','eventorganiser' );?> </a>
|
224 |
+
</td>
|
225 |
+
</tr>
|
226 |
+
|
227 |
+
<!-- Venue Map -->
|
228 |
+
<tr valign="top" class="venue_row <?php if ( !$venue_id ) echo 'novenue';?>" >
|
229 |
+
<td class="eo-label"></td>
|
230 |
+
<td>
|
231 |
+
<div id="eventorganiser_venue_meta" style="display:none;">
|
232 |
+
<input type="hidden" id="eo_venue_Lat" name="eo_venue[latitude]" value="<?php eo_venue_lat( $venue_id );?>" />
|
233 |
+
<input type="hidden" id="eo_venue_Lng" name="eo_venue[longtitude]" value="<?php eo_venue_lng( $venue_id ); ?>" />
|
234 |
+
</div>
|
235 |
+
<div id="venuemap" class="ui-widget-content ui-corner-all gmap3"></div>
|
236 |
+
<div class="clear"></div>
|
237 |
+
</td>
|
238 |
+
</tr>
|
239 |
+
</table>
|
240 |
+
</div>
|
241 |
+
<?php
|
242 |
+
|
243 |
+
// create a custom nonce for submit verification later
|
244 |
+
wp_nonce_field( 'eventorganiser_event_update_'.get_the_ID(), '_eononce' );
|
245 |
+
}
|
246 |
+
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Saves the event data posted from the event metabox.
|
250 |
+
* Hooked to the 'save_post' action
|
251 |
+
*
|
252 |
+
* @since 1.0.0
|
253 |
+
*
|
254 |
+
* @param int $post_id the event post ID
|
255 |
+
* @return int $post_id the event post ID
|
256 |
+
*/
|
257 |
+
function eventorganiser_details_save( $post_id ) {
|
258 |
+
|
259 |
+
//make sure data came from our meta box
|
260 |
+
if ( !isset( $_POST['_eononce'] ) || !wp_verify_nonce( $_POST['_eononce'], 'eventorganiser_event_update_'.$post_id ) ) return;
|
261 |
+
|
262 |
+
// verify this is not an auto save routine.
|
263 |
+
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
|
264 |
+
|
265 |
+
//authentication checks
|
266 |
+
if (!current_user_can( 'edit_event', $post_id ) ) return;
|
267 |
+
|
268 |
+
//Collect raw data
|
269 |
+
$raw_data = ( isset( $_POST['eo_input'] ) ? $_POST['eo_input'] : array() );
|
270 |
+
$raw_data = wp_parse_args( $raw_data, array(
|
271 |
+
'StartDate' => '', 'EndDate' => '', 'StartTime' => '00:00', 'FinishTime' => '23:59', 'schedule' => 'once', 'event_frequency' => 1,
|
272 |
+
'schedule_end' => '', 'allday' => 0, 'schedule_meta' => '', 'days' => array(), 'include' => '', 'exclude' => '', ) );
|
273 |
+
|
274 |
+
//Update venue
|
275 |
+
$venue_id = !empty( $raw_data['event-venue'] ) ? intval( $raw_data['event-venue'] ) : null;
|
276 |
+
|
277 |
+
//Maybe create a new venue
|
278 |
+
if ( empty( $venue_id ) && !empty( $_POST['eo_venue']) && current_user_can( 'manage_venues' ) ){
|
279 |
+
$venue = $_POST['eo_venue'];
|
280 |
+
if ( !empty( $venue['name'] ) ){
|
281 |
+
$new_venue = eo_insert_venue( $venue['name'], $venue );
|
282 |
+
if ( !is_wp_error( $new_venue ) )
|
283 |
+
$venue_id = $new_venue['term_id'];
|
284 |
+
}
|
285 |
+
}
|
286 |
+
|
287 |
+
//Set venue
|
288 |
+
$r = wp_set_post_terms( $post_id, array( $venue_id ), 'event-venue', false );
|
289 |
+
|
290 |
+
|
291 |
+
//If reocurring, but not editing occurrences, can abort here, but trigger hook.
|
292 |
+
if ( eo_reoccurs( $post_id ) && ( !isset( $raw_data['AlterRe'] ) || 'yes' != $raw_data['AlterRe'] ) ){
|
293 |
+
do_action( 'eventorganiser_save_event', $post_id );//Need this to update cache
|
294 |
+
return;
|
295 |
+
}
|
296 |
+
|
297 |
+
//Set times for all day events
|
298 |
+
$all_day = intval($raw_data['allday']);
|
299 |
+
if ( $all_day ){
|
300 |
+
$raw_data['StartTime'] = '00:00';
|
301 |
+
$raw_data['FinishTime'] = '23:59';
|
302 |
+
}
|
303 |
+
|
304 |
+
//Check dates
|
305 |
+
$start = _eventorganiser_check_datetime( trim( $raw_data['StartDate'] ) . ' ' . trim( $raw_data['StartTime'] ) );
|
306 |
+
$end = _eventorganiser_check_datetime( trim( $raw_data['EndDate'] ) . ' ' . trim( $raw_data['FinishTime'] ) );
|
307 |
+
$schedule_last = _eventorganiser_check_datetime( trim( $raw_data['schedule_end'] ) . ' ' . trim( $raw_data['StartTime'] ) );
|
308 |
+
|
309 |
+
//Collect schedule meta
|
310 |
+
$schedule = $raw_data['schedule'];
|
311 |
+
if ( 'weekly' == $schedule ){
|
312 |
+
$schedule_meta = $raw_data['days'];
|
313 |
+
$occurs_by = '';
|
314 |
+
} elseif ( 'monthly' == $schedule ){
|
315 |
+
$schedule_meta = $raw_data['schedule_meta'];
|
316 |
+
$occurs_by = trim( $schedule_meta, '=' );
|
317 |
+
} else {
|
318 |
+
$schedule_meta = '';
|
319 |
+
$occurs_by = '';
|
320 |
+
}
|
321 |
+
|
322 |
+
//Collect include/exclude
|
323 |
+
$in_ex = array();
|
324 |
+
foreach ( array( 'include', 'exclude' ) as $key ):
|
325 |
+
$in_ex[$key] = array();
|
326 |
+
$arr = explode( ',', sanitize_text_field( $raw_data[$key] ) );
|
327 |
+
if ( !empty( $arr ) ){
|
328 |
+
foreach ( $arr as $date ):
|
329 |
+
$date_obj = _eventorganiser_check_datetime( $date . ' ' . $raw_data['StartTime'], 'Y-m-d' );
|
330 |
+
if( $date_obj )
|
331 |
+
$in_ex[$key][] = $date_obj;
|
332 |
+
endforeach;
|
333 |
+
}
|
334 |
+
endforeach;
|
335 |
+
|
336 |
+
$event_data = array(
|
337 |
+
'start' => $start,
|
338 |
+
'end' => $end,
|
339 |
+
'all_day' => $all_day,
|
340 |
+
'schedule' => $schedule,
|
341 |
+
'frequency' => (int) $raw_data['event_frequency'],
|
342 |
+
'schedule_last' => $schedule_last,
|
343 |
+
'schedule_meta' => $schedule_meta,
|
344 |
+
'occurs_by' => $occurs_by,
|
345 |
+
'include' => $in_ex['include'],
|
346 |
+
'exclude' => $in_ex['exclude'],
|
347 |
+
);
|
348 |
+
|
349 |
+
$response = eo_update_event( $post_id, $event_data );
|
350 |
+
|
351 |
+
if ( is_wp_error( $response ) ){
|
352 |
+
global $EO_Errors;
|
353 |
+
$code = $response->get_error_code();
|
354 |
+
$message = $response->get_error_message( $code );
|
355 |
+
$errors[$post_id][] = __( 'Event dates were not saved.', 'eventorganiser' );
|
356 |
+
$errors[$post_id][] = $message;
|
357 |
+
$EO_Errors->add( 'eo_error',$message );
|
358 |
+
update_option( 'eo_notice', $errors );
|
359 |
+
}
|
360 |
+
|
361 |
+
return;
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Display custom error or alert messages on events CPT page
|
366 |
+
*
|
367 |
+
* @ignore
|
368 |
+
* @since 1.0.0
|
369 |
+
*/
|
370 |
+
add_action( 'admin_notices', '_eventorganiser_event_edit_admin_notice', 0 );
|
371 |
+
function _eventorganiser_event_edit_admin_notice(){
|
372 |
+
|
373 |
+
global $post;
|
374 |
+
|
375 |
+
$notice = get_option( 'eo_notice' );
|
376 |
+
if ( empty( $notice ) || empty( $post->ID ) ) return '';
|
377 |
+
|
378 |
+
foreach ( $notice as $pid => $messages ){
|
379 |
+
if ( $post->ID == $pid ){
|
380 |
+
printf( '<div id="message" class="error"> <p> %s </p> </div>', implode( ' </p> <p> ', $messages ) );
|
381 |
+
|
382 |
+
//make sure to remove notice after its displayed so its only displayed when needed.
|
383 |
+
unset( $notice[0] );
|
384 |
+
unset( $notice[$pid] );
|
385 |
+
update_option( 'eo_notice', $notice );
|
386 |
+
}
|
387 |
+
}
|
388 |
+
}
|
389 |
+
?>
|
event-organiser-go-pro.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Calendar Admin Page
|
4 |
+
*/
|
5 |
+
if(!class_exists('EventOrganiser_Admin_Page')){
|
6 |
+
require_once(EVENT_ORGANISER_DIR.'classes/class-eventorganiser-admin-page.php' );
|
7 |
+
}
|
8 |
+
/**
|
9 |
+
* Calendar Admin Page
|
10 |
+
*
|
11 |
+
* Extends the EentOrganiser_Admin_Page class. Creates the calendar admin page
|
12 |
+
* @version 1.0
|
13 |
+
* @see EventOrganiser_Admin_Page
|
14 |
+
* @package event organiser
|
15 |
+
*/
|
16 |
+
class EventOrganiser_Pro_Page extends EventOrganiser_Admin_Page
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
* This sets the calendar page variables
|
20 |
+
*/
|
21 |
+
function set_constants(){
|
22 |
+
$this->hook = 'edit.php?post_type=event';
|
23 |
+
$this->title = __('Get Event Organiser Pro Add-On','eventorganiser');
|
24 |
+
$this->menu =__('Go Pro','eventorganiser');
|
25 |
+
$this->permissions ='manage_options';
|
26 |
+
$this->slug ='eo-pro';
|
27 |
+
}
|
28 |
+
|
29 |
+
function add_page(){
|
30 |
+
self::$page = add_dashboard_page($this->title, $this->menu, $this->permissions,$this->slug, array($this,'render_page'),10);
|
31 |
+
add_action('load-'.self::$page, array($this,'page_actions'),9);
|
32 |
+
add_action('admin_print_scripts-'.self::$page, array($this,'page_styles'),10);
|
33 |
+
add_action('admin_print_styles-'.self::$page, array($this,'page_scripts'),10);
|
34 |
+
add_action("admin_footer-".self::$page,array($this,'footer_scripts'));
|
35 |
+
remove_submenu_page('index.php',$this->slug);
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Enqueues the page's scripts and styles, and localises them.
|
40 |
+
*/
|
41 |
+
function page_scripts(){
|
42 |
+
}
|
43 |
+
|
44 |
+
|
45 |
+
function display(){
|
46 |
+
$plugins = get_plugins();
|
47 |
+
$plugin = $plugins['event-organiser/event-organiser.php'];
|
48 |
+
?>
|
49 |
+
<div class="wrap">
|
50 |
+
<div class="wrap about-wrap">
|
51 |
+
<h1> <?php printf(__('Get Event Organiser Pro', 'eventorganiser'), $plugin['Version']); ?> </h1>
|
52 |
+
|
53 |
+
<div class="about-text"><?php
|
54 |
+
echo '<p>'.__( 'Event Organiser Pro is a premium add-on bringing advanced booking management to Event Organiser.', 'eventorganiser' );
|
55 |
+
echo '<p>'.__( "But that's not all …", 'eventorganiser' ); ?>
|
56 |
+
</div>
|
57 |
+
|
58 |
+
<div class="event-organiser-logo" style="background: url('<?php echo EVENT_ORGANISER_URL.'css/images/eobadge.png';?>');padding-top: 150px;height: 52px;width: 185px;color: #666;font-weight: bold;font-size: 14px;text-align: center;text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8);margin: 0 -5px;position: absolute;top: 0;right: 0;"></div>
|
59 |
+
|
60 |
+
<hr style="color:#CCC;background-color:#CCC;border:0;border-bottom:1px solid #CCC;">
|
61 |
+
|
62 |
+
<style>
|
63 |
+
.eo-feature-section {float: left;margin: 2%;width: 29%;}
|
64 |
+
.eo-feature-section img{border: 1px #CCC solid;-webkit-box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.3 );box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.3 );}
|
65 |
+
</style>
|
66 |
+
|
67 |
+
<?php
|
68 |
+
|
69 |
+
self::print_feature(
|
70 |
+
__( 'Flexible Booking Options', 'eventorganiser' ),
|
71 |
+
__("Sell tickets for specific dates or sell tickets for all dates of an event – such as booking places on a course. You can offer multiple tickets, and customise the booking form to suit your needs.", 'eventorganiser'),
|
72 |
+
'eo-pro-ticket-picker.png'
|
73 |
+
);
|
74 |
+
self::print_feature(
|
75 |
+
__( 'Additional shortcodes & improved UI', 'eventorganiser' ),
|
76 |
+
__( 'Give your users the ability to search and filter through your events with the event search shortcode. Event Organiser Pro also adds a text editor button to make inserting and configuring your shorcodes that bit easier. ', 'eventorganiser' ),
|
77 |
+
'eo-pro-event-search.png'
|
78 |
+
);
|
79 |
+
self::print_feature(
|
80 |
+
__( 'Venue custom fields & thumbnails', 'eventorganiser' ),
|
81 |
+
__( "Add action information on your venue pages with venue custom fields, or give your venues more attentioned with their own 'featured image'", 'eventorganiser' ),
|
82 |
+
'eo-pro-venue-cf.png'
|
83 |
+
);
|
84 |
+
?>
|
85 |
+
|
86 |
+
<div style="clear:both"></div>
|
87 |
+
|
88 |
+
<p>
|
89 |
+
<strong><a href="http://wp-event-organiser.com/pro-features"><?php _e('Find out more …', 'eventorganiser')?></a></strong>
|
90 |
+
</p>
|
91 |
+
|
92 |
+
<hr style="color:#CCC;background-color:#CCC;border:0;border-bottom:1px solid #CCC;">
|
93 |
+
|
94 |
+
<div class="return-to-dashboard">
|
95 |
+
<a href="<?php echo admin_url('options-general.php?page=event-settings');?>"><?php _e('Go to Event Organiser settings', 'eventorganiser');?></a>
|
96 |
+
</div>
|
97 |
+
</div>
|
98 |
+
</div><!-- .wrap -->
|
99 |
+
<?php
|
100 |
+
}
|
101 |
+
|
102 |
+
static function print_feature( $title, $content, $img ){
|
103 |
+
?>
|
104 |
+
<div class="eo-feature-section images-stagger-right">
|
105 |
+
<img src="<?php echo EVENT_ORGANISER_URL.'css/images/'.$img?>">
|
106 |
+
<?php echo '<h4>'.$title.'</h4>'; ?>
|
107 |
+
<p> <?php echo $content; ?></p>
|
108 |
+
</div>
|
109 |
+
<?php
|
110 |
+
}
|
111 |
+
|
112 |
+
}
|
113 |
+
$calendar_page = new EventOrganiser_Pro_Page();
|
114 |
+
|
115 |
+
?>
|
event-organiser-manage.php
ADDED
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Functions altering the CPT Event table
|
4 |
+
*
|
5 |
+
* @since 1.0.0
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Adds custom columns to Event CPT table
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
add_filter( 'manage_edit-event_columns', 'eventorganiser_event_add_columns' );
|
13 |
+
function eventorganiser_event_add_columns( $columns ) {
|
14 |
+
|
15 |
+
unset( $columns['date'] );//Unset unnecessary columns
|
16 |
+
|
17 |
+
//Set 'title' column title
|
18 |
+
$columns['title'] = __( 'Event', 'eventorganiser' );
|
19 |
+
|
20 |
+
//If displaying 'author', change title
|
21 |
+
if ( isset( $columns['author'] ) )
|
22 |
+
$columns['author'] = __( 'Organiser', 'eventorganiser' );
|
23 |
+
|
24 |
+
$columns['venue'] = __( 'Venue', 'eventorganiser' );
|
25 |
+
$columns['eventcategories'] = __( 'Categories' );
|
26 |
+
$columns['datestart'] = __( 'Start Date/Time', 'eventorganiser' );
|
27 |
+
$columns['dateend'] = __( 'End Date/Time', 'eventorganiser' );
|
28 |
+
$columns['reoccurence'] = __( 'Reoccurrence', 'eventorganiser' );
|
29 |
+
|
30 |
+
return $columns;
|
31 |
+
}
|
32 |
+
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Registers the custom columns in Event CPT table to be sortable
|
36 |
+
* @since 1.0.0
|
37 |
+
*/
|
38 |
+
add_filter( 'manage_edit-event_sortable_columns', 'eventorganiser_event_sortable_columns' );
|
39 |
+
function eventorganiser_event_sortable_columns( $columns ) {
|
40 |
+
$columns['datestart'] = 'eventstart';
|
41 |
+
$columns['dateend'] = 'eventend';
|
42 |
+
return $columns;
|
43 |
+
}
|
44 |
+
|
45 |
+
|
46 |
+
/**
|
47 |
+
* What to display in custom columns of Event CPT table
|
48 |
+
* @since 1.0.0
|
49 |
+
*/
|
50 |
+
add_action( 'manage_event_posts_custom_column', 'eventorganiser_event_fill_columns', 10, 2 );
|
51 |
+
function eventorganiser_event_fill_columns( $column_name, $id ) {
|
52 |
+
global $post;
|
53 |
+
|
54 |
+
$series_id = ( empty( $post->event_id) ? $id :'' );
|
55 |
+
|
56 |
+
$phpFormat = 'M, j Y';
|
57 |
+
if ( !eo_is_all_day( $series_id ) )
|
58 |
+
$phpFormat .= '\<\/\b\r\>'. get_option( 'time_format' );
|
59 |
+
|
60 |
+
switch ( $column_name ) {
|
61 |
+
case 'venue':
|
62 |
+
$terms = get_the_terms( $post->ID, 'event-venue' );
|
63 |
+
|
64 |
+
if ( !empty( $terms) ) {
|
65 |
+
foreach ( $terms as $term )
|
66 |
+
$post_terms[] = '<a href="'. add_query_arg( 'event-venue', $term->slug ) .'">'.esc_html( sanitize_term_field( 'name', $term->name, $term->term_id, 'event-venue', 'display' ) ) . '</a>';
|
67 |
+
echo join( ', ', $post_terms );
|
68 |
+
echo '<input type="hidden" value="'.$term->term_id.'"/>';
|
69 |
+
}
|
70 |
+
break;
|
71 |
+
|
72 |
+
case 'datestart':
|
73 |
+
eo_the_start( $phpFormat, $series_id );
|
74 |
+
break;
|
75 |
+
|
76 |
+
case 'dateend':
|
77 |
+
eo_the_end( $phpFormat, $series_id );
|
78 |
+
break;
|
79 |
+
|
80 |
+
case 'reoccurence':
|
81 |
+
eo_display_reoccurence( $series_id );
|
82 |
+
break;
|
83 |
+
|
84 |
+
case 'eventcategories':
|
85 |
+
$terms = get_the_terms( $post->ID, 'event-category' );
|
86 |
+
|
87 |
+
if ( !empty( $terms) ) {
|
88 |
+
foreach ( $terms as $term )
|
89 |
+
$post_terms[] = '<a href=""'.add_query_arg( 'event-category', $term->slug ).'">'.esc_html( sanitize_term_field( 'name', $term->name, $term->term_id, 'event-category', 'display' ) ).'</a>';
|
90 |
+
echo join( ', ', $post_terms );
|
91 |
+
}
|
92 |
+
break;
|
93 |
+
|
94 |
+
default:
|
95 |
+
break;
|
96 |
+
} // end switch
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Adds a drop-down filter to the Event CPT table by category
|
101 |
+
* @since 1.0.0
|
102 |
+
*/
|
103 |
+
add_action( 'restrict_manage_posts', 'eventorganiser_restrict_events_by_category' );
|
104 |
+
function eventorganiser_restrict_events_by_category() {
|
105 |
+
|
106 |
+
// only display these taxonomy filters on desired custom post_type listings
|
107 |
+
global $typenow, $wp_query;
|
108 |
+
if ( $typenow == 'event' ) {
|
109 |
+
eo_event_category_dropdown( array( 'hide_empty' => false, 'show_option_all' => __( 'View all categories' ) ) );
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Adds a drop-down filter to the Event CPT table by venue
|
115 |
+
* @since 1.0.0
|
116 |
+
*/
|
117 |
+
add_action( 'restrict_manage_posts', 'eventorganiser_restrict_events_by_venue' );
|
118 |
+
function eventorganiser_restrict_events_by_venue() {
|
119 |
+
global $typenow;
|
120 |
+
|
121 |
+
//Only add if CPT is event
|
122 |
+
if ( $typenow == 'event' ) :
|
123 |
+
eo_event_venue_dropdown( array( 'hide_empty' => false, 'show_option_all' => __( 'View all venues', 'eventorganiser' ) ) );
|
124 |
+
endif;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Adds a drop-down filter to the Event CPT table by intervals
|
129 |
+
* @since 1.2.0
|
130 |
+
*/
|
131 |
+
add_action( 'restrict_manage_posts', 'eventorganiser_display_occurrences' );
|
132 |
+
function eventorganiser_display_occurrences() {
|
133 |
+
global $typenow, $wp_query;
|
134 |
+
if ( $typenow == 'event' ):
|
135 |
+
$intervals = array(
|
136 |
+
'all' => __( 'View all events', 'eventorganiser' ),
|
137 |
+
'future' => __( 'Future events', 'eventorganiser' ),
|
138 |
+
'expired' => __( 'Expired events', 'eventorganiser' ),
|
139 |
+
'P1D' => __( 'Events within 24 hours', 'eventorganiser' ),
|
140 |
+
'P1W' => __( 'Events within 1 week', 'eventorganiser' ),
|
141 |
+
'P2W' => sprintf( __( 'Events within %d weeks', 'eventorganiser' ), 2 ),
|
142 |
+
'P1M' => __( 'Events within 1 month', 'eventorganiser' ),
|
143 |
+
'P6M' => sprintf( __( 'Events within %d months', 'eventorganiser' ), 6 ),
|
144 |
+
'P1Y' => __( 'Events within 1 year', 'eventorganiser' ),
|
145 |
+
);
|
146 |
+
$current = ( !empty( $wp_query->query_vars['eo_interval'] ) ? $wp_query->query_vars['eo_interval'] : 'all' );
|
147 |
+
?>
|
148 |
+
<select style="width:150px;" name='eo_interval' id='show-events-in-interval' class='postform'>
|
149 |
+
<?php foreach ( $intervals as $id => $interval ): ?>
|
150 |
+
<option value="<?php echo $id; ?>" <?php selected( $current, $id )?>> <?php echo $interval;?> </option>
|
151 |
+
<?php endforeach; ?>
|
152 |
+
</select>
|
153 |
+
<?php
|
154 |
+
endif;//End if CPT is event
|
155 |
+
}
|
156 |
+
|
157 |
+
|
158 |
+
/*
|
159 |
+
* Bulk and quick editting of venues. Add drop-down menu for quick editing
|
160 |
+
* @Since 1.3
|
161 |
+
*/
|
162 |
+
add_action( 'quick_edit_custom_box', 'eventorganiser_quick_edit_box', 10, 2 );
|
163 |
+
function eventorganiser_quick_edit_box( $column_name, $post_type ) {
|
164 |
+
if ( $column_name != 'venue' || $post_type != 'event' ) return;?>
|
165 |
+
|
166 |
+
<fieldset class="inline-edit-col-left"><div class="inline-edit-col">
|
167 |
+
<?php wp_nonce_field( 'eventorganiser_event_quick_edit', '_eononce' );?>
|
168 |
+
<label class="">
|
169 |
+
<span class="title">Event Venue</span><?php
|
170 |
+
$args = array( 'show_option_all' => 'No venue', 'orderby' => 'name', 'hide_empty' => 0, 'name' => 'eo_input[event-venue]', 'id' => 'eventorganiser_venue', 'taxonomy' => 'event-venue' );
|
171 |
+
wp_dropdown_categories( $args ); ?>
|
172 |
+
</label>
|
173 |
+
</div></fieldset>
|
174 |
+
<?php
|
175 |
+
}
|
176 |
+
|
177 |
+
/*
|
178 |
+
* Bulk and quick editting of venues. Add drop-down menu for bulk editing
|
179 |
+
* @Since 1.3
|
180 |
+
*/
|
181 |
+
add_action( 'bulk_edit_custom_box', 'eventorganiser_bulk_edit_box', 10, 2 );
|
182 |
+
function eventorganiser_bulk_edit_box( $column_name, $post_type ) {
|
183 |
+
if ( $column_name != 'venue' || $post_type != 'event' ) return;?>
|
184 |
+
|
185 |
+
<fieldset class="inline-edit-col-left"><div class="inline-edit-col">
|
186 |
+
<?php wp_nonce_field( 'eventorganiser_event_quick_edit', '_eononce' );?>
|
187 |
+
<label class="">
|
188 |
+
<span class="title">Event Venue</span><?php
|
189 |
+
$args = array( 'show_option_none' => __( '— No Change —' ), 'orderby' => 'name', 'hide_empty' => 0, 'name' => 'eo_input[event-venue]', 'id' => 'eventorganiser_venue_bulk', 'taxonomy' => 'event-venue' );
|
190 |
+
wp_dropdown_categories( $args ); ?>
|
191 |
+
</label>
|
192 |
+
</div></fieldset>
|
193 |
+
<?php
|
194 |
+
}
|
195 |
+
|
196 |
+
/*
|
197 |
+
* Bulk and quick editting of venues. Save venue update.
|
198 |
+
* @Since 1.3
|
199 |
+
*/
|
200 |
+
add_action( 'save_post', 'eventorganiser_quick_edit_save' );
|
201 |
+
function eventorganiser_quick_edit_save( $post_id ) {
|
202 |
+
global $wpdb;
|
203 |
+
|
204 |
+
// verify this is not an auto save routine.
|
205 |
+
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return $post_id;
|
206 |
+
|
207 |
+
//make sure data came from our quick/bulk box
|
208 |
+
if ( !isset( $_REQUEST['_eononce'] ) || !wp_verify_nonce( $_REQUEST['_eononce'], 'eventorganiser_event_quick_edit' ) )
|
209 |
+
return;
|
210 |
+
|
211 |
+
//authentication checks
|
212 |
+
if ( !current_user_can( 'edit_event', $post_id ) ) return $post_id;
|
213 |
+
|
214 |
+
$venue_id = ( isset( $_REQUEST['eo_input']['event-venue'] ) ? (int) $_REQUEST['eo_input']['event-venue'] : - 1 );
|
215 |
+
|
216 |
+
if ( $venue_id >= 0 ) {
|
217 |
+
$r = wp_set_post_terms( $post_id, array( $venue_id ), 'event-venue', false );
|
218 |
+
}
|
219 |
+
|
220 |
+
do_action( 'eventorganiser_save_event', $post_id );
|
221 |
+
return;
|
222 |
+
}
|
223 |
+
|
224 |
+
|
225 |
+
add_action( 'admin_head-edit.php', 'eventorganiser_quick_edit_script' );
|
226 |
+
function eventorganiser_quick_edit_script() { ?>
|
227 |
+
<script type="text/javascript">
|
228 |
+
jQuery(document).ready(function() {
|
229 |
+
jQuery( 'a.editinline' ).live( 'click', function() {
|
230 |
+
jQuery( '#eventorganiser_venue option' ).attr("selected", false);
|
231 |
+
var id = inlineEditPost.getId(this);
|
232 |
+
var val = parseInt(jQuery( '#post-' + id + ' td.column-venue input' ).val() );
|
233 |
+
jQuery( '#eventorganiser_venue option[value="'+val+'"]' ).attr( 'selected', 'selected' );
|
234 |
+
});
|
235 |
+
});
|
236 |
+
</script>
|
237 |
+
<?php
|
238 |
+
}
|
239 |
+
|
240 |
+
?>
|
event-organiser-settings.php
ADDED
@@ -0,0 +1,562 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/****** SETTINGS PAGE ******/
|
3 |
+
if ( !class_exists( 'EventOrganiser_Admin_Page' ) ){
|
4 |
+
require_once(EVENT_ORGANISER_DIR.'classes/class-eventorganiser-admin-page.php' );
|
5 |
+
}
|
6 |
+
class EventOrganiser_Settings_Page extends EventOrganiser_Admin_Page{
|
7 |
+
|
8 |
+
static $eventorganiser_roles;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Initialises the tabs.
|
12 |
+
*/
|
13 |
+
function setup_tabs(){
|
14 |
+
return apply_filters( 'eventorganiser_settings_tabs', array(
|
15 |
+
'general' => __( 'General', 'eventorganiser' ),
|
16 |
+
'permissions' => __( 'Permissions', 'eventorganiser' ),
|
17 |
+
'permalinks' => __( 'Permalinks', 'eventorganiser' ),
|
18 |
+
'imexport' => __( 'Import', 'eventorganiser' ).'/'.__( 'Export', 'eventorganiser' ),
|
19 |
+
)
|
20 |
+
);
|
21 |
+
}
|
22 |
+
|
23 |
+
function set_constants(){
|
24 |
+
$this->hook = 'options-general.php';
|
25 |
+
$this->title = __( 'Event Organiser Settings', 'eventorganiser' );
|
26 |
+
$this->menu = __( 'Event Organiser', 'eventorganiser' );
|
27 |
+
$this->permissions = 'manage_options';
|
28 |
+
$this->slug = 'event-settings';
|
29 |
+
}
|
30 |
+
|
31 |
+
function admin_init_actions(){
|
32 |
+
//Register options
|
33 |
+
register_setting( 'eventorganiser_options', 'eventorganiser_options', array( $this, 'validate' ) );
|
34 |
+
|
35 |
+
add_action( 'eventorganiser_event_settings_permalinks', 'flush_rewrite_rules' );
|
36 |
+
|
37 |
+
//Initialise the tab array
|
38 |
+
$this->tabs = $this->setup_tabs();
|
39 |
+
|
40 |
+
foreach ( $this->tabs as $tab_id => $label ){
|
41 |
+
//Add sections to each tabbed page
|
42 |
+
switch ( $tab_id){
|
43 |
+
case 'general':
|
44 |
+
register_setting( 'eventorganiser_'.$tab_id, 'eventorganiser_options', array( $this, 'validate' ) );
|
45 |
+
add_settings_section( $tab_id,__( 'General', 'eventorganiser' ), '__return_false', 'eventorganiser_'.$tab_id);
|
46 |
+
add_settings_section( $tab_id.'_templates',__( 'Templates', 'eventorganiser' ), '__return_false', 'eventorganiser_'.$tab_id);
|
47 |
+
break;
|
48 |
+
case 'permissions':
|
49 |
+
register_setting( 'eventorganiser_'.$tab_id, 'eventorganiser_options', array( $this, 'validate' ) );
|
50 |
+
add_settings_section( $tab_id, '',array( $this, 'display_permissions' ), 'eventorganiser_'.$tab_id);
|
51 |
+
break;
|
52 |
+
case 'permalinks':
|
53 |
+
register_setting( 'eventorganiser_'.$tab_id, 'eventorganiser_options', array( $this, 'validate' ) );
|
54 |
+
add_settings_section( $tab_id, '',array( $this, 'display_permalinks' ), 'eventorganiser_'.$tab_id);
|
55 |
+
break;
|
56 |
+
case 'imexport':
|
57 |
+
register_setting( 'eventorganiser_'.$tab_id, 'eventorganiser_options', array( $this, 'validate' ) );
|
58 |
+
add_settings_section( $tab_id, '',array( $this, 'display_imexport' ), 'eventorganiser_'.$tab_id );
|
59 |
+
break;
|
60 |
+
}
|
61 |
+
do_action("eventorganiser_register_tab_{$tab_id}", $tab_id );
|
62 |
+
$this->add_fields( $tab_id );
|
63 |
+
}
|
64 |
+
|
65 |
+
self::$eventorganiser_roles = array(
|
66 |
+
'edit_events' => __( 'Edit Events', 'eventorganiser' ),
|
67 |
+
'publish_events' => __( 'Publish Events', 'eventorganiser' ),
|
68 |
+
'delete_events' => __( 'Delete Events', 'eventorganiser' ),
|
69 |
+
'edit_others_events' => __( 'Edit Others\' Events', 'eventorganiser' ),
|
70 |
+
'delete_others_events' => __( 'Delete Other\'s Events', 'eventorganiser' ),
|
71 |
+
'read_private_events' => __( 'Read Private Events', 'eventorganiser' ),
|
72 |
+
'manage_venues' => __( 'Manage Venues', 'eventorganiser' ),
|
73 |
+
'manage_event_categories' => __( 'Manage Event Categories & Tags', 'eventorganiser' ),
|
74 |
+
);
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
/**
|
79 |
+
* This is called in the register_settings method.
|
80 |
+
* Once the tabs have been registered, and sections added to each tabbed page, we now add the fields for each section
|
81 |
+
* A section should have the form {tab_id}._{identifer} (e.g. general_main, or gateways_google).
|
82 |
+
*
|
83 |
+
* @param $tab_id - the string identifer for the tab (given in $this->tabs as the key).
|
84 |
+
* @uses add_settings_field
|
85 |
+
*/
|
86 |
+
function add_fields( $tab_id){
|
87 |
+
|
88 |
+
switch( $tab_id){
|
89 |
+
case 'general':
|
90 |
+
/* General - main */
|
91 |
+
add_settings_field( 'supports', __( 'Select which features events should support', 'eventorganiser' ), 'eventorganiser_checkbox_field', 'eventorganiser_'.$tab_id, $tab_id,
|
92 |
+
array(
|
93 |
+
'label_for' => 'supports',
|
94 |
+
'checked' => eventorganiser_get_option( 'supports' ),
|
95 |
+
'options' => array(
|
96 |
+
'author' => __( 'Organiser', 'eventorganiser' ).' ( '.__( 'Author' ).' )',
|
97 |
+
'thumbnail' => __( 'Thumbnail' ),
|
98 |
+
'excerpt' => __( 'Excerpt' ),
|
99 |
+
'custom-fields' => __( 'Custom Fields' ),
|
100 |
+
'comments' => __( 'Comments' ),
|
101 |
+
'revisions' => __( 'Revisions' ),
|
102 |
+
'eventtag' => __( 'Event Tags', 'eventorganiser' ),
|
103 |
+
),
|
104 |
+
'name' => 'eventorganiser_options[supports]'
|
105 |
+
) );
|
106 |
+
|
107 |
+
add_settings_field( 'showpast', __("Show past events:", 'eventorganiser' ), 'eventorganiser_checkbox_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
108 |
+
array(
|
109 |
+
'label_for' => 'showpast',
|
110 |
+
'name' => 'eventorganiser_options[showpast]',
|
111 |
+
'options' => 1,
|
112 |
+
'checked' => eventorganiser_get_option( 'showpast' ),
|
113 |
+
'help' => __("Display past events on calendars, event lists and archives (this can be over-ridden by shortcode attributes and widget options).", 'eventorganiser' )
|
114 |
+
) );
|
115 |
+
|
116 |
+
add_settings_field( 'addtomenu', __("Add an 'events' link to the navigation menu:", 'eventorganiser' ), array( $this, 'menu_option' ), 'eventorganiser_'.$tab_id, $tab_id,
|
117 |
+
array(
|
118 |
+
'label_for' => 'addtomenu',
|
119 |
+
) );
|
120 |
+
|
121 |
+
add_settings_field( 'dateformat', __( 'Date Format:', 'eventorganiser' ), 'eventorganiser_select_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
122 |
+
array(
|
123 |
+
'label_for' => 'dateformat',
|
124 |
+
'selected' => eventorganiser_get_option( 'dateformat' ),
|
125 |
+
'name' => 'eventorganiser_options[dateformat]',
|
126 |
+
'options' => array(
|
127 |
+
'd-m-Y' => __( 'dd-mm-yyyy', 'eventorganiser' ),
|
128 |
+
'm-d-Y' => __( 'mm-dd-yyyy', 'eventorganiser' ),
|
129 |
+
'Y-m-d' => __( 'yyyy-mm-dd', 'eventorganiser' ),
|
130 |
+
),
|
131 |
+
'help' => __("This alters the default format for inputting dates.", 'eventorganiser' ),
|
132 |
+
) );
|
133 |
+
|
134 |
+
add_settings_field( 'showpast', __("Show past events:", 'eventorganiser' ), 'eventorganiser_checkbox_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
135 |
+
array(
|
136 |
+
'label_for' => 'showpast',
|
137 |
+
'name' => 'eventorganiser_options[showpast]',
|
138 |
+
'options' => 1,
|
139 |
+
'checked' => eventorganiser_get_option( 'showpast' ),
|
140 |
+
'help' => __("Display past events on calendars, event lists and archives (this can be over-ridden by shortcode attributes and widget options).", 'eventorganiser' )
|
141 |
+
) );
|
142 |
+
|
143 |
+
add_settings_field( 'group_events', __("Group occurrences", 'eventorganiser' ), 'eventorganiser_checkbox_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
144 |
+
array(
|
145 |
+
'label_for' => 'group_events',
|
146 |
+
'name' => 'eventorganiser_options[group_events]',
|
147 |
+
'options' => 'series',
|
148 |
+
'checked' => eventorganiser_get_option( 'group_events' ),
|
149 |
+
'help' => __("If selected only one occurrence of an event will be displayed on event lists and archives (this can be over-ridden by shortcode attributes and widget options.", 'eventorganiser' )
|
150 |
+
) );
|
151 |
+
|
152 |
+
add_settings_field( 'runningisnotpast', __("Are current events past?", 'eventorganiser' ), 'eventorganiser_select_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
153 |
+
array(
|
154 |
+
'label_for' => 'runningisnotpast',
|
155 |
+
'name' => 'eventorganiser_options[runningisnotpast]',
|
156 |
+
'selected' => eventorganiser_get_option( 'runningisnotpast',0),
|
157 |
+
'options' => array(
|
158 |
+
'0' => __( 'No', 'eventorganiser' ),
|
159 |
+
'1' => __( 'Yes', 'eventorganiser' ),
|
160 |
+
),
|
161 |
+
'help' => __("If 'no' is selected, an occurrence of an event is only past when it has finished. Otherwise, an occurrence is considered 'past' as soon as it starts.", 'eventorganiser' ),
|
162 |
+
) );
|
163 |
+
|
164 |
+
add_settings_field( 'deleteexpired', __("Delete expired events:", 'eventorganiser' ), 'eventorganiser_checkbox_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
165 |
+
array(
|
166 |
+
'label_for' => 'deleteexpired',
|
167 |
+
'name' => 'eventorganiser_options[deleteexpired]',
|
168 |
+
'options' => 1,
|
169 |
+
'checked' => eventorganiser_get_option( 'deleteexpired' ),
|
170 |
+
'help' => __("If selected the event will be automatically trashed 24 hours after the last occurrence finishes.", 'eventorganiser' )
|
171 |
+
) );
|
172 |
+
|
173 |
+
add_settings_field( 'feed', __("Enable events ICAL feed:", 'eventorganiser' ), 'eventorganiser_checkbox_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
174 |
+
array(
|
175 |
+
'label_for' => 'feed',
|
176 |
+
'name' => 'eventorganiser_options[feed]',
|
177 |
+
'options' => 1,
|
178 |
+
'checked' => eventorganiser_get_option( 'feed' ),
|
179 |
+
'help' => sprintf(__( 'If selected, visitors can subscribe to your events with the url: %s', 'eventorganiser' ), '<code>'.eo_get_events_feed().'</code>' )
|
180 |
+
) );
|
181 |
+
|
182 |
+
add_settings_field( 'excludefromsearch', __("Exclude events from searches:", 'eventorganiser' ), 'eventorganiser_checkbox_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
183 |
+
array(
|
184 |
+
'label_for' => 'excludefromsearch',
|
185 |
+
'name' => 'eventorganiser_options[excludefromsearch]',
|
186 |
+
'options' => 1,
|
187 |
+
'checked' => eventorganiser_get_option( 'excludefromsearch' ),
|
188 |
+
) );
|
189 |
+
|
190 |
+
add_settings_field( 'templates', __("Enable templates:", 'eventorganiser' ), 'eventorganiser_checkbox_field' , 'eventorganiser_'.$tab_id, $tab_id.'_templates',
|
191 |
+
array(
|
192 |
+
'label_for' => 'templates',
|
193 |
+
'name' => 'eventorganiser_options[templates]',
|
194 |
+
'options' => 1,
|
195 |
+
'checked' => eventorganiser_get_option( 'templates' ),
|
196 |
+
'help' => __("For each of the pages, the corresponding template is used. To use your own template simply give it the same name and store in your theme folder. By default, if Event Organiser cannot find a template in your theme directory, it will use its own default template. To prevent this, uncheck this option. WordPress will then decide which template from your theme's folder to use.", 'eventorganiser' ). sprintf("<p><strong> %s </strong><code>archive-event.php</code></p>
|
197 |
+
<p><strong> %s </strong><code>single-event.php</code></p>
|
198 |
+
<p><strong> %s </strong><code>venue-template.php</code></p>
|
199 |
+
<p><strong> %s </strong><code>taxonomy-event-category.php</code></p>",
|
200 |
+
__("Events archives:", 'eventorganiser' ),
|
201 |
+
__("Event page:", 'eventorganiser' ),
|
202 |
+
__("Venue page:", 'eventorganiser' ),
|
203 |
+
__("Events Category page:", 'eventorganiser' )
|
204 |
+
)
|
205 |
+
) );
|
206 |
+
break;
|
207 |
+
|
208 |
+
|
209 |
+
case 'permissions':
|
210 |
+
break;
|
211 |
+
|
212 |
+
case 'permalinks':
|
213 |
+
add_settings_field( 'prettyurl', __("Enable event pretty permalinks:", 'eventorganiser' ), 'eventorganiser_checkbox_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
214 |
+
array(
|
215 |
+
'label_for' => 'prettyurl',
|
216 |
+
'name' => 'eventorganiser_options[prettyurl]',
|
217 |
+
'options' => 1,
|
218 |
+
'checked' => eventorganiser_get_option( 'prettyurl' ),
|
219 |
+
'help' => __("If you have pretty permalinks enabled, select to have pretty premalinks for events.", 'eventorganiser' )
|
220 |
+
) );
|
221 |
+
|
222 |
+
$home_url = home_url();
|
223 |
+
add_settings_field( 'url_event', __("Event (single)", 'eventorganiser' ), 'eventorganiser_text_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
224 |
+
array(
|
225 |
+
'label_for' => 'url_event',
|
226 |
+
'name' => 'eventorganiser_options[url_event]',
|
227 |
+
'value' => eventorganiser_get_option( 'url_event' ),
|
228 |
+
'help' => "<code>{$home_url}/<strong>".eventorganiser_get_option( 'url_event' )."</strong>/[event_slug]</code>"
|
229 |
+
) );
|
230 |
+
|
231 |
+
$now = new DateTime();
|
232 |
+
add_settings_field( 'url_events', __("Event (archive)", 'eventorganiser' ), 'eventorganiser_text_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
233 |
+
array(
|
234 |
+
'label_for' => 'url_events',
|
235 |
+
'name' => 'eventorganiser_options[url_events]',
|
236 |
+
'value' => eventorganiser_get_option( 'url_events' ),
|
237 |
+
'help' => "<code>{$home_url}/<strong>".eventorganiser_get_option( 'url_events' )."</strong></code>".'<br>'
|
238 |
+
."<code>{$home_url}/<strong>".eventorganiser_get_option( 'url_events' )."</strong>/on/{$now->format('Y')}</code> ".__('Year archive', 'eventorganiser').'<br>'
|
239 |
+
."<code>{$home_url}/<strong>".eventorganiser_get_option( 'url_events' )."</strong>/on/{$now->format('Y/m')}</code>".__('Month archive', 'eventorganiser').'<br>'
|
240 |
+
."<code>{$home_url}/<strong>".eventorganiser_get_option( 'url_events' )."</strong>/on/{$now->format('Y/m/d')}</code>".__('Day archive', 'eventorganiser')
|
241 |
+
) );
|
242 |
+
|
243 |
+
add_settings_field( 'url_venue', __("Venues", 'eventorganiser' ), 'eventorganiser_text_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
244 |
+
array(
|
245 |
+
'label_for' => 'url_venue',
|
246 |
+
'name' => 'eventorganiser_options[url_venue]',
|
247 |
+
'value' => eventorganiser_get_option( 'url_venue' ),
|
248 |
+
'help' => "<code>{$home_url}/<strong>".eventorganiser_get_option( 'url_venue' )."</strong>/[venue_slug]</code>"
|
249 |
+
) );
|
250 |
+
|
251 |
+
add_settings_field( 'url_cat', __("Event Categories", 'eventorganiser' ), 'eventorganiser_text_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
252 |
+
array(
|
253 |
+
'label_for' => 'url_cat',
|
254 |
+
'name' => 'eventorganiser_options[url_cat]',
|
255 |
+
'value' => eventorganiser_get_option( 'url_cat' ),
|
256 |
+
'help' => "<code>{$home_url}/<strong>".eventorganiser_get_option( 'url_cat' )."</strong>/[event_cat_slug]</code>"
|
257 |
+
) );
|
258 |
+
|
259 |
+
add_settings_field( 'url_tag', __("Event Tags", 'eventorganiser' ), 'eventorganiser_text_field' , 'eventorganiser_'.$tab_id, $tab_id,
|
260 |
+
array(
|
261 |
+
'label_for' => 'url_tag',
|
262 |
+
'name' => 'eventorganiser_options[url_tag]',
|
263 |
+
'value' => eventorganiser_get_option( 'url_tag' ),
|
264 |
+
'help' => "<label><code>{$home_url}/<strong>".eventorganiser_get_option( 'url_tag' )."</strong>/[event_tag_slug]</code></label>"
|
265 |
+
) );
|
266 |
+
|
267 |
+
break;
|
268 |
+
}
|
269 |
+
}
|
270 |
+
|
271 |
+
|
272 |
+
function validate( $option ){
|
273 |
+
/* Backwards compatibility: all EO options are in one row, but on seperate pages. Merge with existing options*/
|
274 |
+
|
275 |
+
if ( isset( $option['tab'] ) ){
|
276 |
+
$tab = $option['tab'];
|
277 |
+
unset( $option['tab'] );
|
278 |
+
} else {
|
279 |
+
$tab = false;
|
280 |
+
}
|
281 |
+
|
282 |
+
$clean = array();
|
283 |
+
|
284 |
+
switch ( $tab ){
|
285 |
+
case 'general':
|
286 |
+
$checkboxes = array( 'showpast', 'templates', 'excludefromsearch', 'deleteexpired', 'feed', 'group_events' );
|
287 |
+
$text = array( 'navtitle', 'dateformat', 'runningisnotpast', 'addtomenu' );
|
288 |
+
|
289 |
+
foreach ( $checkboxes as $cb ){
|
290 |
+
|
291 |
+
//Empty checkboxes send no data..
|
292 |
+
$value = isset( $option[$cb] ) ? $option[$cb] : 0;
|
293 |
+
|
294 |
+
$clean[$cb] = $this->validate_checkbox( $value );
|
295 |
+
}
|
296 |
+
|
297 |
+
foreach ( $text as $txt ){
|
298 |
+
if ( !isset( $option[$txt] ) )
|
299 |
+
continue;
|
300 |
+
|
301 |
+
$clean[$txt] = $this->validate_text( $option[$txt] );
|
302 |
+
}
|
303 |
+
|
304 |
+
//Group events is handled differently
|
305 |
+
$clean['group_events'] = ( !empty( $clean['group_events'] ) ? 'series' : '' );
|
306 |
+
|
307 |
+
//Post type supports
|
308 |
+
$clean['supports'] = (isset( $option['supports'] ) ? array_map( 'esc_html',$option['supports'] ) : array() );
|
309 |
+
$clean['supports'] = array_merge( $clean['supports'],array( 'title', 'editor' ) );
|
310 |
+
|
311 |
+
//Navigation menu - $addtomenu int 0 if no menu, menu databse ID otherwise
|
312 |
+
$clean['menu_item_db_id'] = $this->update_nav_menu( $clean['addtomenu'], $clean['navtitle'] );
|
313 |
+
|
314 |
+
if( $clean['deleteexpired'] && !eventorganiser_get_next_cron_time( 'eventorganiser_delete_expired' ) ){
|
315 |
+
eventorganiser_cron_jobs();
|
316 |
+
}elseif( !$clean['deleteexpired'] ){
|
317 |
+
eventorganiser_clear_cron_jobs();
|
318 |
+
}
|
319 |
+
break;
|
320 |
+
|
321 |
+
|
322 |
+
case 'permalinks':
|
323 |
+
$permalinks = array( 'url_event', 'url_events', 'url_venue', 'url_cat', 'url_tag' );
|
324 |
+
|
325 |
+
foreach ( $permalinks as $permalink ){
|
326 |
+
if ( !isset( $option[$permalink] ) )
|
327 |
+
continue;
|
328 |
+
|
329 |
+
$value = $this->validate_permalink( $option[$permalink] );
|
330 |
+
|
331 |
+
if ( !empty( $value) )
|
332 |
+
$clean[$permalink] = $value;
|
333 |
+
}
|
334 |
+
|
335 |
+
$clean['prettyurl'] = isset( $option['prettyurl'] ) ? $this->validate_checkbox( $option['prettyurl'] ) : 0;
|
336 |
+
break;
|
337 |
+
|
338 |
+
|
339 |
+
case 'permissions':
|
340 |
+
//Permissions
|
341 |
+
$permissions = (isset( $option['permissions'] ) ? $option['permissions'] : array() );
|
342 |
+
$this->update_roles( $permissions );
|
343 |
+
break;
|
344 |
+
}
|
345 |
+
|
346 |
+
$existing_options = get_option( 'eventorganiser_options', array() );
|
347 |
+
$clean = array_merge( $existing_options, $clean );
|
348 |
+
return $clean;
|
349 |
+
}
|
350 |
+
|
351 |
+
function validate_checkbox( $value ){
|
352 |
+
return ( !empty( $value ) ? 1 : 0 );
|
353 |
+
}
|
354 |
+
|
355 |
+
function validate_text( $value ){
|
356 |
+
return ( !empty( $value ) ? esc_html( $value ) : false );
|
357 |
+
}
|
358 |
+
|
359 |
+
function validate_permalink( $value ){
|
360 |
+
return trim( str_replace( 'http://', '', esc_url_raw( $value ) ), '/' );
|
361 |
+
return $value;
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
*
|
366 |
+
*@param $menu_databse_id int 0 for no menu, 1 for 'fallback', term ID for menu otherwise
|
367 |
+
*
|
368 |
+
*/
|
369 |
+
function update_nav_menu( $menu_id, $menu_item_title ){
|
370 |
+
|
371 |
+
//Get existing menu item
|
372 |
+
$menu_item_db_id = (int) eventorganiser_get_option( 'menu_item_db_id' );
|
373 |
+
|
374 |
+
//Validate exiting menu item ID
|
375 |
+
if ( !is_nav_menu_item( $menu_item_db_id ) ){
|
376 |
+
$menu_item_db_id = 0;
|
377 |
+
}
|
378 |
+
|
379 |
+
//If Menu is not selected, or 'page list' fallback is, and we have an 'events' item added to some menu, remove it
|
380 |
+
if ( (empty( $menu_id ) || $menu_id == '1' ) && is_nav_menu_item( $menu_item_db_id ) ){
|
381 |
+
//Remove menu item
|
382 |
+
wp_delete_post( $menu_item_db_id, true );
|
383 |
+
$menu_item_db_id = 0;
|
384 |
+
}
|
385 |
+
|
386 |
+
//If the $menu is an int > 1, we are adding/updating an item (post type) so that it has term set to $menu_id
|
387 |
+
if ( ( !empty( $menu_id ) && $menu_id != '1' ) ){
|
388 |
+
$menu_item_data = array();
|
389 |
+
|
390 |
+
//Validate menu ID
|
391 |
+
$menu_obj = wp_get_nav_menu_object( $menu_id );
|
392 |
+
$menu_id = ( $menu_obj ? $menu_obj->term_id : 0 );
|
393 |
+
|
394 |
+
//Set status
|
395 |
+
$status = ( $menu_id == 0 ? '' : 'publish' );
|
396 |
+
|
397 |
+
$menu_item_data = array(
|
398 |
+
'menu-item-title' => $menu_item_title,
|
399 |
+
'menu-item-url' => get_post_type_archive_link( 'event' ),
|
400 |
+
'menu-item-object' => 'event',
|
401 |
+
'menu-item-status' => $status,
|
402 |
+
'menu-item-type' => 'post_type_archive',
|
403 |
+
);
|
404 |
+
|
405 |
+
//If we're updating preserve parent and position
|
406 |
+
if( is_nav_menu_item( $menu_item_db_id ) ){
|
407 |
+
$menu_item = wp_setup_nav_menu_item( get_post( $menu_item_db_id ) );
|
408 |
+
$menu_item_data += array(
|
409 |
+
'menu-item-parent-id' => $menu_item->menu_item_parent,
|
410 |
+
'menu-item-position' => $menu_item->menu_order,
|
411 |
+
);
|
412 |
+
}
|
413 |
+
|
414 |
+
//Update menu item (post type) to have taxonom term $menu_id
|
415 |
+
$menu_item_db_id = wp_update_nav_menu_item( $menu_id, $menu_item_db_id,$menu_item_data );
|
416 |
+
}
|
417 |
+
|
418 |
+
//Return the menu item (post type) ID. 0 For no item added, or item removed.
|
419 |
+
return $menu_item_db_id;
|
420 |
+
}
|
421 |
+
|
422 |
+
|
423 |
+
function update_roles( $permissions ){
|
424 |
+
global $wp_roles,$EO_Errors;
|
425 |
+
|
426 |
+
foreach ( get_editable_roles() as $role_name => $display_name ):
|
427 |
+
$role = $wp_roles->get_role( $role_name );
|
428 |
+
//Don't edit the administrator
|
429 |
+
if ( $role_name == 'administrator' )
|
430 |
+
continue;
|
431 |
+
|
432 |
+
//Foreach custom role, add or remove option.
|
433 |
+
foreach ( self::$eventorganiser_roles as $eo_role => $eo_role_display ):
|
434 |
+
if ( isset( $permissions[$role_name][$eo_role] ) && $permissions[$role_name][$eo_role] == 1 ){
|
435 |
+
$role->add_cap( $eo_role );
|
436 |
+
} else {
|
437 |
+
$role->remove_cap( $eo_role );
|
438 |
+
}
|
439 |
+
endforeach; //End foreach $eventRoles
|
440 |
+
endforeach; //End foreach $editable_roles
|
441 |
+
}
|
442 |
+
|
443 |
+
|
444 |
+
|
445 |
+
function display(){
|
446 |
+
?>
|
447 |
+
<div class="wrap">
|
448 |
+
|
449 |
+
<?php screen_icon( 'options-general' ); ?>
|
450 |
+
<?php
|
451 |
+
|
452 |
+
$active_tab = ( isset( $_GET[ 'tab' ] ) && isset( $this->tabs[$_GET[ 'tab' ]] ) ? $_GET[ 'tab' ] : 'general' );
|
453 |
+
$page = $this->slug;
|
454 |
+
|
455 |
+
echo '<h2 class="nav-tab-wrapper">';
|
456 |
+
|
457 |
+
foreach ( $this->tabs as $tab_id => $label ){
|
458 |
+
printf(
|
459 |
+
'<a href="?page=%s&tab=%s" class="nav-tab %s">%s</a>',
|
460 |
+
$page,
|
461 |
+
$tab_id,
|
462 |
+
( $active_tab == $tab_id ? 'nav-tab-active' : '' ),
|
463 |
+
esc_html( $label )
|
464 |
+
);
|
465 |
+
}
|
466 |
+
echo '</h2>';
|
467 |
+
?>
|
468 |
+
|
469 |
+
<?php if ( 'imexport' != $active_tab ){
|
470 |
+
echo '<form method="post" action="options.php">';
|
471 |
+
settings_fields( 'eventorganiser_'.$active_tab );
|
472 |
+
do_settings_sections( 'eventorganiser_'.$active_tab );
|
473 |
+
//Tab identifier - so we know which tab we are validating. See $this->validate().
|
474 |
+
do_action( 'eventorganiser_event_settings_'.$active_tab );
|
475 |
+
printf( '<input type="hidden" name="eventorganiser_options[tab]" value="%s" />', esc_attr( $active_tab ) );
|
476 |
+
submit_button();
|
477 |
+
echo '</form>';
|
478 |
+
} else {
|
479 |
+
do_action( 'eventorganiser_event_settings_imexport' );
|
480 |
+
}
|
481 |
+
?>
|
482 |
+
|
483 |
+
</div><!-- /.wrap -->
|
484 |
+
|
485 |
+
<?php
|
486 |
+
}
|
487 |
+
|
488 |
+
function display_imexport(){
|
489 |
+
do_action( 'eventorganiser_event_settings_imexport' );
|
490 |
+
}
|
491 |
+
|
492 |
+
function display_permissions(){
|
493 |
+
global $wp_roles;
|
494 |
+
echo '<p>'.__( 'Set permissions for events and venue management', 'eventorganiser' ).'</p>';
|
495 |
+
?>
|
496 |
+
<table class="widefat fixed posts">
|
497 |
+
<thead>
|
498 |
+
<tr>
|
499 |
+
<th><?php _e( 'Role', 'eventorganiser' ); ?></th>
|
500 |
+
<?php foreach ( self::$eventorganiser_roles as $eo_role => $eo_role_display ): ?>
|
501 |
+
<th><?php echo esc_html( $eo_role_display );?></th>
|
502 |
+
<?php endforeach; ?>
|
503 |
+
</tr>
|
504 |
+
</thead>
|
505 |
+
<tbody id="the-list">
|
506 |
+
<?php
|
507 |
+
$array_index = 0;
|
508 |
+
foreach ( get_editable_roles() as $role_name => $display_name ):
|
509 |
+
$role = $wp_roles->get_role( $role_name );
|
510 |
+
$role_name = isset( $wp_roles->role_names[$role_name] ) ? translate_user_role( $wp_roles->role_names[$role_name] ) : __( 'None' );
|
511 |
+
|
512 |
+
printf( '<tr %s>', $array_index == 0 ? 'class="alternate"' : '' );
|
513 |
+
printf( '<td> %s </td>',esc_html( $role_name ) );
|
514 |
+
|
515 |
+
foreach ( self::$eventorganiser_roles as $eo_role => $eo_role_display ):
|
516 |
+
printf(
|
517 |
+
'<td>
|
518 |
+
<input type="checkbox" name="eventorganiser_options[permissions][%s][%s]" value="1" %s %s />
|
519 |
+
</td>',
|
520 |
+
esc_attr( $role->name ),
|
521 |
+
esc_attr( $eo_role ),
|
522 |
+
checked( '1', $role->has_cap( $eo_role ), false ),
|
523 |
+
disabled( $role->name, 'administrator', false )
|
524 |
+
);
|
525 |
+
endforeach; //End foreach $eventRoles
|
526 |
+
echo '</tr>';
|
527 |
+
|
528 |
+
$array_index = ( $array_index + 1) % 2;
|
529 |
+
endforeach; //End foreach $editable_role ?>
|
530 |
+
</tbody>
|
531 |
+
</table>
|
532 |
+
<?php
|
533 |
+
}
|
534 |
+
|
535 |
+
|
536 |
+
function display_permalinks(){
|
537 |
+
printf(
|
538 |
+
'<p> %s </p> <p> %s %s </p>',
|
539 |
+
esc_html__( 'Choose a custom permalink structure for events, venues, event categories and event tags.', 'eventorganiser' ),
|
540 |
+
esc_html__( 'Please note to enable these structures you must first have pretty permalinks enabled on WordPress in Settings > Permalinks.', 'eventorganiser' ),
|
541 |
+
esc_html__( "You may also need to go to WordPress Settings > Permalinks and click 'Save Changes' before any changes will take effect.", 'eventorganiser' )
|
542 |
+
);
|
543 |
+
}
|
544 |
+
|
545 |
+
|
546 |
+
function menu_option(){
|
547 |
+
|
548 |
+
$menus = get_terms( 'nav_menu' );?>
|
549 |
+
<select name="eventorganiser_options[addtomenu]">
|
550 |
+
<option <?php selected( 0,eventorganiser_get_option( 'addtomenu' ) );?> value="0"><?php _e( 'Do not add to menu', 'eventorganiser' ); ?> </option>
|
551 |
+
<?php foreach ( $menus as $menu ): ?>
|
552 |
+
<option <?php selected( $menu->slug,eventorganiser_get_option( 'addtomenu' ) );?> value="<?php echo $menu->slug; ?>"><?php echo $menu->name;?> </option>
|
553 |
+
<?php endforeach; ?>
|
554 |
+
<option <?php selected( 1, eventorganiser_get_option( 'addtomenu' ) );?> value="1"><?php _e( 'Page list (fallback)', 'eventorganiser' ); ?></option>
|
555 |
+
</select>
|
556 |
+
|
557 |
+
<?php printf( '<input type="hidden" name ="eventorganiser_options[menu_item_db_id]" value="%d" />',eventorganiser_get_option( 'menu_item_db_id' ) ); ?>
|
558 |
+
<?php printf( '<input type="text" name="eventorganiser_options[navtitle]" value="%s" />',eventorganiser_get_option( 'navtitle' ) );
|
559 |
+
}
|
560 |
+
}
|
561 |
+
$settings_page = new EventOrganiser_Settings_Page();
|
562 |
+
?>
|
event-organiser-venues.php
ADDED
@@ -0,0 +1,433 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/****** VENUE PAGE ******/
|
3 |
+
if ( !class_exists( 'EventOrganiser_Admin_Page' ) ){
|
4 |
+
require_once( EVENT_ORGANISER_DIR.'classes/class-eventorganiser-admin-page.php' );
|
5 |
+
}
|
6 |
+
class EventOrganiser_Venues_Page extends EventOrganiser_Admin_Page
|
7 |
+
{
|
8 |
+
function set_constants(){
|
9 |
+
$this->hook = 'edit.php?post_type=event';
|
10 |
+
$this->title = __( 'Venues', 'eventorganiser' );
|
11 |
+
$this->menu = __( 'Venues', 'eventorganiser' );
|
12 |
+
$this->permissions = 'manage_venues';
|
13 |
+
$this->slug = 'venues';
|
14 |
+
|
15 |
+
//Workaround for bug http://core.trac.wordpress.org/ticket/18958
|
16 |
+
add_filter( 'set-screen-option', array( $this, 'set_per_page' ),10,3 );
|
17 |
+
}
|
18 |
+
|
19 |
+
/*
|
20 |
+
* Actions to be taken prior to page loading. Hooked on to load-{page}
|
21 |
+
*/
|
22 |
+
function page_actions(){
|
23 |
+
|
24 |
+
global $EO_Errors;
|
25 |
+
add_action( 'admin_notices',array( $this, 'admin_notices' ) );
|
26 |
+
|
27 |
+
//Determine action if any
|
28 |
+
$action = $this->current_action();
|
29 |
+
$venue = ( isset( $_REQUEST['event-venue'] ) ? $_REQUEST['event-venue'] : false );
|
30 |
+
|
31 |
+
if ( ( $action && $venue ) || $action == 'add' ):
|
32 |
+
|
33 |
+
if ( !current_user_can( 'manage_venues' ) )
|
34 |
+
wp_die( __( 'You do not have permission to manage venues', 'eventorganiser' ) );
|
35 |
+
|
36 |
+
switch( $action ):
|
37 |
+
case 'update':
|
38 |
+
if( !check_admin_referer( 'eventorganiser_update_venue_'.$venue ) )
|
39 |
+
wp_die( __( 'You do not have permission to edit this venue.', 'eventorganiser' ) );
|
40 |
+
|
41 |
+
$venue = get_term_by( 'slug', esc_attr( $venue ), 'event-venue' );
|
42 |
+
|
43 |
+
$return = eo_update_venue( $venue->term_id, $_POST['eo_venue'] );
|
44 |
+
|
45 |
+
if ( is_wp_error( $return ) ){
|
46 |
+
$EO_Errors->add( 'eo_error', __( 'Venue <strong>was not</strong> updated', 'eventorganiser' ).': '.$return->get_error_message() );
|
47 |
+
} else{
|
48 |
+
$term_id = (int) $return['term_id'];
|
49 |
+
$venue = get_term( $term_id, 'event-venue' );
|
50 |
+
$url = add_query_arg(
|
51 |
+
array(
|
52 |
+
'page' => 'venues',
|
53 |
+
'action' => 'edit',
|
54 |
+
'event-venue' => $venue->slug,
|
55 |
+
'message' => 2,
|
56 |
+
),
|
57 |
+
admin_url( 'edit.php?post_type=event' )
|
58 |
+
);
|
59 |
+
|
60 |
+
wp_redirect( $url );
|
61 |
+
exit();
|
62 |
+
}
|
63 |
+
break;
|
64 |
+
|
65 |
+
|
66 |
+
case 'add':
|
67 |
+
if( !check_admin_referer( 'eventorganiser_add_venue' ) )
|
68 |
+
wp_die( __( 'You do not have permission to edit this venue.', 'eventorganiser' ) );
|
69 |
+
|
70 |
+
$args = $_POST['eo_venue'];
|
71 |
+
$name = isset( $args['name'] ) ? $args['name'] : '';
|
72 |
+
|
73 |
+
//Venue may already exist in database since it may have been added via ajax (by pro plug-in);
|
74 |
+
if ( !empty( $args['venue_id'] ) && $_venue = eo_get_venue_by( 'id', $args['venue_id'] ) ){
|
75 |
+
//Since we're updating, need to explicitly provide slug to update it. Slug will be 'new-venue'.
|
76 |
+
$args['slug'] = sanitize_title( $args['name'] );
|
77 |
+
$return = eo_update_venue( $_venue->term_id, $args );
|
78 |
+
} else{
|
79 |
+
$return = eo_insert_venue( $name, $args );
|
80 |
+
}
|
81 |
+
|
82 |
+
if ( is_wp_error( $return ) ){
|
83 |
+
$EO_Errors->add( 'eo_error', __( 'Venue <strong>was not</strong> created', 'eventorganiser' ).': '.$return->get_error_message() );
|
84 |
+
$_REQUEST['action'] = 'create';
|
85 |
+
} else{
|
86 |
+
$term_id = (int) $return['term_id'];
|
87 |
+
$venue = get_term( $term_id, 'event-venue' );
|
88 |
+
|
89 |
+
$url = add_query_arg(
|
90 |
+
array(
|
91 |
+
'page' => 'venues',
|
92 |
+
'action' => 'edit',
|
93 |
+
'event-venue' => $venue->slug,
|
94 |
+
'message' => 1,
|
95 |
+
),
|
96 |
+
admin_url( 'edit.php?post_type=event' )
|
97 |
+
);
|
98 |
+
|
99 |
+
wp_redirect( $url );
|
100 |
+
exit();
|
101 |
+
}
|
102 |
+
break;
|
103 |
+
|
104 |
+
|
105 |
+
case 'delete':
|
106 |
+
if( is_array( $_REQUEST['event-venue'] ) )
|
107 |
+
$nonce = 'bulk-venues';
|
108 |
+
else
|
109 |
+
$nonce = 'eventorganiser_delete_venue_'.$venue;
|
110 |
+
|
111 |
+
if( !check_admin_referer( $nonce ) )
|
112 |
+
wp_die( __( 'You do not have permission to delete this venue', 'eventorganiser' ) );
|
113 |
+
|
114 |
+
$venues = (array) $venue;
|
115 |
+
|
116 |
+
//Count the number of deleted venues
|
117 |
+
$deleted = 0;
|
118 |
+
|
119 |
+
foreach ( $venues as $venue ):
|
120 |
+
$venue = get_term_by( 'slug',esc_attr( $venue ), 'event-venue' );
|
121 |
+
$resp = eo_delete_venue( $venue->term_id );
|
122 |
+
|
123 |
+
if ( !is_wp_error( $resp) && true === $resp ){
|
124 |
+
$deleted++;
|
125 |
+
}
|
126 |
+
endforeach;
|
127 |
+
|
128 |
+
if ( $deleted > 0 ){
|
129 |
+
$url = add_query_arg(
|
130 |
+
array(
|
131 |
+
'page' => 'venues',
|
132 |
+
'message' => 3,
|
133 |
+
),
|
134 |
+
admin_url( 'edit.php?post_type=event' )
|
135 |
+
);
|
136 |
+
wp_redirect( $url );
|
137 |
+
exit();
|
138 |
+
} else{
|
139 |
+
$EO_Errors = new WP_Error( 'eo_error', __( 'Venue(s) <strong>were not </strong> deleted', 'eventorganiser' ) );
|
140 |
+
}
|
141 |
+
break;
|
142 |
+
endswitch;
|
143 |
+
endif;
|
144 |
+
|
145 |
+
$action = $this->current_action();
|
146 |
+
|
147 |
+
if ( in_array( $action, array( 'edit', 'update', 'create' ) ) ){
|
148 |
+
$venue = ( isset( $_REQUEST['event-venue'] ) ? $_REQUEST['event-venue'] : false );
|
149 |
+
|
150 |
+
//Venued edit page
|
151 |
+
add_meta_box( 'submitdiv', __( 'Save', 'eventorganiser' ), 'eventorganiser_venue_submit', 'event_page_venues', 'side', 'high' );
|
152 |
+
do_action( 'add_meta_boxes_event_page_venues', $venue );
|
153 |
+
do_action( 'add_meta_boxes', 'event_page_venues', $venue );
|
154 |
+
add_screen_option( 'layout_columns', array( 'max' => 2, 'default' => 2 ) );
|
155 |
+
} else{
|
156 |
+
//Venue admin list
|
157 |
+
require_once( 'classes/class-eo-venue-list-table.php' );
|
158 |
+
add_filter( 'manage_event_page_venues_columns', 'eventorganiser_venue_admin_columns' ) ;
|
159 |
+
add_screen_option( 'per_page', array( 'option' => 'edit_event_venue_per_page', 'label' => __( 'Venues', 'eventorganiser' ), 'default' => 20 ) );
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
|
164 |
+
function admin_notices(){
|
165 |
+
$m = isset( $_GET['message'] ) ? (int) $_GET['message'] : 0;
|
166 |
+
$messages = array(
|
167 |
+
1 => __( 'Venue <strong>created</strong>', 'eventorganiser' ),
|
168 |
+
2 => __( 'Venue <strong>updated</strong>', 'eventorganiser' ),
|
169 |
+
3 => __( 'Venue(s) <strong>deleted</strong>', 'eventorganiser' )
|
170 |
+
);
|
171 |
+
|
172 |
+
if( isset( $messages[$m]) )
|
173 |
+
printf( '<div class="updated"><p>%s</p></div>', $messages[$m] );
|
174 |
+
}
|
175 |
+
|
176 |
+
function page_scripts(){
|
177 |
+
$action = $this->current_action();
|
178 |
+
$screen = get_current_screen();
|
179 |
+
|
180 |
+
if ( in_array( $action,array( 'create', 'edit', 'add', 'update' ) ) ):
|
181 |
+
wp_enqueue_script( 'eo_venue' );
|
182 |
+
wp_localize_script( 'eo_venue', 'EO_Venue', array( 'location' => get_option( 'timezone_string' ), 'draggable' => true, 'screen_id' => $screen->id) );
|
183 |
+
wp_enqueue_style( 'eventorganiser-style' );
|
184 |
+
wp_enqueue_script( 'media-upload' );
|
185 |
+
wp_enqueue_script( 'postbox' );
|
186 |
+
add_thickbox();
|
187 |
+
endif;
|
188 |
+
}
|
189 |
+
|
190 |
+
function set_per_page( $validated_value, $option, $value ){
|
191 |
+
//Workaround for bug http://core.trac.wordpress.org/ticket/18958
|
192 |
+
|
193 |
+
if ( 'edit_event_venue_per_page' != $option )
|
194 |
+
return $validated_value;
|
195 |
+
|
196 |
+
$value = (int) $value;
|
197 |
+
if ( $value < 1 || $value > 999 )
|
198 |
+
return false;
|
199 |
+
|
200 |
+
return $value;
|
201 |
+
}
|
202 |
+
|
203 |
+
|
204 |
+
function display(){
|
205 |
+
|
206 |
+
$action = $this->current_action();
|
207 |
+
$venue = ( isset( $_REQUEST['event-venue'] ) ? $_REQUEST['event-venue'] : false );
|
208 |
+
?>
|
209 |
+
<div class="wrap">
|
210 |
+
<?php screen_icon( 'edit' );?>
|
211 |
+
|
212 |
+
<?php
|
213 |
+
if ( ( ( $action == 'edit' || $action == 'update' ) && $venue ) || $action == 'create' ):
|
214 |
+
$this->edit_form( $venue );
|
215 |
+
|
216 |
+
else:
|
217 |
+
|
218 |
+
//Else we are not creating or editing. Display table
|
219 |
+
$venue_table = new EO_Venue_List_Table();
|
220 |
+
$venue_table->prepare_items();
|
221 |
+
|
222 |
+
//Check if we have searched the venues
|
223 |
+
$search_term = ( isset( $_REQUEST['s'] ) ? esc_attr( $_REQUEST['s']) : '' );?>
|
224 |
+
|
225 |
+
<h2>
|
226 |
+
<?php _e( 'Venues', 'eventorganiser' );?>
|
227 |
+
<a href="edit.php?post_type=event&page=venues&action=create" class="add-new-h2"><?php _ex( 'Add New', 'post' ); ?></a>
|
228 |
+
<?php
|
229 |
+
if ( $search_term)
|
230 |
+
printf( '<span class="subtitle">' . __( 'Search results for “%s”' ) . '</span>', $search_term )
|
231 |
+
?>
|
232 |
+
</h2>
|
233 |
+
|
234 |
+
<form id="eo-venue-table" method="get">
|
235 |
+
<!-- Ensure that the form posts back to our current page -->
|
236 |
+
<input type="hidden" name="page" value="venues" />
|
237 |
+
<input type="hidden" name="post_type" value="event" />
|
238 |
+
|
239 |
+
<!-- Now we can render the completed list table -->
|
240 |
+
<?php $venue_table->search_box( __( 'Search Venues', 'eventorganiser' ), 's' ); ?>
|
241 |
+
<?php $venue_table->display(); ?>
|
242 |
+
</form>
|
243 |
+
<?php endif;?>
|
244 |
+
|
245 |
+
</div><!--End .wrap -->
|
246 |
+
<?php
|
247 |
+
}
|
248 |
+
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Display form for creating / editing venues
|
252 |
+
*
|
253 |
+
* @since 1.0.0
|
254 |
+
*/
|
255 |
+
function edit_form( $venue = false ){
|
256 |
+
|
257 |
+
$venue = get_term_by( 'slug', $venue, 'event-venue' );
|
258 |
+
$term_id = isset( $venue->term_id ) ? (int) $venue->term_id : 0;
|
259 |
+
$do = ( $this->current_action() == 'edit' ? 'update' : 'add' );
|
260 |
+
$nonce = ( $do == 'update' ? 'eventorganiser_update_venue_'.$venue->slug : 'eventorganiser_add_venue' );
|
261 |
+
|
262 |
+
if ( $this->current_action() == 'edit' ) : ?>
|
263 |
+
<h2>
|
264 |
+
<?php _e( 'Edit Venue', 'eventorganiser' ); ?>
|
265 |
+
<a href="edit.php?post_type=event&page=venues&action=create" class="add-new-h2"><?php _ex( 'Add New', 'post' ); ?></a>
|
266 |
+
</h2>
|
267 |
+
<?php else: ?>
|
268 |
+
<h2>
|
269 |
+
<?php _e( 'Add New Venue', 'eventorganiser' );?>
|
270 |
+
</h2>
|
271 |
+
<?php endif; ?>
|
272 |
+
|
273 |
+
<form name="venuedetails" id="eo_venue_form" method="post" action="<?php echo admin_url( 'edit.php?post_type=event&page=venues' ); ?>">
|
274 |
+
<input type="hidden" name="action" value="<?php echo $do; ?>">
|
275 |
+
<input type="hidden" id="eo_venue_id" name="eo_venue[venue_id]" value="<?php echo $term_id;?>">
|
276 |
+
<input type="hidden" name="event-venue" value="<?php echo ( isset( $venue->slug ) ? $venue->slug : '' ) ;?>">
|
277 |
+
|
278 |
+
<?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
|
279 |
+
<?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
|
280 |
+
<?php wp_nonce_field( $nonce ); ?>
|
281 |
+
|
282 |
+
<?php
|
283 |
+
//WP3.3-3.3.1 backwards compabt
|
284 |
+
if( version_compare( get_bloginfo('version'), 3.4 ) < 0 )
|
285 |
+
$columns = '1';
|
286 |
+
else
|
287 |
+
$columns = (1 == get_current_screen()->get_columns() ? '1' : '2' );
|
288 |
+
?>
|
289 |
+
<div id="poststuff">
|
290 |
+
|
291 |
+
<div id="post-body" class="metabox-holder columns-<?php echo $columns;?>">
|
292 |
+
|
293 |
+
<div id="post-body-content">
|
294 |
+
<div id="titlediv"><?php eventorganiser_venue_title( $venue ); ?></div>
|
295 |
+
<div class="postbox " id="venue_address">
|
296 |
+
<div class="handlediv" title="Click to toggle"><br></div>
|
297 |
+
<h3 class="hndle"><span><?php _e( 'Venue Location', 'eventorganiser' );?></span></h3>
|
298 |
+
<div class="inside"><?php eventorganiser_venue_location( $venue ); ?></div>
|
299 |
+
</div><!-- .postbox -->
|
300 |
+
<div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="venue_description postarea">
|
301 |
+
<?php wp_editor(eo_get_venue_meta($term_id,'_description'), 'content', array( 'textarea_name' => 'eo_venue[description]', 'dfw' => false, 'tabindex' => 7 ) ); ?>
|
302 |
+
</div>
|
303 |
+
</div><!-- #post-body-content -->
|
304 |
+
|
305 |
+
<div id="postbox-container-1" class="postbox-container">
|
306 |
+
<?php do_meta_boxes( '', 'side', $venue ); ?>
|
307 |
+
</div>
|
308 |
+
|
309 |
+
<div id="postbox-container-2" class="postbox-container">
|
310 |
+
<?php do_meta_boxes( '', 'normal', $venue ); ?>
|
311 |
+
<?php do_meta_boxes( '', 'advanced', $venue ); ?>
|
312 |
+
</div>
|
313 |
+
|
314 |
+
</div><!-- #post-body -->
|
315 |
+
<br class="clear">
|
316 |
+
|
317 |
+
</div><!-- #poststuff -->
|
318 |
+
</form>
|
319 |
+
<?php
|
320 |
+
}
|
321 |
+
}
|
322 |
+
$venues_page = new EventOrganiser_Venues_Page();
|
323 |
+
|
324 |
+
|
325 |
+
//Helper function to get the 'structure' of the event-venue taxonomy
|
326 |
+
function eo_get_venue_permastructure(){
|
327 |
+
global $wp_rewrite;
|
328 |
+
$termlink = $wp_rewrite->get_extra_permastruct( 'event-venue' );
|
329 |
+
if ( empty( $termlink ) ){
|
330 |
+
$t = get_taxonomy( 'event-venue' );
|
331 |
+
$termlink = "?$t->query_var=";
|
332 |
+
} else{
|
333 |
+
$termlink = preg_replace( '/%event-venue%/', '', $termlink );
|
334 |
+
}
|
335 |
+
$termlink = home_url( $termlink );
|
336 |
+
|
337 |
+
return $termlink;
|
338 |
+
}
|
339 |
+
|
340 |
+
//Submit metabox
|
341 |
+
function eventorganiser_venue_submit( $venue ){
|
342 |
+
$value = $venue ? __( 'Update Venue', 'eventorganiser' ) : __( 'Add Venue', 'eventorganiser' ); ?>
|
343 |
+
|
344 |
+
<div id="minor-publishing-actions">
|
345 |
+
<div id="save-action">
|
346 |
+
<input type="submit" class="button button-primary" id="save-venue" name="eo_venue[Submit]" value="<?php echo esc_attr( $value ); ?>" tabindex="10" />
|
347 |
+
</div>
|
348 |
+
<div class="clear"></div>
|
349 |
+
</div>
|
350 |
+
|
351 |
+
<?php
|
352 |
+
}
|
353 |
+
|
354 |
+
//Location metabox - called directly. Is not movable.
|
355 |
+
function eventorganiser_venue_location( $venue ){
|
356 |
+
$term_id = isset( $venue->term_id ) ? (int) $venue->term_id : 0;
|
357 |
+
$address = eo_get_venue_address( $term_id );?>
|
358 |
+
|
359 |
+
<table class ="address">
|
360 |
+
<tbody>
|
361 |
+
<?php
|
362 |
+
$address_fields = _eventorganiser_get_venue_address_fields();
|
363 |
+
$tabindex = 2;
|
364 |
+
foreach ( $address_fields as $key => $label ){
|
365 |
+
//Keys are prefixed by '_'.
|
366 |
+
$key = trim( $key, '_' );
|
367 |
+
printf(
|
368 |
+
'<tr>
|
369 |
+
<th><label>%1$s:</label></th>
|
370 |
+
<td><input type="text" name="eo_venue[%2$s]" class="eo_addressInput" id="eo-venue-%2$s" value="%3$s" tabindex="%4$s"/></td>
|
371 |
+
</tr>',
|
372 |
+
$label,
|
373 |
+
esc_attr( $key ),
|
374 |
+
esc_attr( $address[$key] ),
|
375 |
+
$tabindex++
|
376 |
+
);
|
377 |
+
}
|
378 |
+
?>
|
379 |
+
</tbody>
|
380 |
+
</table>
|
381 |
+
|
382 |
+
<div id="venuemap" class="gmap3"></div>
|
383 |
+
<div class="clear"></div>
|
384 |
+
|
385 |
+
<input type="hidden" name="eo_venue[latitude]" id="eo_venue_Lat" value="<?php echo esc_attr( eo_get_venue_lat( $term_id ) ); ?>"/>
|
386 |
+
<input type="hidden" name="eo_venue[longtitude]" id="eo_venue_Lng" value="<?php echo esc_attr( eo_get_venue_lng( $term_id ) ); ?>"/>
|
387 |
+
<?php
|
388 |
+
}
|
389 |
+
|
390 |
+
//Venue title input
|
391 |
+
function eventorganiser_venue_title( $venue ){
|
392 |
+
$term_id = isset( $venue->term_id) ? (int) $venue->term_id : 0;
|
393 |
+
$name = isset( $venue->name ) ? $venue->name : ''; ?>
|
394 |
+
|
395 |
+
<div id="titlewrap">
|
396 |
+
<input type="text" placeholder="<?php esc_attr_e( 'Venue name', 'eventorganiser' );?>" autocomplete="off" id="title" value="<?php echo esc_attr( $name );?>" tabindex="1" size="30" name="eo_venue[name]">
|
397 |
+
</div>
|
398 |
+
|
399 |
+
<div class="inside">
|
400 |
+
<div id="edit-slug-box">
|
401 |
+
<?php if ( $venue ): ?>
|
402 |
+
<strong><?php _e( 'Permalink:' );?></strong>
|
403 |
+
<span id="sample-permalink">
|
404 |
+
<?php echo eo_get_venue_permastructure();?>
|
405 |
+
<input type="text" name="eo_venue[slug]"value="<?php echo ( isset( $venue->slug ) ? esc_attr( $venue->slug ) : '' ) ;?>" id="<?php echo $term_id; ?>-slug">
|
406 |
+
</span>
|
407 |
+
|
408 |
+
<input type="hidden" value="<?php echo get_term_link( $venue, 'event-venue' ); ?>" id="shortlink">
|
409 |
+
<a onclick="prompt( 'URL:', jQuery( '#shortlink' ).val() ); return false;" class="button" href=""><?php _e( 'Get Link', 'eventorganiser' );?></a>
|
410 |
+
<span id='view-post-btn'><a href="<?php echo get_term_link( $venue, 'event-venue' ); ?>" class='button' target='_blank'><?php _e( 'View Venue', 'eventorganiser' );?></a></span>
|
411 |
+
<?php endif;?>
|
412 |
+
</div><!-- #edit-slug-box -->
|
413 |
+
</div> <!-- .inside -->
|
414 |
+
<?php
|
415 |
+
}
|
416 |
+
|
417 |
+
|
418 |
+
function eventorganiser_venue_admin_columns( $columns ){
|
419 |
+
$columns = array(
|
420 |
+
'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
|
421 |
+
'name' => __( 'Venue', 'eventorganiser' ),
|
422 |
+
);
|
423 |
+
$address_columns = _eventorganiser_get_venue_address_fields();
|
424 |
+
foreach( $address_columns as $key => $label )
|
425 |
+
$columns['venue'.$key] = $label;
|
426 |
+
|
427 |
+
$columns += array(
|
428 |
+
'venue_slug' => __( 'Slug' ),
|
429 |
+
'posts' => __( 'Events', 'eventorganiser' ),
|
430 |
+
);
|
431 |
+
|
432 |
+
return $columns;
|
433 |
+
}
|
event-organiser.php
ADDED
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: Event Organiser
|
4 |
+
Plugin URI: http://www.wp-event-organiser.com
|
5 |
+
Version: 2.0.2
|
6 |
+
Description: Creates a custom post type 'events' with features such as reoccurring events, venues, Google Maps, calendar views and events and venue pages
|
7 |
+
Author: Stephen Harris
|
8 |
+
Author URI: http://www.stephenharris.info
|
9 |
+
Network: false
|
10 |
+
Text Domain: eventorganiser
|
11 |
+
Domain Path: /languages
|
12 |
+
*/
|
13 |
+
/* Copyright 2011 Stephen Harris (contact@stephenharris.info)
|
14 |
+
|
15 |
+
This program is free software; you can redistribute it and/or modify
|
16 |
+
it under the terms of the GNU General Public License as published by
|
17 |
+
the Free Software Foundation; either version 2 of the License, or
|
18 |
+
(at your option) any later version.
|
19 |
+
|
20 |
+
This program is distributed in the hope that it will be useful,
|
21 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
22 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
23 |
+
GNU General Public License for more details.
|
24 |
+
|
25 |
+
You should have received a copy of the GNU General Public License
|
26 |
+
along with this program; if not, write to the Free Software
|
27 |
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
28 |
+
*/
|
29 |
+
/* Cookies used:
|
30 |
+
eo_admin_cal_last_viewed_date - stores the last viewed date on the admin calendar.
|
31 |
+
eo_admin_cal_last_view - stores the last used admin calendar view (month, week, day).
|
32 |
+
Expires: 10 minutes. Used for persitant admin calendar
|
33 |
+
*/
|
34 |
+
/**
|
35 |
+
* The main plug-in loader
|
36 |
+
*/
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Set the plug-in database version
|
40 |
+
* @global string $eventorganiser_db_version
|
41 |
+
* @name $eventorganiser_db_version
|
42 |
+
*/
|
43 |
+
global $eventorganiser_db_version;
|
44 |
+
$eventorganiser_db_version = '2.0.2';
|
45 |
+
|
46 |
+
|
47 |
+
add_action( 'after_setup_theme', '_eventorganiser_set_constants' );
|
48 |
+
function _eventorganiser_set_constants(){
|
49 |
+
/*
|
50 |
+
* Defines the plug-in directory url
|
51 |
+
* <code>url:http://mysite.com/wp-content/plugins/event-organiser</code>
|
52 |
+
*/
|
53 |
+
define( 'EVENT_ORGANISER_URL', plugin_dir_url( __FILE__ ) );
|
54 |
+
}
|
55 |
+
|
56 |
+
/*
|
57 |
+
* Defines the plug-in directory path
|
58 |
+
* <code>/home/mysite/public_html/wp-content/plugins/event-organiser</code>
|
59 |
+
*/
|
60 |
+
define( 'EVENT_ORGANISER_DIR', plugin_dir_path( __FILE__ ) );
|
61 |
+
|
62 |
+
/**
|
63 |
+
* For use in datetime formats. To return a datetime object rather than formatted string
|
64 |
+
*/
|
65 |
+
define( 'DATETIMEOBJ', 'DATETIMEOBJ', true );
|
66 |
+
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Load the translation file for current language. Checks in wp-content/languages first
|
70 |
+
* and then the event-organiser/languages.
|
71 |
+
*
|
72 |
+
* Edits to translation files inside event-organiser/languages will be lost with an update
|
73 |
+
* **If you're creating custom translation files, please use the global language folder.**
|
74 |
+
*
|
75 |
+
* @since 1.3
|
76 |
+
* @ignore
|
77 |
+
* @uses apply_filters() Calls 'plugin_locale' with the get_locale() value
|
78 |
+
* @uses load_textdomain() To load the textdomain from global language folder
|
79 |
+
* @uses load_plugin_textdomain() To load the textdomain from plugin folder
|
80 |
+
*/
|
81 |
+
function eventorganiser_load_textdomain() {
|
82 |
+
$domain = 'eventorganiser';
|
83 |
+
$locale = apply_filters( 'plugin_locale', get_locale(), $domain );
|
84 |
+
|
85 |
+
$mofile = $domain . '-' . $locale . '.mo';
|
86 |
+
|
87 |
+
/* Check the global language folder */
|
88 |
+
$files = array( WP_LANG_DIR . '/event-organiser/' . $mofile, WP_LANG_DIR . '/' . $mofile );
|
89 |
+
foreach ( $files as $file ){
|
90 |
+
if( file_exists( $file ) )
|
91 |
+
return load_textdomain( $domain, $file );
|
92 |
+
}
|
93 |
+
|
94 |
+
//If we got this far, fallback to the plug-in language folder.
|
95 |
+
//We could use load_textdomain - but this avoids touching any more constants.
|
96 |
+
load_plugin_textdomain( 'eventorganiser', false, basename( dirname( __FILE__ ) ).'/languages' );
|
97 |
+
}
|
98 |
+
add_action( 'init', 'eventorganiser_load_textdomain' );
|
99 |
+
|
100 |
+
global $eventorganiser_roles;
|
101 |
+
$eventorganiser_roles = array(
|
102 |
+
'edit_events' => __( 'Edit Events', 'eventorganiser' ),
|
103 |
+
'publish_events' => __( 'Publish Events', 'eventorganiser' ),
|
104 |
+
'delete_events' => __( 'Delete Events', 'eventorganiser' ),
|
105 |
+
'edit_others_events' => __( 'Edit Others\' Events', 'eventorganiser' ),
|
106 |
+
'delete_others_events' => __( 'Delete Other\'s Events', 'eventorganiser' ),
|
107 |
+
'read_private_events' => __( 'Read Private Events', 'eventorganiser' ),
|
108 |
+
'manage_venues' => __( 'Manage Venues', 'eventorganiser' ),
|
109 |
+
'manage_event_categories' => __( 'Manage Event Categories & Tags', 'eventorganiser' ),
|
110 |
+
);
|
111 |
+
|
112 |
+
/****** Install, activation & deactivation******/
|
113 |
+
require_once( EVENT_ORGANISER_DIR . 'includes/event-organiser-install.php' );
|
114 |
+
|
115 |
+
register_activation_hook( __FILE__, 'eventorganiser_install' );
|
116 |
+
register_deactivation_hook( __FILE__, 'eventorganiser_deactivate' );
|
117 |
+
register_uninstall_hook( __FILE__, 'eventorganiser_uninstall' );
|
118 |
+
|
119 |
+
|
120 |
+
function eventorganiser_get_option( $option, $default = false ){
|
121 |
+
|
122 |
+
$defaults = array(
|
123 |
+
'url_event' => 'events/event',
|
124 |
+
'url_events' => 'events/event',
|
125 |
+
'url_venue' => 'events/venue',
|
126 |
+
'url_cat' => 'events/category',
|
127 |
+
'url_tag' => 'events/tag',
|
128 |
+
'navtitle' => __( 'Events', 'eventorganiser' ),
|
129 |
+
'group_events' => '',
|
130 |
+
'feed' => 1,
|
131 |
+
'deleteexpired' => 0,
|
132 |
+
'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'custom-fields', 'comments', 'eventtag' ),
|
133 |
+
'event_redirect' => 'events',
|
134 |
+
'dateformat' => 'd-m-Y',
|
135 |
+
'prettyurl' => 1,
|
136 |
+
'templates' => 1,
|
137 |
+
'addtomenu' => 0,
|
138 |
+
'menu_item_db_id' => 0,
|
139 |
+
'excludefromsearch' => 0,
|
140 |
+
'showpast' => 0,
|
141 |
+
'runningisnotpast' => 0,
|
142 |
+
);
|
143 |
+
$options = get_option( 'eventorganiser_options', $defaults );
|
144 |
+
$options = wp_parse_args( $options, $defaults );
|
145 |
+
|
146 |
+
/* Backwards compatibility for 'eventag' option */
|
147 |
+
if( $option === 'eventtag' )
|
148 |
+
return in_array( 'eventtag', $options['supports'] );
|
149 |
+
|
150 |
+
if( $option === 'dateformat' ){
|
151 |
+
//Backwards compatibility (migration from mm-dd/dd-mm to php format):
|
152 |
+
if( $options[$option] == 'mm-dd' ){
|
153 |
+
$options[$option] = 'm-d-Y';
|
154 |
+
}elseif( $options[$option] == 'dd-mm' ){
|
155 |
+
$options[$option] = 'd-m-Y';
|
156 |
+
}
|
157 |
+
}
|
158 |
+
|
159 |
+
if( !isset($options[$option]) )
|
160 |
+
return $default;
|
161 |
+
|
162 |
+
return $options[$option];
|
163 |
+
}
|
164 |
+
|
165 |
+
|
166 |
+
/****** Register event post type and event taxonomy******/
|
167 |
+
require_once(EVENT_ORGANISER_DIR.'includes/event-organiser-cpt.php');
|
168 |
+
|
169 |
+
/****** Register scripts, styles and actions******/
|
170 |
+
require_once(EVENT_ORGANISER_DIR.'includes/event-organiser-register.php');
|
171 |
+
|
172 |
+
/****** Deals with the queries******/
|
173 |
+
require_once(EVENT_ORGANISER_DIR.'includes/event-organiser-archives.php');
|
174 |
+
|
175 |
+
/****** Deals with importing/exporting & subscriptions******/
|
176 |
+
require_once(EVENT_ORGANISER_DIR.'includes/class-event-organiser-im-export.php');
|
177 |
+
|
178 |
+
if ( is_admin() ):
|
179 |
+
require_once(EVENT_ORGANISER_DIR.'classes/class-eventorganiser-admin-page.php');
|
180 |
+
|
181 |
+
/****** event editing pages******/
|
182 |
+
require_once(EVENT_ORGANISER_DIR.'event-organiser-edit.php');
|
183 |
+
require_once(EVENT_ORGANISER_DIR.'event-organiser-manage.php');
|
184 |
+
|
185 |
+
/****** settings, venue and calendar pages******/
|
186 |
+
require_once(EVENT_ORGANISER_DIR.'event-organiser-settings.php');
|
187 |
+
require_once(EVENT_ORGANISER_DIR.'event-organiser-venues.php');
|
188 |
+
require_once(EVENT_ORGANISER_DIR.'event-organiser-calendar.php');
|
189 |
+
|
190 |
+
require_once(EVENT_ORGANISER_DIR.'event-organiser-debug.php');
|
191 |
+
require_once(EVENT_ORGANISER_DIR.'event-organiser-go-pro.php');
|
192 |
+
else:
|
193 |
+
if( defined( 'WP_DEBUG' ) && WP_DEBUG ){
|
194 |
+
require_once(EVENT_ORGANISER_DIR.'includes/debug.php');
|
195 |
+
}
|
196 |
+
|
197 |
+
endif;
|
198 |
+
|
199 |
+
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
200 |
+
/****** Ajax actions ******/
|
201 |
+
require_once(EVENT_ORGANISER_DIR.'includes/event-organiser-ajax.php');
|
202 |
+
}
|
203 |
+
|
204 |
+
if( defined( 'WP_DEBUG' ) && WP_DEBUG ){
|
205 |
+
add_action( 'register_sidebar', '_eventorganiser_check_sidebars' );
|
206 |
+
}
|
207 |
+
|
208 |
+
/****** Functions ******/
|
209 |
+
require_once(EVENT_ORGANISER_DIR.'includes/event-organiser-event-functions.php');
|
210 |
+
require_once(EVENT_ORGANISER_DIR.'includes/event-organiser-venue-functions.php');
|
211 |
+
require_once(EVENT_ORGANISER_DIR.'includes/event-organiser-utility-functions.php');
|
212 |
+
require_once(EVENT_ORGANISER_DIR.'includes/deprecated.php');
|
213 |
+
require_once(EVENT_ORGANISER_DIR.'includes/event.php');
|
214 |
+
|
215 |
+
/****** Templates - note some plug-ins will require this to included admin-side too ******/
|
216 |
+
require_once('includes/event-organiser-templates.php');
|
217 |
+
|
218 |
+
/****** Widgets and Shortcodes ******/
|
219 |
+
require_once(EVENT_ORGANISER_DIR.'classes/class-eo-agenda-widget.php');
|
220 |
+
require_once(EVENT_ORGANISER_DIR.'classes/class-eo-event-list-widget.php');
|
221 |
+
require_once(EVENT_ORGANISER_DIR.'classes/class-eo-calendar-widget.php');
|
222 |
+
require_once(EVENT_ORGANISER_DIR.'classes/class-eo-widget-categories.php');
|
223 |
+
require_once(EVENT_ORGANISER_DIR.'classes/class-eo-widget-venues.php');
|
224 |
+
require_once(EVENT_ORGANISER_DIR.'classes/class-eventorganiser-shortcodes.php');
|
225 |
+
|
226 |
+
add_action( 'widgets_init', 'eventorganiser_widgets_init' );
|
227 |
+
function eventorganiser_widgets_init(){
|
228 |
+
eventorganiser_load_textdomain();
|
229 |
+
register_widget( 'EO_Event_List_Widget' );
|
230 |
+
register_widget( 'EO_Events_Agenda_Widget' );
|
231 |
+
register_widget( 'EO_Calendar_Widget' );
|
232 |
+
register_widget( 'EO_Widget_Categories' );
|
233 |
+
register_widget( 'EO_Widget_Venues' );
|
234 |
+
}
|
includes/class-event-organiser-im-export.php
ADDED
@@ -0,0 +1,852 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Event importer / exporter
|
4 |
+
*/
|
5 |
+
if ( ! function_exists( 'add_action' ) ) {
|
6 |
+
echo "Hi there! I'm just a part of plugin, not much I can do when called directly.";
|
7 |
+
exit;
|
8 |
+
}
|
9 |
+
class Event_Organiser_Im_Export {
|
10 |
+
|
11 |
+
static private $classobj = NULL;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Handler for the action 'init'. Instantiates this class.
|
15 |
+
*/
|
16 |
+
public function get_object() {
|
17 |
+
|
18 |
+
if ( NULL === self :: $classobj ) {
|
19 |
+
self :: $classobj = new self;
|
20 |
+
}
|
21 |
+
|
22 |
+
return self :: $classobj;
|
23 |
+
}
|
24 |
+
|
25 |
+
public function __construct() {
|
26 |
+
global $pagenow, $EO_Errors;
|
27 |
+
|
28 |
+
if(!isset($EO_Errors)) $EO_Errors = new WP_Error();
|
29 |
+
|
30 |
+
if( is_feed('eo-events') && eventorganiser_get_option('feed') ){
|
31 |
+
$this->get_export_file();
|
32 |
+
}
|
33 |
+
|
34 |
+
//If importing / exporting events make sure we a logged in and check nonces.
|
35 |
+
if ( is_admin() && !empty($_POST['eventorganiser_download_events']) && check_admin_referer( 'eventorganiser_download_events' )
|
36 |
+
&& current_user_can('manage_options') ):
|
37 |
+
//Exporting events
|
38 |
+
//mmm... maybe finally a legitimate use of query_posts
|
39 |
+
query_posts(array(
|
40 |
+
'post_type'=>'event',
|
41 |
+
'showpastevents'=>true,
|
42 |
+
'group_events_by'=>'series',
|
43 |
+
'posts_per_page'=>-1,
|
44 |
+
));
|
45 |
+
$this->get_export_file();
|
46 |
+
|
47 |
+
elseif ( is_admin() && !empty($_POST['eventorganiser_import_events']) && check_admin_referer( 'eventorganiser_import_events')
|
48 |
+
&& current_user_can('manage_options') ):
|
49 |
+
//Importing events
|
50 |
+
|
51 |
+
//Perform checks on file:
|
52 |
+
if ( in_array($_FILES["ics"]["type"], array("text/calendar","application/octet-stream")) && ($_FILES["ics"]["size"] < 2097152) ):
|
53 |
+
if($_FILES["ics"]["error"] > 0){
|
54 |
+
$EO_Errors = new WP_Error('eo_error', sprintf(__("File Error encountered: %d",'eventorganiser'), $_FILES["ics"]["error"]));
|
55 |
+
}else{
|
56 |
+
//Import file
|
57 |
+
$this->import_file($_FILES['ics']['tmp_name']);
|
58 |
+
}
|
59 |
+
|
60 |
+
elseif(!isset($_FILES) || empty($_FILES['ics']['name'])):
|
61 |
+
$EO_Errors = new WP_Error('eo_error', __("No file detected.",'eventorganiser'));
|
62 |
+
|
63 |
+
else:
|
64 |
+
$EO_Errors = new WP_Error('eo_error', __("Invalid file uploaded. The file must be a ics calendar file of type 'text/calendar', no larger than 2MB.",'eventorganiser'));
|
65 |
+
$size = size_format($_FILES["ics"]["size"],2);
|
66 |
+
$details = sprintf( __('File size: %s. File type: %s','eventorganiser'),$size, $_FILES["ics"]["type"]);
|
67 |
+
$EO_Errors->add('eo_error', $details);
|
68 |
+
|
69 |
+
endif;
|
70 |
+
|
71 |
+
endif;
|
72 |
+
|
73 |
+
add_action( 'eventorganiser_event_settings_imexport', array( $this, 'get_im_export_markup' ) );
|
74 |
+
}
|
75 |
+
|
76 |
+
|
77 |
+
/**
|
78 |
+
* get markup for ex- and import on settings page
|
79 |
+
*
|
80 |
+
* @since 1.0.0
|
81 |
+
*/
|
82 |
+
public function get_im_export_markup() {
|
83 |
+
?>
|
84 |
+
<h3 class="title"><?php _e('Export Events', 'eventorganiser'); ?></h3>
|
85 |
+
<form method="post" action="">
|
86 |
+
<?php settings_fields( 'eventorganiser_imexport'); ?>
|
87 |
+
<p><?php _e( 'The export button below generates an ICS file of your events that can be imported in to other calendar applications such as Google Calendar.', 'eventorganiser'); ?></p>
|
88 |
+
<?php wp_nonce_field('eventorganiser_download_events'); ?>
|
89 |
+
<input type="hidden" name="eventorganiser_download_events" value="true" />
|
90 |
+
<?php submit_button( __( 'Download Export File', 'eventorganiser' )." »", 'secondary', 'eventorganiser_download_events' ); ?>
|
91 |
+
</form>
|
92 |
+
|
93 |
+
<h3 class="title"><?php _e('Import Events', 'eventorganiser'); ?></h3>
|
94 |
+
<form method="post" action="" enctype="multipart/form-data">
|
95 |
+
<div class="inside">
|
96 |
+
<p><?php _e( 'Import an ICS file.', 'eventorganiser'); ?></p>
|
97 |
+
<label><input type="checkbox" name="eo_import_venue" value=1 /> <?php _e( 'Import venues', 'eventorganiser' ); ?></label>
|
98 |
+
<label><input type="checkbox" name="eo_import_cat" value=1 /> <?php _e( 'Import categories', 'eventorganiser' ); ?></label>
|
99 |
+
<p><input type="file" name="ics" /></p>
|
100 |
+
<?php wp_nonce_field('eventorganiser_import_events'); ?>
|
101 |
+
<input type="hidden" name="eventorganiser_import_events" value="true" />
|
102 |
+
<?php submit_button( __( 'Upload ICS file', 'eventorganiser' )." »", 'secondary', 'eventorganiser_import_events' ); ?>
|
103 |
+
</div>
|
104 |
+
</form>
|
105 |
+
<?php
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Gets an ICAL file of events in the database, to be downloaded
|
110 |
+
|
111 |
+
* @since 1.0.0
|
112 |
+
*/
|
113 |
+
public function get_export_file() {
|
114 |
+
$filename = urlencode( 'event-organiser_' . date('Y-m-d') . '.ics' );
|
115 |
+
$this->export_events( $filename, 'text/calendar' );
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Creates an ICAL file of events in the database
|
120 |
+
|
121 |
+
* @since 1.0.0
|
122 |
+
* @param string filename - the name of the file to be created
|
123 |
+
* @param string filetype - the type of the file ('text/calendar')
|
124 |
+
*/
|
125 |
+
public function export_events( $filename, $filetype ){
|
126 |
+
//Collect output
|
127 |
+
ob_start();
|
128 |
+
|
129 |
+
// File header
|
130 |
+
header( 'Content-Description: File Transfer' );
|
131 |
+
header( 'Content-Disposition: attachment; filename=' . $filename );
|
132 |
+
header('Content-type: text/calendar; charset=' . get_option('blog_charset').';');
|
133 |
+
header("Pragma: 0");
|
134 |
+
header("Expires: 0");
|
135 |
+
?>
|
136 |
+
BEGIN:VCALENDAR
|
137 |
+
VERSION:2.0
|
138 |
+
PRODID:-//<?php get_bloginfo('name'); ?>//NONSGML Events //EN
|
139 |
+
CALSCALE:GREGORIAN
|
140 |
+
X-WR-CALNAME:<?php echo get_bloginfo('name');?> - Events
|
141 |
+
X-ORIGINAL-URL:<?php echo get_post_type_archive_link('event'); ?>
|
142 |
+
|
143 |
+
X-WR-CALDESC:<?php echo get_bloginfo('name');?> - Events
|
144 |
+
<?php
|
145 |
+
|
146 |
+
// Loop through events
|
147 |
+
if ( have_posts() ):
|
148 |
+
$now = new DateTime();
|
149 |
+
$dtstamp =$now->format('Ymd\THis\Z');
|
150 |
+
$UTC_tz = new DateTimeZone('UTC');
|
151 |
+
|
152 |
+
while( have_posts() ): the_post();
|
153 |
+
global $post;
|
154 |
+
|
155 |
+
//If event has no corresponding row in events table then skip it
|
156 |
+
if(!isset($post->event_id) || $post->event_id==-1)
|
157 |
+
continue;
|
158 |
+
|
159 |
+
$start = eo_get_the_start(DATETIMEOBJ);
|
160 |
+
$end = eo_get_the_end(DATETIMEOBJ);
|
161 |
+
|
162 |
+
$created_date = get_post_time('Ymd\THis\Z',true);
|
163 |
+
$modified_date = get_post_modified_time('Ymd\THis\Z',true);
|
164 |
+
|
165 |
+
$schedule_data = eo_get_event_schedule();
|
166 |
+
|
167 |
+
//Set up start and end date times
|
168 |
+
if( eo_is_all_day() ){
|
169 |
+
$format = 'Ymd';
|
170 |
+
$start_date = $start->format($format);
|
171 |
+
$end->modify('+1 minute');
|
172 |
+
$end_date = $end->format($format);
|
173 |
+
}else{
|
174 |
+
$format = 'Ymd\THis\Z';
|
175 |
+
$start->setTimezone($UTC_tz);
|
176 |
+
$start_date =$start->format($format);
|
177 |
+
$end->setTimezone($UTC_tz);
|
178 |
+
$end_date = $end->format($format);
|
179 |
+
}
|
180 |
+
|
181 |
+
//Get the reoccurrence rule in ICS format
|
182 |
+
$reoccurrence_rule = eventorganiser_generate_ics_rrule();
|
183 |
+
|
184 |
+
//Generate Event status
|
185 |
+
if( get_post_status(get_the_ID()) == 'publish' )
|
186 |
+
$status = 'CONFIRMED';
|
187 |
+
else
|
188 |
+
$status = 'TENTATIVE';
|
189 |
+
|
190 |
+
//Generate a globally unique UID:
|
191 |
+
$rand='';
|
192 |
+
$host = $_SERVER['SERVER_NAME'];
|
193 |
+
$base = 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPrRsStTuUvVxXuUvVwWzZ1234567890';
|
194 |
+
$start = 0;
|
195 |
+
$end = strlen( $base ) - 1;
|
196 |
+
$length = 6;
|
197 |
+
|
198 |
+
for( $p = 0; $p < $length; $p++ ):
|
199 |
+
$rand .= $base{mt_rand( $start, $end )};
|
200 |
+
endfor;
|
201 |
+
|
202 |
+
$uid = $now->format('Ymd\THiT').microtime(true).'-'.$rand.'-EO'.$post->ID.'@'.$host;
|
203 |
+
|
204 |
+
//Output event
|
205 |
+
?>
|
206 |
+
BEGIN:VEVENT
|
207 |
+
UID:<?php echo $uid;?>
|
208 |
+
|
209 |
+
STATUS:<?php echo $status;?>
|
210 |
+
|
211 |
+
DTSTAMP:<?php echo $dtstamp;?>
|
212 |
+
|
213 |
+
CREATED:<?php echo $created_date;?>
|
214 |
+
|
215 |
+
LAST-MODIFIED:<?php echo $modified_date;?>
|
216 |
+
|
217 |
+
<?php if( eo_is_all_day() ): ?>
|
218 |
+
DTSTART;VALUE=DATE:<?php echo $start_date ; ?>
|
219 |
+
|
220 |
+
DTEND;VALUE=DATE:<?php echo $end_date; ?>
|
221 |
+
<?php else: ?>
|
222 |
+
DTSTART:<?php echo $start_date ; ?>
|
223 |
+
|
224 |
+
DTEND:<?php echo $end_date; ?>
|
225 |
+
<?php endif;?>
|
226 |
+
|
227 |
+
<?php if ($reoccurrence_rule):?>
|
228 |
+
RRULE:<?php echo $reoccurrence_rule;?>
|
229 |
+
|
230 |
+
<?php endif;?>
|
231 |
+
<?php if( !empty($schedule_data['exclude']) ):
|
232 |
+
$exclude_strings = array();
|
233 |
+
foreach ( $schedule_data['exclude'] as $exclude ){
|
234 |
+
if( !eo_is_all_day() ){
|
235 |
+
$vdate='';
|
236 |
+
$exclude->setTimezone($UTC_tz);
|
237 |
+
$exclude_strings[] = $exclude->format('Ymd\THis\Z');
|
238 |
+
}else{
|
239 |
+
$vdate=';VALUE=DATE';
|
240 |
+
$exclude_strings[] = $exclude->format('Ymd');
|
241 |
+
}
|
242 |
+
}?>
|
243 |
+
EXDATE<?php echo $vdate;?>:<?php echo implode(',',$exclude_strings);?>
|
244 |
+
|
245 |
+
<?php endif;?>
|
246 |
+
<?php if( !empty($schedule_data['include']) ):
|
247 |
+
$include_strings = array();
|
248 |
+
foreach ( $schedule_data['include'] as $include ){
|
249 |
+
if( !eo_is_all_day() ){
|
250 |
+
$vdate='';
|
251 |
+
$include->setTimezone($UTC_tz);
|
252 |
+
$include_strings[] = $include->format('Ymd\THis\Z');
|
253 |
+
}else{
|
254 |
+
$vdate=';VALUE=DATE';
|
255 |
+
$include_strings[] = $include->format('Ymd');
|
256 |
+
}
|
257 |
+
}?>
|
258 |
+
|
259 |
+
RDATE<?php echo $vdate;?>:<?php echo implode(',',$include_strings);?>
|
260 |
+
|
261 |
+
<?php endif; ?>
|
262 |
+
SUMMARY:<?php echo $this->escape_icalText(get_the_title_rss()); ?>
|
263 |
+
|
264 |
+
<?php
|
265 |
+
$excerpt = get_the_excerpt();
|
266 |
+
$excerpt = apply_filters('the_excerpt_rss', $excerpt);
|
267 |
+
if(!empty($excerpt)):
|
268 |
+
?>
|
269 |
+
DESCRIPTION:<?php echo html_entity_decode($this->escape_icalText($excerpt));?>
|
270 |
+
|
271 |
+
<?php endif;
|
272 |
+
|
273 |
+
$cats = get_the_terms( get_the_ID(), 'event-category' );
|
274 |
+
if( $cats && !is_wp_error($cats) ):
|
275 |
+
$cat_names = wp_list_pluck($cats, 'name');
|
276 |
+
$cat_names = array_map(array($this,'parse_icalText'),$cat_names); ?>
|
277 |
+
CATEGORIES:<?php echo implode(',',$cat_names); ?>
|
278 |
+
|
279 |
+
<?php endif; ?>
|
280 |
+
<?php
|
281 |
+
if( eo_get_venue() ):
|
282 |
+
$venue =eo_get_venue_name(eo_get_venue());
|
283 |
+
?>
|
284 |
+
LOCATION: <?php echo $this->escape_icalText($venue);;?>
|
285 |
+
|
286 |
+
<?php endif;
|
287 |
+
$author = get_the_author();
|
288 |
+
?>
|
289 |
+
ORGANIZER: <?php echo $this->escape_icalText($author);?>
|
290 |
+
|
291 |
+
END:VEVENT
|
292 |
+
<?php
|
293 |
+
endwhile;
|
294 |
+
|
295 |
+
endif;
|
296 |
+
?>
|
297 |
+
END:VCALENDAR
|
298 |
+
<?php
|
299 |
+
|
300 |
+
//Collect output and echo
|
301 |
+
$eventsical = ob_get_contents();
|
302 |
+
ob_end_clean();
|
303 |
+
echo $eventsical;
|
304 |
+
exit();
|
305 |
+
}
|
306 |
+
|
307 |
+
|
308 |
+
function escape_icalText($text){
|
309 |
+
$text = str_replace("\\", "\\\\", $text);
|
310 |
+
$text = str_replace(",", "\,", $text);
|
311 |
+
$text = str_replace(";", "\;", $text);
|
312 |
+
$text = str_replace("\n", "\n ", $text);
|
313 |
+
|
314 |
+
return $text;
|
315 |
+
}
|
316 |
+
|
317 |
+
|
318 |
+
/**
|
319 |
+
* Reads in an ICAL file into an array, then parses the array and inserts events into database
|
320 |
+
|
321 |
+
* @since 1.1.0
|
322 |
+
*
|
323 |
+
* @param string $cal_file - the file to import
|
324 |
+
*/
|
325 |
+
function import_file($cal_file){
|
326 |
+
global $EO_Errors;
|
327 |
+
|
328 |
+
if ( ! current_user_can( 'manage_options' ) || ! current_user_can( 'edit_events' ))
|
329 |
+
wp_die( __('You do not have sufficient permissions to import events.','eventorganiser') );
|
330 |
+
|
331 |
+
//Returns the file as an array of lines
|
332 |
+
$file_array =$this->parse_file($cal_file);
|
333 |
+
|
334 |
+
//Go through array and import events and insert them into database.
|
335 |
+
$result = $this->import_events($file_array);
|
336 |
+
}
|
337 |
+
|
338 |
+
/* Reads an ICAL into an array ofline
|
339 |
+
|
340 |
+
* @since 1.1.0
|
341 |
+
*
|
342 |
+
* @param string $cal_file - the file to parse
|
343 |
+
*/
|
344 |
+
function parse_file($cal_file){
|
345 |
+
global $EO_Errors;
|
346 |
+
|
347 |
+
$file_handle = @fopen($cal_file, "rb");
|
348 |
+
$lines = array();
|
349 |
+
|
350 |
+
if(!$file_handle)
|
351 |
+
return false;
|
352 |
+
|
353 |
+
//Feed lines into array
|
354 |
+
while (!feof($file_handle) ):
|
355 |
+
$line_of_text = fgets($file_handle, 4096);
|
356 |
+
$lines[]= $line_of_text;
|
357 |
+
endwhile;
|
358 |
+
|
359 |
+
fclose($file_handle);
|
360 |
+
|
361 |
+
return $lines;
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Parses through an array of lines (of an ICAL file), creates events and inserts them as they are found.
|
366 |
+
|
367 |
+
* @since 1.1.0
|
368 |
+
*
|
369 |
+
* @param array - $lines, array of lines of an ICAL file
|
370 |
+
*/
|
371 |
+
function import_events($lines){
|
372 |
+
global $EO_Errors;
|
373 |
+
$state = "NONE";
|
374 |
+
$error = false;
|
375 |
+
|
376 |
+
$error_count =0;
|
377 |
+
$event_count =0;
|
378 |
+
|
379 |
+
$event_array = array();
|
380 |
+
$event_array['event'] = array();
|
381 |
+
$event_array['event_post'] = array();
|
382 |
+
$event_array['event_meta'] = array();
|
383 |
+
|
384 |
+
//Get Blog timezone, set Calendar timezone to this by default
|
385 |
+
$blog_tz = eo_get_blog_timezone();
|
386 |
+
$cal_tz =$blog_tz;
|
387 |
+
$output="";
|
388 |
+
|
389 |
+
//Record number of venues / categories created
|
390 |
+
global $eventorganiser_venues_created,$eventorganiser_cats_created;
|
391 |
+
$eventorganiser_venues_created = 0;
|
392 |
+
$eventorganiser_cats_created = 0;
|
393 |
+
|
394 |
+
//Read through each line
|
395 |
+
for ( $n = 0; $n < count ( $lines ) && ! $error; $n++ ):
|
396 |
+
$buff = trim($lines[$n]);
|
397 |
+
|
398 |
+
if(!empty($buff)):
|
399 |
+
$line = explode(':',$buff,2);
|
400 |
+
|
401 |
+
//On the right side of the line we may have DTSTART;TZID= or DTSTART;VALUE=
|
402 |
+
$modifiers = explode (';', $line[0]);
|
403 |
+
$property =array_shift($modifiers);
|
404 |
+
$value = (isset($line[1]) ? trim($line[1]) : '');
|
405 |
+
|
406 |
+
//If we are in EVENT state
|
407 |
+
if ($state == "VEVENT") {
|
408 |
+
|
409 |
+
//If END:VEVENT, insert event into database
|
410 |
+
if($property=='END' && $value=='VEVENT'){
|
411 |
+
$state = "VCALENDAR";
|
412 |
+
|
413 |
+
//Insert new post from objects
|
414 |
+
$post_id = eo_insert_event($event_array['event_post'],$event_array['event']);
|
415 |
+
|
416 |
+
if(!$post_id || is_wp_error($post_id) ){
|
417 |
+
$error_count++;
|
418 |
+
}
|
419 |
+
|
420 |
+
}else{
|
421 |
+
//Otherwise, parse event property
|
422 |
+
try{
|
423 |
+
while( isset( $lines[$n+1] ) && $lines[$n+1][0] == ' ' ){
|
424 |
+
$value .= $lines[$n+1];
|
425 |
+
$n++;
|
426 |
+
}
|
427 |
+
$event_array = $this->parse_Event_Property($event_array,$property,$value,$modifiers,$blog_tz,$cal_tz);
|
428 |
+
|
429 |
+
}catch(Exception $e){
|
430 |
+
$error_count++;
|
431 |
+
$preamble= sprintf( __('Line: %1$d','eventorganiser'),$n+1);
|
432 |
+
$EO_Errors->add('eo_error', $preamble.' '.$e->getMessage());
|
433 |
+
|
434 |
+
//Abort parsing event
|
435 |
+
$state = "VCALENDAR";
|
436 |
+
}
|
437 |
+
}
|
438 |
+
|
439 |
+
// If we are in CALENDAR state
|
440 |
+
}elseif ($state == "VCALENDAR") {
|
441 |
+
|
442 |
+
//Begin event
|
443 |
+
if( $property=='BEGIN' && $value=='VEVENT'){
|
444 |
+
$state = "VEVENT";
|
445 |
+
$event_count++;
|
446 |
+
$event_array['event'] = array();
|
447 |
+
$event_array['event_post'] = array();
|
448 |
+
$event_array['event_meta'] = array();
|
449 |
+
|
450 |
+
}elseif ( $property=='END' && $value=='VCALENDAR'){
|
451 |
+
$state = "NONE";
|
452 |
+
|
453 |
+
}elseif($property=='X-WR-TIMEZONE'){
|
454 |
+
try{
|
455 |
+
$cal_tz = self::parse_TZID($value);
|
456 |
+
}catch(Exception $e){
|
457 |
+
$preamble= sprintf( __('Line: %1$d','eventorganiser'),$n+1);
|
458 |
+
$EO_Errors->add('eo_error', $preamble.' '.$e->getMessage());
|
459 |
+
break;
|
460 |
+
}
|
461 |
+
}
|
462 |
+
|
463 |
+
}elseif($state == "NONE" && $property=='BEGIN' && $value=='VCALENDAR') {
|
464 |
+
$state = "VCALENDAR";
|
465 |
+
}
|
466 |
+
|
467 |
+
endif; //If line is not empty
|
468 |
+
endfor; //For each line
|
469 |
+
|
470 |
+
//Display message
|
471 |
+
if($event_count ==0):
|
472 |
+
$EO_Errors->add('eo_error', __("No events were imported.",'eventorganiser'));
|
473 |
+
elseif($error_count >0):
|
474 |
+
$EO_Errors->add('eo_error',sprintf( __('There was an error with %1$d of %2$d events in the ical file'),$error_count, $event_count));
|
475 |
+
else:
|
476 |
+
|
477 |
+
if($event_count==1)
|
478 |
+
$message=__("1 event was successfully imported",'eventorganiser').".";
|
479 |
+
else
|
480 |
+
$message= sprintf( __("%d events were successfully imported",'eventorganiser'),$event_count).".";
|
481 |
+
|
482 |
+
if($eventorganiser_venues_created==1){
|
483 |
+
$message.= " ".__("1 venue was created",'eventorganiser').".";
|
484 |
+
}elseif($eventorganiser_venues_created>1){
|
485 |
+
$message .= " ".sprintf( __("%d venues were created",'eventorganiser'),$eventorganiser_venues_created).".";
|
486 |
+
}
|
487 |
+
|
488 |
+
if($eventorganiser_cats_created==1){
|
489 |
+
$message.= " ".__("1 category was created",'eventorganiser').".";
|
490 |
+
}elseif($eventorganiser_cats_created>1){
|
491 |
+
$message .= " ".sprintf( __("%d categories were created",'eventorganiser'),$eventorganiser_cats_created).".";
|
492 |
+
}
|
493 |
+
|
494 |
+
$EO_Errors->add('eo_notice',$message);
|
495 |
+
endif;
|
496 |
+
return true;
|
497 |
+
}
|
498 |
+
|
499 |
+
/**
|
500 |
+
* Returns the supplied array with the additional data parsed from the given property-value pair
|
501 |
+
* May require the blog and/or calendar time-zone in date manipulations
|
502 |
+
* May also require modifiers in date manipulations (e.g. TZID, VALUE)
|
503 |
+
*
|
504 |
+
* @since 1.1.0
|
505 |
+
*
|
506 |
+
* @param array $event_array - array of event details to be added to
|
507 |
+
* @param string $property - the property being parsed
|
508 |
+
* @param string $value - the value of the property being parsed
|
509 |
+
* @param string $modifiers - array of modifiers associated with the property
|
510 |
+
* @param DateTimeZone $blog_tz - blog's timezone
|
511 |
+
* @param DateTimeZone $cal_tzid - calendar's default timezone
|
512 |
+
* @return DateTimeZone - the timezone with the given identifier or false if it isn't recognised
|
513 |
+
*/
|
514 |
+
function parse_Event_Property($event_array,$property,$value,$modifiers,$blog_tz,$cal_tz){
|
515 |
+
extract($event_array);
|
516 |
+
|
517 |
+
$import_venues = (isset($_POST['eo_import_venue']) ? true : false);
|
518 |
+
$import_cats = (isset($_POST['eo_import_cat']) ? true : false);
|
519 |
+
|
520 |
+
$date_tz="";
|
521 |
+
|
522 |
+
if(!empty($modifiers)):
|
523 |
+
foreach($modifiers as $modifier):
|
524 |
+
if (stristr($modifier, 'TZID')){
|
525 |
+
$date_tz = self::parse_TZID(substr($modifier, 5));
|
526 |
+
|
527 |
+
}elseif(stristr($modifier, 'VALUE')){
|
528 |
+
$meta = substr($modifier, 6);
|
529 |
+
}
|
530 |
+
endforeach;
|
531 |
+
endif;
|
532 |
+
|
533 |
+
//For dates - if there is not an associated timezone, use calendar default.
|
534 |
+
if(empty($date_tz))
|
535 |
+
$date_tz = $cal_tz;
|
536 |
+
|
537 |
+
switch($property):
|
538 |
+
//Date properties
|
539 |
+
case 'CREATED':
|
540 |
+
case 'DTSTART':
|
541 |
+
case 'DTEND':
|
542 |
+
if(isset($meta) && $meta=='DATE'):
|
543 |
+
$date = $this->parse_icalDate($value, $blog_tz);
|
544 |
+
$allday=1;
|
545 |
+
else:
|
546 |
+
$date = $this->parse_icalDateTime($value, $date_tz);
|
547 |
+
$allday=0;
|
548 |
+
endif;
|
549 |
+
|
550 |
+
if(empty($date))
|
551 |
+
break;
|
552 |
+
|
553 |
+
switch($property):
|
554 |
+
case'DTSTART':
|
555 |
+
$event['start']= $date;
|
556 |
+
$event['all_day']=$allday;
|
557 |
+
break;
|
558 |
+
|
559 |
+
case 'DTEND':
|
560 |
+
if($allday==1)
|
561 |
+
$date->modify('-1 second');
|
562 |
+
$event['end']= $date;
|
563 |
+
break;
|
564 |
+
|
565 |
+
case 'CREATED':
|
566 |
+
$date->setTimezone(new DateTimeZone('utc'));
|
567 |
+
$event_post['post_date_gmt']= $date->format('Y-m-d H:i:s');
|
568 |
+
break;
|
569 |
+
|
570 |
+
endswitch;
|
571 |
+
break;
|
572 |
+
|
573 |
+
case 'EXDATE':
|
574 |
+
case 'RDATE':
|
575 |
+
//The modifiers have been dealt with above. We do similiar to above, except for an array of dates...
|
576 |
+
$value_array = explode(',',$value);
|
577 |
+
|
578 |
+
//Note, we only consider the Date part and ignore the time
|
579 |
+
foreach($value_array as $val):
|
580 |
+
$date = $this->parse_icalDate($val, $blog_tz);
|
581 |
+
if( $property == 'EXDATE' ){
|
582 |
+
$event['exclude'][] = $date;
|
583 |
+
}else{
|
584 |
+
$event['include'][] = $date;
|
585 |
+
}
|
586 |
+
endforeach;
|
587 |
+
|
588 |
+
break;
|
589 |
+
|
590 |
+
//Reoccurrence rule properties
|
591 |
+
case 'RRULE':
|
592 |
+
$event += $this->parse_RRule($value);
|
593 |
+
break;
|
594 |
+
|
595 |
+
//The event's summary (AKA post title)
|
596 |
+
case 'SUMMARY':
|
597 |
+
$event_post['post_title']=$this->parse_icalText($value);
|
598 |
+
break;
|
599 |
+
|
600 |
+
//The event's description (AKA post content)
|
601 |
+
case 'DESCRIPTION':
|
602 |
+
$event_post['post_content']=$this->parse_icalText($value);
|
603 |
+
break;
|
604 |
+
|
605 |
+
//Event venues, assign to existing venue - or if set, create new one
|
606 |
+
case 'LOCATION':
|
607 |
+
$venue_ids = array();
|
608 |
+
if( !empty($value) ):
|
609 |
+
$venue_name = trim($value);
|
610 |
+
$venue = get_term_by('name',$venue_name,'event-venue');
|
611 |
+
if($venue){
|
612 |
+
$venue_ids[] = (int) $venue->term_id;
|
613 |
+
|
614 |
+
}elseif($import_venues){
|
615 |
+
//Create new venue, get ID. Count of venues created++
|
616 |
+
global $eventorganiser_venues_created;
|
617 |
+
$return = eo_insert_venue($venue_name);
|
618 |
+
|
619 |
+
if( !is_wp_error($return) && !$return ){
|
620 |
+
$venue_ids[] = (int) $return['term_id'];
|
621 |
+
$eventorganiser_venues_created++;
|
622 |
+
$event['venue']= $return['term_id']; //XXX This is depreciated
|
623 |
+
}
|
624 |
+
}
|
625 |
+
$venue_ids = array_filter($venue_ids);
|
626 |
+
if(!empty($venue_ids)){
|
627 |
+
$event_post['tax_input']['event-venue']=$venue_ids;
|
628 |
+
}
|
629 |
+
endif;
|
630 |
+
break;
|
631 |
+
|
632 |
+
//Event categories, assign to existing categories - or if set, create new ones
|
633 |
+
case 'CATEGORIES':
|
634 |
+
$cats=explode(',',$value);
|
635 |
+
$cat_ids = array();
|
636 |
+
if(!empty($cats)):
|
637 |
+
foreach ($cats as $cat_name):
|
638 |
+
$cat_name = trim($cat_name);
|
639 |
+
$cat = get_term_by('name',$cat_name,'event-category');
|
640 |
+
if($cat){
|
641 |
+
$cat_ids[] = (int) $cat->term_id;
|
642 |
+
}elseif($import_cats){
|
643 |
+
//Create new category, get ID. Count of cats created++
|
644 |
+
global $eventorganiser_cats_created;
|
645 |
+
$return = wp_insert_term($cat_name,'event-category',array());
|
646 |
+
if(!is_wp_error($return)){
|
647 |
+
$cat_ids[] = (int) $return['term_id'];
|
648 |
+
$eventorganiser_cats_created++;
|
649 |
+
}
|
650 |
+
}
|
651 |
+
endforeach;
|
652 |
+
|
653 |
+
$cat_ids = array_filter($cat_ids);
|
654 |
+
if(!empty($cat_ids))
|
655 |
+
$event_post['tax_input']['event-category']=$cat_ids;
|
656 |
+
endif;
|
657 |
+
break;
|
658 |
+
|
659 |
+
//The event's status
|
660 |
+
case 'STATUS':
|
661 |
+
switch($value):
|
662 |
+
case 'CONFIRMED':
|
663 |
+
$event_post['post_status'] = 'publish';
|
664 |
+
break;
|
665 |
+
|
666 |
+
case 'CANCELLED':
|
667 |
+
$event_post['post_status'] = 'trash';
|
668 |
+
break;
|
669 |
+
|
670 |
+
default:
|
671 |
+
$event_post['post_status'] = 'draft';
|
672 |
+
endswitch;
|
673 |
+
break;
|
674 |
+
|
675 |
+
//An url associated with the event
|
676 |
+
case 'URL':
|
677 |
+
$event_meta['eo_url']=$value;
|
678 |
+
break;
|
679 |
+
|
680 |
+
endswitch;
|
681 |
+
|
682 |
+
$event_array= array('event'=>$event,'event_post'=>$event_post,'event_meta'=>$event_meta);
|
683 |
+
|
684 |
+
return $event_array;
|
685 |
+
}
|
686 |
+
|
687 |
+
/**
|
688 |
+
* Takes escaped text and returns the text unescaped.
|
689 |
+
|
690 |
+
* @since 1.1.0
|
691 |
+
*
|
692 |
+
* @param string $text - the escaped test
|
693 |
+
* @return string $text - the text, unescaped.
|
694 |
+
*/
|
695 |
+
function parse_icalText($text){
|
696 |
+
//Get rid of carriage returns:
|
697 |
+
$text = str_replace("\r\n","\n",$text);
|
698 |
+
$text = str_replace("\r","\n",$text);
|
699 |
+
|
700 |
+
//Some calendar apps break up text
|
701 |
+
$text = str_replace("\n ","",$text);
|
702 |
+
$text = str_replace("\r ","",$text);
|
703 |
+
|
704 |
+
//Any intended carriage returns/new-lines converted to HTML
|
705 |
+
$text = str_replace("\\r\\n","",$text);
|
706 |
+
$text = str_replace("\\n","</br>",$text);
|
707 |
+
$text = stripslashes($text);
|
708 |
+
return $text;
|
709 |
+
}
|
710 |
+
|
711 |
+
/**
|
712 |
+
* Takes a date-time in ICAL and returns a datetime object
|
713 |
+
|
714 |
+
* @since 1.1.0
|
715 |
+
*
|
716 |
+
* @param string $tzid - the value of the ICAL TZID property
|
717 |
+
* @return DateTimeZone - the timezone with the given identifier or false if it isn't recognised
|
718 |
+
*/
|
719 |
+
function parse_TZID($tzid){
|
720 |
+
$tzid = str_replace('-','/',$tzid);
|
721 |
+
$tz = new DateTimeZone($tzid);
|
722 |
+
return $tz;
|
723 |
+
}
|
724 |
+
|
725 |
+
/**
|
726 |
+
* Takes a date in ICAL and returns a datetime object
|
727 |
+
|
728 |
+
* @since 1.1.0
|
729 |
+
*
|
730 |
+
* @param string $ical_date - date in ICAL format
|
731 |
+
* @param DateTimeZone $blog_tz - Blog timezone object
|
732 |
+
* @return DateTime - the $ical_date as DateTime object
|
733 |
+
*/
|
734 |
+
function parse_icalDate($ical_date, $blog_tz){
|
735 |
+
//Expects: YYYYMMDD;
|
736 |
+
preg_match('/^(\d{8})*/', $ical_date, $matches);
|
737 |
+
|
738 |
+
if(count($matches)!=2){
|
739 |
+
throw new Exception(__('Invalid date. Date expected in YYYYMMDD format.','eventorganiser'));
|
740 |
+
}
|
741 |
+
|
742 |
+
$datetime = new DateTime($matches[1],$blog_tz);
|
743 |
+
|
744 |
+
return $datetime;
|
745 |
+
}
|
746 |
+
|
747 |
+
/**
|
748 |
+
* Takes a date-time in ICAL and returns a datetime object
|
749 |
+
|
750 |
+
* @since 1.1.0
|
751 |
+
*
|
752 |
+
* @param string $ical_date - date-time in ICAL format
|
753 |
+
* @param DateTimeZone $blog_tz - Blog timezone object
|
754 |
+
* @return DateTime - the $ical_date as DateTime object
|
755 |
+
*/
|
756 |
+
function parse_icalDateTime($ical_date,$tz){
|
757 |
+
/*
|
758 |
+
Expects
|
759 |
+
utc: YYYYMMDDTHHiissZ
|
760 |
+
local: YYYYMMDDTHHiiss
|
761 |
+
*/
|
762 |
+
preg_match('/^((\d{8}T\d{6})(Z)?)/', $ical_date, $matches);
|
763 |
+
|
764 |
+
if(count($matches)==3){
|
765 |
+
//floating / local date
|
766 |
+
|
767 |
+
}elseif(count($matches)==4){
|
768 |
+
$tz = new DateTimeZone('UTC');
|
769 |
+
|
770 |
+
}else{
|
771 |
+
throw new Exception(__('Invalid datetime. Date expected in YYYYMMDDTHHiissZ or YYYYMMDDTHHiiss format.','eventorganiser'));
|
772 |
+
return false;
|
773 |
+
}
|
774 |
+
|
775 |
+
$datetime = new DateTime($matches[2],$tz);
|
776 |
+
|
777 |
+
return $datetime;
|
778 |
+
}
|
779 |
+
|
780 |
+
/**
|
781 |
+
* Takes a date-time in ICAL and returns a datetime object
|
782 |
+
|
783 |
+
* @since 1.1.0
|
784 |
+
*
|
785 |
+
* @param string $RRule - the value of the ICAL RRule property
|
786 |
+
* @return array - a reoccurrence rule array as understood by Event Organiser
|
787 |
+
*/
|
788 |
+
function parse_RRule($RRule){
|
789 |
+
//RRule is a sequence of rule parts seperated by ';'
|
790 |
+
$rule_parts = explode(';',$RRule);
|
791 |
+
|
792 |
+
foreach ($rule_parts as $rule_part):
|
793 |
+
|
794 |
+
//Each rule part is of the form PROPERTY=VALUE
|
795 |
+
$prop_value = explode('=',$rule_part, 2);
|
796 |
+
$property = $prop_value[0];
|
797 |
+
$value = $prop_value[1];
|
798 |
+
|
799 |
+
switch($property):
|
800 |
+
case 'FREQ':
|
801 |
+
$rule_array['schedule'] =strtolower($value);
|
802 |
+
break;
|
803 |
+
|
804 |
+
case 'INTERVAL':
|
805 |
+
$rule_array['frequency'] =intval($value);
|
806 |
+
break;
|
807 |
+
|
808 |
+
case 'UNTIL':
|
809 |
+
//Is the scheduled end a date-time or just a date?
|
810 |
+
if(preg_match('/^((\d{8}T\d{6})(Z)?)/', $value))
|
811 |
+
$date = $this->parse_icalDateTime($value, new DateTimeZone('UTC'));
|
812 |
+
else
|
813 |
+
$date = $this->parse_icalDate($value, new DateTimeZone('UTC'));
|
814 |
+
|
815 |
+
$rule_array['schedule_last'] = $date;
|
816 |
+
break;
|
817 |
+
|
818 |
+
case 'BYDAY':
|
819 |
+
$byday = $value;
|
820 |
+
break;
|
821 |
+
|
822 |
+
case 'BYMONTHDAY':
|
823 |
+
$bymonthday = $value;
|
824 |
+
break;
|
825 |
+
endswitch;
|
826 |
+
|
827 |
+
endforeach;
|
828 |
+
|
829 |
+
//Meta-data for Weekly and Monthly schedules
|
830 |
+
if($rule_array['schedule']=='monthly'):
|
831 |
+
if(isset($byday)){
|
832 |
+
preg_match('/(\d+)([a-zA-Z]+)/', $byday, $matches);
|
833 |
+
$rule_array['schedule_meta'] ='BYDAY='.$matches[1].$matches[2];
|
834 |
+
|
835 |
+
}elseif(isset($bymonthday)){
|
836 |
+
$rule_array['schedule_meta'] ='BYMONTHDAY='.$bymonthday;
|
837 |
+
|
838 |
+
}else{
|
839 |
+
throw new Exception('Incomplete scheduling information');
|
840 |
+
}
|
841 |
+
|
842 |
+
elseif($rule_array['schedule']=='weekly'):
|
843 |
+
preg_match('/([a-zA-Z,]+)/', $byday, $matches);
|
844 |
+
$rule_array['schedule_meta'] =explode(',',$matches[1]);
|
845 |
+
|
846 |
+
endif;
|
847 |
+
|
848 |
+
return $rule_array;
|
849 |
+
}
|
850 |
+
|
851 |
+
|
852 |
+
} // end class
|
includes/debug.php
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Checks if wp_footer() is called.
|
4 |
+
*/
|
5 |
+
class EventOrganiser_No_WP_Footer
|
6 |
+
{
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Instance
|
10 |
+
* @static
|
11 |
+
* @access private
|
12 |
+
* @var object
|
13 |
+
*/
|
14 |
+
private static $instance;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Was `wp_footer()` fired?
|
18 |
+
* @static
|
19 |
+
* @var bool
|
20 |
+
*/
|
21 |
+
static $footer_fired = false;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Creates a new static instance
|
25 |
+
* @static
|
26 |
+
* @return void
|
27 |
+
*/
|
28 |
+
public static function get_instance() {
|
29 |
+
if ( ! self::$instance ) {
|
30 |
+
self::$instance = new self();
|
31 |
+
}
|
32 |
+
return self::$instance;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Hook the functions.
|
37 |
+
* Check for wp_footer() only on admin pages (via shutdown).
|
38 |
+
* Display notice only if the option 'sh_no_wp_footer' is present in the database, but is not set to 'suppress'.
|
39 |
+
*/
|
40 |
+
private function __construct() {
|
41 |
+
add_action( 'shutdown', array( __CLASS__, 'did_footer' ) );
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Checks if wp_footer() was fired.
|
46 |
+
* Hooked onto shutdown.
|
47 |
+
* If wp_footer() wasn't fired it sets 'sh_no_wp_footer' option to true, unless it already set to 'supress'
|
48 |
+
* If wp_footer() was fired it removes the 'sh_no_wp_footer' option.
|
49 |
+
*/
|
50 |
+
static function did_footer(){
|
51 |
+
if( !did_action( 'wp_footer' ) )
|
52 |
+
update_option( 'eo_wp_footer_present', -1 );
|
53 |
+
elseif( did_action( 'wp_footer' ) )
|
54 |
+
update_option( 'eo_wp_footer_present', 1 );
|
55 |
+
}
|
56 |
+
}
|
57 |
+
$eo_no_wp_footer = EventOrganiser_No_WP_Footer::get_instance();
|
includes/deprecated.php
ADDED
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*@package deprecated
|
4 |
+
*/
|
5 |
+
/**
|
6 |
+
* Returns an array of DateTime objects for each start date of occurrence
|
7 |
+
* @since 1.0.0
|
8 |
+
* @deprecated 1.5
|
9 |
+
* @see eo_get_the_occurrences_of()
|
10 |
+
*
|
11 |
+
* @param int $post_id Optional, the event (post) ID,
|
12 |
+
* @return array|false Array of DateTime objects of the start date-times of occurences. False if none exist.
|
13 |
+
*/
|
14 |
+
function eo_get_the_occurrences($post_id=0){
|
15 |
+
//_deprecated_function( __FUNCTION__, '1.5', 'eo_get_the_occurrences_of()' );
|
16 |
+
$occurrences = eo_get_the_occurrences_of($post_id);
|
17 |
+
if( $occurrences )
|
18 |
+
return wp_list_pluck($occurrences, 'start');
|
19 |
+
return false;
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Return true is the event is an all day event.
|
24 |
+
* @since 1.2
|
25 |
+
* @deprecated 1.5
|
26 |
+
* @see eo_is_all_day()
|
27 |
+
*
|
28 |
+
* @param int $post_id Optional, the event series (post) ID,
|
29 |
+
* @return bool True if event runs all day, or false otherwise
|
30 |
+
*/
|
31 |
+
function eo_is_allday($post_id=0){
|
32 |
+
_deprecated_function( __FUNCTION__, '1.5', 'eo_is_all_day()' );
|
33 |
+
return eo_is_all_day($post_id);
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Returns the formated date of the last occurrence of an event
|
38 |
+
* @since 1.0.0
|
39 |
+
* @deprecated 1.5 use eo_get_schedule_last
|
40 |
+
* @see eo_get_schedule_last
|
41 |
+
*
|
42 |
+
* @param string $format the format to use, using PHP Date format
|
43 |
+
* @param int $post_id Optional, the event (post) ID,
|
44 |
+
* @return string the formatted date
|
45 |
+
*/
|
46 |
+
function eo_get_schedule_end($format='d-m-Y',$post_id=0){
|
47 |
+
return eo_get_schedule_last($format,$post_id);
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Prints the formated date of the last occurrence of an event
|
52 |
+
* @since 1.0.0
|
53 |
+
* @deprecated 1.5 use eo_schedule_last
|
54 |
+
* @see eo_schedule_last
|
55 |
+
*
|
56 |
+
* @param string $format the format to use, using PHP Date format
|
57 |
+
* @param int $post_id Optional, the event (post) ID,
|
58 |
+
*/
|
59 |
+
function eo_schedule_end($format='d-m-Y',$post_id=0){
|
60 |
+
echo eo_get_schedule_last($format,$post_id);
|
61 |
+
}
|
62 |
+
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Returns an array with details of the event's reoccurences
|
66 |
+
* @since 1.0.0
|
67 |
+
* @deprecated 1.6
|
68 |
+
* @see eo_get_event_schedule()
|
69 |
+
*
|
70 |
+
* @param int $post_id Optional, the event (post) ID,
|
71 |
+
* @return array Schedule information
|
72 |
+
*/
|
73 |
+
function eo_get_reoccurrence($post_id=0){
|
74 |
+
return eo_get_reoccurence($post_id);
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Returns an array with details of the event's reoccurences.
|
80 |
+
* Note this is is identical to eo_get_reoccurrence() which corrects a spelling error.
|
81 |
+
*
|
82 |
+
* @param int Optional, the event (post) ID,
|
83 |
+
* @since 1.0.0
|
84 |
+
* @deprecated 1.6
|
85 |
+
* @see eo_get_event_schedule()
|
86 |
+
*
|
87 |
+
* @param int $post_id Optional, the event (post) ID,
|
88 |
+
* @return array Schedule information
|
89 |
+
*/
|
90 |
+
function eo_get_reoccurence($post_id=0){
|
91 |
+
_deprecated_function( __FUNCTION__, '1.5', 'eo_get_event_schedule()' );
|
92 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
93 |
+
|
94 |
+
if( empty($post_id) || 'event' != get_post_type($post_id) )
|
95 |
+
return false;
|
96 |
+
|
97 |
+
$return = eo_get_event_schedule( $post_id );
|
98 |
+
|
99 |
+
if ( !$return )
|
100 |
+
return false;
|
101 |
+
|
102 |
+
$return['reoccurrence'] =$return['schedule'];
|
103 |
+
$return['meta'] = $return['schedule_meta'];
|
104 |
+
$return['end'] = $return['schedule_last'];
|
105 |
+
return $return;
|
106 |
+
}
|
107 |
+
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Returns the colour of a category associated with the event
|
111 |
+
* @since 1.3.3
|
112 |
+
* @deprecated 1.6
|
113 |
+
* @see eo_get_event_color()
|
114 |
+
*
|
115 |
+
* @param int $post_id The event (post) ID
|
116 |
+
* @return string The colour of the category in HEX format
|
117 |
+
*/
|
118 |
+
function eo_event_color($post_id=0){
|
119 |
+
_deprecated_function( __FUNCTION__, '1.6', 'eo_get_event_color()' );
|
120 |
+
return eo_get_event_color($post_id);
|
121 |
+
}
|
122 |
+
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Retrieve array of venues. Acts as a wrapper for get_terms, except hide_empty defaults to false.
|
126 |
+
* @since 1.0.0
|
127 |
+
* @deprecated 1.6
|
128 |
+
* @see eo_get_venues()
|
129 |
+
*
|
130 |
+
* @param string|array $args The values of what to search for when returning venues
|
131 |
+
* @return array List of Term (venue) Objects
|
132 |
+
*/
|
133 |
+
function eo_get_the_venues($args=array()){
|
134 |
+
_deprecated_function( __FUNCTION__, '1.6', 'eo_get_venues()' );
|
135 |
+
return eo_get_venues($args);
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Deletes the event data associated with post. Should be called when an event is being deleted.
|
140 |
+
* This does not delete the post.
|
141 |
+
* @since 1.0.0
|
142 |
+
* @deprecated 1.6
|
143 |
+
* @see eo_delete_event_occurrences()
|
144 |
+
*
|
145 |
+
* @param int $post_id The event (post) ID
|
146 |
+
*/
|
147 |
+
function eventorganiser_event_delete($post_id){
|
148 |
+
eo_delete_event_occurrences($post_id);
|
149 |
+
}
|
150 |
+
|
151 |
+
?>
|
includes/event-organiser-ajax.php
ADDED
@@ -0,0 +1,596 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Deals with the plug-in's AJAX requests
|
4 |
+
*/
|
5 |
+
|
6 |
+
add_action( 'wp_ajax_eventorganiser-fullcal', 'eventorganiser_public_fullcalendar' );
|
7 |
+
add_action( 'wp_ajax_nopriv_eventorganiser-fullcal', 'eventorganiser_public_fullcalendar' );
|
8 |
+
add_action( 'wp_ajax_event-admin-cal', 'eventorganiser_admin_calendar' );
|
9 |
+
add_action( 'wp_ajax_eofc-format-time', 'eventorganiser_admin_cal_time_format' );
|
10 |
+
add_action( 'wp_ajax_eo-search-venue', 'eventorganiser_search_venues' );
|
11 |
+
add_action( 'wp_ajax_nopriv_eo_widget_agenda', 'eventorganiser_widget_agenda' );
|
12 |
+
add_action( 'wp_ajax_eo_widget_agenda', 'eventorganiser_widget_agenda' );
|
13 |
+
add_action( 'wp_ajax_nopriv_eo_widget_cal', 'eventorganiser_widget_cal' );
|
14 |
+
add_action( 'wp_ajax_eo_widget_cal', 'eventorganiser_widget_cal' );
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Ajax response for the public full calendar. This returns events to be displayed on the front-end full calendar
|
18 |
+
*
|
19 |
+
*@since 1.3
|
20 |
+
*@access private
|
21 |
+
*@ignore
|
22 |
+
*/
|
23 |
+
function eventorganiser_public_fullcalendar() {
|
24 |
+
$request = array(
|
25 |
+
'event_start_before'=>$_GET['end'],
|
26 |
+
'event_end_after'=>$_GET['start'],
|
27 |
+
);
|
28 |
+
|
29 |
+
$time_format = !empty($_GET['timeformat']) ? $_GET['timeformat'] : get_option('time_format');
|
30 |
+
|
31 |
+
//Restrict by category and/or venue
|
32 |
+
if( !empty($_GET['category']) ){
|
33 |
+
$cats = explode(',',esc_attr($_GET['category']));
|
34 |
+
$request['tax_query'][] = array(
|
35 |
+
'taxonomy' => 'event-category',
|
36 |
+
'field' => 'slug',
|
37 |
+
'terms' => $cats,
|
38 |
+
'operator' => 'IN'
|
39 |
+
);
|
40 |
+
}
|
41 |
+
|
42 |
+
if( !empty($_GET['venue']) ){
|
43 |
+
$venues = explode(',',esc_attr($_GET['venue']));
|
44 |
+
$request['tax_query'][] = array(
|
45 |
+
'taxonomy' => 'event-venue',
|
46 |
+
'field' => 'slug',
|
47 |
+
'terms' => $venues,
|
48 |
+
'operator' => 'IN'
|
49 |
+
);
|
50 |
+
}
|
51 |
+
|
52 |
+
$presets = array('numberposts'=>-1, 'group_events_by'=>'','showpastevents'=>true);
|
53 |
+
|
54 |
+
//Retrieve events
|
55 |
+
$query = array_merge($request,$presets,array($time_format));
|
56 |
+
$key = 'eo_fc_'.md5(serialize($query));
|
57 |
+
$calendar = get_transient('eo_full_calendar_public');
|
58 |
+
if( $calendar && is_array($calendar) && isset($calendar[$key]) ){
|
59 |
+
echo json_encode($calendar[$key]);
|
60 |
+
exit;
|
61 |
+
}
|
62 |
+
|
63 |
+
$events = eo_get_events($query);
|
64 |
+
$eventsarray = array();
|
65 |
+
|
66 |
+
//Blog timezone
|
67 |
+
$tz = eo_get_blog_timezone();
|
68 |
+
|
69 |
+
//Loop through events
|
70 |
+
global $post;
|
71 |
+
if ($events) :
|
72 |
+
foreach ($events as $post) :
|
73 |
+
setup_postdata( $post );
|
74 |
+
$event=array();
|
75 |
+
$event['className']=array('eo-event');
|
76 |
+
|
77 |
+
//Title and url
|
78 |
+
$event['title']=html_entity_decode(get_the_title($post->ID),ENT_QUOTES,'UTF-8');
|
79 |
+
$link = esc_js(get_permalink( $post->ID));
|
80 |
+
$event['url'] = apply_filters('eventorganiser_calendar_event_link',$link,$post->ID,$post->occurrence_id);
|
81 |
+
|
82 |
+
//All day or not?
|
83 |
+
$event['allDay'] = eo_is_all_day();
|
84 |
+
|
85 |
+
//Get Event Start and End date, set timezone to the blog's timzone
|
86 |
+
$event_start = new DateTime($post->StartDate.' '.$post->StartTime, $tz);
|
87 |
+
$event_end = new DateTime($post->EndDate.' '.$post->FinishTime, $tz);
|
88 |
+
$event['start']= $event_start->format('Y-m-d\TH:i:s\Z');
|
89 |
+
$event['end']= $event_end->format('Y-m-d\TH:i:s\Z');
|
90 |
+
|
91 |
+
//Don't use get_the_excerpt as this adds a link
|
92 |
+
$excerpt_length = apply_filters('excerpt_length', 55);
|
93 |
+
|
94 |
+
$description = wp_trim_words( strip_shortcodes(get_the_content()), $excerpt_length, '...' );
|
95 |
+
|
96 |
+
if( $event_start->format('Y-m-d') != $event_end->format('Y-m-d') ){
|
97 |
+
//Start & ends on different days
|
98 |
+
|
99 |
+
if( !eo_is_all_day() ){
|
100 |
+
//Not all day, include time
|
101 |
+
$date = eo_format_datetime($event_start,'F j '.$time_format).' - '.eo_format_datetime($event_end,'F j '.$time_format);
|
102 |
+
}else{
|
103 |
+
//All day, don't include date
|
104 |
+
if( $event_start->format('Y-m') == $event_end->format('Y-m') ){
|
105 |
+
//Same month
|
106 |
+
$date = eo_format_datetime($event_start,'F j').' - '.eo_format_datetime($event_end,'j, Y');
|
107 |
+
}else{
|
108 |
+
//Different month
|
109 |
+
$date = eo_format_datetime($event_start,'F j').' - '.eo_format_datetime($event_end,'F j');
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
}else{
|
114 |
+
//Start and end on the same day
|
115 |
+
|
116 |
+
if( !eo_is_all_day() ){
|
117 |
+
//Not all day, include time
|
118 |
+
$date = eo_format_datetime($event_start,$format="F j, Y $time_format").' - '.eo_format_datetime($event_end,$time_format);
|
119 |
+
}else{
|
120 |
+
//All day
|
121 |
+
$date = eo_format_datetime($event_start,$format='F j, Y');
|
122 |
+
}
|
123 |
+
}
|
124 |
+
$description = $date.'</br></br>'.$description;
|
125 |
+
|
126 |
+
$event['description'] = apply_filters('eventorganiser_event_tooltip', $description, $post->ID,$post->occurrence_id,$post);
|
127 |
+
|
128 |
+
//Colour past events
|
129 |
+
$now = new DateTime(null,$tz);
|
130 |
+
if($event_start <= $now)
|
131 |
+
$event['className'][] = 'eo-past-event';
|
132 |
+
else
|
133 |
+
$event['className'][] = 'eo-future-event';
|
134 |
+
|
135 |
+
//Add class if event is all day
|
136 |
+
if( eo_is_all_day() )
|
137 |
+
$event['className'][] = 'eo-all-day';
|
138 |
+
|
139 |
+
//Include venue if this is set
|
140 |
+
$venue = eo_get_venue($post->ID);
|
141 |
+
|
142 |
+
if($venue && !is_wp_error($venue)){
|
143 |
+
$event['className'][]= 'venue-'.eo_get_venue_slug($post->ID);
|
144 |
+
$event['venue']=$venue;
|
145 |
+
}
|
146 |
+
|
147 |
+
//Event categories
|
148 |
+
$terms = get_the_terms( $post->ID, 'event-category' );
|
149 |
+
$event['category']=array();
|
150 |
+
if($terms):
|
151 |
+
foreach ($terms as $term):
|
152 |
+
$event['category'][]= $term->slug;
|
153 |
+
$event['className'][]='category-'.$term->slug;
|
154 |
+
endforeach;
|
155 |
+
endif;
|
156 |
+
|
157 |
+
//Event colour
|
158 |
+
if( eo_get_event_color() )
|
159 |
+
$event['color'] = eo_get_event_color();
|
160 |
+
|
161 |
+
//Add event to array
|
162 |
+
$event = apply_filters('eventorganiser_fullcalendar_event',$event, $post->ID,$post->occurrence_id);
|
163 |
+
if( $event )
|
164 |
+
$eventsarray[]=$event;
|
165 |
+
|
166 |
+
endforeach;
|
167 |
+
wp_reset_postdata();
|
168 |
+
endif;
|
169 |
+
|
170 |
+
if( !$calendar || !is_array($calendar) )
|
171 |
+
$calendar = array();
|
172 |
+
|
173 |
+
$calendar[$key] = $eventsarray;
|
174 |
+
|
175 |
+
set_transient('eo_full_calendar_public',$calendar, 60*60*24);
|
176 |
+
|
177 |
+
//Echo result and exit
|
178 |
+
echo json_encode($eventsarray);
|
179 |
+
exit;
|
180 |
+
}
|
181 |
+
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Ajax response for the admin full calendar.
|
185 |
+
*
|
186 |
+
* This gets events and generates summaries for events to be displayed.
|
187 |
+
* in the admin 'calendar view'.
|
188 |
+
* Applies 'eventorganiser_admin_cal_summary' to event summary
|
189 |
+
* Applies eventorganiser_admin_calendar to the event array
|
190 |
+
*
|
191 |
+
*@since 1.0
|
192 |
+
*@access private
|
193 |
+
*@ignore
|
194 |
+
*/
|
195 |
+
function eventorganiser_admin_calendar() {
|
196 |
+
//request
|
197 |
+
$request = array(
|
198 |
+
'event_end_after'=>$_GET['start'],
|
199 |
+
'event_start_before'=>$_GET['end']
|
200 |
+
);
|
201 |
+
|
202 |
+
//Presets
|
203 |
+
$presets = array(
|
204 |
+
'posts_per_page'=>-1,
|
205 |
+
'post_type'=>'event',
|
206 |
+
'group_events_by'=>'',
|
207 |
+
'perm' => 'readable');
|
208 |
+
|
209 |
+
$calendar = get_transient('eo_full_calendar_admin');
|
210 |
+
$key = $_GET['start'].'--'.$_GET['end'];
|
211 |
+
|
212 |
+
if( ( !defined('WP_DEBUG') || !WP_DEBUG ) && $calendar && is_array($calendar) && isset($calendar[$key]) ){
|
213 |
+
echo json_encode($calendar[$key]);
|
214 |
+
exit;
|
215 |
+
}
|
216 |
+
|
217 |
+
//Create query
|
218 |
+
$query_array = array_merge($presets, $request);
|
219 |
+
$query = new WP_Query($query_array );
|
220 |
+
|
221 |
+
//Retrieve events
|
222 |
+
$query->get_posts();
|
223 |
+
$eventsarray = array();
|
224 |
+
|
225 |
+
//Blog timezone
|
226 |
+
$tz = eo_get_blog_timezone();
|
227 |
+
|
228 |
+
//Loop through events
|
229 |
+
global $post;
|
230 |
+
if ( $query->have_posts() ) :
|
231 |
+
while ( $query->have_posts() ) : $query->the_post();
|
232 |
+
$event=array();
|
233 |
+
$colour='';
|
234 |
+
//Get title, append status if applicable
|
235 |
+
$title = get_the_title();
|
236 |
+
if(!empty($post->post_password)){
|
237 |
+
$title.=' - '.__('Protected');
|
238 |
+
}elseif($post->post_status=='private'){
|
239 |
+
$title.=' - '.__('Private');
|
240 |
+
}elseif ($post->post_status=='draft'){
|
241 |
+
$title.=' - '.__('Draft');
|
242 |
+
}
|
243 |
+
$event['title']= html_entity_decode ($title,ENT_QUOTES,'UTF-8');
|
244 |
+
|
245 |
+
$schedule = eo_get_event_schedule($post->ID);
|
246 |
+
|
247 |
+
//Check if all day, set format accordingly
|
248 |
+
if( $schedule['all_day'] ){
|
249 |
+
$event['allDay'] = true;
|
250 |
+
$format = get_option('date_format');
|
251 |
+
}else{
|
252 |
+
$event['allDay'] = false;
|
253 |
+
$format = get_option('date_format').' '.get_option('time_format');
|
254 |
+
}
|
255 |
+
|
256 |
+
//Get author (or organiser)
|
257 |
+
$organiser = get_userdata( $post->post_author)->display_name;
|
258 |
+
|
259 |
+
//Get Event Start and End date, set timezone to the blog's timzone
|
260 |
+
$event_start = new DateTime($post->StartDate.' '.$post->StartTime, $tz);
|
261 |
+
$event_end = new DateTime($post->EndDate.' '.$post->FinishTime, $tz);
|
262 |
+
|
263 |
+
$event['start']= $event_start->format('Y-m-d\TH:i:s\Z');
|
264 |
+
$event['end']= $event_end->format('Y-m-d\TH:i:s\Z');
|
265 |
+
|
266 |
+
//Produce summary of event
|
267 |
+
$summary= "<table class='form-table' >"
|
268 |
+
."<tr><th> ".__('Start','eventorganiser').": </th><td> ".eo_format_datetime($event_start,$format)."</td></tr>"
|
269 |
+
."<tr><th> ".__('End','eventorganiser').": </th><td> ".eo_format_datetime($event_end, $format)."</td></tr>"
|
270 |
+
."<tr><th> ".__('Organiser','eventorganiser').": </th><td>".$organiser."</td></tr>";
|
271 |
+
|
272 |
+
$event['className']=array('event');
|
273 |
+
|
274 |
+
$now = new DateTime(null,$tz);
|
275 |
+
if($event_start <= $now)
|
276 |
+
$event['className'][]='past-event';
|
277 |
+
|
278 |
+
//Include venue if this is set
|
279 |
+
$venue = eo_get_venue($post->ID);
|
280 |
+
|
281 |
+
if($venue && !is_wp_error($venue)){
|
282 |
+
$summary .="<tr><th>".__('Where','eventorganiser').": </th><td>".eo_get_venue_name($venue)."</td></tr>";
|
283 |
+
$event['className'][]= 'venue-'.eo_get_venue_slug($post->ID);
|
284 |
+
$event['venue']=$venue;
|
285 |
+
}
|
286 |
+
|
287 |
+
$summary = apply_filters('eventorganiser_admin_cal_summary',$summary,$post->ID,$post->occurrence_id,$post);
|
288 |
+
|
289 |
+
$summary .= "</table><p>";
|
290 |
+
|
291 |
+
//Include schedule summary if event reoccurrs
|
292 |
+
|
293 |
+
if( $schedule['schedule'] != 'once' )
|
294 |
+
$summary .='<em>'.__('This event reoccurs','eventorganiser').' '.eo_get_schedule_summary().'</em>';
|
295 |
+
$summary .='</p>';
|
296 |
+
|
297 |
+
//Include edit link in summary if user has permission
|
298 |
+
if (current_user_can('edit_event', $post->ID)){
|
299 |
+
$edit_link = get_edit_post_link( $post->ID,'');
|
300 |
+
$summary .= "<span class='edit'><a title='Edit this item' href='".$edit_link."'> ".__('Edit Event','eventorganiser')."</a></span>";
|
301 |
+
$event['url']= $edit_link;
|
302 |
+
}
|
303 |
+
|
304 |
+
//Include a delete occurrence link in summary if user has permission
|
305 |
+
if (current_user_can('delete_event', $post->ID)){
|
306 |
+
$admin_url = admin_url('edit.php');
|
307 |
+
|
308 |
+
$delete_url = add_query_arg(array(
|
309 |
+
'post_type'=>'event',
|
310 |
+
'page'=>'calendar',
|
311 |
+
'series'=>$post->ID,
|
312 |
+
'event'=>$post->occurrence_id,
|
313 |
+
'action'=>'delete_occurrence'
|
314 |
+
),$admin_url);
|
315 |
+
|
316 |
+
$delete_url = wp_nonce_url( $delete_url , 'eventorganiser_delete_occurrence_'.$post->occurrence_id);
|
317 |
+
|
318 |
+
$summary .= "<span class='delete'>
|
319 |
+
<a class='submitdelete' style='color:red;float:right' title='".__('Delete this occurrence','eventorganiser')."' href='".$delete_url."'> ".__('Delete this occurrence','eventorganiser')."</a>
|
320 |
+
</span>";
|
321 |
+
|
322 |
+
if( $schedule['schedule'] !='once'){
|
323 |
+
$break_url = add_query_arg(array(
|
324 |
+
'post_type'=>'event',
|
325 |
+
'page'=>'calendar',
|
326 |
+
'series'=>$post->ID,
|
327 |
+
'event'=>$post->occurrence_id,
|
328 |
+
'action'=>'break_series'
|
329 |
+
),$admin_url);
|
330 |
+
$break_url = wp_nonce_url( $break_url , 'eventorganiser_break_series_'.$post->occurrence_id);
|
331 |
+
|
332 |
+
$summary .= "<span class='break'>
|
333 |
+
<a class='submitbreak' style='color:red;float:right;padding-right: 2em;' title='".__('Break this series','eventorganiser')."' href='".$break_url."'> ".__('Break this series','eventorganiser')."</a>
|
334 |
+
</span>";
|
335 |
+
}
|
336 |
+
|
337 |
+
}
|
338 |
+
|
339 |
+
//Event categories
|
340 |
+
$terms = get_the_terms( $post->ID, 'event-category' );
|
341 |
+
$event['category']=array();
|
342 |
+
if($terms):
|
343 |
+
foreach ($terms as $term):
|
344 |
+
$event['category'][]= $term->slug;
|
345 |
+
$event['className'][]='category-'.$term->slug;
|
346 |
+
endforeach;
|
347 |
+
endif;
|
348 |
+
|
349 |
+
//Event colour
|
350 |
+
if( eo_get_event_color() )
|
351 |
+
$event['color'] = eo_get_event_color();
|
352 |
+
|
353 |
+
//Event summary
|
354 |
+
$event['summary'] = '<div id="eo-cal-meta">'.$summary.'</div>';
|
355 |
+
|
356 |
+
//Filter the event array
|
357 |
+
$event = apply_filters('eventorganiser_admin_calendar',$event, $post);
|
358 |
+
|
359 |
+
//Add event to array
|
360 |
+
$eventsarray[]=$event;
|
361 |
+
endwhile;
|
362 |
+
endif;
|
363 |
+
|
364 |
+
if( !$calendar || !is_array($calendar) )
|
365 |
+
$calendar = array();
|
366 |
+
|
367 |
+
$calendar[$key] = $eventsarray;
|
368 |
+
|
369 |
+
set_transient('eo_full_calendar_admin',$calendar, 60*60*24);
|
370 |
+
|
371 |
+
//Echo result and exit
|
372 |
+
echo json_encode($eventsarray);
|
373 |
+
exit;
|
374 |
+
}
|
375 |
+
|
376 |
+
|
377 |
+
/**
|
378 |
+
* Ajax response for the widget calendar
|
379 |
+
*
|
380 |
+
* This gets the month being requested and generates the
|
381 |
+
* html code to view that month and its events.
|
382 |
+
*
|
383 |
+
*@since 1.0
|
384 |
+
*@access private
|
385 |
+
*@ignore
|
386 |
+
*/
|
387 |
+
function eventorganiser_widget_cal() {
|
388 |
+
|
389 |
+
/*Retrieve the month we are after. $month must be a
|
390 |
+
DateTime object of the first of that month*/
|
391 |
+
if(isset($_GET['eo_month'])){
|
392 |
+
$month = new DateTime($_GET['eo_month'].'-01');
|
393 |
+
}else{
|
394 |
+
$month = new DateTime('now');
|
395 |
+
$month = date_create($month->format('Y-m-1'));
|
396 |
+
}
|
397 |
+
|
398 |
+
$args = array();
|
399 |
+
|
400 |
+
//Restrict by category and/or venue
|
401 |
+
foreach( array('event-venue','event-category') as $tax ){
|
402 |
+
if( empty($_GET[$tax]) )
|
403 |
+
continue;
|
404 |
+
|
405 |
+
$terms = explode(',',trim($_GET[$tax]));
|
406 |
+
|
407 |
+
$args['tax_query'][] = array(
|
408 |
+
'taxonomy' => $tax,
|
409 |
+
'field' => 'slug',
|
410 |
+
'terms' => $terms,
|
411 |
+
'operator' => 'IN'
|
412 |
+
);
|
413 |
+
}
|
414 |
+
|
415 |
+
//Options for the calendar
|
416 |
+
$args['showpastevents'] = (empty($_GET['showpastevents']) ? 0 : 1);
|
417 |
+
|
418 |
+
echo json_encode(EO_Calendar_Widget::generate_output($month,$args));
|
419 |
+
exit;
|
420 |
+
}
|
421 |
+
|
422 |
+
|
423 |
+
/**
|
424 |
+
* Ajax response for the agenda widget
|
425 |
+
*
|
426 |
+
* This gets the month being viewed and generates the
|
427 |
+
*
|
428 |
+
*@since 1.0
|
429 |
+
*@access private
|
430 |
+
*@ignore
|
431 |
+
*/
|
432 |
+
function eventorganiser_widget_agenda() {
|
433 |
+
global $wpdb;
|
434 |
+
|
435 |
+
$number = (int) $_GET['instance_number'];
|
436 |
+
$wid = new EO_Events_Agenda_Widget();
|
437 |
+
$settings = $wid->get_settings();
|
438 |
+
$instance = $settings[$number];
|
439 |
+
$today= new DateTime('now', eo_get_blog_timezone());
|
440 |
+
$query=array();
|
441 |
+
$return_array = array();
|
442 |
+
|
443 |
+
$query['mode'] = !empty($instance['mode']) ? $instance['mode'] : 'day';
|
444 |
+
$query['direction'] = intval($_GET['direction']);
|
445 |
+
$query['date'] = ($query['direction'] <1? $_GET['start'] : $_GET['end']);
|
446 |
+
$query['order'] = ($query['direction'] <1? 'DESC' : 'ASC');
|
447 |
+
|
448 |
+
$key = 'eo_ag_'.md5(serialize($query)).get_locale();
|
449 |
+
$agenda = get_transient('eo_widget_agenda');
|
450 |
+
if( $agenda && is_array($agenda) && isset($agenda[$key]) ){
|
451 |
+
echo json_encode($agenda[$key]);
|
452 |
+
exit;
|
453 |
+
}
|
454 |
+
|
455 |
+
if( 'day' == $query['mode'] ){
|
456 |
+
//Day mode
|
457 |
+
$selectDates="SELECT DISTINCT StartDate FROM {$wpdb->eo_events}";
|
458 |
+
$whereDates = " WHERE {$wpdb->eo_events}.StartDate".( $query['order']=='ASC' ? " >= " : " <= ")."%s ";
|
459 |
+
$whereDates .= " AND {$wpdb->eo_events}.StartDate >= %s ";
|
460 |
+
$orderlimit = "ORDER BY {$wpdb->eo_events}.StartDate {$query['order']} LIMIT 4";
|
461 |
+
$dates = $wpdb->get_col($wpdb->prepare($selectDates.$whereDates.$orderlimit, $query['date'],$today->format('Y-m-d')));
|
462 |
+
|
463 |
+
if(!$dates)
|
464 |
+
return false;
|
465 |
+
|
466 |
+
$query['date1'] = min($dates[0],$dates[count($dates)-1]);
|
467 |
+
$query['date2'] = max($dates[0],$dates[count($dates)-1]);
|
468 |
+
|
469 |
+
}elseif( 'week' == $query['mode'] ){
|
470 |
+
//Week mode - find the week of the next/previous event
|
471 |
+
$selectDates="SELECT DISTINCT StartDate FROM {$wpdb->eo_events}";
|
472 |
+
$whereDates = " WHERE {$wpdb->eo_events}.StartDate".( $query['order']=='ASC' ? " > " : " < ")."%s ";
|
473 |
+
$whereDates .= " AND {$wpdb->eo_events}.StartDate >= %s ";
|
474 |
+
$orderlimit = "ORDER BY {$wpdb->eo_events}.StartDate {$query['order']} LIMIT 1";
|
475 |
+
$date = $wpdb->get_row($wpdb->prepare($selectDates.$whereDates.$orderlimit, $query['date'],$today->format('Y-m-d')));
|
476 |
+
|
477 |
+
if(!$date)
|
478 |
+
return false;
|
479 |
+
|
480 |
+
$datetime = new DateTime($date->StartDate, eo_get_blog_timezone());
|
481 |
+
|
482 |
+
//Get the week day, and the start of the week
|
483 |
+
$week_start_day = (int) get_option('start_of_week');
|
484 |
+
$event_day = (int) $datetime->format('w');
|
485 |
+
$offset_from_week_start = ($event_day - $week_start_day +7)%7;
|
486 |
+
$week_start_date = clone $datetime;
|
487 |
+
$week_start_date->modify('- '.$offset_from_week_start.' days');
|
488 |
+
$week_end_date = clone $week_start_date;
|
489 |
+
$week_end_date->modify('+6 days');//Query is inclusive.
|
490 |
+
|
491 |
+
$query['date1'] = $week_start_date->format('Y-m-d');
|
492 |
+
$query['date2'] = $week_end_date->format('Y-m-d');
|
493 |
+
|
494 |
+
}else{
|
495 |
+
//Month mode - find the month of the next date
|
496 |
+
$selectDates="SELECT DISTINCT StartDate FROM {$wpdb->eo_events}";
|
497 |
+
$whereDates = " WHERE {$wpdb->eo_events}.StartDate".( $query['order']=='ASC' ? " > " : " < ")."%s ";
|
498 |
+
$whereDates .= " AND {$wpdb->eo_events}.StartDate >= %s ";
|
499 |
+
$orderlimit = "ORDER BY {$wpdb->eo_events}.StartDate {$query['order']} LIMIT 1";
|
500 |
+
$date = $wpdb->get_row($wpdb->prepare($selectDates.$whereDates.$orderlimit, $query['date'],$today->format('Y-m-d')));
|
501 |
+
|
502 |
+
if(!$date)
|
503 |
+
return false;
|
504 |
+
|
505 |
+
$datetime = new DateTime($date->StartDate, eo_get_blog_timezone());
|
506 |
+
$query['date1'] = $datetime->format('Y-m-01');
|
507 |
+
$query['date2'] = $datetime->format('Y-m-t');
|
508 |
+
}
|
509 |
+
|
510 |
+
$events = eo_get_events(array(
|
511 |
+
'event_start_after'=>$query['date1'],
|
512 |
+
'event_start_before'=>$query['date2']
|
513 |
+
));
|
514 |
+
|
515 |
+
global $post;
|
516 |
+
foreach ($events as $post):
|
517 |
+
$return_array[] = array(
|
518 |
+
'StartDate'=>$post->StartDate,
|
519 |
+
'display'=>eo_get_the_start($instance['group_format']),
|
520 |
+
'time'=> ( ($instance['mode']=='day' && eo_is_all_day()) ? __('All Day','eventorganiser') : eo_get_the_start($instance['item_format']) ),
|
521 |
+
'post_title'=>get_the_title(),
|
522 |
+
'color'=>eo_get_event_color(),
|
523 |
+
'event_url'=>get_permalink(),
|
524 |
+
'link'=>'<a href="'.get_permalink().'">'.__('View','eventorganiser').'</a>',
|
525 |
+
'Glink'=>'<a href="'.eo_get_the_GoogleLink().'" target="_blank">'.__('Add To Google Calendar','eventorganiser').'</a>'
|
526 |
+
);
|
527 |
+
endforeach;
|
528 |
+
|
529 |
+
if( !$agenda || !is_array($agenda) )
|
530 |
+
$agenda = array();
|
531 |
+
|
532 |
+
$agenda[$key] = $return_array;
|
533 |
+
|
534 |
+
set_transient('eo_widget_agenda',$agenda, 60*60*24);
|
535 |
+
|
536 |
+
echo json_encode($return_array);
|
537 |
+
exit;
|
538 |
+
}
|
539 |
+
|
540 |
+
|
541 |
+
/**
|
542 |
+
* Ajax response for searcheing venues. Searches by venue name.
|
543 |
+
*
|
544 |
+
*@since 1.0
|
545 |
+
*@access private
|
546 |
+
*@ignore
|
547 |
+
*/
|
548 |
+
function eventorganiser_search_venues() {
|
549 |
+
|
550 |
+
// Query the venues with the given term
|
551 |
+
$value = trim(esc_attr($_GET["term"]));
|
552 |
+
$venues = eo_get_venues(array('search'=>$value));
|
553 |
+
|
554 |
+
foreach($venues as $venue){
|
555 |
+
$venue_id = (int) $venue->term_id;
|
556 |
+
|
557 |
+
if( !isset($term->venue_address) ){
|
558 |
+
/* This is all deprecated - use the API {@link http://wp-event-organiser.com/documentation/function/eo_get_venue_address/} */
|
559 |
+
$address = eo_get_venue_address($venue_id);
|
560 |
+
$venue->venue_address = isset($address['address']) ? $address['address'] : '';
|
561 |
+
$venue->venue_postal = isset($address['postcode']) ? $address['postcode'] : '';
|
562 |
+
$venue->venue_postcode = isset($address['postcode']) ? $address['postcode'] : '';
|
563 |
+
$venue->venue_city = isset($address['city']) ? $address['city'] : '';
|
564 |
+
$venue->venue_country = isset($address['country']) ? $address['country'] : '';
|
565 |
+
$venue->venue_state = isset($address['state']) ? $address['state'] : '';
|
566 |
+
}
|
567 |
+
|
568 |
+
if( !isset($venue->venue_lat) || !isset($venue->venue_lng) ){
|
569 |
+
$venue->venue_lat = number_format(floatval(eo_get_venue_lat($venue_id)), 6);
|
570 |
+
$venue->venue_lng = number_format(floatval(eo_get_venue_lng($venue_id)), 6);
|
571 |
+
}
|
572 |
+
}
|
573 |
+
|
574 |
+
$novenue = array('term_id'=>0,'name'=>__('No Venue','eventorganiser'));
|
575 |
+
$venues =array_merge (array($novenue),$venues);
|
576 |
+
|
577 |
+
//echo JSON to page
|
578 |
+
$response = $_GET["callback"] . "(" . json_encode($venues) . ")";
|
579 |
+
echo $response;
|
580 |
+
exit;
|
581 |
+
}
|
582 |
+
|
583 |
+
/**
|
584 |
+
* Saves the ajax request to update the 24/12 hour setting of admin calendar
|
585 |
+
*
|
586 |
+
*@since 1.5
|
587 |
+
*@access private
|
588 |
+
*@ignore
|
589 |
+
*/
|
590 |
+
function eventorganiser_admin_cal_time_format(){
|
591 |
+
$is24 = ( $_POST['is24'] == 'false' ? 1: 0 );
|
592 |
+
$user =wp_get_current_user();
|
593 |
+
$is12hour = update_user_meta($user->ID,'eofc_time_format',$is24);
|
594 |
+
exit();
|
595 |
+
}
|
596 |
+
?>
|
includes/event-organiser-archives.php
ADDED
@@ -0,0 +1,517 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Handles the query manipulation of events
|
4 |
+
*/
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Registers our custom query variables
|
8 |
+
*
|
9 |
+
* Hooked onto query_vars
|
10 |
+
* @since 1.0.0
|
11 |
+
* @access private
|
12 |
+
* @ignore;
|
13 |
+
*
|
14 |
+
* @param array $qvars Query variables
|
15 |
+
* @param array Query variables with plug-in added variables
|
16 |
+
*/
|
17 |
+
function eventorganiser_register_query_vars( $qvars ){
|
18 |
+
//Add these query variables
|
19 |
+
$qvars[] = 'venue';//Depreciated
|
20 |
+
$qvars[] = 'ondate';
|
21 |
+
$qvars[] = 'showrepeats';
|
22 |
+
$qvars[] = 'eo_interval';
|
23 |
+
$qvars[] = 'event_start_before';
|
24 |
+
$qvars[] = 'event_start_after';
|
25 |
+
$qvars[] = 'event_end_before';
|
26 |
+
$qvars[] = 'event_after_after';
|
27 |
+
$qvars[] = 'event_series';
|
28 |
+
return $qvars;
|
29 |
+
}
|
30 |
+
add_filter('query_vars', 'eventorganiser_register_query_vars' );
|
31 |
+
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Parses event queries and alters the WP_Query object appropriately
|
35 |
+
*
|
36 |
+
* Parse's the query, and sets date range and other event specific query variables.
|
37 |
+
* If query is for 'event' post type - the posts_* filters are added.
|
38 |
+
*
|
39 |
+
* Hooked onto pre_get_posts
|
40 |
+
* @since 1.0.0
|
41 |
+
* @access private
|
42 |
+
* @ignore;
|
43 |
+
*
|
44 |
+
* @param WP_Query $query The query
|
45 |
+
*/
|
46 |
+
function eventorganiser_pre_get_posts( $query ) {
|
47 |
+
|
48 |
+
//Deprecated, use event-venue instead.
|
49 |
+
if( !empty($query->query_vars['venue']) ){
|
50 |
+
$venue = $query->get('venue');
|
51 |
+
$query->set('event-venue',$venue);
|
52 |
+
$query->set( 'post_type', 'event' );
|
53 |
+
}
|
54 |
+
|
55 |
+
//If the query is for eo-events feed, set post type
|
56 |
+
if( $query->is_feed( 'eo-events' ) ){
|
57 |
+
$query->set( 'post_type', 'event' );
|
58 |
+
}
|
59 |
+
|
60 |
+
//If querying for all events starting on given date, set the date parameters
|
61 |
+
if( !empty($query->query_vars['ondate']) ) {
|
62 |
+
|
63 |
+
$ondate_start = str_replace('/','-',$query->query_vars['ondate']);
|
64 |
+
$ondate_end = str_replace('/','-',$query->query_vars['ondate']);
|
65 |
+
|
66 |
+
$parts = count(explode('-',$ondate_start));
|
67 |
+
if( $parts == 1 && is_numeric($ondate_start) ){
|
68 |
+
//Numeric - interpret as year
|
69 |
+
$ondate_start .= '-01-01';
|
70 |
+
$ondate_end .= '-12-31';
|
71 |
+
}elseif( $parts == 2 ){
|
72 |
+
// 2012-01 format: interpret as month
|
73 |
+
$ondate_start .= '-01';
|
74 |
+
try{
|
75 |
+
$end = new DateTime($ondate_start);
|
76 |
+
$ondate_end = $end->format('Y-m-t');
|
77 |
+
}catch( Exception $e){
|
78 |
+
$query->set('ondate',false);
|
79 |
+
break;
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
$query->set( 'post_type', 'event' );
|
84 |
+
$query->set( 'event_start_before', $ondate_end );
|
85 |
+
$query->set( 'event_end_after', $ondate_start );
|
86 |
+
}
|
87 |
+
|
88 |
+
//If not on event, stop here.
|
89 |
+
if( ! eventorganiser_is_event_query( $query, true ) )
|
90 |
+
return $query;
|
91 |
+
|
92 |
+
$blog_now = new DateTime(null, eo_get_blog_timezone());
|
93 |
+
|
94 |
+
//Determine whether or not to show past events and each occurrence. //If not set, use options
|
95 |
+
if( !is_admin() && !is_single() && !$query->is_feed('eo-events') && !isset($query->query_vars['showpastevents']) ){
|
96 |
+
//If showpastevents is not set - use options (except for admin / single pages.
|
97 |
+
$query->set('showpastevents', eventorganiser_get_option('showpast') );
|
98 |
+
}
|
99 |
+
|
100 |
+
//Deprecated: showrepeats - use group_events_by instead
|
101 |
+
if( isset($query->query_vars['showrepeats']) && !isset($query->query_vars['group_events_by']) ){
|
102 |
+
if( !$query->query_vars['showrepeats'] )
|
103 |
+
$query->set('group_events_by','series');
|
104 |
+
}
|
105 |
+
|
106 |
+
//Determine how to group events: by series or show each occurrence
|
107 |
+
if( !isset($query->query_vars['group_events_by']) ){
|
108 |
+
|
109 |
+
//Group by isn't set - default depends on context:
|
110 |
+
if( $query->is_main_query() && (is_admin() || is_single() || $query->is_feed('eo-events') ) ){
|
111 |
+
|
112 |
+
//If in admin or single page - we probably don't want to see duplicates of (recurrent) events - unless specified otherwise.
|
113 |
+
$query->set('group_events_by','series');
|
114 |
+
|
115 |
+
}elseif( eventorganiser_get_option('group_events') == 'series' ){
|
116 |
+
//In other instances (archives, shortcode listing) if showrepeats option is false display only the next event.
|
117 |
+
$query->set('group_events_by','series');
|
118 |
+
}else{
|
119 |
+
$query->set('group_events_by','occurrence');
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
//Parse user input as date-time objects
|
124 |
+
$date_objs = array('event_start_after'=>'','event_start_before'=>'','event_end_after'=>'','event_end_before'=>'');
|
125 |
+
foreach($date_objs as $prop => $value):
|
126 |
+
$date = $query->get($prop);
|
127 |
+
try{
|
128 |
+
$date = ( empty($date) ? false : new DateTime($date, eo_get_blog_timezone()) );
|
129 |
+
}catch( Exception $e){
|
130 |
+
$date = false;
|
131 |
+
}
|
132 |
+
$date_objs[$prop] = $date;
|
133 |
+
$query->set($prop, $date);
|
134 |
+
|
135 |
+
endforeach;
|
136 |
+
|
137 |
+
//If eo_interval is set, determine date ranges
|
138 |
+
if( !empty($query->query_vars['eo_interval']) ){
|
139 |
+
switch($query->get('eo_interval')):
|
140 |
+
case 'expired':
|
141 |
+
$meta_query = (array) $query->get('meta_query');
|
142 |
+
$meta_query[] =array(
|
143 |
+
'key' => '_eventorganiser_schedule_last_finish',
|
144 |
+
'value' => $blog_now->format('Y-m-d H:i:s'),
|
145 |
+
'compare' => '<='
|
146 |
+
);
|
147 |
+
$query->set('meta_query',$meta_query) ;
|
148 |
+
break;
|
149 |
+
|
150 |
+
case 'future':
|
151 |
+
$meta_query = $query->get('meta_query');
|
152 |
+
$meta_query = empty($meta_query) ? array() : $meta_query;
|
153 |
+
$meta_query[] =array(
|
154 |
+
'key' => '_eventorganiser_schedule_last_start',
|
155 |
+
'value' => $blog_now->format('Y-m-d H:i:s'),
|
156 |
+
'compare' => '>='
|
157 |
+
);
|
158 |
+
$query->set('meta_query',$meta_query) ;
|
159 |
+
break;
|
160 |
+
|
161 |
+
case 'P1D':
|
162 |
+
case 'P1W':
|
163 |
+
case 'P1M':
|
164 |
+
case 'P6M':
|
165 |
+
case 'P1Y':
|
166 |
+
//I hate you php5.2
|
167 |
+
$intervals = array('P1D'=>'+1 day', 'P1W'=>'+1 week','P1M'=>'+1 month','P6M'=>'+6 month','P1Y'=>'+1 Year');
|
168 |
+
$cutoff = clone $blog_now;
|
169 |
+
$cutoff->modify($intervals[$query->query_vars['eo_interval']]);
|
170 |
+
|
171 |
+
if( is_admin() && 'series' == $query->get('group_events_by') ){
|
172 |
+
//On admin we want to show the **first** occurrence of a recurring event which has an occurrence in the interval
|
173 |
+
global $wpdb;
|
174 |
+
$post_ids = $wpdb->get_results($wpdb->prepare(
|
175 |
+
"SELECT DISTINCT post_id FROM {$wpdb->eo_events}
|
176 |
+
WHERE {$wpdb->eo_events}.StartDate <= %s
|
177 |
+
AND {$wpdb->eo_events}.EndDate >= %s",
|
178 |
+
$cutoff->format('Y-m-d'),$blog_now->format('Y-m-d')));
|
179 |
+
|
180 |
+
if($post_ids)
|
181 |
+
$query->set('post__in',wp_list_pluck($post_ids, 'post_id'));
|
182 |
+
|
183 |
+
}else{
|
184 |
+
if( empty($date_objs['event_start_before']) || $cutoff < $date_objs['event_start_before'] ){
|
185 |
+
$date_objs['event_start_before'] = $cutoff;
|
186 |
+
}
|
187 |
+
if( empty($date_objs['event_end_after']) || $blog_now > $date_objs['event_end_after'] ){
|
188 |
+
$date_objs['event_end_after'] = $blog_now;
|
189 |
+
}
|
190 |
+
}
|
191 |
+
endswitch;
|
192 |
+
}//Endif interval set
|
193 |
+
|
194 |
+
$running_event_is_past= ( eventorganiser_get_option('runningisnotpast') ? true : false);
|
195 |
+
|
196 |
+
//Set date range according to whether we show past events
|
197 |
+
if(isset($query->query_vars['showpastevents'])&& !$query->query_vars['showpastevents'] ){
|
198 |
+
//Showing only future events
|
199 |
+
|
200 |
+
//Running event is past - Get events which start in the future
|
201 |
+
//A current event is not past - Get events which finish in the future
|
202 |
+
$key = ( $running_event_is_past ? 'event_start_after' : 'event_end_after');
|
203 |
+
|
204 |
+
//If current queried date is not set or before now, set the queried date to now
|
205 |
+
$date_objs[$key] = (empty($date_objs[$key]) || $blog_now > $date_objs[$key]) ? $blog_now : $date_objs[$key];
|
206 |
+
}
|
207 |
+
|
208 |
+
|
209 |
+
//Set event dates to 'Y-m-d H:i:s' format.
|
210 |
+
foreach ($date_objs as $prop => $datetime ){
|
211 |
+
if( !empty($datetime) )
|
212 |
+
$query->set($prop, $datetime->format('Y-m-d H:i:s'));
|
213 |
+
}
|
214 |
+
|
215 |
+
if( $query->is_feed('eo-events') ){
|
216 |
+
//Posts per page for feeds bug http://core.trac.wordpress.org/ticket/17853
|
217 |
+
add_filter('post_limits','wp17853_eventorganiser_workaround');
|
218 |
+
$query->set('posts_per_page',-1);
|
219 |
+
}
|
220 |
+
|
221 |
+
//Add the posts_* filters to modify the query
|
222 |
+
add_filter('posts_fields', 'eventorganiser_event_fields',10,2);
|
223 |
+
add_filter('posts_join', 'eventorganiser_join_tables',10,2);
|
224 |
+
add_filter('posts_where','eventorganiser_events_where',10,2);
|
225 |
+
add_filter('posts_orderby','eventorganiser_sort_events',10,2);
|
226 |
+
add_filter('posts_groupby', 'eventorganiser_event_groupby',10,2);
|
227 |
+
}
|
228 |
+
add_action( 'pre_get_posts', 'eventorganiser_pre_get_posts', 11 );
|
229 |
+
|
230 |
+
//Workaround for https://github.com/stephenharris/Event-Organiser/issues/55,
|
231 |
+
add_action( 'pre_get_posts', '__return_false', 10 );
|
232 |
+
|
233 |
+
|
234 |
+
/**
|
235 |
+
* A work around for a bug that posts_per_page is over-ridden by the posts_per_rss option. http://core.trac.wordpress.org/ticket/17853
|
236 |
+
|
237 |
+
* posts_per_rss option overirdes posts_per_page and nopaging is also set to 'false'.
|
238 |
+
* For ics feeds nopaging should be true and post_per_page should be -1. We intercept the LIMIT part of the query and remove it.
|
239 |
+
* We return '' so there is no LIMIT part to the query.
|
240 |
+
* Hooked on in eventorganiser_pre_get_posts
|
241 |
+
* @since 1.5.7
|
242 |
+
* @access private
|
243 |
+
* @ignore;
|
244 |
+
*
|
245 |
+
*@param string $limit LIMIT part of the SQL statement
|
246 |
+
*@return string Empty string
|
247 |
+
*/
|
248 |
+
function wp17853_eventorganiser_workaround( $limit ){
|
249 |
+
remove_filter(current_filter(),__FUNCTION__);
|
250 |
+
return '';
|
251 |
+
}
|
252 |
+
|
253 |
+
|
254 |
+
/**
|
255 |
+
* SELECT only date fields from events and venue table for events
|
256 |
+
* All other fields deprecated and stored in post meta since 1.5
|
257 |
+
* Hooked onto posts_fields
|
258 |
+
*
|
259 |
+
*@since 1.0.0
|
260 |
+
*@access private
|
261 |
+
*@ignore
|
262 |
+
*@param string $select SELECT part of the SQL statement
|
263 |
+
*@param string $query WP_Query
|
264 |
+
*@return string
|
265 |
+
*/
|
266 |
+
function eventorganiser_event_fields( $select, $query ){
|
267 |
+
global $wpdb;
|
268 |
+
|
269 |
+
if( eventorganiser_is_event_query( $query, true ) ){
|
270 |
+
$et =$wpdb->eo_events;
|
271 |
+
/* Include 'event_occurrence' for backwards compatibility. Will eventually be removed. */
|
272 |
+
/* Renaming event_id as occurrence id. Keep event_id for backwards compatibility */
|
273 |
+
if( 'series'== $query->get('group_events_by') ) {
|
274 |
+
//Work-around for group_events_by series.
|
275 |
+
$select = "{$et}.event_id, {$et}.event_id AS occurrence_id, {$et}.StartTime, min({$et}.StartDate) as StartDate, min({$et}.EndDate) as EndDate, {$et}.FinishTime, {$et}.event_occurrence, ".$select;
|
276 |
+
}else{
|
277 |
+
$select = "{$et}.event_id, {$et}.event_id AS occurrence_id, {$et}.StartDate, {$et}.StartTime, {$et}.EndDate, {$et}.FinishTime, {$et}.event_occurrence, ".$select;
|
278 |
+
}
|
279 |
+
}
|
280 |
+
return $select;
|
281 |
+
}
|
282 |
+
|
283 |
+
|
284 |
+
/**
|
285 |
+
* GROUP BY Event (occurrence) ID
|
286 |
+
* Event posts do not want to be grouped by post, but by occurrence - unless otherwise specified.
|
287 |
+
* Hooked onto posts_groupby
|
288 |
+
*
|
289 |
+
*@since 1.0.0
|
290 |
+
*@access private
|
291 |
+
*@ignore
|
292 |
+
*@param string $groupby GROUP BY part of the SQL statement
|
293 |
+
*@param string $query WP_Query
|
294 |
+
*@return string
|
295 |
+
*/
|
296 |
+
function eventorganiser_event_groupby( $groupby, $query ){
|
297 |
+
global $wpdb;
|
298 |
+
|
299 |
+
if(!empty($query->query_vars['group_events_by']) && $query->query_vars['group_events_by'] == 'series'){
|
300 |
+
return "{$wpdb->eo_events}.post_id";
|
301 |
+
}
|
302 |
+
|
303 |
+
if( eventorganiser_is_event_query( $query, true ) ):
|
304 |
+
if(empty($groupby))
|
305 |
+
return $groupby;
|
306 |
+
|
307 |
+
return "{$wpdb->eo_events}.event_id";
|
308 |
+
endif;
|
309 |
+
|
310 |
+
return $groupby;
|
311 |
+
}
|
312 |
+
|
313 |
+
|
314 |
+
/**
|
315 |
+
* LEFT JOIN all EVENTS.
|
316 |
+
* Joins events table when querying for events
|
317 |
+
* Hooked onto posts_join
|
318 |
+
*
|
319 |
+
*@since 1.0.0
|
320 |
+
*@access private
|
321 |
+
*@ignore
|
322 |
+
*@param string $join JOIN part of the SQL statement
|
323 |
+
*@param string $query WP_Query
|
324 |
+
*@return string
|
325 |
+
*/
|
326 |
+
function eventorganiser_join_tables( $join, $query ){
|
327 |
+
global $wpdb;
|
328 |
+
|
329 |
+
if( eventorganiser_is_event_query( $query, true ) ){
|
330 |
+
$join .=" LEFT JOIN $wpdb->eo_events ON $wpdb->posts.id = {$wpdb->eo_events}.post_id ";
|
331 |
+
}
|
332 |
+
return $join;
|
333 |
+
}
|
334 |
+
|
335 |
+
|
336 |
+
function eventorganiser_is_event_query( $query, $exclusive = false ){
|
337 |
+
|
338 |
+
$post_types = $query->get( 'post_type' );
|
339 |
+
if( 'any' == $post_types )
|
340 |
+
$post_types = get_post_types( array('exclude_from_search' => false) );
|
341 |
+
|
342 |
+
if( $post_types == 'event' ){
|
343 |
+
$bool = true;
|
344 |
+
|
345 |
+
}elseif( ( $query && $query->is_feed('eo-events') ) || is_feed( 'eo-events' ) ){
|
346 |
+
$bool = true;
|
347 |
+
|
348 |
+
}elseif( empty( $post_types ) && eo_is_event_taxonomy( $query ) ){
|
349 |
+
|
350 |
+
//Querying by taxonomy - check if 'event' is the only post type
|
351 |
+
$post_types = array();
|
352 |
+
$taxonomies = wp_list_pluck( $query->tax_query->queries, 'taxonomy' );
|
353 |
+
|
354 |
+
foreach ( get_post_types() as $pt ) {
|
355 |
+
|
356 |
+
if( version_compare( '3.4', get_bloginfo( 'version' ) ) <= 0 ){
|
357 |
+
$object_taxonomies = $pt === 'attachment' ? get_taxonomies_for_attachments() : get_object_taxonomies( $pt );
|
358 |
+
}else{
|
359 |
+
//Backwards compat for 3.3
|
360 |
+
$object_taxonomies = $pt === 'attachment' ? array() : get_object_taxonomies( $pt );
|
361 |
+
}
|
362 |
+
|
363 |
+
if ( array_intersect( $taxonomies, $object_taxonomies ) )
|
364 |
+
$post_types[] = $pt;
|
365 |
+
}
|
366 |
+
|
367 |
+
if( in_array( 'event', $post_types ) ){
|
368 |
+
if( $exclusive && 1 == count( $post_types ) ){
|
369 |
+
$query->set( 'post_type', 'event' );
|
370 |
+
$bool = true;
|
371 |
+
}elseif( !$exclusive ){
|
372 |
+
$bool = true;
|
373 |
+
}else{
|
374 |
+
$bool = false;
|
375 |
+
}
|
376 |
+
}else{
|
377 |
+
$bool = false;
|
378 |
+
}
|
379 |
+
|
380 |
+
}elseif( $exclusive ){
|
381 |
+
$bool = false;
|
382 |
+
|
383 |
+
}elseif( ( is_array( $post_types ) && in_array( 'event', $post_types ) ) ){
|
384 |
+
$bool = true;
|
385 |
+
|
386 |
+
}else{
|
387 |
+
$bool = false;
|
388 |
+
|
389 |
+
}
|
390 |
+
|
391 |
+
return apply_filters( 'eventorganiser_is_event_query', $bool, $query, $exclusive );
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* Selects posts which satisfy custom WHERE statements
|
396 |
+
* Hooked onto posts_where
|
397 |
+
*
|
398 |
+
*@since 1.0.0
|
399 |
+
*@access private
|
400 |
+
*@ignore
|
401 |
+
*@param string $where WHERE part of the SQL statement
|
402 |
+
*@param string $query WP_Query
|
403 |
+
*@return string
|
404 |
+
*/
|
405 |
+
function eventorganiser_events_where( $where, $query ){
|
406 |
+
global $wpdb;
|
407 |
+
|
408 |
+
//Only alter event queries
|
409 |
+
if( eventorganiser_is_event_query( $query, true ) ):
|
410 |
+
|
411 |
+
//If we only want events (or occurrences of events) that belong to a particular 'event'
|
412 |
+
if(isset($query->query_vars['event_series'])):
|
413 |
+
$series_id =$query->query_vars['event_series'];
|
414 |
+
$where .= $wpdb->prepare(" AND {$wpdb->eo_events}.post_id =%d ",$series_id);
|
415 |
+
endif;
|
416 |
+
|
417 |
+
if(isset($query->query_vars['event_occurrence_id'])):
|
418 |
+
$occurrence_id =$query->query_vars['event_occurrence_id'];
|
419 |
+
$where .= $wpdb->prepare(" AND {$wpdb->eo_events}.event_id=%d ",$occurrence_id);
|
420 |
+
endif;
|
421 |
+
|
422 |
+
//Check date ranges were are interested in.
|
423 |
+
$date_queries = array(
|
424 |
+
'event_start_after'=>array(
|
425 |
+
'notstrict' =>" AND {$wpdb->eo_events}.StartDate >= %s ",
|
426 |
+
'strict' => " AND ({$wpdb->eo_events}.StartDate > %s OR ({$wpdb->eo_events}.StartDate = %s AND {$wpdb->eo_events}.StartTime > %s)) "
|
427 |
+
),
|
428 |
+
'event_start_before'=>array(
|
429 |
+
'notstrict' =>" AND {$wpdb->eo_events}.StartDate <= %s ",
|
430 |
+
'strict' => " AND ({$wpdb->eo_events}.StartDate < %s OR ({$wpdb->eo_events}.StartDate = %s AND {$wpdb->eo_events}.StartTime < %s)) "
|
431 |
+
),
|
432 |
+
'event_end_after'=>array(
|
433 |
+
'notstrict' =>" AND {$wpdb->eo_events}.EndDate >= %s ",
|
434 |
+
'strict' => " AND ({$wpdb->eo_events}.EndDate > %s OR ({$wpdb->eo_events}.EndDate = %s AND {$wpdb->eo_events}.FinishTime > %s)) "
|
435 |
+
),
|
436 |
+
'event_end_before'=>array(
|
437 |
+
'notstrict' =>" AND {$wpdb->eo_events}.EndDate <= %s ",
|
438 |
+
'strict' => " AND ({$wpdb->eo_events}.EndDate < %s OR ({$wpdb->eo_events}.EndDate = %s AND {$wpdb->eo_events}.FinishTime < %s)) "
|
439 |
+
)
|
440 |
+
);
|
441 |
+
|
442 |
+
//Construct sql query.
|
443 |
+
foreach ( $date_queries as $prop => $_sql ){
|
444 |
+
$datetime = $query->get($prop);
|
445 |
+
if( !empty( $datetime) ) {
|
446 |
+
$date = eo_format_date($datetime,'Y-m-d');
|
447 |
+
$time = eo_format_date($datetime,'H:i:s');
|
448 |
+
if( $time == '00:00:00' ){
|
449 |
+
$sql = $_sql['notstrict'];
|
450 |
+
$where .= $wpdb->prepare($sql, $date);
|
451 |
+
}else{
|
452 |
+
$sql = $_sql['strict'];
|
453 |
+
$where .= $wpdb->prepare($sql, $date, $date, $time);
|
454 |
+
}
|
455 |
+
}
|
456 |
+
}
|
457 |
+
endif;
|
458 |
+
|
459 |
+
return $where;
|
460 |
+
}
|
461 |
+
|
462 |
+
/**
|
463 |
+
* Alter the order of posts.
|
464 |
+
* This function allows to sort our events by a custom order (venue, date etc)
|
465 |
+
* Hooked onto posts_orderby
|
466 |
+
*
|
467 |
+
*@since 1.0.0
|
468 |
+
*@access private
|
469 |
+
*@ignore
|
470 |
+
*@param string $orderby ORDER BY part of the SQL statement
|
471 |
+
*@param string $query WP_Query
|
472 |
+
*@return string
|
473 |
+
*/
|
474 |
+
function eventorganiser_sort_events( $orderby, $query ){
|
475 |
+
global $wpdb;
|
476 |
+
|
477 |
+
if( !empty($query->query_vars['orderby']) ){
|
478 |
+
//If the query sets an orderby return what to do if it is one of our custom orderbys
|
479 |
+
|
480 |
+
$order_crit= $query->query_vars['orderby'];
|
481 |
+
$order_dir = $query->query_vars['order'];
|
482 |
+
|
483 |
+
switch($order_crit):
|
484 |
+
case 'eventstart':
|
485 |
+
return " {$wpdb->eo_events}.StartDate $order_dir, {$wpdb->eo_events}.StartTime $order_dir";
|
486 |
+
break;
|
487 |
+
|
488 |
+
case 'eventend':
|
489 |
+
return " {$wpdb->eo_events}.EndDate $order_dir, {$wpdb->eo_events}.FinishTime $order_dir";
|
490 |
+
break;
|
491 |
+
|
492 |
+
default:
|
493 |
+
return $orderby;
|
494 |
+
endswitch;
|
495 |
+
|
496 |
+
}elseif( eventorganiser_is_event_query( $query, true ) ){
|
497 |
+
//If no orderby is set, but we are querying events, return the default order for events;
|
498 |
+
$orderby = " {$wpdb->eo_events}.StartDate ASC, {$wpdb->eo_events}.StartTime ASC";
|
499 |
+
}
|
500 |
+
return $orderby;
|
501 |
+
}
|
502 |
+
|
503 |
+
|
504 |
+
|
505 |
+
|
506 |
+
/**
|
507 |
+
* Checks if the main query is for a venue
|
508 |
+
* This will be deprecated shortly
|
509 |
+
*@since 1.0.0
|
510 |
+
*@ignore
|
511 |
+
*@return bool True if the main query is for a venue, false otherwise.
|
512 |
+
*/
|
513 |
+
function eo_is_venue(){
|
514 |
+
global $wp_query;
|
515 |
+
return (isset($wp_query->query_vars['venue'] ) || is_tax('event-venue'));
|
516 |
+
}
|
517 |
+
?>
|
includes/event-organiser-cpt.php
ADDED
@@ -0,0 +1,1057 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Registers the event taxonomies: event-venue, event-category and optinally event-tag
|
5 |
+
* Hooked onto init
|
6 |
+
*
|
7 |
+
* @ignore
|
8 |
+
* @access private
|
9 |
+
* @since 1.0
|
10 |
+
*/
|
11 |
+
function eventorganiser_create_event_taxonomies() {
|
12 |
+
|
13 |
+
if( !eventorganiser_get_option('prettyurl') ){
|
14 |
+
$cat_rewrite =$tag_rewrite=$venue_rewrite= false;
|
15 |
+
|
16 |
+
}else{
|
17 |
+
$cat_slug = trim(eventorganiser_get_option('url_cat','events/category'), "/");
|
18 |
+
$cat_rewrite = array( 'slug' => $cat_slug, 'with_front' => false );
|
19 |
+
|
20 |
+
$tag_slug = trim(eventorganiser_get_option('url_tag','events/tag'), "/");
|
21 |
+
$tag_rewrite = array( 'slug' => $tag_slug, 'with_front' => false );
|
22 |
+
|
23 |
+
$venue_slug = trim(eventorganiser_get_option('url_venue','events/venue'), "/");
|
24 |
+
$venue_rewrite = array( 'slug' => $venue_slug, 'with_front' => false );
|
25 |
+
}
|
26 |
+
|
27 |
+
$venue_labels = array(
|
28 |
+
'name' => __('Event Venues','eventorganiser'),
|
29 |
+
'singular_name' => _x( 'Venues', 'taxonomy singular name'),
|
30 |
+
'search_items' => __( 'Search Venues'),
|
31 |
+
'all_items' => __( 'All Venues'),
|
32 |
+
'edit_item' => __( 'Edit Venue'),
|
33 |
+
'update_item' => __( 'Update Venue'),
|
34 |
+
'add_new_item' => __( 'Add New Venue'),
|
35 |
+
'new_item_name' => __( 'New Venue Name'),
|
36 |
+
'not_found' => __('No venues found'),
|
37 |
+
'add_or_remove_items' => __( 'Add or remove venues' ),
|
38 |
+
'separate_items_with_commas' => __( 'Separate venues with commas' )
|
39 |
+
);
|
40 |
+
|
41 |
+
register_taxonomy('event-venue',array('event'), array(
|
42 |
+
'hierarchical' => false,
|
43 |
+
'labels' => $venue_labels,
|
44 |
+
'public'=> true,
|
45 |
+
'show_in_nav_menus'=>false,
|
46 |
+
'show_ui' => false,//Use custom UI
|
47 |
+
'update_count_callback' => '_update_post_term_count',
|
48 |
+
'query_var' => true,
|
49 |
+
'capabilities'=>array(
|
50 |
+
'manage_terms' => 'manage_venues',
|
51 |
+
'edit_terms' => 'manage_venues',
|
52 |
+
'delete_terms' => 'manage_venues',
|
53 |
+
'assign_terms' =>'edit_events'),
|
54 |
+
'rewrite' => $venue_rewrite
|
55 |
+
));
|
56 |
+
|
57 |
+
// Add new taxonomy, make it hierarchical (like categories)
|
58 |
+
$category_labels = array(
|
59 |
+
'name' => __('Event Categories', 'eventorganiser'),
|
60 |
+
'singular_name' => _x( 'Category', 'taxonomy singular name'),
|
61 |
+
'search_items' => __( 'Search Categories' ),
|
62 |
+
'all_items' => __( 'All Categories' ),
|
63 |
+
'parent_item' => __( 'Parent Category' ),
|
64 |
+
'parent_item_colon' => __( 'Parent Category' ).':',
|
65 |
+
'edit_item' => __( 'Edit Category' ),
|
66 |
+
'update_item' => __( 'Update Category' ),
|
67 |
+
'add_new_item' => __( 'Add New Category' ),
|
68 |
+
'new_item_name' => __( 'New Category Name' ),
|
69 |
+
'not_found' => __('No categories found'),
|
70 |
+
'menu_name' => __( 'Categories' ),
|
71 |
+
);
|
72 |
+
|
73 |
+
register_taxonomy('event-category',array('event'), array(
|
74 |
+
'hierarchical' => true,
|
75 |
+
'labels' => $category_labels,
|
76 |
+
'show_ui' => true,
|
77 |
+
'update_count_callback' => '_update_post_term_count',
|
78 |
+
'query_var' => true,
|
79 |
+
'capabilities'=>array(
|
80 |
+
'manage_terms' => 'manage_event_categories',
|
81 |
+
'edit_terms' => 'manage_event_categories',
|
82 |
+
'delete_terms' => 'manage_event_categories',
|
83 |
+
'assign_terms' =>'edit_events'),
|
84 |
+
'public'=> true,
|
85 |
+
'rewrite' => $cat_rewrite
|
86 |
+
));
|
87 |
+
|
88 |
+
if( eventorganiser_get_option('eventtag') ):
|
89 |
+
// Add new taxonomy, make it non-hierarchical (like tags)
|
90 |
+
$tag_labels = array(
|
91 |
+
'name' => __('Event Tags','eventorganiser'),
|
92 |
+
'singular_name' => _x( 'Tag', 'taxonomy singular name'),
|
93 |
+
'search_items' => __( 'Search Tags'),
|
94 |
+
'all_items' => __( 'All Tags'),
|
95 |
+
'popular_items' => __( 'Popular Tags'),
|
96 |
+
'parent_item' => null,
|
97 |
+
'parent_item_colon' => null,
|
98 |
+
'edit_item' => __( 'Edit Tag'),
|
99 |
+
'update_item' => __( 'Update Tag'),
|
100 |
+
'add_new_item' => __( 'Add New Tag'),
|
101 |
+
'new_item_name' => __( 'New Tag Name'),
|
102 |
+
'not_found' => __('No tags found'),
|
103 |
+
'choose_from_most_used' => __( 'Choose from the most used tags' ),
|
104 |
+
'menu_name' => __( 'Tags' ),
|
105 |
+
'add_or_remove_items' => __( 'Add or remove tags' ),
|
106 |
+
'separate_items_with_commas' => __( 'Separate tags with commas' )
|
107 |
+
);
|
108 |
+
|
109 |
+
register_taxonomy('event-tag',array('event'), array(
|
110 |
+
'hierarchical' => false,
|
111 |
+
'labels' => $tag_labels,
|
112 |
+
'show_ui' => true,
|
113 |
+
'update_count_callback' => '_update_post_term_count',
|
114 |
+
'query_var' => true,
|
115 |
+
'capabilities'=>array(
|
116 |
+
'manage_terms' => 'manage_event_categories',
|
117 |
+
'edit_terms' => 'manage_event_categories',
|
118 |
+
'delete_terms' => 'manage_event_categories',
|
119 |
+
'assign_terms' =>'edit_events'),
|
120 |
+
'public'=> true,
|
121 |
+
'rewrite' => $tag_rewrite
|
122 |
+
));
|
123 |
+
endif;
|
124 |
+
}
|
125 |
+
add_action( 'init', 'eventorganiser_create_event_taxonomies', 10 );
|
126 |
+
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Registers the event custom post type
|
130 |
+
* Hooked onto init
|
131 |
+
*
|
132 |
+
* @ignore
|
133 |
+
* @access private
|
134 |
+
* @since 1.0
|
135 |
+
*/
|
136 |
+
function eventorganiser_cpt_register() {
|
137 |
+
|
138 |
+
$labels = array(
|
139 |
+
'name' => __('Events','eventorganiser'),
|
140 |
+
'singular_name' => __('Event','eventorganiser'),
|
141 |
+
'add_new' => _x('Add New','post'),
|
142 |
+
'add_new_item' => __('Add New Event','eventorganiser'),
|
143 |
+
'edit_item' => __('Edit Event','eventorganiser'),
|
144 |
+
'new_item' => __('New Event','eventorganiser'),
|
145 |
+
'all_items' =>__('All events','eventorganiser'),
|
146 |
+
'view_item' =>__('View Event','eventorganiser'),
|
147 |
+
'search_items' =>__('Search events','eventorganiser'),
|
148 |
+
'not_found' => __('No events found','eventorganiser'),
|
149 |
+
'not_found_in_trash' => __('No events found in Trash','eventorganiser'),
|
150 |
+
'parent_item_colon' => '',
|
151 |
+
'menu_name' => __('Events','eventorganiser'),
|
152 |
+
);
|
153 |
+
|
154 |
+
$exclude_from_search = (eventorganiser_get_option('excludefromsearch')==0) ? false : true;
|
155 |
+
|
156 |
+
if( !eventorganiser_get_option('prettyurl') ){
|
157 |
+
$event_rewrite = false;
|
158 |
+
$events_slug = true;
|
159 |
+
}else{
|
160 |
+
$event_slug = trim(eventorganiser_get_option('url_event','events/event'), "/");
|
161 |
+
$events_slug = trim(eventorganiser_get_option('url_events','events/event'), "/");
|
162 |
+
$event_rewrite = array( 'slug' => $event_slug, 'with_front' => false,'feeds'=> true,'pages'=> true );
|
163 |
+
|
164 |
+
/* Workaround for http://core.trac.wordpress.org/ticket/19871 */
|
165 |
+
global $wp_rewrite;
|
166 |
+
$wp_rewrite->add_rewrite_tag('%event_ondate%','([0-9]{4}(?:/[0-9]{2}(?:/[0-9]{2})?)?)','post_type=event&ondate=');
|
167 |
+
add_permastruct('event_archive', $events_slug.'/on/%event_ondate%', array( 'with_front' => false ) );
|
168 |
+
}
|
169 |
+
|
170 |
+
$args = array(
|
171 |
+
'labels' => $labels,
|
172 |
+
'public' => true,
|
173 |
+
'publicly_queryable' => true,
|
174 |
+
'exclude_from_search'=>$exclude_from_search,
|
175 |
+
'show_ui' => true,
|
176 |
+
'show_in_menu' => true,
|
177 |
+
'query_var' => true,
|
178 |
+
'capability_type' => 'event',
|
179 |
+
'rewrite' => $event_rewrite,
|
180 |
+
'capabilities' => array(
|
181 |
+
'publish_posts' => 'publish_events',
|
182 |
+
'edit_posts' => 'edit_events',
|
183 |
+
'edit_others_posts' => 'edit_others_events',
|
184 |
+
'delete_posts' => 'delete_events',
|
185 |
+
'delete_others_posts' => 'delete_others_events',
|
186 |
+
'read_private_posts' => 'read_private_events',
|
187 |
+
'edit_post' => 'edit_event',
|
188 |
+
'delete_post' => 'delete_event',
|
189 |
+
'read_post' => 'read_event',
|
190 |
+
),
|
191 |
+
'has_archive' => $events_slug,
|
192 |
+
'hierarchical' => false,
|
193 |
+
'menu_icon' => EVENT_ORGANISER_URL.'css/images/eoicon-16.png',
|
194 |
+
'menu_position' => apply_filters('eventorganiser_menu_position',5),
|
195 |
+
'supports' => eventorganiser_get_option('supports'),
|
196 |
+
);
|
197 |
+
|
198 |
+
register_post_type('event',$args);
|
199 |
+
}
|
200 |
+
add_action('init', 'eventorganiser_cpt_register');
|
201 |
+
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Sets the messages that appear when an event is updated / saved.
|
205 |
+
* Hooked onto post_updated_messages
|
206 |
+
*
|
207 |
+
* @ignore
|
208 |
+
* @access private
|
209 |
+
* @since 1.0
|
210 |
+
*/
|
211 |
+
function eventorganiser_messages( $messages ) {
|
212 |
+
global $post, $post_ID;
|
213 |
+
|
214 |
+
$messages['event'] = array(
|
215 |
+
0 => '', // Unused. Messages start at index 1.
|
216 |
+
1 => sprintf( __('Event updated. <a href="%s">View event</a>','eventorganiser'), esc_url( get_permalink($post_ID) ) ),
|
217 |
+
2 => __('Custom field updated.'),
|
218 |
+
3 => __('Custom field deleted.'),
|
219 |
+
4 => __('Event updated.','eventorganiser'),
|
220 |
+
/* translators: %s: date and time of the revision */
|
221 |
+
5 => isset($_GET['revision']) ? sprintf( __('Event restored to revision from %s','eventorganiser'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
222 |
+
6 => sprintf( __('Event published. <a href="%s">View event</a>','eventorganiser'), esc_url( get_permalink($post_ID) ) ),
|
223 |
+
7 => __('Event saved.'),
|
224 |
+
8 => sprintf( __('Event submitted. <a target="_blank" href="%s">Preview event</a>','eventorganiser'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
|
225 |
+
9 => sprintf( __('Event scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview event</a>','eventorganiser'),
|
226 |
+
// translators: Publish box date format, see http://php.net/date
|
227 |
+
date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
|
228 |
+
10 => sprintf( __('Event draft updated. <a target="_blank" href="%s">Preview event</a>','eventorganiser'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
|
229 |
+
);
|
230 |
+
return $messages;
|
231 |
+
}
|
232 |
+
add_filter('post_updated_messages', 'eventorganiser_messages');
|
233 |
+
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Maps meta capabilities to primitve ones for event post type
|
237 |
+
*
|
238 |
+
* @ignore
|
239 |
+
* @access private
|
240 |
+
* @since 1.0
|
241 |
+
*/
|
242 |
+
function eventorganiser_event_meta_cap( $caps, $cap, $user_id, $args ) {
|
243 |
+
|
244 |
+
/* If editing, deleting, or reading a event, get the post and post type object. */
|
245 |
+
if ( 'edit_event' == $cap || 'delete_event' == $cap || 'read_event' == $cap ) {
|
246 |
+
$post = get_post( $args[0] );
|
247 |
+
$post_type = get_post_type_object( $post->post_type );
|
248 |
+
|
249 |
+
/* Set an empty array for the caps. */
|
250 |
+
$caps = array();
|
251 |
+
if($post->post_type!='event')
|
252 |
+
return $caps;
|
253 |
+
}
|
254 |
+
|
255 |
+
/* If editing a event, assign the required capability. */
|
256 |
+
if ( 'edit_event' == $cap ) {
|
257 |
+
if ( $user_id == $post->post_author )
|
258 |
+
$caps[] = $post_type->cap->edit_posts;
|
259 |
+
else
|
260 |
+
$caps[] = $post_type->cap->edit_others_posts;
|
261 |
+
}
|
262 |
+
|
263 |
+
/* If deleting a event, assign the required capability. */
|
264 |
+
elseif ( 'delete_event' == $cap ) {
|
265 |
+
if (isset($post->post_author ) && $user_id == $post->post_author)
|
266 |
+
$caps[] = $post_type->cap->delete_posts;
|
267 |
+
else
|
268 |
+
$caps[] = $post_type->cap->delete_others_posts;
|
269 |
+
}
|
270 |
+
|
271 |
+
/* If reading a private event, assign the required capability. */
|
272 |
+
elseif ( 'read_event' == $cap ) {
|
273 |
+
|
274 |
+
if ( 'private' != $post->post_status )
|
275 |
+
$caps[] = 'read';
|
276 |
+
elseif ( $user_id == $post->post_author )
|
277 |
+
$caps[] = 'read';
|
278 |
+
else
|
279 |
+
$caps[] = $post_type->cap->read_private_posts;
|
280 |
+
}
|
281 |
+
|
282 |
+
/* Return the capabilities required by the user. */
|
283 |
+
return $caps;
|
284 |
+
}
|
285 |
+
add_filter( 'map_meta_cap', 'eventorganiser_event_meta_cap', 10, 4 );
|
286 |
+
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Adds the Event Organiser icon to the page head
|
290 |
+
* Hooked onto admin_head
|
291 |
+
*
|
292 |
+
* @ignore
|
293 |
+
* @access private
|
294 |
+
* @since 1.0
|
295 |
+
*/
|
296 |
+
function eventorganiser_plugin_header_image() {
|
297 |
+
global $post_type;
|
298 |
+
|
299 |
+
if ((isset($_GET['post_type']) && $_GET['post_type'] == 'event') || ($post_type == 'event')) : ?>
|
300 |
+
<style>
|
301 |
+
#icon-edit { background:transparent url('<?php echo EVENT_ORGANISER_URL.'/css/images/eoicon-32.png';?>') no-repeat; }
|
302 |
+
</style>
|
303 |
+
<?php endif;
|
304 |
+
}
|
305 |
+
add_action('admin_head', 'eventorganiser_plugin_header_image');
|
306 |
+
|
307 |
+
/**
|
308 |
+
* With appropriate settings we add a menu item of 'post_type_archive' type.
|
309 |
+
* WP doesn't understand this so we set the url ourself - hooking just before its saved to db.
|
310 |
+
* Hooked onto wp_update_nav_menu_item
|
311 |
+
*
|
312 |
+
* @ignore
|
313 |
+
* @access private
|
314 |
+
* @since 1.0
|
315 |
+
*/
|
316 |
+
function eventorganiser_update_nav_item($menu_id,$menu_item_db_id,$args){
|
317 |
+
if($args['menu-item-type'] == 'post_type_archive' && $args['menu-item-object'] =='event'){
|
318 |
+
$post_type = $args['menu-item-object'];
|
319 |
+
$args['menu-item-url'] = get_post_type_archive_link($post_type);
|
320 |
+
update_post_meta( $menu_item_db_id, '_menu_item_url', esc_url_raw($args['menu-item-url']) );
|
321 |
+
}
|
322 |
+
}
|
323 |
+
add_action('wp_update_nav_menu_item','eventorganiser_update_nav_item',10,3);
|
324 |
+
|
325 |
+
|
326 |
+
/**
|
327 |
+
* WP doesn't know when our custom menu item ('Events') is 'current'. We make it 'current', by
|
328 |
+
* adding the appropriate classes if viewing an event, event archive or event taxonomy
|
329 |
+
* Hooked onto wp_nav_menu_objects
|
330 |
+
*
|
331 |
+
* @ignore
|
332 |
+
* @access private
|
333 |
+
* @since 1.0
|
334 |
+
*/
|
335 |
+
function eventorganiser_make_item_current($items,$args){
|
336 |
+
if(is_post_type_archive('event')|| is_singular('event')|| eo_is_event_taxonomy()){
|
337 |
+
foreach ($items as $item){
|
338 |
+
if('post_type_archive'!=$item->type || 'event'!=$item->object)
|
339 |
+
continue;
|
340 |
+
|
341 |
+
$item->classes[] = 'current-menu-item';
|
342 |
+
|
343 |
+
$_anc_id = (int) $item->db_id;
|
344 |
+
$active_ancestor_item_ids=array();
|
345 |
+
while(( $_anc_id = get_post_meta( $_anc_id, '_menu_item_menu_item_parent', true ) ) &&
|
346 |
+
! in_array( $_anc_id, $active_ancestor_item_ids ) ){
|
347 |
+
$active_ancestor_item_ids[] = $_anc_id;
|
348 |
+
}
|
349 |
+
|
350 |
+
//Loop through ancestors and give them 'ancestor' or 'parent' class
|
351 |
+
foreach ($items as $key=>$parent_item){
|
352 |
+
$classes = (array) $parent_item->classes;
|
353 |
+
|
354 |
+
//If menu item is the parent
|
355 |
+
if ($parent_item->db_id == $item->menu_item_parent ) {
|
356 |
+
$classes[] = 'current-menu-parent';
|
357 |
+
$items[$key]->current_item_parent = true;
|
358 |
+
}
|
359 |
+
|
360 |
+
//If menu item is an ancestor
|
361 |
+
if ( in_array( intval( $parent_item->db_id ), $active_ancestor_item_ids ) ) {
|
362 |
+
$classes[] = 'current-menu-ancestor';
|
363 |
+
$items[$key]->current_item_ancestor = true;
|
364 |
+
}
|
365 |
+
|
366 |
+
$items[$key]->classes = array_unique( $classes );
|
367 |
+
}
|
368 |
+
}
|
369 |
+
}
|
370 |
+
return $items;
|
371 |
+
}
|
372 |
+
add_filter( 'wp_nav_menu_objects', 'eventorganiser_make_item_current',10,2);
|
373 |
+
|
374 |
+
|
375 |
+
/**
|
376 |
+
* If a menu isn't being used the above won't work. They're using wp_list_pages, so the
|
377 |
+
* best we can do is append a link to the end of the list.
|
378 |
+
* Hooked onto wp_list_pages
|
379 |
+
*
|
380 |
+
* @ignore
|
381 |
+
* @access private
|
382 |
+
* @since 1.0
|
383 |
+
*/
|
384 |
+
function eventorganiser_menu_link($items) {
|
385 |
+
|
386 |
+
if( eventorganiser_get_option('addtomenu') != '1' )
|
387 |
+
return $items;
|
388 |
+
|
389 |
+
$class ='menu-item menu-item-type-event';
|
390 |
+
|
391 |
+
if(is_post_type_archive('event')|| is_singular('event')|| eo_is_event_taxonomy())
|
392 |
+
$class = 'current_page_item';
|
393 |
+
|
394 |
+
$items .= sprintf('<li class="%s"><a href="%s" > %s </a></li>',
|
395 |
+
$class,
|
396 |
+
get_post_type_archive_link('event'),
|
397 |
+
esc_html(eventorganiser_get_option('navtitle'))
|
398 |
+
);
|
399 |
+
return $items;
|
400 |
+
}
|
401 |
+
add_filter( 'wp_list_pages', 'eventorganiser_menu_link',10,1 );
|
402 |
+
|
403 |
+
/**
|
404 |
+
* Contextual help for event pages
|
405 |
+
*
|
406 |
+
* @ignore
|
407 |
+
* @access private
|
408 |
+
* @since 1.0
|
409 |
+
*/
|
410 |
+
function eventorganiser_cpt_help_text($contextual_help, $screen_id, $screen) {
|
411 |
+
|
412 |
+
//The add_help_tab function for screen was introduced in WordPress 3.3. Add it only to event pages.
|
413 |
+
if( ! method_exists($screen, 'add_help_tab') || ! in_array($screen_id, array('event','edit-event','event_page_venues','event_page_calendar')) )
|
414 |
+
return $contextual_help;
|
415 |
+
|
416 |
+
switch($screen_id):
|
417 |
+
//Add help for event editing / creating page
|
418 |
+
case ('event'):
|
419 |
+
$screen->add_help_tab( array(
|
420 |
+
'id' => 'creating-events',
|
421 |
+
'title' => __('Creating events','eventorganiser'),
|
422 |
+
'content' => '<p>' . __('Creating events:','eventorganiser') . '</p>'.
|
423 |
+
'<ul>' .
|
424 |
+
'<li>' . __('The start date is the date the event starts. If the event is a reoccuring event, this is the start date of the first occurrence.','eventorganiser') . '</li>' .
|
425 |
+
'<li>' . __('The end date is the date the event finishes. If the event is a reoccuring event, this is the end date of the first occurrence.','eventorganiser') . '</li>' .
|
426 |
+
'<li>' . __('All dates and times must be entered in the specified format. This format can changed in the settings page.','eventorganiser') . '</li>' .
|
427 |
+
'</ul>'
|
428 |
+
));
|
429 |
+
$screen->add_help_tab( array(
|
430 |
+
'id' => 'repeating-events',
|
431 |
+
'title' => __('Repeating events','eventorganiser'),
|
432 |
+
'content' => '<p>' . __('To repeat an event according to some regular pattern, use the reocurrence dropdown menu to select how the event is to repeat. Further options then appear, ','eventorganiser') . '</p>' .
|
433 |
+
'<ul>' .
|
434 |
+
'<li>' . __('Specify how regularly the event should repeat (default 1)','eventorganiser') . '</li>' .
|
435 |
+
'<li>' . __('Choose the reoccurrence end date. No further occurrences are added after this date, but an occurrence that starts before may finish after this date.','eventorganiser') . '</li>' .
|
436 |
+
'<li>' . __('If monthly reoccurrence is selected, select whether this should repeat on that date of the month (e.g. on the 24th) or on the day of the month (e.g. on the third Tuesday) ','eventorganiser') . '</li>' .
|
437 |
+
'<li>' . __('If weekly reoccurrence is selected, select which days of the week the event should be repeated. If no days are selected, the day of the start date is used','eventorganiser') . '</li>' .
|
438 |
+
'</ul>'
|
439 |
+
));
|
440 |
+
$screen->add_help_tab( array(
|
441 |
+
'id' => 'selecting-venues',
|
442 |
+
'title' => __('Selecting a venue','eventorganiser'),
|
443 |
+
'content' => '<p>' . __('Selecting a venue','eventorganiser') . '</p>' .
|
444 |
+
'<ul>' .
|
445 |
+
'<li>' . __('Use the venues input field to search for existing venues','eventorganiser') . '</li>' .
|
446 |
+
'<li>' . __('Only pre-existing venues can be selected. To add a venue, go to the venues page.','eventorganiser') . '</li>' .
|
447 |
+
'</ul>'
|
448 |
+
));
|
449 |
+
break;
|
450 |
+
|
451 |
+
//Add help for event admin table page
|
452 |
+
case ('edit-event'):
|
453 |
+
|
454 |
+
$screen->add_help_tab( array(
|
455 |
+
'id'=>'overview',
|
456 |
+
'title' => __('Overview'),
|
457 |
+
'content'=>'<p>' . __('This is the list of all saved events. Note that <strong> reoccurring events appear as a single row </strong> in the table and the start and end date refers to the first occurrence of that event.','eventorganiser') . '</p>' ));
|
458 |
+
break;
|
459 |
+
|
460 |
+
//Add help for venue admin table page
|
461 |
+
case ('event_page_venues'):
|
462 |
+
$contextual_help =
|
463 |
+
'<p>' . __("Hovering over a row in the venues list will display action links that allow you to manage that venue. You can perform the following actions:",'eventorganiser') . '</p>' .
|
464 |
+
'<ul>' .
|
465 |
+
'<li>' . __('Edit takes you to the editing screen for that venue. You can also reach that screen by clicking on the venue title.','eventorganiser') . '</li>' .
|
466 |
+
'<li>' . __('Delete will permanently remove the venue','eventorganiser') . '</li>' .
|
467 |
+
'<li>' . __("View will take you to the venue's page",'eventorganiser') . '</li>' .
|
468 |
+
'</ul>';
|
469 |
+
break;
|
470 |
+
|
471 |
+
//Add help for calendar view
|
472 |
+
case ('event_page_calendar'):
|
473 |
+
$screen->add_help_tab( array(
|
474 |
+
'id'=>'overview',
|
475 |
+
'title'=>__('Overview'),
|
476 |
+
'content'=>'<p>' . __("This page shows all (occurrances of) events. You can view the summary of an event by clicking on it. If you have the necessary permissions, a link to the event's edit page will appear also.",'eventorganiser'). '</p>' .
|
477 |
+
'<p>' . __("By clicking the relevant tab, you can view events in Month, Week or Day mode. You can also filter the events by events by category and venue. The 'go to date' button allows you to quickly jump to a specific date.",'eventorganiser'). '</p>'
|
478 |
+
));
|
479 |
+
$screen->add_help_tab( array(
|
480 |
+
'id'=>'add-event',
|
481 |
+
'title'=>__('Add Event','eventorganiser'),
|
482 |
+
'content'=>'<p>' . __("You can create an event on this Calendar, by clicking on day or dragging over multiple days (in Month view) or multiple times (in Week and Day view). You can give the event a title, specify a venue and provide a descripton. The event can be immediately published or saved as a draft. In any case, the event is created and you are forwarded to that event's edit page.",'eventorganiser') . '</p>' ));
|
483 |
+
break;
|
484 |
+
endswitch;
|
485 |
+
|
486 |
+
//Add a link to Event Organiser documentation on every EO page
|
487 |
+
$screen->set_help_sidebar(
|
488 |
+
'<p> <strong>'. __('For more information','eventorganiser').'</strong></br>'
|
489 |
+
.sprintf(__('See the <a %s> documentation</a>','eventorganiser'),'target="_blank" href="http://wp-event-organiser.com/documentation/"').'</p>'
|
490 |
+
.sprintf('<p><strong><a href="%s">%s</a></strong></p>', 'http://wordpress.org/support/plugin/event-organiser',__('Have a question?','eventorganiser'))
|
491 |
+
.sprintf('<p><strong><a href="%s">%s</a></strong></p>', admin_url('index.php?page=eo-pro'),__('Go Pro!','eventorganiser'))
|
492 |
+
);
|
493 |
+
|
494 |
+
return $contextual_help;
|
495 |
+
}
|
496 |
+
add_action( 'contextual_help', 'eventorganiser_cpt_help_text', 10, 3 );
|
497 |
+
|
498 |
+
/*
|
499 |
+
* The following adds the ability to associate a colour with an event-category.
|
500 |
+
* Currently stores data in the options table/
|
501 |
+
* If Taxonomy meta table becomes core, then these options will be migrated there.
|
502 |
+
*/
|
503 |
+
|
504 |
+
/**
|
505 |
+
* Enqueue the javascript necessary for colour-picker on category pages.
|
506 |
+
* Hooked onto admin_menu. Why?
|
507 |
+
*
|
508 |
+
* @ignore
|
509 |
+
* @access private
|
510 |
+
* @since 1.3
|
511 |
+
*/
|
512 |
+
function eventorganiser_colour_scripts() {
|
513 |
+
wp_enqueue_style( 'farbtastic' );
|
514 |
+
wp_enqueue_script( 'farbtastic' );
|
515 |
+
wp_enqueue_script( 'jQuery' );
|
516 |
+
}
|
517 |
+
add_action( 'admin_menu', 'eventorganiser_colour_scripts' );
|
518 |
+
|
519 |
+
|
520 |
+
/**
|
521 |
+
* When a category is created/updated save its color
|
522 |
+
* Hooked onto created_event-category and edited_event-category
|
523 |
+
*
|
524 |
+
* @ignore
|
525 |
+
* @access private
|
526 |
+
* @since 1.3
|
527 |
+
*/
|
528 |
+
function eventorganiser_save_event_cat_meta( $term_id ) {
|
529 |
+
if ( isset( $_POST['eo_term_meta'] ) ):
|
530 |
+
$term_meta = get_option( "eo-event-category_$term_id");
|
531 |
+
$cat_keys = array_keys($_POST['eo_term_meta']);
|
532 |
+
|
533 |
+
foreach ($cat_keys as $key):
|
534 |
+
if (isset($_POST['eo_term_meta'][$key]))
|
535 |
+
$term_meta[$key] = $_POST['eo_term_meta'][$key];
|
536 |
+
endforeach;
|
537 |
+
|
538 |
+
//save the option array
|
539 |
+
update_option( "eo-event-category_$term_id", $term_meta );
|
540 |
+
endif;
|
541 |
+
}
|
542 |
+
add_action('created_event-category', 'eventorganiser_save_event_cat_meta', 10, 2);
|
543 |
+
add_action( 'edited_event-category', 'eventorganiser_save_event_cat_meta', 10, 2);
|
544 |
+
|
545 |
+
/**
|
546 |
+
* When a category is deleted, delete the saved colour (saved in options table).
|
547 |
+
* Hooked onto delete_event-category
|
548 |
+
*
|
549 |
+
* @ignore
|
550 |
+
* @access private
|
551 |
+
* @since 1.3
|
552 |
+
*/
|
553 |
+
function eventorganiser_tax_term_deleted($term_id, $tt_id){
|
554 |
+
//Delete taxonomies meta
|
555 |
+
delete_option('eo-event-category_'.$term_id);
|
556 |
+
}
|
557 |
+
add_action('delete_event-category','eventorganiser_tax_term_deleted',10,2);
|
558 |
+
|
559 |
+
/**
|
560 |
+
* Add the colour picker forms to main taxonomy page: (This one needs stuff wrapped in Divs)
|
561 |
+
* uses eventorganiser_tax_meta_form to display the guts of the form.
|
562 |
+
* Hooked onto event-category_add_form_fields
|
563 |
+
* @uses eventorganiser_tax_meta_form
|
564 |
+
*
|
565 |
+
* @ignore
|
566 |
+
* @access private
|
567 |
+
* @since 1.3
|
568 |
+
*/
|
569 |
+
function eventorganiser_add_tax_meta($taxonomy){
|
570 |
+
?>
|
571 |
+
<div class="form-field"><?php eventorganiser_tax_meta_form('');?></div>
|
572 |
+
<p> </br> </p>
|
573 |
+
<?php
|
574 |
+
}
|
575 |
+
add_action('event-category_add_form_fields', 'eventorganiser_add_tax_meta',10,1);
|
576 |
+
|
577 |
+
|
578 |
+
/**
|
579 |
+
* Add the colour picker forms to taxonomy-edit page: (This one needs stuff wrapped in rows)
|
580 |
+
* uses eventorganiser_tax_meta_form to display the guts of the form.
|
581 |
+
* Hooked onto event-category_edit_form_fields
|
582 |
+
* @uses eventorganiser_tax_meta_form
|
583 |
+
*
|
584 |
+
* @ignore
|
585 |
+
* @access private
|
586 |
+
* @since 1.3
|
587 |
+
*/
|
588 |
+
function eventorganiser_edit_tax_meta($term,$taxonomy){
|
589 |
+
//Check for existing data
|
590 |
+
$term_meta = get_option( "eo-event-category_$term->term_id");
|
591 |
+
$colour = (!empty($term_meta) && isset($term_meta['colour']) ? $term_meta['colour'] : '');
|
592 |
+
?>
|
593 |
+
<tr class="form-field"><?php eventorganiser_tax_meta_form($colour);?></tr>
|
594 |
+
<?php
|
595 |
+
}
|
596 |
+
add_action( 'event-category_edit_form_fields', 'eventorganiser_edit_tax_meta', 10, 2);
|
597 |
+
|
598 |
+
/**
|
599 |
+
* Displays the guts of the taxonomy-meta form (i.e. colour picker);
|
600 |
+
*
|
601 |
+
* @ignore
|
602 |
+
* @access private
|
603 |
+
* @since 1.3
|
604 |
+
*/
|
605 |
+
function eventorganiser_tax_meta_form($colour){
|
606 |
+
?>
|
607 |
+
<th>
|
608 |
+
<label for="tag-description"><?php _e('Color','eventorganiser')?></label>
|
609 |
+
</th>
|
610 |
+
<td>
|
611 |
+
<input type="text" style="width:100px" name="eo_term_meta[colour]" class="color colour-input" id="color" value="<?php echo $colour; ?>" />
|
612 |
+
<a id="link-color-example" class="color hide-if-no-js" style="border: 1px solid #DFDFDF;border-radius: 4px 4px 4px 4px;margin: 0 7px 0 3px;padding: 4px 14px;"></a>
|
613 |
+
<div style="z-index: 100; background: none repeat scroll 0% 0% rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); position: absolute;display: none;" id="colorpicker"></div>
|
614 |
+
<p><?php _e('Assign the category a colour.','eventorganiser')?></p>
|
615 |
+
</td>
|
616 |
+
<script>
|
617 |
+
var farbtastic;(function($){var pickColor=function(a){farbtastic.setColor(a);$('.colour-input').val(a);$('a.color').css('background-color',a)};$(document).ready(function(){farbtastic=$.farbtastic('#colorpicker',pickColor);pickColor($('.colour-input').val());$('.color').click(function(e){e.preventDefault();if($('#colorpicker').is(":visible")){$('#colorpicker').hide()}else{$('#colorpicker').show()}});$('.colour-input').keyup(function(){var a=$('.colour-input').val(),b=a;a=a.replace(/[^a-fA-F0-9]/,'');if('#'+a!==b)$('.colour-input').val(a);if(a.length===3||a.length===6)pickColor('#'+a)});$(document).mousedown(function(){$('#colorpicker').hide()})})})(jQuery);
|
618 |
+
</script>
|
619 |
+
<?php
|
620 |
+
}
|
621 |
+
|
622 |
+
/**
|
623 |
+
* Add the colour of the category to the term object.
|
624 |
+
* Hooked onto get_event-category
|
625 |
+
*
|
626 |
+
* @ignore
|
627 |
+
* @access private
|
628 |
+
* @since 1.3
|
629 |
+
*/
|
630 |
+
function eventorganiser_append_cat_meta($term){
|
631 |
+
if($term):
|
632 |
+
$term_meta = get_option( "eo-event-category_{$term->term_id}");
|
633 |
+
$colour = (isset($term_meta['colour']) ? $term_meta['colour'] : '');
|
634 |
+
$term->color = $colour;
|
635 |
+
endif;
|
636 |
+
return $term;
|
637 |
+
}
|
638 |
+
add_filter('get_event-category','eventorganiser_append_cat_meta');
|
639 |
+
|
640 |
+
|
641 |
+
/**
|
642 |
+
* Add the colour of the category to the term object.
|
643 |
+
* Hooked onto get_event-category
|
644 |
+
*
|
645 |
+
* @ignore
|
646 |
+
* @access private
|
647 |
+
* @since 1.3
|
648 |
+
*/
|
649 |
+
function eventorganiser_get_terms_meta($terms){
|
650 |
+
if($terms):
|
651 |
+
foreach($terms as $term):
|
652 |
+
if(isset($term->taxonomy) && $term->taxonomy=='event-category'){
|
653 |
+
$term_meta = get_option( "eo-event-category_{$term->term_id}");
|
654 |
+
$colour = (isset($term_meta['colour']) ? $term_meta['colour'] : '');
|
655 |
+
$term->color = $colour;
|
656 |
+
}
|
657 |
+
endforeach;
|
658 |
+
endif;
|
659 |
+
return $terms;
|
660 |
+
}
|
661 |
+
add_filter('get_terms','eventorganiser_get_terms_meta');
|
662 |
+
add_filter('get_the_terms','eventorganiser_get_terms_meta');
|
663 |
+
|
664 |
+
|
665 |
+
/**
|
666 |
+
* Retrieve a category term's colour.
|
667 |
+
*
|
668 |
+
* @since 1.3
|
669 |
+
* @param term|slug $term The event category term object, or slug. Can be empty to get colour of term being viewed.
|
670 |
+
* @return string The event category colour in Hex format
|
671 |
+
*/
|
672 |
+
function eo_get_category_meta($term='',$key=''){
|
673 |
+
if( $key != 'color' )
|
674 |
+
return false;
|
675 |
+
|
676 |
+
if (is_object($term)){
|
677 |
+
if(isset($term->color))
|
678 |
+
return $term->color;
|
679 |
+
else
|
680 |
+
$term = $term->slug;
|
681 |
+
}
|
682 |
+
|
683 |
+
if( !empty($term) ){
|
684 |
+
$term = get_term_by('slug', $term,'event-category');
|
685 |
+
if( isset($term->color))
|
686 |
+
return $term->color;
|
687 |
+
|
688 |
+
}elseif( is_tax('event-category') ){
|
689 |
+
$term = get_queried_object();
|
690 |
+
$term = $term->term_id;
|
691 |
+
$term = get_term( $term, 'event-category' );
|
692 |
+
if( isset($term->color))
|
693 |
+
return $term->color;
|
694 |
+
}
|
695 |
+
|
696 |
+
return false;
|
697 |
+
}
|
698 |
+
|
699 |
+
/**
|
700 |
+
* Adds custom tables to $wpdb;
|
701 |
+
*
|
702 |
+
* @ignore
|
703 |
+
* @access private
|
704 |
+
* @since 1.5
|
705 |
+
*/
|
706 |
+
function eventorganiser_wpdb_fix(){
|
707 |
+
global $wpdb;
|
708 |
+
$wpdb->eo_venuemeta = "{$wpdb->prefix}eo_venuemeta";
|
709 |
+
$wpdb->eo_events = "{$wpdb->prefix}eo_events";
|
710 |
+
}
|
711 |
+
add_action( 'init', 'eventorganiser_wpdb_fix',1);
|
712 |
+
add_action( 'switch_blog', 'eventorganiser_wpdb_fix');
|
713 |
+
|
714 |
+
|
715 |
+
/**
|
716 |
+
* Updates venue meta cache when an event's venue is retrieved..
|
717 |
+
* Hooked onto wp_get_object_terms
|
718 |
+
*
|
719 |
+
* @ignore
|
720 |
+
* @access private
|
721 |
+
* @since 1.5
|
722 |
+
*/
|
723 |
+
function _eventorganiser_get_event_venue($terms, $post_ids,$taxonomies,$args){
|
724 |
+
//Passes taxonomies as a string inside quotes...
|
725 |
+
$taxonomies = explode(',',trim($taxonomies,"\x22\x27"));
|
726 |
+
return eventorganiser_update_venue_meta_cache( $terms, $taxonomies);
|
727 |
+
}
|
728 |
+
add_filter('wp_get_object_terms','_eventorganiser_get_event_venue',10,4);
|
729 |
+
|
730 |
+
|
731 |
+
/**
|
732 |
+
* Updates venue meta cache when event venues are retrieved.
|
733 |
+
*
|
734 |
+
* For backwards compatibility it adds the venue details to the taxonomy terms.
|
735 |
+
* Hooked onto get_terms and get_event-venue
|
736 |
+
*
|
737 |
+
* @ignore
|
738 |
+
* @access private
|
739 |
+
* @since 1.5
|
740 |
+
*
|
741 |
+
* @param array $terms Array of terms,
|
742 |
+
* @param string $tax Should be (an array containing) 'event-venue'.
|
743 |
+
* @param array Array of event-venue terms,
|
744 |
+
*/
|
745 |
+
function eventorganiser_update_venue_meta_cache( $terms, $tax){
|
746 |
+
|
747 |
+
if( is_array($tax) && !in_array('event-venue',$tax) ){
|
748 |
+
return $terms;
|
749 |
+
}
|
750 |
+
if( !is_array($tax) && $tax != 'event-venue'){
|
751 |
+
return $terms;
|
752 |
+
}
|
753 |
+
|
754 |
+
$single = false;
|
755 |
+
if( ! is_array($terms) ){
|
756 |
+
$single = true;
|
757 |
+
$terms = array( $terms );
|
758 |
+
}
|
759 |
+
|
760 |
+
if( empty($terms) )
|
761 |
+
return $terms;
|
762 |
+
|
763 |
+
//TODO Sort this out when $terms is an array of IDs not objects.
|
764 |
+
$term_ids = wp_list_pluck($terms,'term_id');
|
765 |
+
|
766 |
+
update_meta_cache('eo_venue',$term_ids);
|
767 |
+
|
768 |
+
//Backwards compatible. Depreciated - use the functions, not properties.
|
769 |
+
foreach ($terms as $term){
|
770 |
+
if( !is_object($term) )
|
771 |
+
continue;
|
772 |
+
$term_id = (int) $term->term_id;
|
773 |
+
|
774 |
+
if( !isset($term->venue_address) ){
|
775 |
+
$address = eo_get_venue_address($term_id);
|
776 |
+
foreach( $address as $key => $value )
|
777 |
+
$term->{'venue_'.$key} = $value;
|
778 |
+
}
|
779 |
+
|
780 |
+
if( !isset($term->venue_lat) || !isset($term->venue_lng) ){
|
781 |
+
$term->venue_lat = number_format(floatval(eo_get_venue_lat($term_id)), 6);
|
782 |
+
$term->venue_lng = number_format(floatval(eo_get_venue_lng($term_id)), 6);
|
783 |
+
}
|
784 |
+
|
785 |
+
}
|
786 |
+
|
787 |
+
if( $single ) return $terms[0];
|
788 |
+
|
789 |
+
return $terms;
|
790 |
+
}
|
791 |
+
add_filter('get_terms','eventorganiser_update_venue_meta_cache',10,2);
|
792 |
+
add_filter('get_event-venue','eventorganiser_update_venue_meta_cache',10,2);
|
793 |
+
|
794 |
+
|
795 |
+
|
796 |
+
/**
|
797 |
+
* Allows event-venue terms to be sorted by address, city, state, country, or postcode (on venue admin table)
|
798 |
+
* Hooked onto terms_clauses
|
799 |
+
*
|
800 |
+
* @ignore
|
801 |
+
* @access private
|
802 |
+
* @since 1.5
|
803 |
+
*/
|
804 |
+
function eventorganiser_join_venue_meta($pieces,$taxonomies,$args){
|
805 |
+
global $wpdb;
|
806 |
+
|
807 |
+
if( ! in_array('event-venue',$taxonomies) )
|
808 |
+
return $pieces;
|
809 |
+
|
810 |
+
/* Order by */
|
811 |
+
$address_keys = array_keys(_eventorganiser_get_venue_address_fields());
|
812 |
+
if( in_array('_'.$args['orderby'], $address_keys) )
|
813 |
+
$meta_key ='_'.$args['orderby'];
|
814 |
+
else
|
815 |
+
$meta_key = false;
|
816 |
+
|
817 |
+
if(false === $meta_key)
|
818 |
+
return $pieces;
|
819 |
+
|
820 |
+
$sql = get_meta_sql(array(array('key'=>$meta_key)), 'eo_venue', 't', 'term_id');
|
821 |
+
|
822 |
+
$pieces['join'] .= $sql['join'];
|
823 |
+
$pieces['where'] .= $sql['where'];
|
824 |
+
$pieces['orderby'] = "ORDER BY {$wpdb->eo_venuemeta}.meta_value";
|
825 |
+
return $pieces;
|
826 |
+
}
|
827 |
+
add_filter('terms_clauses', 'eventorganiser_join_venue_meta',10,3);
|
828 |
+
|
829 |
+
/**
|
830 |
+
* Filters to the edit venue term link so that points to the correct place
|
831 |
+
* Hooked onto get_edit_term_link
|
832 |
+
*
|
833 |
+
* @ignore
|
834 |
+
* @access private
|
835 |
+
* @since 1.5
|
836 |
+
*/
|
837 |
+
function eventorganiser_edit_venue_link($link, $term_id, $taxonomy){
|
838 |
+
|
839 |
+
if( $taxonomy != 'event-venue' )
|
840 |
+
return $link;
|
841 |
+
|
842 |
+
$tax = get_taxonomy( $taxonomy );
|
843 |
+
if ( !current_user_can( $tax->cap->edit_terms ) )
|
844 |
+
return;
|
845 |
+
|
846 |
+
$venue = get_term($term_id, $taxonomy);
|
847 |
+
|
848 |
+
$link = add_query_arg(array(
|
849 |
+
'page'=>'venues',
|
850 |
+
'action'=>'edit',
|
851 |
+
'event-venue'=> $venue->slug,
|
852 |
+
), admin_url('edit.php?post_type=event'));
|
853 |
+
|
854 |
+
return $link;
|
855 |
+
}
|
856 |
+
add_filter('get_edit_term_link','eventorganiser_edit_venue_link',10,3);
|
857 |
+
|
858 |
+
|
859 |
+
/*
|
860 |
+
* A walker class to use that extends wp_dropdown_categories and allows it to use the term's slug as a value rather than ID.
|
861 |
+
*
|
862 |
+
* See http://core.trac.wordpress.org/ticket/13258
|
863 |
+
*
|
864 |
+
* Usage, as normal:
|
865 |
+
* wp_dropdown_categories($args);
|
866 |
+
*
|
867 |
+
* But specify the custom walker class, and (optionally) a 'id' or 'slug' for the 'value' parameter:
|
868 |
+
* $args=array('walker'=> new EO_Walker_TaxonomyDropdown(), 'value'=>'slug', .... );
|
869 |
+
* wp_dropdown_categories($args);
|
870 |
+
*
|
871 |
+
* If the 'value' parameter is not set it will use term ID for categories, and the term's slug for other taxonomies in the value attribute of the term's <option>.
|
872 |
+
*/
|
873 |
+
|
874 |
+
class EO_Walker_TaxonomyDropdown extends Walker_CategoryDropdown{
|
875 |
+
|
876 |
+
function start_el(&$output, $category, $depth, $args) {
|
877 |
+
$pad = str_repeat(' ', $depth * 3);
|
878 |
+
$cat_name = apply_filters('list_cats', $category->name, $category);
|
879 |
+
|
880 |
+
if( !isset($args['value']) ){
|
881 |
+
$args['value'] = ( $category->taxonomy != 'category' ? 'slug' : 'id' );
|
882 |
+
}
|
883 |
+
|
884 |
+
$value = ($args['value']=='slug' ? $category->slug : $category->term_id );
|
885 |
+
|
886 |
+
$output .= "\t<option class=\"level-$depth\" value=\"".$value."\"";
|
887 |
+
if ( $value === (string) $args['selected'] ){
|
888 |
+
$output .= ' selected="selected"';
|
889 |
+
}
|
890 |
+
$output .= '>';
|
891 |
+
$output .= $pad.$cat_name;
|
892 |
+
if ( $args['show_count'] )
|
893 |
+
$output .= ' ('. $category->count .')';
|
894 |
+
|
895 |
+
$output .= "</option>\n";
|
896 |
+
}
|
897 |
+
|
898 |
+
}
|
899 |
+
|
900 |
+
/**
|
901 |
+
* For this to work you need to add the following to the custom field exceptions on the ThreeWP settings page:
|
902 |
+
*
|
903 |
+
* _eventorganiser_event_schedule
|
904 |
+
* _eventorganiser_schedule_start_start
|
905 |
+
* _eventorganiser_schedule_start_finish
|
906 |
+
*_eventorganiser_schedule_last_start
|
907 |
+
*_eventorganiser_schedule_last_finish
|
908 |
+
*
|
909 |
+
* @access private
|
910 |
+
* @ignore
|
911 |
+
*
|
912 |
+
*/
|
913 |
+
function eventorganiser_threeWP( $activity ){
|
914 |
+
|
915 |
+
|
916 |
+
if( isset( $activity['activity_id'] ) && $activity['activity_id'] == '3broadcast_broadcasted' && 'event' == get_post_type( get_the_ID() ) ){
|
917 |
+
|
918 |
+
$details = $activity['activity_details'];
|
919 |
+
$current_blog_id = get_current_blog_id();
|
920 |
+
$original_id = get_the_ID();
|
921 |
+
$original_cats = get_the_terms( $original_id, 'event-category' );
|
922 |
+
$original_venue_id = eo_get_venue( $original_id );
|
923 |
+
|
924 |
+
//Venue Meta &Thumbnail
|
925 |
+
$venue_meta = eo_get_venue_meta( $original_venue_id, '', false );
|
926 |
+
if( $original_venue_id && $venue_thumbnail_id = eo_get_venue_meta( $original_venue_id, '_eventorganiser_thumbnail_id', true ) ){
|
927 |
+
|
928 |
+
$original_upload_dir = wp_upload_dir();
|
929 |
+
$metadata = wp_get_attachment_metadata( $venue_thumbnail_id );
|
930 |
+
$data = get_post( $venue_thumbnail_id );
|
931 |
+
$file = $metadata['file'];
|
932 |
+
$guid = $data->guid;
|
933 |
+
$post_title = $data->post_title;
|
934 |
+
$menu_order = $data->menu_order;
|
935 |
+
$post_excerpt = $data->post_excerpt;
|
936 |
+
$filename_base = basename( $metadata['file'] );
|
937 |
+
$filename_path = $original_upload_dir[ 'basedir' ] . '/' . $metadata[ 'file' ];
|
938 |
+
|
939 |
+
$venue_thumbnail = compact( 'filename_path' , 'file', 'filename_base', 'post_title', 'guid', 'menu_order', 'post_excerpt' );
|
940 |
+
unset( $venue_meta['_eventorganiser_thumbnail_id'] );
|
941 |
+
}
|
942 |
+
|
943 |
+
foreach( $details as $broadcast ){
|
944 |
+
$blog_id = $broadcast['blog_id'];
|
945 |
+
$post_id = $broadcast['post_id'];
|
946 |
+
switch_to_blog( $blog_id );
|
947 |
+
|
948 |
+
$event_data = array ( 'force_regenerate_dates' => true );
|
949 |
+
eo_update_event($post_id, $event_data );
|
950 |
+
|
951 |
+
$venue_id = eo_get_venue( $post_id );
|
952 |
+
//Delete old venue meta
|
953 |
+
if( $old_meta = eo_get_venue_meta( $venue_id, '', false ) ){
|
954 |
+
$old_meta_keys = array_keys( $old_meta );
|
955 |
+
foreach( $old_meta_keys as $key ){
|
956 |
+
eo_delete_venue_meta( $venue_id, $key );
|
957 |
+
}
|
958 |
+
}
|
959 |
+
//Add new venue meta
|
960 |
+
foreach( $venue_meta as $key => $values ){
|
961 |
+
foreach( $values as $value ){
|
962 |
+
eo_add_venue_meta( $venue_id, $key, $value );
|
963 |
+
}
|
964 |
+
}
|
965 |
+
|
966 |
+
//Sync cat colours
|
967 |
+
$cats = get_the_terms( $post_id, 'event-category' );
|
968 |
+
foreach( $cats as $cat ){
|
969 |
+
//Find original cat
|
970 |
+
foreach( $original_cats as $original_cat ){
|
971 |
+
if( $original_cat->slug == $cat->slug ){
|
972 |
+
$re = update_option( "eo-event-category_{$cat->term_id}", array( 'colour' => $original_cat->color ) );
|
973 |
+
break;
|
974 |
+
}
|
975 |
+
}
|
976 |
+
}
|
977 |
+
|
978 |
+
//Sync venue thumbnails
|
979 |
+
$upload_dir = wp_upload_dir();
|
980 |
+
if ( file_exists( $venue_thumbnail['filename_path'] ) ){
|
981 |
+
$file_path = $upload_dir['path'] . '/' . $venue_thumbnail['filename_base'];
|
982 |
+
|
983 |
+
// Copy the file to the blog's upload directory
|
984 |
+
copy( $venue_thumbnail['filename_path'], $file_path );
|
985 |
+
|
986 |
+
if( false == ( $attachment_id = eventorganiser_file_to_attachment( $venue_thumbnail['file'] ) ) ){
|
987 |
+
|
988 |
+
// And now create the attachment stuff.
|
989 |
+
// This is taken almost directly from http://codex.wordpress.org/Function_Reference/wp_insert_attachment
|
990 |
+
$wp_filetype = wp_check_filetype( $venue_thumbnail['filename_base'], null );
|
991 |
+
$attachment = array(
|
992 |
+
'guid' => $upload_dir['url'] . '/' . $venue_thumbnail['filename_base'],
|
993 |
+
'menu_order' => $venue_thumbnail['menu_order'],
|
994 |
+
'post_excerpt' =>$venue_thumbnail['post_excerpt'],
|
995 |
+
'post_mime_type' => $wp_filetype['type'],
|
996 |
+
'post_title' => $venue_thumbnail['post_title'],
|
997 |
+
'post_status' => 'inherit',
|
998 |
+
);
|
999 |
+
$attachment_id = wp_insert_attachment( $attachment, $file_path, 0 );
|
1000 |
+
|
1001 |
+
// Now to handle the metadata.
|
1002 |
+
require_once(ABSPATH . "wp-admin" . '/includes/image.php' );
|
1003 |
+
$attach_data = wp_generate_attachment_metadata( $attachment_id, $file_path );
|
1004 |
+
wp_update_attachment_metadata( $attachment_id, $attach_data );
|
1005 |
+
}//If attachment post doesn't exist
|
1006 |
+
|
1007 |
+
eo_update_venue_meta( $venue_id, '_eventorganiser_thumbnail_id', $attachment_id );
|
1008 |
+
}//If original file exists
|
1009 |
+
|
1010 |
+
}//Foreach blog
|
1011 |
+
switch_to_blog( $current_blog_id );
|
1012 |
+
}//If broadcasting
|
1013 |
+
|
1014 |
+
}
|
1015 |
+
|
1016 |
+
|
1017 |
+
function eventorganiser_file_to_attachment( $file ){
|
1018 |
+
|
1019 |
+
$attachments = get_posts( array(
|
1020 |
+
'numberposts' => 1,
|
1021 |
+
'post_type' => 'attachment',
|
1022 |
+
'fields' => 'ids',
|
1023 |
+
'meta_query' => array(
|
1024 |
+
array(
|
1025 |
+
'value' => $file,
|
1026 |
+
'key' => '_wp_attached_file',
|
1027 |
+
),
|
1028 |
+
)
|
1029 |
+
));
|
1030 |
+
if( $attachments )
|
1031 |
+
return intval( $attachments[0] );
|
1032 |
+
else
|
1033 |
+
return false;
|
1034 |
+
}
|
1035 |
+
|
1036 |
+
add_action( 'threewp_activity_monitor_new_activity', 'eventorganiser_threeWP' );
|
1037 |
+
|
1038 |
+
|
1039 |
+
function eventorganiser_event_shortlink( $shortlink, $id, $context ) {
|
1040 |
+
|
1041 |
+
//Context can be post/blog/meta ID
|
1042 |
+
$event_id = 0;
|
1043 |
+
if( 'query' == $context && is_singular( 'event' ) ){
|
1044 |
+
$event_id = get_queried_object_id();
|
1045 |
+
}elseif( 'post' == $context ){
|
1046 |
+
$event_id = $id;
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
//Only do something if of event post type
|
1050 |
+
if( 'event' == get_post_type( $event_id ) ){
|
1051 |
+
$shortlink = home_url( '?p=' . $event_id );
|
1052 |
+
}
|
1053 |
+
|
1054 |
+
return $shortlink;
|
1055 |
+
}
|
1056 |
+
add_filter( 'pre_get_shortlink', 'eventorganiser_event_shortlink', 10, 3 );
|
1057 |
+
?>
|
includes/event-organiser-event-functions.php
ADDED
@@ -0,0 +1,1231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Event related functions
|
4 |
+
*
|
5 |
+
* @package event-functions
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Retrieve list of events matching criteria.
|
10 |
+
*
|
11 |
+
* This function is a wrapper for get_posts(). **As such parameters from {@see `get_posts()`} and {@link http://codex.wordpress.org/Class_Reference/WP_Query `WP_Query`} can also be used**.
|
12 |
+
* Their default values are as indicated by the relevant codex page unless specified below.
|
13 |
+
* You can also use {@see `get_posts()`} and {@link http://codex.wordpress.org/Class_Reference/WP_Query `WP_Query`} instead to retrieve events.
|
14 |
+
*
|
15 |
+
* The `$args` array can include the following.
|
16 |
+
*
|
17 |
+
* * **event_start_before** - default: `null`
|
18 |
+
* * **event_end_before** - default: `null`
|
19 |
+
* * **event_start_after** - default: `null`
|
20 |
+
* * **event_end_after** - default: `null`. This argument, and those expect dates in **Y-m-d** format or {@link http://wp-event-organiser.com/documentation/relative-date-formats/ relative dates}.
|
21 |
+
* * **numberposts** - default is `-1` (all events)
|
22 |
+
* * **orderby** - default is `eventstart`. You can also have `eventend`.
|
23 |
+
* * **showpastevents** - default is `true` (it's recommended to use `event_start_after=today` or `event_end_after=today` instead)
|
24 |
+
*
|
25 |
+
* If you use `get_posts()` or `WP_Query` instead then you should ensure the following:
|
26 |
+
*
|
27 |
+
* * **post_type** - is set to 'event'
|
28 |
+
* * **suppress_filters** - is set to false
|
29 |
+
*
|
30 |
+
*
|
31 |
+
* ###Example
|
32 |
+
*
|
33 |
+
* <?php
|
34 |
+
* $events = eo_get_events(array(
|
35 |
+
* 'numberposts'=>5,
|
36 |
+
* 'event_start_after'=>'today',
|
37 |
+
* 'showpastevents'=>true,//Will be deprecated, but set it to true to play it safe.
|
38 |
+
* ));
|
39 |
+
*
|
40 |
+
* if($events):
|
41 |
+
* echo '<ul>';
|
42 |
+
* foreach ($events as $event):
|
43 |
+
* //Check if all day, set format accordingly
|
44 |
+
* $format = ( eo_is_all_day($event->ID) ? get_option('date_format') : get_option('date_format').' '.get_option('time_format') );
|
45 |
+
* printf(
|
46 |
+
* '<li><a href="%s"> %s </a> on %s </li>',
|
47 |
+
* get_permalink($event->ID),
|
48 |
+
* get_the_title($event->ID),
|
49 |
+
* eo_get_the_start($format, $event->ID,null,$event->occurrence_id)
|
50 |
+
* );
|
51 |
+
* endforeach;
|
52 |
+
* echo '</ul>';
|
53 |
+
* endif;
|
54 |
+
* ?>
|
55 |
+
*
|
56 |
+
* @since 1.0.0
|
57 |
+
* @uses get_posts()
|
58 |
+
* @package event-query-functions
|
59 |
+
* @link https://gist.github.com/4165380 List up-coming events
|
60 |
+
*@link https://gist.github.com/4190351 Adds up-coming events in the venue tooltip
|
61 |
+
*@link http://wp-event-organiser.com/documentation/relative-date-formats/ Using relative dates in event queries
|
62 |
+
*@link http://wp-event-organiser.com/forums/topic/retrieving-events-using-wp_query/ Retrieving events with `WP_Query`
|
63 |
+
* @param array $args Event query arguments.
|
64 |
+
* @return array An array of event (post) objects. Like get_posts. In case of failure it returns null.
|
65 |
+
*/
|
66 |
+
function eo_get_events($args=array()){
|
67 |
+
|
68 |
+
//In case an empty string is passed
|
69 |
+
if(empty($args))
|
70 |
+
$args = array();
|
71 |
+
|
72 |
+
//These are preset to ensure the plugin functions properly
|
73 |
+
$required = array('post_type'=> 'event','suppress_filters'=>false);
|
74 |
+
|
75 |
+
//These are the defaults
|
76 |
+
$defaults = array(
|
77 |
+
'numberposts'=>-1,
|
78 |
+
'orderby'=> 'eventstart',
|
79 |
+
'order'=> 'ASC',
|
80 |
+
'showrepeats'=>1,
|
81 |
+
'group_events_by'=>'',
|
82 |
+
'showpastevents'=>true);
|
83 |
+
|
84 |
+
//Construct the query array
|
85 |
+
$query_array = array_merge($defaults,$args,$required);
|
86 |
+
|
87 |
+
if(!empty($query_array['venue'])){
|
88 |
+
$query_array['event-venue'] = $query_array['venue'];
|
89 |
+
unset($query_array['venue']);
|
90 |
+
}
|
91 |
+
|
92 |
+
//Ensure all date queries are yyyy-mm-dd format. Process relative strings ('today','tomorrow','+1 week')
|
93 |
+
$dates = array('ondate','event_start_after','event_start_before','event_end_before','event_end_after');
|
94 |
+
foreach($dates as $prop):
|
95 |
+
if(!empty($query_array[$prop]))
|
96 |
+
$query_array[$prop] = eo_format_date($query_array[$prop],'Y-m-d');
|
97 |
+
endforeach;
|
98 |
+
|
99 |
+
//Make sure 'false' is passed as integer 0
|
100 |
+
if(strtolower($query_array['showpastevents'])==='false') $query_array['showpastevents']=0;
|
101 |
+
|
102 |
+
if($query_array){
|
103 |
+
$events=get_posts($query_array);
|
104 |
+
return $events;
|
105 |
+
}
|
106 |
+
|
107 |
+
return null;
|
108 |
+
}
|
109 |
+
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Retrieve a row object from events table of the event by ID of the event
|
113 |
+
* @access private
|
114 |
+
*@ignore
|
115 |
+
* @since 1.0
|
116 |
+
*
|
117 |
+
* @param int $post_id Post ID of the event.
|
118 |
+
* @param int $deprecated The occurrence number. Deprecated use $occurrence_id
|
119 |
+
* @param int $occurrence_id The occurrence ID
|
120 |
+
* @return row object of event's row in Events table
|
121 |
+
*/
|
122 |
+
function eo_get_by_postid($post_id,$deprecated=0, $occurrence_id=0){
|
123 |
+
global $wpdb;
|
124 |
+
|
125 |
+
if( !empty($occurrence_id) ){
|
126 |
+
$column = 'event_id';
|
127 |
+
$value = $occurrence_id;
|
128 |
+
}else{
|
129 |
+
//Backwards compatibility!
|
130 |
+
$column = 'event_occurrence';
|
131 |
+
$value = $deprecated;
|
132 |
+
}
|
133 |
+
|
134 |
+
$querystr = $wpdb->prepare("
|
135 |
+
SELECT StartDate,EndDate,StartTime,FinishTime FROM {$wpdb->eo_events}
|
136 |
+
WHERE {$wpdb->eo_events}.post_id=%d
|
137 |
+
AND ({$wpdb->eo_events}.{$column}=%d)
|
138 |
+
LIMIT 1",$post_id,$value);
|
139 |
+
|
140 |
+
return $wpdb->get_row($querystr);
|
141 |
+
}
|
142 |
+
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Returns the start date of occurrence of event.
|
146 |
+
* If used inside the loop, with no id no set, returns start date of
|
147 |
+
* current event occurrence.
|
148 |
+
* @since 1.0.0
|
149 |
+
* @package event-date-functions
|
150 |
+
*
|
151 |
+
* @param string $format String of format as accepted by PHP date
|
152 |
+
* @param int $post_id Post ID of the event
|
153 |
+
* @param int $deprecated The occurrence number. Deprecated. Use $occurrence_id
|
154 |
+
* @param int $occurrence_id The occurrence ID
|
155 |
+
* @return string the start date formated to given format, as accepted by PHP date
|
156 |
+
*/
|
157 |
+
function eo_get_the_start($format='d-m-Y',$post_id=0,$deprecated=0, $occurrence_id=0){
|
158 |
+
global $post;
|
159 |
+
$event = $post;
|
160 |
+
|
161 |
+
if( !empty($deprecated) ){
|
162 |
+
_deprecated_argument( __FUNCTION__, '1.5.6', 'Third argument is depreciated. Please use a fourth argument - occurrence ID. Available from $post->occurrence_id' );
|
163 |
+
|
164 |
+
//Backwards compatiblity
|
165 |
+
if( !empty($post_id) ) $event = eo_get_by_postid($post_id,$deprecated, $occurrence_id);
|
166 |
+
|
167 |
+
if(empty($event))
|
168 |
+
return false;
|
169 |
+
|
170 |
+
$date = trim($event->StartDate).' '.trim($event->StartTime);
|
171 |
+
|
172 |
+
if(empty($date)||$date==" ")
|
173 |
+
return false;
|
174 |
+
|
175 |
+
return eo_format_date($date,$format);
|
176 |
+
}
|
177 |
+
|
178 |
+
$occurrence_id = (int) ( empty($occurrence_id) && isset($event->occurrence_id) ? $event->occurrence_id : $occurrence_id);
|
179 |
+
|
180 |
+
$occurrences = eo_get_the_occurrences_of($post_id);
|
181 |
+
|
182 |
+
if( !$occurrences || !isset($occurrences[$occurrence_id]) )
|
183 |
+
return false;
|
184 |
+
|
185 |
+
$start = $occurrences[$occurrence_id]['start'];
|
186 |
+
|
187 |
+
return apply_filters('eventorganiser_get_the_start', eo_format_datetime( $start, $format ), $start, $format, $post_id, $occurrence_id );
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Returns the start date of occurrence of event an event, like {@see `eo_get_the_start()`}.
|
192 |
+
* The difference is that the occurrence ID *must* be supplied (event ID is not).
|
193 |
+
* @since 1.6
|
194 |
+
* @ignore
|
195 |
+
*
|
196 |
+
* @param string $format String of format as accepted by PHP date
|
197 |
+
* @param int $occurrence_id The occurrence ID
|
198 |
+
* @return string the start date formated to given format, as accepted by PHP date
|
199 |
+
*/
|
200 |
+
function eo_get_the_occurrence_start($format='d-m-Y',$occurrence_id){
|
201 |
+
global $wpdb;
|
202 |
+
|
203 |
+
$querystr = $wpdb->prepare("
|
204 |
+
SELECT StartDate,StartTime FROM {$wpdb->eo_events}
|
205 |
+
WHERE {$wpdb->eo_events}.event_id=%d
|
206 |
+
LIMIT 1",$occurrence_id);
|
207 |
+
|
208 |
+
$occurrence = $wpdb->get_row($querystr);
|
209 |
+
|
210 |
+
if( !$occurrence )
|
211 |
+
return false;
|
212 |
+
|
213 |
+
$date = trim($occurrence->StartDate).' '.trim($occurrence->StartTime);
|
214 |
+
|
215 |
+
if(empty($date)||$date==" ")
|
216 |
+
return false;
|
217 |
+
|
218 |
+
return eo_format_date($date,$format);
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Echos the start date of occurence of event
|
223 |
+
* @since 1.0.0
|
224 |
+
* @uses eo_get_the_start()
|
225 |
+
* @package event-date-functions
|
226 |
+
*
|
227 |
+
* @param string $format String of format as accepted by PHP date
|
228 |
+
* @param int $post_id Post ID of the event
|
229 |
+
* @param int $deprecated The occurrence number. Deprecated. Use $occurrence_id instead
|
230 |
+
* @param int $occurrence_id The occurrence ID
|
231 |
+
*/
|
232 |
+
function eo_the_start($format='d-m-Y',$post_id=0,$deprecated=0,$occurrence_id=0){
|
233 |
+
echo eo_get_the_start($format,$post_id,$deprecated, $occurrence_id);
|
234 |
+
}
|
235 |
+
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Returns the end date of occurrence of event.
|
239 |
+
* If used inside the loop, with no id no set, returns end date of
|
240 |
+
* current event occurrence.
|
241 |
+
* @since 1.0.0
|
242 |
+
* @package event-date-functions
|
243 |
+
*
|
244 |
+
* @param string $format String of format as accepted by PHP date
|
245 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
246 |
+
* @param int $deprecated The occurrence number. Deprecated. Use $occurrence_id instead
|
247 |
+
* @param int $occurrence_id The occurrence ID
|
248 |
+
* @return string the end date formated to given format, as accepted by PHP date
|
249 |
+
*/
|
250 |
+
function eo_get_the_end($format='d-m-Y',$post_id=0,$deprecated=0, $occurrence_id=0){
|
251 |
+
global $post;
|
252 |
+
$event = $post;
|
253 |
+
|
254 |
+
if( !empty($deprecated) ){
|
255 |
+
_deprecated_argument( __FUNCTION__, '1.5.6', 'Third argument is depreciated. Please use a fourth argument - occurrence ID. Available from $post->occurrence_id' );
|
256 |
+
|
257 |
+
//Backwards compatiblity
|
258 |
+
if( !empty($post_id) ) $event = eo_get_by_postid($post_id,$deprecated, $occurrence_id);
|
259 |
+
|
260 |
+
if(empty($event))
|
261 |
+
return false;
|
262 |
+
|
263 |
+
$date = trim($event->EndDate).' '.trim($event->FinishTime);
|
264 |
+
|
265 |
+
if(empty($date)||$date==" ")
|
266 |
+
return false;
|
267 |
+
|
268 |
+
return eo_format_date($date,$format);
|
269 |
+
}
|
270 |
+
$occurrence_id = (int) ( empty($occurrence_id) && isset($event->occurrence_id) ? $event->occurrence_id : $occurrence_id);
|
271 |
+
|
272 |
+
$occurrences = eo_get_the_occurrences_of($post_id);
|
273 |
+
|
274 |
+
if( !$occurrences || !isset($occurrences[$occurrence_id]) )
|
275 |
+
return false;
|
276 |
+
|
277 |
+
$end = $occurrences[$occurrence_id]['end'];
|
278 |
+
|
279 |
+
return apply_filters('eventorganiser_get_the_end', eo_format_datetime( $end, $format ), $end, $format, $post_id, $occurrence_id );
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Echos the end date of occurence of event
|
284 |
+
* @since 1.0.0
|
285 |
+
* @uses eo_get_the_end()
|
286 |
+
* @package event-date-functions
|
287 |
+
*
|
288 |
+
* @param string $format String of format as accepted by PHP date
|
289 |
+
* @param int $post_id Post ID of the event
|
290 |
+
* @param int $occurrence The occurrence number. Deprecated. Use $occurrence_id instead
|
291 |
+
* @param int $occurrence_id The occurrence ID
|
292 |
+
*/
|
293 |
+
function eo_the_end($format='d-m-Y',$post_id=0,$occurrence=0, $occurrence_id=0){
|
294 |
+
echo eo_get_the_end($format,$post_id,$occurrence, $occurrence_id);
|
295 |
+
}
|
296 |
+
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Gets the formated date of next occurrence of an event
|
300 |
+
* @since 1.0.0
|
301 |
+
* @package event-date-functions
|
302 |
+
*
|
303 |
+
* @param string $format The format to use, using PHP Date format
|
304 |
+
* @param int $post_id The event (post) ID,
|
305 |
+
* @return string The formatted date or false if no date exists
|
306 |
+
*/
|
307 |
+
function eo_get_next_occurrence($format='d-m-Y',$post_id=0){
|
308 |
+
$next_occurrence = eo_get_next_occurrence_of($post_id);
|
309 |
+
|
310 |
+
if( !$next_occurrence )
|
311 |
+
return false;
|
312 |
+
|
313 |
+
$next = $next_occurrence['start'];
|
314 |
+
return apply_filters('eventorganiser_get_next_occurrence', eo_format_datetime( $next, $format ), $next, $format, $post_id );
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Returns an array of datetimes (start and end) corresponding to the next occurrence of an event
|
319 |
+
* {@see `eo_get_next_occurrence()`} on the other hand returns a formated datetime of the start date.
|
320 |
+
* To get the current occurrence{@see `eo_get_current_occurrence_of()`}
|
321 |
+
*
|
322 |
+
* @package event-date-functions
|
323 |
+
* @since 1.6
|
324 |
+
*
|
325 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
326 |
+
* @return array Array with keys 'start' and 'end', with corresponding datetime objects
|
327 |
+
*/
|
328 |
+
function eo_get_next_occurrence_of($post_id=0){
|
329 |
+
global $wpdb;
|
330 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
331 |
+
|
332 |
+
//Retrieve the blog's local time and create the date part
|
333 |
+
$tz = eo_get_blog_timezone();
|
334 |
+
$blog_now = new DateTime(null, $tz );
|
335 |
+
$now_date =$blog_now->format('Y-m-d');
|
336 |
+
$now_time =$blog_now->format('H:i:s');
|
337 |
+
|
338 |
+
$nextoccurrence = $wpdb->get_row($wpdb->prepare("
|
339 |
+
SELECT StartDate, StartTime, EndDate, FinishTime
|
340 |
+
FROM {$wpdb->eo_events}
|
341 |
+
WHERE {$wpdb->eo_events}.post_id=%d
|
342 |
+
AND (
|
343 |
+
({$wpdb->eo_events}.StartDate > %s) OR
|
344 |
+
({$wpdb->eo_events}.StartDate = %s AND {$wpdb->eo_events}.StartTime >= %s))
|
345 |
+
ORDER BY {$wpdb->eo_events}.StartDate ASC
|
346 |
+
LIMIT 1",$post_id,$now_date,$now_date,$now_time));
|
347 |
+
|
348 |
+
if( ! $nextoccurrence )
|
349 |
+
return false;
|
350 |
+
|
351 |
+
$start = new DateTime($nextoccurrence->StartDate.' '.$nextoccurrence->StartTime, $tz);
|
352 |
+
$end = new DateTime($nextoccurrence->EndDate.' '.$nextoccurrence->FinishTime, $tz);
|
353 |
+
|
354 |
+
return compact('start','end');
|
355 |
+
}
|
356 |
+
|
357 |
+
|
358 |
+
/**
|
359 |
+
* Prints the formated date of next occurrence of an event
|
360 |
+
* @since 1.0.0
|
361 |
+
* @uses eo_get_next_occurence()
|
362 |
+
* @package event-date-functions
|
363 |
+
*
|
364 |
+
* @param string $format The format to use, using PHP Date format
|
365 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
366 |
+
*/
|
367 |
+
function eo_next_occurence($format='',$post_id=0){
|
368 |
+
echo eo_get_next_occurence($format,$post_id);
|
369 |
+
}
|
370 |
+
|
371 |
+
/**
|
372 |
+
* Returns an array of datetimes (start and end) corresponding to the current occurrence of an event.
|
373 |
+
* If the event has multiple overlapping occurrences currently running, returns the one with the latest start date.
|
374 |
+
* To get the next occurrence{@see `eo_get_next_occurrence_of()`}
|
375 |
+
*
|
376 |
+
* @since 1.7
|
377 |
+
* @package event-date-functions
|
378 |
+
*
|
379 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
380 |
+
* @return array Array with keys 'start' and 'end', with corresponding datetime objects
|
381 |
+
*/
|
382 |
+
function eo_get_current_occurrence_of($post_id=0){
|
383 |
+
global $wpdb;
|
384 |
+
|
385 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
386 |
+
|
387 |
+
//Retrieve the blog's local time and create the date part
|
388 |
+
$tz = eo_get_blog_timezone();
|
389 |
+
$blog_now = new DateTime(null, $tz );
|
390 |
+
$now_date =$blog_now->format('Y-m-d');
|
391 |
+
$now_time =$blog_now->format('H:i:s');
|
392 |
+
|
393 |
+
//Get the current occurrence. May be multiple (overlapping) occurrences. Pick the latest.
|
394 |
+
$current_occurrence = $wpdb->get_row($wpdb->prepare("
|
395 |
+
SELECT StartDate, StartTime, EndDate, FinishTime
|
396 |
+
FROM {$wpdb->eo_events}
|
397 |
+
WHERE {$wpdb->eo_events}.post_id=%d
|
398 |
+
AND (
|
399 |
+
({$wpdb->eo_events}.StartDate < %s) OR
|
400 |
+
({$wpdb->eo_events}.StartDate = %s AND {$wpdb->eo_events}.StartTime <= %s)
|
401 |
+
)AND(
|
402 |
+
({$wpdb->eo_events}.EndDate > %s) OR
|
403 |
+
({$wpdb->eo_events}.EndDate = %s AND {$wpdb->eo_events}.EndDate >= %s)
|
404 |
+
)
|
405 |
+
ORDER BY {$wpdb->eo_events}.StartDate DESC
|
406 |
+
LIMIT 1",$post_id,$now_date,$now_date,$now_time, $now_date,$now_date,$now_time));
|
407 |
+
|
408 |
+
if( ! $current_occurrence )
|
409 |
+
return false;
|
410 |
+
|
411 |
+
$start = new DateTime($current_occurrence->StartDate.' '.$current_occurrence->StartTime, $tz);
|
412 |
+
$end = new DateTime($current_occurrence->EndDate.' '.$current_occurrence->FinishTime, $tz);
|
413 |
+
|
414 |
+
return compact('start','end');
|
415 |
+
}
|
416 |
+
|
417 |
+
|
418 |
+
/**
|
419 |
+
* Return true is the event is an all day event.
|
420 |
+
* @since 1.2
|
421 |
+
*
|
422 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
423 |
+
* @return bool True if event runs all day, or false otherwise
|
424 |
+
*/
|
425 |
+
function eo_is_all_day($post_id=0){
|
426 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
427 |
+
|
428 |
+
if( empty($post_id) )
|
429 |
+
return false;
|
430 |
+
|
431 |
+
$schedule = eo_get_event_schedule($post_id);
|
432 |
+
|
433 |
+
return (bool) $schedule['all_day'];
|
434 |
+
}
|
435 |
+
|
436 |
+
/**
|
437 |
+
* Returns the formated date of first occurrence of an event
|
438 |
+
* @since 1.0.0
|
439 |
+
* @package event-date-functions
|
440 |
+
*
|
441 |
+
* @param string $format the format to use, using PHP Date format
|
442 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
443 |
+
* @return string The formatted date
|
444 |
+
*/
|
445 |
+
function eo_get_schedule_start($format='d-m-Y',$post_id=0){
|
446 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
447 |
+
$schedule = eo_get_event_schedule($post_id);
|
448 |
+
$schedule_start = $schedule['schedule_start'];
|
449 |
+
return apply_filters('eventorganiser_get_schedule_start', eo_format_datetime( $schedule_start, $format ), $schedule_start, $format, $post_id );
|
450 |
+
}
|
451 |
+
|
452 |
+
/**
|
453 |
+
* Prints the formated date of first occurrence of an event
|
454 |
+
* @since 1.0.0
|
455 |
+
* @uses eo_get_schedule_start()
|
456 |
+
* @package event-date-functions
|
457 |
+
*
|
458 |
+
* @param string $format The format to use, using PHP Date format
|
459 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
460 |
+
*/
|
461 |
+
function eo_schedule_start($format='d-m-Y',$post_id=0){
|
462 |
+
echo eo_get_schedule_start($format,$post_id);
|
463 |
+
}
|
464 |
+
|
465 |
+
|
466 |
+
/**
|
467 |
+
* Returns the formated date of the last occurrence of an event
|
468 |
+
* @since 1.4.0
|
469 |
+
* @package event-date-functions
|
470 |
+
*
|
471 |
+
* @param string $format The format to use, using PHP Date format
|
472 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
473 |
+
* @return string The formatted date
|
474 |
+
*/
|
475 |
+
function eo_get_schedule_last($format='d-m-Y',$post_id=0){
|
476 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
477 |
+
$schedule = eo_get_event_schedule($post_id);
|
478 |
+
$schedule_last = $schedule['schedule_last'];
|
479 |
+
return apply_filters('eventorganiser_get_schedule_last', eo_format_datetime( $schedule_last, $format ), $schedule_last, $format, $post_id );
|
480 |
+
}
|
481 |
+
|
482 |
+
/**
|
483 |
+
* Prints the formated date of the last occurrence of an event
|
484 |
+
* @since 1.4.0
|
485 |
+
* @uses eo_get_schedule_last()
|
486 |
+
* @package event-date-functions
|
487 |
+
*
|
488 |
+
* @param string $format The format to use, using PHP Date format
|
489 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
490 |
+
* @return string The formatted date
|
491 |
+
*/
|
492 |
+
function eo_schedule_last($format='d-m-Y',$post_id=0){
|
493 |
+
echo eo_get_schedule_last($format,$post_id);
|
494 |
+
}
|
495 |
+
|
496 |
+
|
497 |
+
/**
|
498 |
+
* Returns true if event reoccurs or false if it is a one time event.
|
499 |
+
* @since 1.0.0
|
500 |
+
*
|
501 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
502 |
+
* @return bool true if event a reoccurring event
|
503 |
+
*/
|
504 |
+
function eo_reoccurs($post_id=0){
|
505 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
506 |
+
|
507 |
+
if( empty($post_id) )
|
508 |
+
return false;
|
509 |
+
|
510 |
+
$schedule = eo_get_event_schedule($post_id);
|
511 |
+
|
512 |
+
return ($schedule['schedule'] != 'once');
|
513 |
+
}
|
514 |
+
|
515 |
+
|
516 |
+
/**
|
517 |
+
* Returns a summary of the events schedule.
|
518 |
+
* @since 1.0.0
|
519 |
+
* @ignore
|
520 |
+
*
|
521 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
522 |
+
* @return string A summary of the events schedule.
|
523 |
+
*/
|
524 |
+
function eo_get_schedule_summary($post_id=0){
|
525 |
+
global $post,$wp_locale;
|
526 |
+
|
527 |
+
$ical2day = array('SU'=> $wp_locale->weekday[0],'MO'=>$wp_locale->weekday[1],'TU'=>$wp_locale->weekday[2], 'WE'=>$wp_locale->weekday[3],
|
528 |
+
'TH'=>$wp_locale->weekday[4],'FR'=>$wp_locale->weekday[5],'SA'=>$wp_locale->weekday[6]);
|
529 |
+
|
530 |
+
$nth= array(__('last','eventorganiser'),'',__('first','eventorganiser'),__('second','eventorganiser'),__('third','eventorganiser'),__('fourth','eventorganiser'));
|
531 |
+
|
532 |
+
$reoccur = eo_get_event_schedule($post_id);
|
533 |
+
|
534 |
+
if(empty($reoccur))
|
535 |
+
return false;
|
536 |
+
|
537 |
+
$return='';
|
538 |
+
|
539 |
+
if($reoccur['schedule']=='once'){
|
540 |
+
$return = __('one time only','eventorganiser');
|
541 |
+
|
542 |
+
}elseif($reoccur['schedule']=='custom'){
|
543 |
+
$return = __('custom reoccurrence','eventorganiser');
|
544 |
+
|
545 |
+
}else{
|
546 |
+
switch($reoccur['schedule']):
|
547 |
+
|
548 |
+
case 'daily':
|
549 |
+
if($reoccur['frequency']==1):
|
550 |
+
$return .=__('every day','eventorganiser');
|
551 |
+
else:
|
552 |
+
$return .=sprintf(__('every %d days','eventorganiser'),$reoccur['frequency']);
|
553 |
+
endif;
|
554 |
+
break;
|
555 |
+
|
556 |
+
case 'weekly':
|
557 |
+
if($reoccur['frequency']==1):
|
558 |
+
$return .=__('every week on','eventorganiser');
|
559 |
+
else:
|
560 |
+
$return .=sprintf(__('every %d weeks on','eventorganiser'),$reoccur['frequency']);
|
561 |
+
endif;
|
562 |
+
|
563 |
+
foreach( $reoccur['schedule_meta'] as $ical_day){
|
564 |
+
$days[] = $ical2day[$ical_day];
|
565 |
+
}
|
566 |
+
$return .=' '.implode(', ',$days);
|
567 |
+
break;
|
568 |
+
|
569 |
+
case 'monthly':
|
570 |
+
if($reoccur['frequency']==1):
|
571 |
+
$return .=__('every month on the','eventorganiser');
|
572 |
+
else:
|
573 |
+
$return .=sprintf(__('every %d months on the','eventorganiser'),$reoccur['frequency']);
|
574 |
+
endif;
|
575 |
+
$return .= ' ';
|
576 |
+
$bymonthday =preg_match('/^BYMONTHDAY=(\d{1,2})/' ,$reoccur['schedule_meta'],$matches);
|
577 |
+
|
578 |
+
if( $bymonthday ){
|
579 |
+
$d = intval($matches[1]);
|
580 |
+
$m =intval($reoccur['schedule_start']->format('n'));
|
581 |
+
$y =intval($reoccur['schedule_start']->format('Y'));
|
582 |
+
$reoccur['start']->setDate($y,$m,$d);
|
583 |
+
$return .= $reoccur['schedule_start']->format('jS');
|
584 |
+
|
585 |
+
}elseif($reoccur['schedule_meta']=='date'){
|
586 |
+
$return .= $reoccur['schedule_start']->format('jS');
|
587 |
+
|
588 |
+
}else{
|
589 |
+
$byday = preg_match('/^BYDAY=(-?\d{1,2})([a-zA-Z]{2})/' ,$reoccur['schedule_meta'],$matches);
|
590 |
+
if($byday):
|
591 |
+
$n=intval($matches[1])+1;
|
592 |
+
$return .=$nth[$n].' '.$ical2day[$matches[2]];
|
593 |
+
else:
|
594 |
+
$bydayOLD = preg_match('/^(-?\d{1,2})([a-zA-Z]{2})/' ,$reoccur['schedule_meta'],$matchesOLD);
|
595 |
+
$n=intval($matchesOLD[1])+1;
|
596 |
+
$return .=$nth[$n].' '.$ical2day[$matchesOLD[2]];
|
597 |
+
endif;
|
598 |
+
}
|
599 |
+
break;
|
600 |
+
case 'yearly':
|
601 |
+
if($reoccur['frequency']==1):
|
602 |
+
$return .=__('every year','eventorganiser');
|
603 |
+
else:
|
604 |
+
$return .=sprintf(__('every %d years','eventorganiser'),$reoccur['frequency']);
|
605 |
+
endif;
|
606 |
+
break;
|
607 |
+
|
608 |
+
endswitch;
|
609 |
+
$return .= ' '.__('until','eventorganiser').' '. eo_format_datetime($reoccur['schedule_last'],'M, jS Y');
|
610 |
+
}
|
611 |
+
|
612 |
+
return $return;
|
613 |
+
}
|
614 |
+
|
615 |
+
/**
|
616 |
+
* Prints a summary of the events schedule.
|
617 |
+
* @since 1.0.0
|
618 |
+
* @uses eo_get_schedule_summary()
|
619 |
+
* @ignore
|
620 |
+
*
|
621 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
622 |
+
*/
|
623 |
+
function eo_display_reoccurence($post_id=0){
|
624 |
+
echo eo_get_schedule_summary($post_id);
|
625 |
+
}
|
626 |
+
|
627 |
+
/**
|
628 |
+
* Returns an array of occurrences. Each occurrence is an array with 'start' and 'end' key.
|
629 |
+
* Both of these hold a DateTime object (for the start and end of that occurrence respecitvely).
|
630 |
+
* @since 1.5
|
631 |
+
* @package event-date-functions
|
632 |
+
* @access private
|
633 |
+
* @ignore
|
634 |
+
*
|
635 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
636 |
+
* @return array Array of arrays of DateTime objects of the start and end date-times of occurences. False if none exist.
|
637 |
+
*/
|
638 |
+
function eo_get_the_future_occurrences_of( $post_id=0 ){
|
639 |
+
global $wpdb;
|
640 |
+
|
641 |
+
$today = new DateTime('now',eo_get_blog_timezone());
|
642 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
643 |
+
|
644 |
+
if(empty($post_id))
|
645 |
+
return false;
|
646 |
+
|
647 |
+
$results = $wpdb->get_results(
|
648 |
+
$wpdb->prepare(
|
649 |
+
"SELECT event_id, StartDate,StartTime,EndDate,FinishTime FROM {$wpdb->eo_events}
|
650 |
+
WHERE {$wpdb->eo_events}.post_id=%d AND ( StartDate > %s OR ( StartDate = %s AND StartTime >= %s) ) ORDER BY StartDate ASC",
|
651 |
+
$post_id,
|
652 |
+
$today->format('Y-m-d'),
|
653 |
+
$today->format('Y-m-d'),
|
654 |
+
$today->format('H:i:s')
|
655 |
+
)
|
656 |
+
);
|
657 |
+
|
658 |
+
if( !$results )
|
659 |
+
return false;
|
660 |
+
|
661 |
+
$occurrences=array();
|
662 |
+
foreach($results as $row):
|
663 |
+
$occurrences[$row->event_id] = array(
|
664 |
+
'start' => new DateTime($row->StartDate.' '.$row->StartTime, eo_get_blog_timezone()),
|
665 |
+
'end' => new DateTime($row->EndDate.' '.$row->FinishTime, eo_get_blog_timezone())
|
666 |
+
);
|
667 |
+
endforeach;
|
668 |
+
|
669 |
+
return apply_filters( 'eventorganiser_get_the_future_occurrences_of', $occurrences, $post_id );
|
670 |
+
}
|
671 |
+
/**
|
672 |
+
* Returns an array of occurrences. Each occurrence is an array with 'start' and 'end' key.
|
673 |
+
* Both of these hold a DateTime object (for the start and end of that occurrence respecitvely).
|
674 |
+
* @since 1.5
|
675 |
+
* @package event-date-functions
|
676 |
+
*
|
677 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
678 |
+
* @return array Array of arrays of DateTime objects of the start and end date-times of occurences. False if none exist.
|
679 |
+
*/
|
680 |
+
function eo_get_the_occurrences_of($post_id=0){
|
681 |
+
global $wpdb;
|
682 |
+
|
683 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
684 |
+
|
685 |
+
if(empty($post_id))
|
686 |
+
return false;
|
687 |
+
|
688 |
+
//Can't cache datetime objects before 5.3
|
689 |
+
//@see{http://wordpress.org/support/topic/warning-datetimeformat-functiondatetime-format?replies=7#post-3940247}
|
690 |
+
if( version_compare(PHP_VERSION, '5.3.0') >= 0 ){
|
691 |
+
$occurrences = wp_cache_get( 'eventorganiser_occurrences_'.$post_id );
|
692 |
+
}else{
|
693 |
+
$occurrences = false;
|
694 |
+
}
|
695 |
+
|
696 |
+
if( !$occurrences ){
|
697 |
+
|
698 |
+
$results = $wpdb->get_results($wpdb->prepare("
|
699 |
+
SELECT event_id, StartDate,StartTime,EndDate,FinishTime FROM {$wpdb->eo_events}
|
700 |
+
WHERE {$wpdb->eo_events}.post_id=%d ORDER BY StartDate ASC",$post_id));
|
701 |
+
|
702 |
+
if( !$results )
|
703 |
+
return false;
|
704 |
+
|
705 |
+
$occurrences=array();
|
706 |
+
foreach($results as $row):
|
707 |
+
$occurrences[$row->event_id] = array(
|
708 |
+
'start' => new DateTime($row->StartDate.' '.$row->StartTime, eo_get_blog_timezone()),
|
709 |
+
'end' => new DateTime($row->EndDate.' '.$row->FinishTime, eo_get_blog_timezone())
|
710 |
+
);
|
711 |
+
endforeach;
|
712 |
+
wp_cache_set( 'eventorganiser_occurrences_'.$post_id, $occurrences );
|
713 |
+
}
|
714 |
+
|
715 |
+
return apply_filters( 'eventorganiser_get_the_occurrences_of', $occurrences, $post_id );
|
716 |
+
}
|
717 |
+
|
718 |
+
/**
|
719 |
+
* Returns the colour of a category
|
720 |
+
* @ignore
|
721 |
+
* @access private
|
722 |
+
*/
|
723 |
+
function eo_get_category_color($term){
|
724 |
+
return eo_get_category_meta($term,'color');
|
725 |
+
}
|
726 |
+
|
727 |
+
/**
|
728 |
+
* Returns the colour of a category associated with the event.
|
729 |
+
* Applies the {@see `eventorganiser_event_color`} filter.
|
730 |
+
* @since 1.6
|
731 |
+
*
|
732 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
733 |
+
* @return string The colour of the category in HEX format
|
734 |
+
*/
|
735 |
+
function eo_get_event_color($post_id=0){
|
736 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
737 |
+
|
738 |
+
if( empty($post_id) )
|
739 |
+
return false;
|
740 |
+
|
741 |
+
$color = false;
|
742 |
+
|
743 |
+
$terms = get_the_terms($post_id, 'event-category');
|
744 |
+
if( $terms && !is_wp_error($terms) ){
|
745 |
+
foreach ($terms as $term):
|
746 |
+
if( ! empty($term->color) ){
|
747 |
+
$color_code = ltrim($term->color, '#');
|
748 |
+
if ( ctype_xdigit($color_code) && (strlen($color_code) == 6 || strlen($color_code) == 3)){
|
749 |
+
$color = '#'.$color_code;
|
750 |
+
break;
|
751 |
+
}
|
752 |
+
}
|
753 |
+
endforeach;
|
754 |
+
}
|
755 |
+
|
756 |
+
/**
|
757 |
+
* Filters the colour associated with an event
|
758 |
+
*@link http://wordpress.org/support/topic/plugin-event-organiser-color-code-for-venues-instead-of-categories
|
759 |
+
*@param string $color Event colour in HEX format
|
760 |
+
*@param int $post_id The event (post) ID
|
761 |
+
*/
|
762 |
+
return apply_filters('eventorganiser_event_color',$color,$post_id);
|
763 |
+
}
|
764 |
+
|
765 |
+
/**
|
766 |
+
* Returns an array of classes associated with an event.
|
767 |
+
* Adds eo-event-venue-[venue slug] for the event's venue.
|
768 |
+
* Adds eo-event-cat-[category slug] for each event category it bleongs to.
|
769 |
+
* Adds eo-event-[future|past|running].
|
770 |
+
* Applies filter {@see `eventorganiser_event_classes`}
|
771 |
+
* @since 1.6
|
772 |
+
*
|
773 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
774 |
+
* @param int $occurrence_id The occurrence ID. Uses current event if empty.
|
775 |
+
* @return array Array of classes
|
776 |
+
*/
|
777 |
+
function eo_get_event_classes($post_id=0, $occurrence_id=0){
|
778 |
+
global $post;
|
779 |
+
|
780 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id );
|
781 |
+
$occurrence_id = (int) ( empty($occurrence_id) && isset($post->occurrence_id) ? $post->occurrence_id : $occurrence_id );
|
782 |
+
|
783 |
+
$event_classes = array();
|
784 |
+
|
785 |
+
//Add venue class
|
786 |
+
if( eo_get_venue_slug() )
|
787 |
+
$event_classes[] = 'eo-event-venue-'.eo_get_venue_slug();
|
788 |
+
|
789 |
+
//Add category classes
|
790 |
+
$cats= get_the_terms(get_the_ID(), 'event-category');
|
791 |
+
if( $cats && !is_wp_error($cats) ){
|
792 |
+
foreach ($cats as $cat)
|
793 |
+
$event_classes[] = 'eo-event-cat-'.$cat->slug;
|
794 |
+
}
|
795 |
+
|
796 |
+
//Add 'time' class
|
797 |
+
$start = eo_get_the_start(DATETIMEOBJ, $post_id, null, $occurrence_id);
|
798 |
+
$end= eo_get_the_end(DATETIMEOBJ, $post_id, null, $occurrence_id);
|
799 |
+
$now = new DateTime('now',eo_get_blog_timezone());
|
800 |
+
if( $start > $now ){
|
801 |
+
$event_classes[] = 'eo-event-future';
|
802 |
+
}elseif( $end < $now ){
|
803 |
+
$event_classes[] = 'eo-event-past';
|
804 |
+
}else{
|
805 |
+
$event_classes[] = 'eo-event-running';
|
806 |
+
}
|
807 |
+
|
808 |
+
$event_classes = array_unique($event_classes);
|
809 |
+
return apply_filters('eventorganiser_event_classes', $event_classes, $post_id, $occurrence_id);
|
810 |
+
}
|
811 |
+
|
812 |
+
|
813 |
+
/**
|
814 |
+
* Checks if the query is for an event taxonomy.
|
815 |
+
*
|
816 |
+
* When no $query is passed, acts as a simple wrapper for `is_tax()`.
|
817 |
+
* More generally acts as a wrapper for `$query->is_tax()`.
|
818 |
+
*
|
819 |
+
* @since 1.6
|
820 |
+
*
|
821 |
+
* @param $query - The query to check. If not passed, uses the global $wp_query;
|
822 |
+
* @return bool True if query is for any event taxonomy (e.g. 'event-venue', 'event-category', 'event-tag').
|
823 |
+
*/
|
824 |
+
function eo_is_event_taxonomy( $query = false ){
|
825 |
+
$event_tax = get_object_taxonomies( 'event' );
|
826 |
+
|
827 |
+
//Handle post tags
|
828 |
+
if( in_array( 'post_tag', $event_tax ) ){
|
829 |
+
if( ( !$query && is_tag() ) || $query->is_tag() )
|
830 |
+
return true;
|
831 |
+
}
|
832 |
+
|
833 |
+
//Handle categories
|
834 |
+
if( in_array( 'category', $event_tax ) ){
|
835 |
+
if( ( !$query && is_category() ) || $query->is_category() )
|
836 |
+
return true;
|
837 |
+
}
|
838 |
+
|
839 |
+
if( !$query ){
|
840 |
+
return is_tax( $event_tax );
|
841 |
+
}else{
|
842 |
+
return $query->is_tax( $event_tax );
|
843 |
+
}
|
844 |
+
}
|
845 |
+
|
846 |
+
/**
|
847 |
+
* Retrieves the permalink for the ICAL event feed. A simple wrapper for `get_feed_link()`.
|
848 |
+
*
|
849 |
+
* Retrieve the permalink for the events feed. The returned link is the url with which visitors can subscribe
|
850 |
+
* to your events. Visiting the url directly will prompt a download an ICAL file of your events. The events feed
|
851 |
+
* includes only **public** events (draft, private and trashed events are not included).
|
852 |
+
*
|
853 |
+
* @since 1.6
|
854 |
+
*
|
855 |
+
* @return string The link to the ICAL event feed..
|
856 |
+
*/
|
857 |
+
function eo_get_events_feed(){
|
858 |
+
return get_feed_link('eo-events');
|
859 |
+
}
|
860 |
+
|
861 |
+
|
862 |
+
/**
|
863 |
+
* Returns a the url which adds a particular occurrence of an event to
|
864 |
+
* a google calendar. Must be used inside the loop
|
865 |
+
*
|
866 |
+
*Returns an url which adds a particular occurrence of an event to a Google calendar. This function can only be used inside the loop.
|
867 |
+
* An entire series cannot be added to a Google calendar - however users can subscribe to your events. Please note that, unlike
|
868 |
+
* subscribing to events, changes made to an event will not be reflected on an event added to the Google calendar.
|
869 |
+
*
|
870 |
+
* @since 1.2.0
|
871 |
+
*
|
872 |
+
* @return string Url which adds event to a google calendar
|
873 |
+
*/
|
874 |
+
function eo_get_the_GoogleLink(){
|
875 |
+
global $post;
|
876 |
+
setup_postdata($post);
|
877 |
+
|
878 |
+
if(empty($post)|| get_post_type($post )!='event'){
|
879 |
+
wp_reset_postdata();
|
880 |
+
return false;
|
881 |
+
}
|
882 |
+
|
883 |
+
$start = eo_get_the_start(DATETIMEOBJ);
|
884 |
+
$end = eo_get_the_start(DATETIMEOBJ);
|
885 |
+
|
886 |
+
if(eo_is_all_day()):
|
887 |
+
$end->modify('+1 second');
|
888 |
+
$format = 'Ymd';
|
889 |
+
else:
|
890 |
+
$format = 'Ymd\THis\Z';
|
891 |
+
$start->setTimezone( new DateTimeZone('UTC') );
|
892 |
+
$end->setTimezone( new DateTimeZone('UTC') );
|
893 |
+
endif;
|
894 |
+
|
895 |
+
$excerpt = apply_filters('the_excerpt_rss', get_the_excerpt());
|
896 |
+
|
897 |
+
$url = add_query_arg(array(
|
898 |
+
'text'=>get_the_title(),
|
899 |
+
'dates'=>$start->format($format).'/'.$end->format($format),
|
900 |
+
'trp'=>false,
|
901 |
+
'details'=> esc_html($excerpt),
|
902 |
+
'sprop'=>get_bloginfo('name')
|
903 |
+
),'http://www.google.com/calendar/event?action=TEMPLATE');
|
904 |
+
|
905 |
+
$venue_id = eo_get_venue();
|
906 |
+
if($venue_id):
|
907 |
+
$venue =eo_get_venue_name($venue_id).", ".implode(', ',eo_get_venue_address($venue_id));
|
908 |
+
$url = add_query_arg('location',$venue, $url);
|
909 |
+
endif;
|
910 |
+
|
911 |
+
wp_reset_postdata();
|
912 |
+
return $url;
|
913 |
+
}
|
914 |
+
|
915 |
+
/**
|
916 |
+
* @ignore
|
917 |
+
*/
|
918 |
+
function eo_has_event_started($id='',$occurrence){
|
919 |
+
$tz = eo_get_blog_timezone();
|
920 |
+
$start = new DateTime(eo_get_the_start('d-m-Y H:i',$id,$occurrence), $tz);
|
921 |
+
$now = new DateTime('now', $tz);
|
922 |
+
|
923 |
+
return ($start <= $now );
|
924 |
+
}
|
925 |
+
|
926 |
+
/**
|
927 |
+
* @ignore
|
928 |
+
*/
|
929 |
+
function eo_has_event_finished($id='',$occurrence=0){
|
930 |
+
$tz = eo_get_blog_timezone();
|
931 |
+
$end = new DateTime(eo_get_the_end('d-m-Y H:i',$id,$occurrence), $tz);
|
932 |
+
$now = new DateTime('now', $tz);
|
933 |
+
|
934 |
+
return ($end <= $now );
|
935 |
+
}
|
936 |
+
|
937 |
+
/**
|
938 |
+
* @ignore
|
939 |
+
*/
|
940 |
+
function eo_event_category_dropdown( $args = '' ) {
|
941 |
+
$defaults = array(
|
942 |
+
'show_option_all' => '',
|
943 |
+
'echo' => 1,
|
944 |
+
'selected' => 0,
|
945 |
+
'name' => 'event-category',
|
946 |
+
'id' => '',
|
947 |
+
'class' => 'postform event-organiser event-category-dropdown event-dropdown',
|
948 |
+
'tab_index' => 0,
|
949 |
+
);
|
950 |
+
|
951 |
+
$defaults['selected'] = (is_tax('event-category') ? get_query_var('event-category') : 0);
|
952 |
+
$r = wp_parse_args( $args, $defaults );
|
953 |
+
$r['taxonomy']='event-category';
|
954 |
+
extract( $r );
|
955 |
+
|
956 |
+
$tab_index_attribute = '';
|
957 |
+
if ( (int) $tab_index > 0 )
|
958 |
+
$tab_index_attribute = " tabindex=\"$tab_index\"";
|
959 |
+
|
960 |
+
$categories = get_terms($taxonomy, $r );
|
961 |
+
$name = esc_attr( $name );
|
962 |
+
$class = esc_attr( $class );
|
963 |
+
$id = $id ? esc_attr( $id ) : $name;
|
964 |
+
|
965 |
+
$output = "<select style='width:150px' name='$name' id='$id' class='$class' $tab_index_attribute>\n";
|
966 |
+
|
967 |
+
if ( $show_option_all ) {
|
968 |
+
$output .= '<option '.selected($selected,0,false).' value="0">'.$show_option_all.'</option>';
|
969 |
+
}
|
970 |
+
|
971 |
+
if ( ! empty( $categories ) ) {
|
972 |
+
foreach ($categories as $term):
|
973 |
+
$output .= '<option value="'.$term->slug.'"'.selected($selected,$term->slug,false).'>'.$term->name.'</option>';
|
974 |
+
endforeach;
|
975 |
+
}
|
976 |
+
$output .= "</select>\n";
|
977 |
+
|
978 |
+
if ( $echo )
|
979 |
+
echo $output;
|
980 |
+
|
981 |
+
return $output;
|
982 |
+
}
|
983 |
+
|
984 |
+
/**
|
985 |
+
* Returns HTML mark-up for the fullCalendar
|
986 |
+
*
|
987 |
+
* It also (indirectly) triggers the enquing of the necessary scripts and styles. The `$args` array
|
988 |
+
* accepts exactly the same arguments as the shortcode, they are
|
989 |
+
*
|
990 |
+
* * **headerleft** (string) What appears on the left of the calendar header. Default 'title'.
|
991 |
+
* * **headercenter** (string) What appears on the left of the calendar header. Default ''.
|
992 |
+
* * **headerright** (string) What appears on the left of the calendar header. Default 'prev next today'.
|
993 |
+
* * **defaultview** (string) The view the calendar loads on. Default 'month',
|
994 |
+
* * **event_category** (string) Restrict calendar to specified category. Default '' (all categories)
|
995 |
+
* * **event_venue** (string) Restrict calendar to specified venue. Default '' (all venues)
|
996 |
+
* * **timeformat** (string) Time format for calendar. Default 'G:i'.
|
997 |
+
* * **axisformat** (string) Axis time format (for day/week views). WP's time format option.
|
998 |
+
* * **key** (bool) Whether to show a category key. Default false.
|
999 |
+
* * **tooltip** (bool) Whether to show a tooltips. Default true.
|
1000 |
+
* * **weekends** (bool) Whether to include weekends in the calendar. Default true.
|
1001 |
+
* * **mintime** (string) Earliest time to show on week/day views. Default '0',
|
1002 |
+
* * **maxtime** (string) Latest time to show on week/day views. Default '24',
|
1003 |
+
* * **alldayslot** (bool) Whether to include an all day slot (week / day views) in the calendar. Default true.
|
1004 |
+
* * **alldaytext** (string) Text to display in all day slot. Default 'All Day'.
|
1005 |
+
* * **columnformatmonth** (string) Dateformat for month columns. Default 'D'.
|
1006 |
+
* * **columnformatweek** (string) Dateformat for month columns. Default 'D n/j'.
|
1007 |
+
* * **columnformatday** (string) Dateformat for month columns. Default 'l n/j',
|
1008 |
+
* * **year** The year the calendar should start on (e.g. 2013)
|
1009 |
+
* * **month** The month the calendar should start on (1=Jan, 12=Dec)
|
1010 |
+
* * **date** The calendar the date should start on
|
1011 |
+
*
|
1012 |
+
* @link http://arshaw.com/fullcalendar/ The fullCalendar (jQuery plug-in)
|
1013 |
+
* @link https://github.com/stephenharris/fullcalendar Event Organiser version of fullCalendar
|
1014 |
+
* @since 1.7
|
1015 |
+
* @param array $args An array of attributes for the calendar
|
1016 |
+
* @return string HTML mark-up.
|
1017 |
+
*/
|
1018 |
+
function eo_get_event_fullcalendar( $args ){
|
1019 |
+
|
1020 |
+
$defaults = array(
|
1021 |
+
'headerleft'=>'title', 'headercenter'=>'', 'headerright'=>'prev next today', 'defaultview'=>'month',
|
1022 |
+
'event_category'=>'', 'event_venue'=>'', 'timeformat'=>'G:i', 'axisformat'=>get_option('time_format'), 'key'=>false,
|
1023 |
+
'tooltip'=>true, 'weekends'=>true, 'mintime'=>'0', 'maxtime'=>'24', 'alldayslot'=>true,
|
1024 |
+
'alldaytext'=>__('All Day','eventorganiser'), 'columnformatmonth'=>'D', 'columnformatweek'=>'D n/j', 'columnformatday'=>'l n/j',
|
1025 |
+
'titleformatmonth' => 'F Y', 'titleformatweek' => "M j[ Y]{ '—'[ M] j Y}", 'titleformatday' => 'l, M j, Y',
|
1026 |
+
'year' => false, 'month' => false, 'date' => false,
|
1027 |
+
);
|
1028 |
+
$args = shortcode_atts( $defaults, $args );
|
1029 |
+
$key = $args['key'];
|
1030 |
+
unset($args['key']);
|
1031 |
+
|
1032 |
+
//Convert php time format into xDate time format
|
1033 |
+
$date_attributes = array( 'timeformat', 'axisformat', 'columnformatday', 'columnformatweek', 'columnformatmonth',
|
1034 |
+
'titleformatmonth', 'titleformatday', 'titleformatweek' );
|
1035 |
+
$args['timeformatphp'] = $args['timeformat'];
|
1036 |
+
foreach ( $date_attributes as $date_attribute ){
|
1037 |
+
$args[$date_attribute] = str_replace( '((', '[', $args[$date_attribute] );
|
1038 |
+
$args[$date_attribute] = str_replace( '))', ']', $args[$date_attribute] );
|
1039 |
+
$args[$date_attribute.'php'] = $args[$date_attribute];
|
1040 |
+
$args[$date_attribute] = eventorganiser_php2xdate( $args[$date_attribute] );
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
//Month expects 0-11, we ask for 1-12.
|
1044 |
+
$args['month'] = ( $args['month'] ? $args['month'] - 1 : false );
|
1045 |
+
|
1046 |
+
EventOrganiser_Shortcodes::$calendars[] = array_merge( $args );
|
1047 |
+
EventOrganiser_Shortcodes::$add_script = true;
|
1048 |
+
$id = count( EventOrganiser_Shortcodes::$calendars );
|
1049 |
+
|
1050 |
+
$html = '<div id="eo_fullcalendar_'.$id.'_loading" style="background:white;position:absolute;z-index:5" >';
|
1051 |
+
$html .= '<img src="'.esc_url(EVENT_ORGANISER_URL.'/css/images/loading-image.gif').'" style="vertical-align:middle; padding: 0px 5px 5px 0px;" />' . __( 'Loading…', 'eventorganiser' );
|
1052 |
+
$html .= '</div>';
|
1053 |
+
$html .= '<div class="eo-fullcalendar eo-fullcalendar-shortcode" id="eo_fullcalendar_'.$id.'"></div>';
|
1054 |
+
|
1055 |
+
if ( $key ){
|
1056 |
+
$args = array( 'orderby' => 'name', 'show_count' => 0, 'hide_empty' => 0 );
|
1057 |
+
$html .= eventorganiser_category_key( $args,$id );
|
1058 |
+
}
|
1059 |
+
return $html;
|
1060 |
+
}
|
1061 |
+
|
1062 |
+
|
1063 |
+
/**
|
1064 |
+
* Returns HTML mark-up for a list of event meta information.
|
1065 |
+
*
|
1066 |
+
* Uses microformat.
|
1067 |
+
* @since 1.7
|
1068 |
+
* @ignore
|
1069 |
+
* @param int $post_id The event (post) ID. Uses current event if not supplied
|
1070 |
+
* @return string|bool HTML mark-up. False if an invalid $post_is provided.
|
1071 |
+
*/
|
1072 |
+
function eo_get_event_meta_list( $post_id=0 ){
|
1073 |
+
|
1074 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
1075 |
+
|
1076 |
+
if( empty($post_id) )
|
1077 |
+
return false;
|
1078 |
+
|
1079 |
+
$html = '<ul class="eo-event-meta" style="margin:10px 0px;">';
|
1080 |
+
|
1081 |
+
if( $venue_id = eo_get_venue($post_id) ){
|
1082 |
+
$html .= sprintf('<li><strong>%s:</strong> <a href="%s">
|
1083 |
+
<span itemprop="location" itemscope itemtype="http://data-vocabulary.org/Organization">
|
1084 |
+
<span itemprop="name">%s</span>
|
1085 |
+
<span itemprop="geo" itemscope itemtype="http://data-vocabulary.org/Geo">
|
1086 |
+
<meta itemprop="latitude" content="%f" />
|
1087 |
+
<meta itemprop="longitude" content="%f" />
|
1088 |
+
</span>
|
1089 |
+
</span></a></li>',
|
1090 |
+
__('Venue','eventorganiser'),
|
1091 |
+
eo_get_venue_link($venue_id),
|
1092 |
+
eo_get_venue_name($venue_id),
|
1093 |
+
eo_get_venue_lat($venue_id),
|
1094 |
+
eo_get_venue_lng($venue_id)
|
1095 |
+
);
|
1096 |
+
}
|
1097 |
+
|
1098 |
+
if( get_the_terms(get_the_ID(),'event-category') ){
|
1099 |
+
$html .= sprintf('<li><strong>%s:</strong> %s</li>',
|
1100 |
+
__('Categories','eventorganiser'),
|
1101 |
+
get_the_term_list( get_the_ID(),'event-category', '', ', ', '' )
|
1102 |
+
);
|
1103 |
+
}
|
1104 |
+
|
1105 |
+
if( get_the_terms(get_the_ID(),'event-tag') && !is_wp_error( get_the_terms(get_the_ID(),'event-tag') ) ){
|
1106 |
+
$html .= sprintf('<li><strong>%s:</strong> %s</li>',
|
1107 |
+
__('Tags','eventorganiser'),
|
1108 |
+
get_the_term_list( get_the_ID(),'event-tag', '', ', ', '' )
|
1109 |
+
);
|
1110 |
+
}
|
1111 |
+
|
1112 |
+
$html .='</ul>';
|
1113 |
+
|
1114 |
+
return apply_filters('eventorganiser_event_meta_list', $html, $post_id);
|
1115 |
+
}
|
1116 |
+
|
1117 |
+
|
1118 |
+
/**
|
1119 |
+
* Returns an the link for the event archive
|
1120 |
+
*
|
1121 |
+
* Optionally provide the year , or month or day to get an year/month/day archive link.
|
1122 |
+
* To get a month archive you should provide a year
|
1123 |
+
* To get a day archive you should provide a year and month.
|
1124 |
+
*
|
1125 |
+
*@since 1.7
|
1126 |
+
*@param int $year Year in full format, e.g. 2018. Must be provide for date-based archive link.
|
1127 |
+
*@param int $month Numeric representation of month. 1 = Jan, 12 = Dec. Must be provide for month or day archive link
|
1128 |
+
*@param int $day Day of the month 1-31
|
1129 |
+
*@return string Link to the requested archive
|
1130 |
+
*
|
1131 |
+
*/
|
1132 |
+
function eo_get_event_archive_link( $year=false,$month=false, $day=false){
|
1133 |
+
global $wp_rewrite;
|
1134 |
+
|
1135 |
+
$archive = get_post_type_archive_link('event');
|
1136 |
+
|
1137 |
+
if( $year == false && $month == false && $day == false )
|
1138 |
+
return $archive;
|
1139 |
+
|
1140 |
+
$_year = str_pad($year, 4, "0", STR_PAD_LEFT);
|
1141 |
+
$_month = str_pad($month, 2, "0", STR_PAD_LEFT);
|
1142 |
+
$_day = str_pad($day, 2, "0", STR_PAD_LEFT);
|
1143 |
+
|
1144 |
+
if( $day ){
|
1145 |
+
$date = compact('_year','_month','_day');
|
1146 |
+
}elseif( $month ){
|
1147 |
+
$date = compact('_year','_month');
|
1148 |
+
}else{
|
1149 |
+
$date = compact('_year');
|
1150 |
+
}
|
1151 |
+
|
1152 |
+
if( $archive && $wp_rewrite->using_mod_rewrite_permalinks() && $permastruct = $wp_rewrite->get_extra_permastruct('event_archive') ){
|
1153 |
+
$archive = home_url( str_replace('%event_ondate%',implode('/',$date), $permastruct ) );
|
1154 |
+
}else{
|
1155 |
+
$archive = add_query_arg('ondate',implode('-',$date),$archive);
|
1156 |
+
}
|
1157 |
+
|
1158 |
+
return $archive;
|
1159 |
+
}
|
1160 |
+
|
1161 |
+
|
1162 |
+
function eo_break_occurrence( $post_id, $event_id ){
|
1163 |
+
|
1164 |
+
global $post;
|
1165 |
+
$post = get_post( $post_id );
|
1166 |
+
setup_postdata( $post_id );
|
1167 |
+
|
1168 |
+
do_action( 'eventorganiser_pre_break_occurrence', $post_id, $event_id );
|
1169 |
+
|
1170 |
+
$tax_input = array();
|
1171 |
+
foreach ( array( 'event-category', 'event-tag', 'event-venue' ) as $tax ):
|
1172 |
+
$terms = get_the_terms( $post->ID, $tax );
|
1173 |
+
if ( $terms && !is_wp_error( $terms ) ){
|
1174 |
+
$tax_input[$tax] = array_map( 'intval', wp_list_pluck( $terms, 'term_id' ) );
|
1175 |
+
}
|
1176 |
+
endforeach;
|
1177 |
+
|
1178 |
+
//Post details
|
1179 |
+
$post_array = array(
|
1180 |
+
'post_title' => $post->post_title, 'post_name' => $post->post_name, 'post_author' => $post->post_author,
|
1181 |
+
'post_content' => $post->post_content, 'post_status' => $post->post_status, 'post_date' => $post->post_date,
|
1182 |
+
'post_date_gmt' => $post->post_date_gmt, 'post_excerpt' => $post->post_excerpt, 'post_password' => $post->post_password,
|
1183 |
+
'post_type' => 'event', 'tax_input' => $tax_input, 'comment_status' => $post->comment_status, 'ping_status' => $post->ping_status,
|
1184 |
+
);
|
1185 |
+
|
1186 |
+
//Event details
|
1187 |
+
$event_array = array(
|
1188 |
+
'start' => eo_get_the_start( DATETIMEOBJ, $post_id, null, $event_id ),
|
1189 |
+
'end' => eo_get_the_end(DATETIMEOBJ, $post_id, null, $event_id ),
|
1190 |
+
'all_day' => ( eo_is_all_day( $post_id ) ? 1 : 0 ),
|
1191 |
+
'schedule' => 'once',
|
1192 |
+
'frequency' => 1,
|
1193 |
+
);
|
1194 |
+
|
1195 |
+
//Create new event with duplicated details (new event clears cache)
|
1196 |
+
$new_event_id = eo_insert_event( $post_array, $event_array );
|
1197 |
+
|
1198 |
+
//delete occurrence, and copy post meta
|
1199 |
+
if ( $new_event_id && !is_wp_error( $new_event_id ) ){
|
1200 |
+
$response = _eventorganiser_remove_occurrence( $post_id, $event_id );
|
1201 |
+
|
1202 |
+
$post_custom = get_post_custom( $post_id );
|
1203 |
+
foreach ( $post_custom as $meta_key => $meta_values ) {
|
1204 |
+
|
1205 |
+
//Don't copy these
|
1206 |
+
$ignore_meta = array( '_eo_tickets', '_edit_last', '_edit_last', '_edit_lock' ) ;
|
1207 |
+
$ignore_meta = apply_filters( 'eventorganiser_breaking_occurrence_exclude_meta', $ignore_meta );
|
1208 |
+
if( in_array( $meta_key, $ignore_meta ) )
|
1209 |
+
continue;
|
1210 |
+
|
1211 |
+
//Don't copy event meta
|
1212 |
+
if( 0 == strncmp( $meta_key, '_eventorganiser', 15 ) )
|
1213 |
+
continue;
|
1214 |
+
|
1215 |
+
foreach ( $meta_values as $meta_value ) {
|
1216 |
+
//get_post_meta() without a key doesn't unserialize:
|
1217 |
+
// @see{https://github.com/WordPress/WordPress/blob/3.5.1/wp-includes/meta.php#L289}
|
1218 |
+
$meta_value = maybe_unserialize( $meta_value );
|
1219 |
+
add_post_meta( $new_event_id, $meta_key, $meta_value );
|
1220 |
+
}
|
1221 |
+
}
|
1222 |
+
}
|
1223 |
+
_eventorganiser_delete_calendar_cache();
|
1224 |
+
|
1225 |
+
do_action( 'eventorganiser_occurrence_broken', $post_id, $event_id, $new_event_id );
|
1226 |
+
|
1227 |
+
wp_reset_postdata();
|
1228 |
+
return $new_event_id;
|
1229 |
+
}
|
1230 |
+
|
1231 |
+
?>
|
includes/event-organiser-install.php
ADDED
@@ -0,0 +1,388 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Install routine
|
5 |
+
*
|
6 |
+
*@since 1.0
|
7 |
+
*@access private
|
8 |
+
*@ignore
|
9 |
+
*/
|
10 |
+
function eventorganiser_install( $is_networkwide = false ){
|
11 |
+
global $wpdb;
|
12 |
+
|
13 |
+
// Is this multisite and did the user click network activate?
|
14 |
+
$is_multisite = ( function_exists('is_multisite') && is_multisite() );
|
15 |
+
|
16 |
+
if ($is_multisite && $is_networkwide) {
|
17 |
+
// Get the current blog so we can return to it.
|
18 |
+
$current_blog_id = get_current_blog_id();
|
19 |
+
|
20 |
+
// Get a list of all blogs.
|
21 |
+
$blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
|
22 |
+
if( $blog_ids ){
|
23 |
+
foreach ( $blog_ids as $blog_id ) {
|
24 |
+
switch_to_blog( $blog_id );
|
25 |
+
eventorganiser_site_install();
|
26 |
+
}
|
27 |
+
switch_to_blog( $current_blog_id );
|
28 |
+
}else{
|
29 |
+
eventorganiser_site_install();
|
30 |
+
}
|
31 |
+
}else {
|
32 |
+
eventorganiser_site_install();
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
function eventorganiser_site_install(){
|
37 |
+
global $wpdb, $eventorganiser_db_version;
|
38 |
+
|
39 |
+
eventorganiser_wpdb_fix();
|
40 |
+
|
41 |
+
$charset_collate = '';
|
42 |
+
if ( ! empty($wpdb->charset) )
|
43 |
+
$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
|
44 |
+
if ( ! empty($wpdb->collate) )
|
45 |
+
$charset_collate .= " COLLATE $wpdb->collate";
|
46 |
+
|
47 |
+
//Events table
|
48 |
+
$sql_events_table = "CREATE TABLE " .$wpdb->eo_events. " (
|
49 |
+
event_id bigint(20) NOT NULL AUTO_INCREMENT,
|
50 |
+
post_id bigint(20) NOT NULL,
|
51 |
+
StartDate DATE NOT NULL,
|
52 |
+
EndDate DATE NOT NULL,
|
53 |
+
StartTime TIME NOT NULL,
|
54 |
+
FinishTime TIME NOT NULL,
|
55 |
+
event_occurrence bigint(20) NOT NULL,
|
56 |
+
PRIMARY KEY (event_id),
|
57 |
+
KEY StartDate (StartDate),
|
58 |
+
KEY EndDate (EndDate)
|
59 |
+
)".$charset_collate;
|
60 |
+
|
61 |
+
//Venue meta table
|
62 |
+
$sql_venuemeta_table ="CREATE TABLE {$wpdb->prefix}eo_venuemeta (
|
63 |
+
meta_id bigint(20) unsigned NOT NULL auto_increment,
|
64 |
+
eo_venue_id bigint(20) unsigned NOT NULL default '0',
|
65 |
+
meta_key varchar(255) default NULL,
|
66 |
+
meta_value longtext,
|
67 |
+
PRIMARY KEY (meta_id),
|
68 |
+
KEY eo_venue_id (eo_venue_id),
|
69 |
+
KEY meta_key (meta_key)
|
70 |
+
) $charset_collate; ";
|
71 |
+
|
72 |
+
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
73 |
+
dbDelta($sql_events_table);
|
74 |
+
dbDelta($sql_venuemeta_table);
|
75 |
+
|
76 |
+
//Add options and capabilities
|
77 |
+
$eventorganiser_options = array (
|
78 |
+
'supports' => array('title','editor','author','thumbnail','excerpt','custom-fields','comments'),
|
79 |
+
'event_redirect' => 'events',
|
80 |
+
'dateformat'=>'dd-mm',
|
81 |
+
'prettyurl'=> 1,
|
82 |
+
'templates'=> 1,
|
83 |
+
'addtomenu'=> 0,
|
84 |
+
'excludefromsearch'=>0,
|
85 |
+
'showpast'=> 0,
|
86 |
+
'group_events'=>'',
|
87 |
+
'url_venue'=>'events/event',
|
88 |
+
'url_venue'=> 'events/venues',
|
89 |
+
'url_cat' => 'events/category',
|
90 |
+
'url_tag' => 'events/tag',
|
91 |
+
'navtitle' => __('Events','eventorganiser'),
|
92 |
+
'eventtag' => 1,
|
93 |
+
'feed' => 1,
|
94 |
+
'runningisnotpast' => 0,
|
95 |
+
'deleteexpired' => 0
|
96 |
+
);
|
97 |
+
add_option('eventorganiser_options',$eventorganiser_options);
|
98 |
+
|
99 |
+
/* Add existing notices */
|
100 |
+
$notices = array('autofillvenue17','changedtemplate17');
|
101 |
+
add_option('eventorganiser_admin_notices',$notices);
|
102 |
+
|
103 |
+
//Add roles to administrator
|
104 |
+
global $wp_roles;
|
105 |
+
$all_roles = $wp_roles->roles;
|
106 |
+
$eventorganiser_roles = array(
|
107 |
+
'edit_events' => __( 'Edit Events', 'eventorganiser' ),
|
108 |
+
'publish_events' => __( 'Publish Events', 'eventorganiser' ),
|
109 |
+
'delete_events' => __( 'Delete Events', 'eventorganiser' ),
|
110 |
+
'edit_others_events' => __( 'Edit Others\' Events', 'eventorganiser' ),
|
111 |
+
'delete_others_events' => __( 'Delete Other\'s Events', 'eventorganiser' ),
|
112 |
+
'read_private_events' => __( 'Read Private Events', 'eventorganiser' ),
|
113 |
+
'manage_venues' => __( 'Manage Venues', 'eventorganiser' ),
|
114 |
+
'manage_event_categories' => __( 'Manage Event Categories & Tags', 'eventorganiser' ),
|
115 |
+
);
|
116 |
+
foreach ($all_roles as $role_name => $display_name):
|
117 |
+
$role = $wp_roles->get_role($role_name);
|
118 |
+
if($role->has_cap('manage_options')){
|
119 |
+
foreach($eventorganiser_roles as $eo_role=>$eo_role_display):
|
120 |
+
$role->add_cap($eo_role);
|
121 |
+
endforeach;
|
122 |
+
}
|
123 |
+
endforeach; //End foreach $all_roles
|
124 |
+
|
125 |
+
//Manually register CPT and CTs ready for flushing
|
126 |
+
eventorganiser_create_event_taxonomies();
|
127 |
+
eventorganiser_cpt_register();
|
128 |
+
|
129 |
+
//Flush rewrite rules only on activation, and after CPT/CTs has been registered.
|
130 |
+
flush_rewrite_rules();
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Deactivate routine
|
135 |
+
*
|
136 |
+
* Flushes rewrite rules. Don't clear cron jobs, as these won't be re-added.
|
137 |
+
*
|
138 |
+
*@since 1.5
|
139 |
+
*@access private
|
140 |
+
*@ignore
|
141 |
+
*/
|
142 |
+
function eventorganiser_deactivate(){
|
143 |
+
flush_rewrite_rules();
|
144 |
+
}
|
145 |
+
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Upgrade routine. Hooked onto admin_init
|
149 |
+
*
|
150 |
+
*@since 1.1
|
151 |
+
*@access private
|
152 |
+
*@ignore
|
153 |
+
*/
|
154 |
+
function eventorganiser_upgradecheck(){
|
155 |
+
global $eventorganiser_db_version, $wpdb;
|
156 |
+
global $EO_Errors;
|
157 |
+
|
158 |
+
$installed_ver = get_option('eventorganiser_version');
|
159 |
+
|
160 |
+
if( empty($installed_ver) ){
|
161 |
+
//This is a fresh install. Add current database version
|
162 |
+
add_option('eventorganiser_version', $eventorganiser_db_version);
|
163 |
+
|
164 |
+
//But a bug in 1.5 means that it could be that they first installed in 1.5 (as no db version was added)
|
165 |
+
//So set to 1.5. Fresh installs will have to go through the 1.6 (and above) update, but this is ok.
|
166 |
+
$installed_ver = '1.5';
|
167 |
+
}
|
168 |
+
|
169 |
+
//If this is an old version, perform some updates.
|
170 |
+
if ( !empty($installed_ver ) && $installed_ver != $eventorganiser_db_version ):
|
171 |
+
|
172 |
+
if($installed_ver <'1.3'){
|
173 |
+
wp_die('You cannot upgrade to this version from 1.3 or before. Please upgrade to 1.5.7 first.');
|
174 |
+
}
|
175 |
+
|
176 |
+
if($installed_ver <'1.4'){
|
177 |
+
eventorganiser_140_update();
|
178 |
+
}
|
179 |
+
|
180 |
+
if($installed_ver <'1.5'){
|
181 |
+
eventorganiser_150_update();
|
182 |
+
}
|
183 |
+
if( $installed_ver < '1.6' ){
|
184 |
+
//Remove columns:
|
185 |
+
$columns = $wpdb->get_col("DESC {$wpdb->eo_events}", 0);
|
186 |
+
$remove_columns = array('Venue','event_schedule','event_schedule_meta', 'event_frequency','reoccurrence_start', 'reoccurrence_end' );
|
187 |
+
$delete_columns = array_intersect($remove_columns, $columns);
|
188 |
+
if( !empty($delete_columns) )
|
189 |
+
$sql = $wpdb->query("ALTER TABLE {$wpdb->eo_events} DROP COLUMN ".implode(', DROP COLUMN ',$delete_columns).';');
|
190 |
+
|
191 |
+
eventorganiser_install();
|
192 |
+
}
|
193 |
+
|
194 |
+
if( $installed_ver < '1.6.2' ){
|
195 |
+
$options = get_option('eventorganiser_options');
|
196 |
+
if( !empty($options['eventtag']) ){
|
197 |
+
$options['supports'][] = 'eventtag';
|
198 |
+
update_option('eventorganiser_options', $options);
|
199 |
+
}
|
200 |
+
}
|
201 |
+
if( $installed_ver < '1.7.1' ){
|
202 |
+
//Forgot to remove event_allday in 1.6 upgrade. This causes problems no Windows servers.
|
203 |
+
$columns = $wpdb->get_col("DESC {$wpdb->eo_events}", 0);
|
204 |
+
$remove_columns = array('event_allday');
|
205 |
+
if( !empty($delete_columns) )
|
206 |
+
$sql = $wpdb->query("ALTER TABLE {$wpdb->eo_events} DROP COLUMN ".implode(', DROP COLUMN ',$delete_columns).';');
|
207 |
+
flush_rewrite_rules();
|
208 |
+
}
|
209 |
+
update_option('eventorganiser_version', $eventorganiser_db_version);
|
210 |
+
|
211 |
+
//Run upgrade checks
|
212 |
+
add_action('admin_notices', 'eventorganiser_db_checks',0);
|
213 |
+
endif;
|
214 |
+
}
|
215 |
+
add_action('admin_init', 'eventorganiser_upgradecheck');
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Upgrade routine for 1.5
|
219 |
+
*
|
220 |
+
*@since 1.5
|
221 |
+
*@access private
|
222 |
+
*@ignore
|
223 |
+
*/
|
224 |
+
function eventorganiser_150_update(){
|
225 |
+
global $wpdb;
|
226 |
+
$et =$wpdb->eo_events;
|
227 |
+
$events = $wpdb->get_results("SELECT*, min({$et}.StartDate) as StartDate, min({$et}.EndDate) as EndDate FROM $wpdb->eo_events GROUP BY {$et}.post_id ORDER BY {$et}.StartDate");
|
228 |
+
if( $events ):
|
229 |
+
foreach( $events as $event ):
|
230 |
+
|
231 |
+
$post_id = (int) $event->post_id;
|
232 |
+
|
233 |
+
$event_data = array(
|
234 |
+
'schedule' => $event->event_schedule,
|
235 |
+
'all_day' => $event->event_allday,
|
236 |
+
'schedule_meta' => ('weekly' == $event->event_schedule ? maybe_unserialize($event->event_schedule_meta) : $event->event_schedule_meta),
|
237 |
+
'frequency' => $event->event_frequency,
|
238 |
+
'exclude'=>array(),
|
239 |
+
'include'=>array(),
|
240 |
+
);
|
241 |
+
$start = new DateTime($event->StartDate.' '.$event->StartTime, eo_get_blog_timezone());
|
242 |
+
$end = new DateTime($event->EndDate.' '.$event->FinishTime, eo_get_blog_timezone());
|
243 |
+
$schedule_last = new DateTime($event->reoccurrence_end.' '.$event->StartTime, eo_get_blog_timezone());
|
244 |
+
|
245 |
+
$seconds = round(abs($start->format('U') - $end->format('U')));
|
246 |
+
$days = floor($seconds/86400);// 86400 = 60*60*24 seconds in a normal day
|
247 |
+
$sec_diff = $seconds - $days*86400;
|
248 |
+
$duration_str = '+'.$days.'days '.$sec_diff.' seconds';
|
249 |
+
$event_data['duration_str'] =$duration_str;
|
250 |
+
|
251 |
+
$schedule_last_end = clone $schedule_last;
|
252 |
+
$schedule_last_end->modify($duration_str);
|
253 |
+
|
254 |
+
update_post_meta( $post_id,'_eventorganiser_event_schedule', $event_data);
|
255 |
+
update_post_meta( $post_id,'_eventorganiser_schedule_start_start', $start->format('Y-m-d H:i:s')); //Schedule start
|
256 |
+
update_post_meta( $post_id,'_eventorganiser_schedule_start_finish', $end->format('Y-m-d H:i:s')); //Schedule start
|
257 |
+
update_post_meta( $post_id,'_eventorganiser_schedule_last_start', $schedule_last->format('Y-m-d H:i:s'));//Schedule last
|
258 |
+
update_post_meta( $post_id,'_eventorganiser_schedule_last_finish', $schedule_last_end->format('Y-m-d H:i:s'));//Schedule last
|
259 |
+
|
260 |
+
endforeach;
|
261 |
+
endif;
|
262 |
+
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Upgrade routine for 1.4
|
267 |
+
*
|
268 |
+
*@since 1.4
|
269 |
+
*@access private
|
270 |
+
*@ignore
|
271 |
+
*/
|
272 |
+
function eventorganiser_140_update(){
|
273 |
+
//Migrates from Venue table to venue meta table
|
274 |
+
|
275 |
+
//Run install to create new table:
|
276 |
+
eventorganiser_install();
|
277 |
+
|
278 |
+
global $wpdb;
|
279 |
+
$eventorganiser_venue_table = $wpdb->prefix."eo_venues";
|
280 |
+
|
281 |
+
$venues = eo_get_the_venues();
|
282 |
+
$venue_metavalues = $wpdb->get_results(" SELECT venue_slug, venue_address, venue_postal, venue_country, venue_lng, venue_lat, venue_description FROM $eventorganiser_venue_table");
|
283 |
+
$fields = array('venue_address'=>'_address','venue_postal'=>'_postcode','venue_country'=>'_country','venue_lng'=>'_lng','venue_lat'=>'_lat','venue_description'=>'_description');
|
284 |
+
|
285 |
+
foreach( $venue_metavalues as $venue ){
|
286 |
+
$term = get_term_by('slug',$venue->venue_slug,'event-venue');
|
287 |
+
if( empty($term) || is_wp_error($term) )
|
288 |
+
continue;
|
289 |
+
|
290 |
+
foreach ($fields as $column_name => $meta_key){
|
291 |
+
if( ! empty($venue->$column_name) ){
|
292 |
+
update_metadata('eo_venue',$term->term_id,$meta_key,$venue->$column_name);
|
293 |
+
}
|
294 |
+
}
|
295 |
+
}
|
296 |
+
}
|
297 |
+
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Uninstall routine
|
301 |
+
*
|
302 |
+
*@since 1.0
|
303 |
+
*@access private
|
304 |
+
*@ignore
|
305 |
+
*/
|
306 |
+
function eventorganiser_uninstall( $is_networkwide = false ){
|
307 |
+
global $wpdb;
|
308 |
+
|
309 |
+
// Is this multisite and did the user click network activate?
|
310 |
+
$is_multisite = ( function_exists('is_multisite') && is_multisite() );
|
311 |
+
|
312 |
+
if ( $is_multisite && $is_networkwide ) {
|
313 |
+
// Get the current blog so we can return to it.
|
314 |
+
$current_blog_id = get_current_blog_id();
|
315 |
+
|
316 |
+
// Get a list of all blogs.
|
317 |
+
$blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
|
318 |
+
if( $blog_ids ){
|
319 |
+
foreach ( $blog_ids as $blog_id ) {
|
320 |
+
switch_to_blog( $blog_id );
|
321 |
+
eventorganiser_uninstall_site();
|
322 |
+
}
|
323 |
+
switch_to_blog( $current_blog_id );
|
324 |
+
}else{
|
325 |
+
eventorganiser_uninstall_site();
|
326 |
+
}
|
327 |
+
}else {
|
328 |
+
eventorganiser_uninstall_site();
|
329 |
+
}
|
330 |
+
|
331 |
+
}
|
332 |
+
|
333 |
+
function eventorganiser_uninstall_site(){
|
334 |
+
global $wpdb,$eventorganiser_roles, $wp_roles,$wp_taxonomies;
|
335 |
+
|
336 |
+
eventorganiser_clear_cron_jobs();
|
337 |
+
eventorganiser_create_event_taxonomies();
|
338 |
+
|
339 |
+
//Remove custom taxonomies and terms.
|
340 |
+
$taxs = array('event-category','event-venue','event-tag');
|
341 |
+
$terms = get_terms($taxs, 'hide_empty=0' );
|
342 |
+
|
343 |
+
if( $terms ){
|
344 |
+
foreach ($terms as $term) {
|
345 |
+
$term_id = (int)$term->term_id;
|
346 |
+
wp_delete_term($term_id ,$term->taxonomy);
|
347 |
+
}
|
348 |
+
}
|
349 |
+
|
350 |
+
//Remove all posts of CPT Event
|
351 |
+
//?? $wpdb->query("DELETE FROM $wpdb->posts WHERE post_type = 'event'");
|
352 |
+
|
353 |
+
//Delete options
|
354 |
+
delete_option('eventorganiser_options');
|
355 |
+
delete_option('eventorganiser_admin_notices');
|
356 |
+
delete_option('eventorganiser_version');
|
357 |
+
delete_option('eo_notice');
|
358 |
+
delete_option('widget_eo_calendar_widget');
|
359 |
+
delete_option('widget_eo_list_widget');
|
360 |
+
|
361 |
+
//Remove Event Organiser capabilities
|
362 |
+
$all_roles = $wp_roles->roles;
|
363 |
+
foreach ($all_roles as $role_name => $display_name):
|
364 |
+
$role = $wp_roles->get_role($role_name);
|
365 |
+
foreach($eventorganiser_roles as $eo_role=>$eo_role_display):
|
366 |
+
$role->remove_cap($eo_role);
|
367 |
+
endforeach;
|
368 |
+
endforeach;
|
369 |
+
|
370 |
+
eventorganiser_clear_cron_jobs();
|
371 |
+
|
372 |
+
//Drop tables
|
373 |
+
$wpdb->query("DROP TABLE IF EXISTS $wpdb->eo_events");
|
374 |
+
$eventorganiser_venue_table = $wpdb->prefix."eo_venues";
|
375 |
+
$wpdb->query("DROP TABLE IF EXISTS $eventorganiser_venue_table");
|
376 |
+
$wpdb->query("DROP TABLE IF EXISTS $wpdb->eo_venuemeta");
|
377 |
+
|
378 |
+
//Remove user-meta-data:
|
379 |
+
$meta_keys = array('metaboxhidden_event','closedpostboxes_event','wp_event_page_venues_per_page','manageedit-eventcolumnshidden');
|
380 |
+
$sql =$wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE ");
|
381 |
+
foreach($meta_keys as $key):
|
382 |
+
$sql .= $wpdb->prepare("meta_key = %s OR ",$key);
|
383 |
+
endforeach;
|
384 |
+
$sql.=" 1=0 "; //Deal with final 'OR', must be something false!
|
385 |
+
$re =$wpdb->get_results( $sql);
|
386 |
+
flush_rewrite_rules();
|
387 |
+
}
|
388 |
+
?>
|
includes/event-organiser-register.php
ADDED
@@ -0,0 +1,780 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Register jQuery scripts and CSS files
|
4 |
+
* Hooked on to init
|
5 |
+
*
|
6 |
+
* @since 1.0.0
|
7 |
+
* @ignore
|
8 |
+
* @access private
|
9 |
+
*/
|
10 |
+
function eventorganiser_register_script() {
|
11 |
+
global $wp_locale;
|
12 |
+
$version = '2.0.1';
|
13 |
+
|
14 |
+
$ext = (defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG) ? '' : '.min';
|
15 |
+
|
16 |
+
/* FullCalendar */
|
17 |
+
wp_register_script( 'eo_fullcalendar', EVENT_ORGANISER_URL."js/fullcalendar{$ext}.js",array(
|
18 |
+
'jquery',
|
19 |
+
'jquery-ui-core',
|
20 |
+
'jquery-ui-widget',
|
21 |
+
'jquery-ui-button',
|
22 |
+
),$version,true);
|
23 |
+
|
24 |
+
/* Google Maps */
|
25 |
+
$protocal = is_ssl() ? 'https://' : 'http://';
|
26 |
+
if( is_admin() )
|
27 |
+
wp_register_script( 'eo_GoogleMap', $protocal.'maps.googleapis.com/maps/api/js?sensor=false&language='.substr(get_locale(),0,2));
|
28 |
+
else
|
29 |
+
wp_register_script( 'eo_GoogleMap', $protocal.'maps.googleapis.com/maps/api/js?sensor=false&callback=eo_load_map&language='.substr(get_locale(),0,2));
|
30 |
+
|
31 |
+
/* Front-end script */
|
32 |
+
wp_register_script( 'eo_front', EVENT_ORGANISER_URL."js/frontend{$ext}.js",array(
|
33 |
+
'jquery','eo_qtip2',
|
34 |
+
'jquery-ui-core',
|
35 |
+
'jquery-ui-widget',
|
36 |
+
'jquery-ui-button',
|
37 |
+
'jquery-ui-datepicker',
|
38 |
+
'eo_fullcalendar',
|
39 |
+
),$version,true);
|
40 |
+
|
41 |
+
/* Add js variables to frontend script */
|
42 |
+
wp_localize_script( 'eo_front', 'EOAjaxFront', array(
|
43 |
+
'adminajax'=>admin_url( 'admin-ajax.php'),
|
44 |
+
'locale'=>array(
|
45 |
+
'locale' => substr(get_locale(),0,2),
|
46 |
+
'monthNames'=>array_values($wp_locale->month),
|
47 |
+
'monthAbbrev'=>array_values($wp_locale->month_abbrev),
|
48 |
+
'dayNames'=>array_values($wp_locale->weekday),
|
49 |
+
'dayAbbrev'=>array_values($wp_locale->weekday_abbrev),
|
50 |
+
'ShowMore'=>__('Show More','eventorganiser'),
|
51 |
+
'ShowLess'=>__('Show Less','eventorganiser'),
|
52 |
+
'today'=>__('today','eventorganiser'),
|
53 |
+
'day'=>__('day','eventorganiser'),
|
54 |
+
'week'=>__('week','eventorganiser'),
|
55 |
+
'month'=>__('month','eventorganiser'),
|
56 |
+
'gotodate'=>__('go to date','eventorganiser'),
|
57 |
+
'cat'=>__('View all categories','eventorganiser'),
|
58 |
+
'venue'=>__('View all venues','eventorganiser'),
|
59 |
+
)
|
60 |
+
));
|
61 |
+
|
62 |
+
/* WP-JS-Hooks */
|
63 |
+
wp_register_script( 'eo-wp-js-hooks', EVENT_ORGANISER_URL."js/event-manager{$ext}.js",array('jquery'),$version,true);
|
64 |
+
|
65 |
+
/* Q-Tip */
|
66 |
+
wp_register_script( 'eo_qtip2', EVENT_ORGANISER_URL.'js/qtip2.js',array('jquery'),$version,true);
|
67 |
+
|
68 |
+
/* Styles */
|
69 |
+
wp_register_style('eo_calendar-style',EVENT_ORGANISER_URL.'css/fullcalendar.css',array(),$version);
|
70 |
+
wp_register_style('eo_front',EVENT_ORGANISER_URL.'css/eventorganiser-front-end.css',array(),$version);
|
71 |
+
}
|
72 |
+
add_action('init', 'eventorganiser_register_script');
|
73 |
+
|
74 |
+
/**
|
75 |
+
*Register jQuery scripts and CSS files for admin
|
76 |
+
*
|
77 |
+
* @since 1.0.0
|
78 |
+
* @ignore
|
79 |
+
* @access private
|
80 |
+
*/
|
81 |
+
function eventorganiser_register_scripts(){
|
82 |
+
$version = '2.0.1';
|
83 |
+
$ext = (defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG) ? '' : '.min';
|
84 |
+
|
85 |
+
/* Venue scripts for venue & event edit */
|
86 |
+
wp_register_script( 'eo_venue', EVENT_ORGANISER_URL."js/venues{$ext}.js",array(
|
87 |
+
'jquery',
|
88 |
+
'eo_GoogleMap'
|
89 |
+
),$version,true);
|
90 |
+
|
91 |
+
/* Script for event edit page */
|
92 |
+
wp_register_script( 'eo_event', EVENT_ORGANISER_URL."js/event{$ext}.js",array(
|
93 |
+
'jquery',
|
94 |
+
'jquery-ui-datepicker',
|
95 |
+
'jquery-ui-autocomplete',
|
96 |
+
'jquery-ui-widget',
|
97 |
+
'jquery-ui-position'
|
98 |
+
),$version,true);
|
99 |
+
|
100 |
+
/* Script for admin calendar */
|
101 |
+
wp_register_script( 'eo_calendar', EVENT_ORGANISER_URL."js/admin-calendar{$ext}.js",array(
|
102 |
+
'eo_fullcalendar',
|
103 |
+
'jquery-ui-dialog',
|
104 |
+
'jquery-ui-tabs',
|
105 |
+
'jquery-ui-position'
|
106 |
+
),$version,true);
|
107 |
+
|
108 |
+
/* Pick and register jQuery UI style */
|
109 |
+
$style = ( 'classic' == get_user_option( 'admin_color') ? 'classic' : 'fresh' );
|
110 |
+
wp_register_style('eventorganiser-jquery-ui-style',EVENT_ORGANISER_URL."css/eventorganiser-admin-{$style}.css",array(),$version);
|
111 |
+
|
112 |
+
/* Admin styling */
|
113 |
+
wp_register_style('eventorganiser-style',EVENT_ORGANISER_URL.'css/eventorganiser-admin-style.css',array('eventorganiser-jquery-ui-style'),$version );
|
114 |
+
|
115 |
+
/* Inline Help */
|
116 |
+
wp_register_script( 'eo-inline-help', EVENT_ORGANISER_URL.'js/inline-help.js',array( 'jquery', 'eo_qtip2' ), $version, true );
|
117 |
+
}
|
118 |
+
add_action( 'admin_init', 'eventorganiser_register_scripts', 5 );
|
119 |
+
|
120 |
+
|
121 |
+
/**
|
122 |
+
* The "Comprehensive Google Map Plugin" plug-in deregisters all other Google scripts registered
|
123 |
+
* by other plug-ins causing these plug-ins not to function. This plug-in removes that behaviour.
|
124 |
+
*
|
125 |
+
* Of course if two google scripts are loaded there may be problems, but this is better than always having
|
126 |
+
* experiencing a 'bug'. At time writing the function responsible `cgmp_google_map_deregister_scripts()`
|
127 |
+
* can be found here {@see https://github.com/azagniotov/Comprehensive-Google-Map-Plugin/blob/master/functions.php#L520 }
|
128 |
+
*
|
129 |
+
* @see https://github.com/stephenharris/Event-Organiser/issues/49
|
130 |
+
* @see http://wordpress.org/support/topic/googlemap-doesnt-shown-on-event-detail-page
|
131 |
+
* @since 1.7.4
|
132 |
+
* @ignore
|
133 |
+
* @access private
|
134 |
+
*/
|
135 |
+
function eventorganiser_cgmp_workaround(){
|
136 |
+
remove_action( 'wp_head', 'cgmp_google_map_deregister_scripts', 200 );
|
137 |
+
}
|
138 |
+
add_action( 'wp_head', 'eventorganiser_cgmp_workaround', 1 );
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Check the export and event creation (from Calendar view) actions.
|
142 |
+
* These cannot be called later. Most other actions are only called when
|
143 |
+
* the appropriate page is loading.
|
144 |
+
*
|
145 |
+
* @since 1.0.0
|
146 |
+
* @ignore
|
147 |
+
* @access private
|
148 |
+
*/
|
149 |
+
function eventorganiser_admin_init(){
|
150 |
+
global $EO_Errors;
|
151 |
+
$EO_Errors = new WP_Error();
|
152 |
+
}
|
153 |
+
add_action('admin_init','eventorganiser_admin_init',0);
|
154 |
+
add_action('admin_init', array('Event_Organiser_Im_Export', 'get_object'));
|
155 |
+
|
156 |
+
/**
|
157 |
+
* @since 1.0.0
|
158 |
+
* @ignore
|
159 |
+
* @access private
|
160 |
+
*/
|
161 |
+
function eventorganiser_public_export(){
|
162 |
+
if( eventorganiser_get_option('feed') ){
|
163 |
+
add_feed('eo-events', array('Event_Organiser_Im_Export','get_object'));
|
164 |
+
}
|
165 |
+
}
|
166 |
+
add_action('init','eventorganiser_public_export');
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Queues up the javascript / style scripts for Events custom page type
|
170 |
+
* Hooked onto admin_enqueue_scripts
|
171 |
+
*
|
172 |
+
* @since 1.0.0
|
173 |
+
* @ignore
|
174 |
+
* @access private
|
175 |
+
*/
|
176 |
+
function eventorganiser_add_admin_scripts( $hook ) {
|
177 |
+
global $post,$current_screen,$wp_locale;
|
178 |
+
|
179 |
+
if ( $hook == 'post-new.php' || $hook == 'post.php') {
|
180 |
+
if( $post->post_type == 'event' ) {
|
181 |
+
|
182 |
+
wp_enqueue_script('eo_event');
|
183 |
+
wp_localize_script( 'eo_event', 'EO_Ajax_Event', array(
|
184 |
+
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
185 |
+
'startday'=>intval(get_option('start_of_week')),
|
186 |
+
'format'=> eventorganiser_php2jquerydate( eventorganiser_get_option('dateformat') ),
|
187 |
+
'current_user_can' => array(
|
188 |
+
'manage_venues' => current_user_can( 'manage_venues' ),
|
189 |
+
),
|
190 |
+
'location'=>get_option('timezone_string'),
|
191 |
+
'locale'=>array(
|
192 |
+
'monthNames'=>array_values($wp_locale->month),
|
193 |
+
'monthAbbrev'=>array_values($wp_locale->month_abbrev),
|
194 |
+
'dayAbbrev'=>array_values($wp_locale->weekday_abbrev),
|
195 |
+
'showDates' => __( 'Show dates', 'eventorganiser' ),
|
196 |
+
'hideDates' => __( 'Hide dates', 'eventorganiser' ),
|
197 |
+
'weekDay'=>$wp_locale->weekday,
|
198 |
+
'hour'=>__('Hour','eventorganiser'),
|
199 |
+
'minute'=>__('Minute','eventorganiser'),
|
200 |
+
'day'=>__('day','eventorganiser'),
|
201 |
+
'days'=>__('days','eventorganiser'),
|
202 |
+
'week'=>__('week','eventorganiser'),
|
203 |
+
'weeks'=>__('weeks','eventorganiser'),
|
204 |
+
'month'=>__('month','eventorganiser'),
|
205 |
+
'months'=>__('months','eventorganiser'),
|
206 |
+
'year'=>__('year','eventorganiser'),
|
207 |
+
'years'=>__('years','eventorganiser'),
|
208 |
+
'daySingle'=>__('every day','eventorganiser'),
|
209 |
+
'dayPlural'=>__('every %d days','eventorganiser'),
|
210 |
+
'weekSingle'=>__('every week on','eventorganiser'),
|
211 |
+
'weekPlural'=>__('every %d weeks on','eventorganiser'),
|
212 |
+
'monthSingle'=>__('every month on the','eventorganiser'),
|
213 |
+
'monthPlural'=>__('every %d months on the','eventorganiser'),
|
214 |
+
'yearSingle'=>__('every year on the','eventorganiser'),
|
215 |
+
'yearPlural'=>__('every %d years on the','eventorganiser'),
|
216 |
+
'summary'=>__('This event will repeat','eventorganiser'),
|
217 |
+
'until'=>__('until','eventorganiser'),
|
218 |
+
'occurrence'=>array(__('first','eventorganiser'),__('second','eventorganiser'),__('third','eventorganiser'),__('fourth','eventorganiser'),__('last','eventorganiser'))
|
219 |
+
)
|
220 |
+
));
|
221 |
+
wp_enqueue_script('eo_venue');
|
222 |
+
wp_enqueue_style('eventorganiser-style');
|
223 |
+
}
|
224 |
+
}elseif($current_screen->id=='edit-event'){
|
225 |
+
wp_enqueue_style('eventorganiser-style');
|
226 |
+
}
|
227 |
+
}
|
228 |
+
add_action( 'admin_enqueue_scripts', 'eventorganiser_add_admin_scripts', 998, 1 );
|
229 |
+
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Perform database and WP version checks. Display appropriate error messages.
|
233 |
+
* Triggered on update.
|
234 |
+
*
|
235 |
+
* @since 1.4.0
|
236 |
+
* @ignore
|
237 |
+
* @access private
|
238 |
+
*/
|
239 |
+
function eventorganiser_db_checks(){
|
240 |
+
global $wpdb;
|
241 |
+
|
242 |
+
//Check tables exist
|
243 |
+
$table_errors = array();
|
244 |
+
if($wpdb->get_var("show tables like '$wpdb->eo_events'") != $wpdb->eo_events):
|
245 |
+
$table_errors[]= $wpdb->eo_events;
|
246 |
+
endif;
|
247 |
+
if($wpdb->get_var("show tables like '$wpdb->eo_venuemeta'") != $wpdb->eo_venuemeta):
|
248 |
+
$table_errors[]=$wpdb->eo_venuemeta;
|
249 |
+
endif;
|
250 |
+
|
251 |
+
if(!empty($table_errors)):?>
|
252 |
+
<div class="error" >
|
253 |
+
<p>There has been an error with Event Organiser. One or more tables are missing:</p>
|
254 |
+
<ul>
|
255 |
+
<?php foreach($table_errors as $table):
|
256 |
+
echo "<li>".$table."</li>";
|
257 |
+
endforeach; ?>
|
258 |
+
</ul>
|
259 |
+
<p>Please try re-installing the plugin.</p>
|
260 |
+
</div>
|
261 |
+
<?php endif;
|
262 |
+
|
263 |
+
//Check WordPress version
|
264 |
+
if(get_bloginfo('version')<'3.3'):?>
|
265 |
+
<div class="error" >
|
266 |
+
<p>Event Organiser requires <strong>WordPress 3.3</strong> to function properly. Your version is <?php echo get_bloginfo('version'); ?>. </p>
|
267 |
+
</div>
|
268 |
+
<?php endif;
|
269 |
+
}
|
270 |
+
|
271 |
+
|
272 |
+
/**
|
273 |
+
* Displays any errors or notices in the global $EO_Errors
|
274 |
+
*
|
275 |
+
* @since 1.4.0
|
276 |
+
* @ignore
|
277 |
+
* @access private
|
278 |
+
*/
|
279 |
+
function eventorganiser_admin_notices(){
|
280 |
+
global $EO_Errors;
|
281 |
+
$errors=array();
|
282 |
+
$notices=array();
|
283 |
+
if(isset($EO_Errors)):
|
284 |
+
$errors = $EO_Errors->get_error_messages('eo_error');
|
285 |
+
$notices= $EO_Errors->get_error_messages('eo_notice');
|
286 |
+
if(!empty($errors)):?>
|
287 |
+
<div class="error" >
|
288 |
+
<?php foreach ($errors as $error):?>
|
289 |
+
<p><?php echo $error;?></p>
|
290 |
+
<?php endforeach;?>
|
291 |
+
</div>
|
292 |
+
<?php endif;?>
|
293 |
+
<?php if(!empty($notices)):?>
|
294 |
+
<div class="updated">
|
295 |
+
<?php foreach ($notices as $notice):?>
|
296 |
+
<p><?php echo $notice;?></p>
|
297 |
+
<?php endforeach;?>
|
298 |
+
</div>
|
299 |
+
<?php endif;
|
300 |
+
endif;
|
301 |
+
}
|
302 |
+
add_action('admin_notices','eventorganiser_admin_notices');
|
303 |
+
|
304 |
+
|
305 |
+
/**
|
306 |
+
* Adds link to the plug-in settings on the settings page
|
307 |
+
*
|
308 |
+
* @since 1.5
|
309 |
+
* @ignore
|
310 |
+
* @access private
|
311 |
+
*/
|
312 |
+
function eventorganiser_plugin_settings_link($links, $file) {
|
313 |
+
|
314 |
+
if( $file == 'event-organiser/event-organiser.php' ) {
|
315 |
+
/* Insert the link at the end*/
|
316 |
+
$links['settings'] = sprintf('<a href="%s"> %s </a>',
|
317 |
+
admin_url('options-general.php?page=event-settings'),
|
318 |
+
__('Settings','eventorganiser')
|
319 |
+
);
|
320 |
+
}
|
321 |
+
return $links;
|
322 |
+
}
|
323 |
+
add_filter('plugin_action_links', 'eventorganiser_plugin_settings_link', 10, 2);
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Schedules cron job for automatically deleting expired events
|
327 |
+
*
|
328 |
+
* @since 1.4.0
|
329 |
+
* @ignore
|
330 |
+
* @access private
|
331 |
+
*/
|
332 |
+
function eventorganiser_cron_jobs(){
|
333 |
+
wp_schedule_event(time()+60, 'daily', 'eventorganiser_delete_expired');
|
334 |
+
}
|
335 |
+
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Clears the 'delete expired events' cron job.
|
339 |
+
*
|
340 |
+
* @since 1.4.0
|
341 |
+
* @ignore
|
342 |
+
* @access private
|
343 |
+
*/
|
344 |
+
function eventorganiser_clear_cron_jobs(){
|
345 |
+
wp_clear_scheduled_hook('eventorganiser_delete_expired');
|
346 |
+
}
|
347 |
+
|
348 |
+
/**
|
349 |
+
* Returns the time in seconds until a specified cron job is scheduled.
|
350 |
+
*
|
351 |
+
*@since 1.8
|
352 |
+
*@see http://wordpress.stackexchange.com/questions/83270/when-does-next-cron-job-run-time-from-now/83279#83279
|
353 |
+
*
|
354 |
+
*@param string $cron_name The name of the cron job
|
355 |
+
*@return int|bool The time in seconds until the cron job is scheduled. False if
|
356 |
+
*it could not be found.
|
357 |
+
*/
|
358 |
+
function eventorganiser_get_next_cron_time( $cron_name ){
|
359 |
+
if( $timestamp = wp_next_scheduled( $cron_name ) ){
|
360 |
+
$timestamp = $timestamp - time();
|
361 |
+
}
|
362 |
+
return $timestamp;
|
363 |
+
}
|
364 |
+
|
365 |
+
|
366 |
+
/**
|
367 |
+
* Callback for the delete expired events cron job. Deletes events that finished at least 24 hours ago.
|
368 |
+
* For recurring events it is only deleted once the last occurrence has expired.
|
369 |
+
*
|
370 |
+
* @since 1.4.0
|
371 |
+
* @ignore
|
372 |
+
* @access private
|
373 |
+
*/
|
374 |
+
function eventorganiser_delete_expired_events(){
|
375 |
+
//Get expired events
|
376 |
+
$events = eo_get_events(array('showrepeats'=>0,'showpastevents'=>1,'eo_interval'=>'expired'));
|
377 |
+
|
378 |
+
$time_until_expired = (int) apply_filters( 'eventorganiser_events_expire_time', 24*60*60 );
|
379 |
+
$time_until_expired = max( $time_until_expired, 0 );
|
380 |
+
|
381 |
+
if($events):
|
382 |
+
$now = new DateTime('now', eo_get_blog_timezone());
|
383 |
+
|
384 |
+
foreach($events as $event):
|
385 |
+
|
386 |
+
$start = eo_get_the_start( DATETIMEOBJ, $event->ID, null, $event->occurrence_id );
|
387 |
+
$end = eo_get_the_end( DATETIMEOBJ, $event->ID, null, $event->occurrence_id );
|
388 |
+
|
389 |
+
$expired = round(abs($end->format('U')-$start->format('U'))) + $time_until_expired; //Duration + expire time
|
390 |
+
|
391 |
+
$finished = eo_get_schedule_last( DATETIMEOBJ, $event->ID );
|
392 |
+
$finished->modify("+$expired seconds");//[Expired time] after the last occurrence finishes
|
393 |
+
|
394 |
+
//Delete if [expired time] has passed
|
395 |
+
if( $finished <= $now ){
|
396 |
+
wp_trash_post((int) $event->ID);
|
397 |
+
}
|
398 |
+
|
399 |
+
endforeach;
|
400 |
+
endif;
|
401 |
+
}
|
402 |
+
add_action('eventorganiser_delete_expired', 'eventorganiser_delete_expired_events');
|
403 |
+
|
404 |
+
|
405 |
+
|
406 |
+
/**
|
407 |
+
* Adds retina support for the screen icon
|
408 |
+
* Thanks to numeeja (http://cubecolour.co.uk/)
|
409 |
+
*
|
410 |
+
* @since 1.5.0
|
411 |
+
* @ignore
|
412 |
+
* @access private
|
413 |
+
*/
|
414 |
+
function eventorganiser_screen_retina_icon(){
|
415 |
+
|
416 |
+
$screen_id = get_current_screen()->id;
|
417 |
+
|
418 |
+
if( !in_array($screen_id, array('event','edit-event','edit-event-tag','edit-event-category','event_page_venues','event_page_calendar')) )
|
419 |
+
return;
|
420 |
+
|
421 |
+
$icon_url = EVENT_ORGANISER_URL.'css/images/eoicon-64.png'
|
422 |
+
?>
|
423 |
+
<style>
|
424 |
+
@media screen and (-webkit-min-device-pixel-ratio: 2) {
|
425 |
+
#icon-edit.icon32 {
|
426 |
+
background: url(<?php echo $icon_url;?>) no-repeat;
|
427 |
+
background-size: 32px 32px;
|
428 |
+
height: 32px;
|
429 |
+
width: 32px;
|
430 |
+
}
|
431 |
+
}
|
432 |
+
</style>
|
433 |
+
<?php
|
434 |
+
}
|
435 |
+
add_action('admin_print_styles','eventorganiser_screen_retina_icon');
|
436 |
+
|
437 |
+
|
438 |
+
/**
|
439 |
+
* Purge the occurrences cache
|
440 |
+
* Hooked onto eventorganiser_save_event and eventorganiser_delete_event
|
441 |
+
*
|
442 |
+
*@access private
|
443 |
+
* @ignore
|
444 |
+
*@since 1.6
|
445 |
+
*/
|
446 |
+
function _eventorganiser_delete_occurrences_cache($post_id=0){
|
447 |
+
wp_cache_delete( 'eventorganiser_occurrences_'.$post_id );
|
448 |
+
}
|
449 |
+
//The following need to trigger the cache clear clearly need to trigger a cache clear
|
450 |
+
$hooks = array('eventorganiser_save_event', 'eventorganiser_delete_event');
|
451 |
+
foreach( $hooks as $hook ){
|
452 |
+
add_action($hook, '_eventorganiser_delete_occurrences_cache');
|
453 |
+
}
|
454 |
+
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Purge the cached results of get_calendar.
|
458 |
+
* Hooked onto eventorganiser_save_event, eventorganiser_delete_event, wp_trash_post,
|
459 |
+
* update_option_gmt_offset,update_option_start_of_week,update_option_rewrite_rules
|
460 |
+
* and edited_event-category.
|
461 |
+
*
|
462 |
+
*@access private
|
463 |
+
* @ignore
|
464 |
+
*@since 1.5
|
465 |
+
*/
|
466 |
+
function _eventorganiser_delete_calendar_cache() {
|
467 |
+
delete_transient( 'eo_widget_calendar' );
|
468 |
+
delete_transient('eo_full_calendar_public');
|
469 |
+
delete_transient('eo_full_calendar_admin');
|
470 |
+
delete_transient('eo_widget_agenda');
|
471 |
+
}
|
472 |
+
|
473 |
+
//The following need to trigger the cache
|
474 |
+
$hooks = array(
|
475 |
+
'eventorganiser_save_event', 'eventorganiser_delete_event', 'wp_trash_post','update_option_gmt_offset', /* obvious */
|
476 |
+
'update_option_start_of_week', /* Start of week is used for calendars */
|
477 |
+
'update_option_rewrite_rules', /* If permalinks updated - links on fullcalendar might now be invalid */
|
478 |
+
'delete_option_rewrite_rules',
|
479 |
+
'update_option_siteurl',
|
480 |
+
'update_option_home',
|
481 |
+
'edited_event-category', /* Colours of events may change */
|
482 |
+
);
|
483 |
+
foreach( $hooks as $hook ){
|
484 |
+
add_action($hook, '_eventorganiser_delete_calendar_cache');
|
485 |
+
}
|
486 |
+
|
487 |
+
|
488 |
+
/**
|
489 |
+
* Handles admin pointers
|
490 |
+
*
|
491 |
+
* Kick starts the enquing. Rename this to something unique (i.e. include your plugin/theme name).
|
492 |
+
*
|
493 |
+
*@access private
|
494 |
+
*@ignore
|
495 |
+
*@since 1.5
|
496 |
+
*/
|
497 |
+
function eventorganiser_pointer_load( $hook_suffix ) {
|
498 |
+
|
499 |
+
$screen_id = get_current_screen()->id;
|
500 |
+
|
501 |
+
//Get pointers for this screen
|
502 |
+
$pointers = apply_filters('eventorganiser_admin_pointers-'.$screen_id, array());
|
503 |
+
|
504 |
+
if( !$pointers || !is_array($pointers) )
|
505 |
+
return;
|
506 |
+
|
507 |
+
// Get dismissed pointers
|
508 |
+
$dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );
|
509 |
+
$valid_pointers =array();
|
510 |
+
|
511 |
+
//Check pointers and remove dismissed ones.
|
512 |
+
foreach ($pointers as $pointer_id => $pointer ){
|
513 |
+
|
514 |
+
//Sanity check
|
515 |
+
if ( in_array( $pointer_id, $dismissed ) || empty($pointer) || empty( $pointer_id ) || empty( $pointer['target'] ) || empty( $pointer['options'] ) )
|
516 |
+
continue;
|
517 |
+
|
518 |
+
$pointer['pointer_id'] = $pointer_id;
|
519 |
+
|
520 |
+
//Add the pointer to $valid_pointers array
|
521 |
+
$valid_pointers['pointers'][] = $pointer;
|
522 |
+
}
|
523 |
+
|
524 |
+
//No valid pointers? Stop here.
|
525 |
+
if( empty($valid_pointers) )
|
526 |
+
return;
|
527 |
+
|
528 |
+
// Add pointers style to queue.
|
529 |
+
wp_enqueue_style( 'wp-pointer' );
|
530 |
+
|
531 |
+
// Add pointers script to queue. Add custom script.
|
532 |
+
wp_enqueue_script('eventorganiser-pointer',EVENT_ORGANISER_URL.'js/eventorganiser-pointer.js',array('wp-pointer','eo_event'));
|
533 |
+
|
534 |
+
// Add pointer options to script.
|
535 |
+
wp_localize_script('eventorganiser-pointer', 'eventorganiserPointer', $valid_pointers);
|
536 |
+
}
|
537 |
+
add_action( 'admin_enqueue_scripts', 'eventorganiser_pointer_load',99999);
|
538 |
+
|
539 |
+
|
540 |
+
/**
|
541 |
+
* Handles admin notices
|
542 |
+
*
|
543 |
+
* This is a class which automates (semi-permant) admin notices. This are notices which persist until an
|
544 |
+
* action is performed or they are manually dismissed by the user. The EO_Admin_Notice_Handle::admin_notice()
|
545 |
+
* generates the mark-up for the notices, and displays them on the appropriate screen. It also triggers printing
|
546 |
+
* javascript so that notices can be dismissed via AJAX. There is also a no-js fallback.
|
547 |
+
*
|
548 |
+
*@access private
|
549 |
+
*@ignore
|
550 |
+
*@since 1.7
|
551 |
+
*/
|
552 |
+
class EO_Admin_Notice_Handler{
|
553 |
+
|
554 |
+
static $prefix = 'eventorganiser';
|
555 |
+
|
556 |
+
/**
|
557 |
+
* Hooks the dismiss listener (ajax and no-js) and maybe shows notices on admin_notices
|
558 |
+
*/
|
559 |
+
static function load(){
|
560 |
+
add_action( 'admin_notices', array(__CLASS__,'admin_notice'));
|
561 |
+
add_action( 'admin_init',array(__CLASS__, 'dismiss_handler'));
|
562 |
+
add_action( 'wp_ajax_'.self::$prefix.'-dismiss-notice', array( __CLASS__, 'dismiss_handler' ) );
|
563 |
+
}
|
564 |
+
|
565 |
+
/**
|
566 |
+
* Print appropriate notices.
|
567 |
+
* Hooks EO_Admin_Notice_Handle::print_footer_scripts to admin_print_footer_scripts to
|
568 |
+
* print js to handle AJAX dismiss.
|
569 |
+
*/
|
570 |
+
static function admin_notice(){
|
571 |
+
|
572 |
+
$screen_id = get_current_screen()->id;
|
573 |
+
|
574 |
+
//Notices of the form ID=> array('screen_id'=>screen ID, 'message' => Message,'type'=>error|alert)
|
575 |
+
$notices = array(
|
576 |
+
'autofillvenue17'=>array(
|
577 |
+
'screen_id'=>'event_page_venues',
|
578 |
+
'message' => sprintf(__("<h4>City & State Fields Added</h4>City and state / province fields for venues have now been added. </br> If you'd like, Event Organiser can <a href='%s'>attempt to auto-fill them</a>. You can always manually change the details aftewards.",'eventorganiser'),
|
579 |
+
add_query_arg('action','eo-autofillcity',admin_url('admin-post.php'))
|
580 |
+
),
|
581 |
+
'type' => 'alert'
|
582 |
+
),
|
583 |
+
'changedtemplate17'=>array(
|
584 |
+
'screen_id'=>'',
|
585 |
+
'message' => __("<h4>The Default Templates Have Changed</h4>Don't panic! If you've set up your own templates in your theme you won't notice any change. </br> If you haven't and want the old templates back, <a href='http://wp-event-organiser.com/blog/new-default-templates-in-1-7'>see this post<a/>.",'eventorganiser'),
|
586 |
+
'type' => 'alert'
|
587 |
+
),
|
588 |
+
);
|
589 |
+
|
590 |
+
if( !$notices )
|
591 |
+
return;
|
592 |
+
|
593 |
+
$seen_notices = get_option(self::$prefix.'_admin_notices',array());
|
594 |
+
|
595 |
+
foreach( $notices as $id => $notice ){
|
596 |
+
$id = sanitize_key($id);
|
597 |
+
|
598 |
+
//Notices cannot have been dismissed and must have a message
|
599 |
+
if( in_array($id, $seen_notices) || empty($notice['message']) )
|
600 |
+
continue;
|
601 |
+
|
602 |
+
$notice_screen_id = (array) $notice['screen_id'];
|
603 |
+
$notice_screen_id = array_filter($notice_screen_id);
|
604 |
+
|
605 |
+
//Notices must for this screen. If empty, its for all screens.
|
606 |
+
if( !empty($notice_screen_id) && !in_array($screen_id, $notice_screen_id) )
|
607 |
+
continue;
|
608 |
+
|
609 |
+
$class = $notice['type'] == 'error' ? 'error' : 'updated';
|
610 |
+
|
611 |
+
printf("<div class='%s-notice {$class}' id='%s'>%s<p> <a class='%s' href='%s' title='%s'><strong>%s</strong></a></p></div>",
|
612 |
+
esc_attr(self::$prefix),
|
613 |
+
esc_attr(self::$prefix.'-notice-'.$id),
|
614 |
+
$notice['message'],
|
615 |
+
esc_attr(self::$prefix.'-dismiss'),
|
616 |
+
esc_url(add_query_arg(array(
|
617 |
+
'action'=>self::$prefix.'-dismiss-notice',
|
618 |
+
'notice'=>$id,
|
619 |
+
'_wpnonce'=>wp_create_nonce(self::$prefix.'-dismiss-'.$id),
|
620 |
+
))),
|
621 |
+
__('Dismiss this notice','eventorganiser'),
|
622 |
+
__('Dismiss','eventorganiser')
|
623 |
+
);
|
624 |
+
}
|
625 |
+
add_action( 'admin_print_footer_scripts', array( __CLASS__, 'print_footer_scripts' ), 11 );
|
626 |
+
|
627 |
+
}
|
628 |
+
|
629 |
+
/**
|
630 |
+
* Handles AJAX and no-js requests to dismiss a notice
|
631 |
+
*/
|
632 |
+
static function dismiss_handler(){
|
633 |
+
|
634 |
+
$notice = isset($_REQUEST['notice']) ? $_REQUEST['notice'] : false;
|
635 |
+
if( empty($notice) )
|
636 |
+
return;
|
637 |
+
|
638 |
+
if ( defined('DOING_AJAX') && DOING_AJAX ){
|
639 |
+
//Ajax dismiss handler
|
640 |
+
if( empty($_REQUEST['notice']) || empty($_REQUEST['_wpnonce']) || $_REQUEST['action'] !== self::$prefix.'-dismiss-notice' )
|
641 |
+
return;
|
642 |
+
|
643 |
+
if( !wp_verify_nonce( $_REQUEST['_wpnonce'],self::$prefix."-ajax-dismiss") )
|
644 |
+
return;
|
645 |
+
|
646 |
+
}else{
|
647 |
+
//Fallback dismiss handler
|
648 |
+
if( empty($_REQUEST['action']) || empty($_REQUEST['notice']) || empty($_REQUEST['_wpnonce']) || $_REQUEST['action'] !== self::$prefix.'-dismiss-notice' )
|
649 |
+
return;
|
650 |
+
|
651 |
+
if( !wp_verify_nonce( $_REQUEST['_wpnonce'],self::$prefix.'-dismiss-'.$notice ) )
|
652 |
+
return;
|
653 |
+
}
|
654 |
+
|
655 |
+
self::dismiss_notice($notice);
|
656 |
+
|
657 |
+
if ( defined('DOING_AJAX') && DOING_AJAX )
|
658 |
+
wp_die(1);
|
659 |
+
}
|
660 |
+
|
661 |
+
/**
|
662 |
+
* Dismiss a given a notice
|
663 |
+
*@param string $notice The notice (ID) to dismiss
|
664 |
+
*/
|
665 |
+
static function dismiss_notice($notice){
|
666 |
+
$seen_notices = get_option(self::$prefix.'_admin_notices',array());
|
667 |
+
$seen_notices[] = $notice;
|
668 |
+
$seen_notices = array_unique($seen_notices);
|
669 |
+
update_option(self::$prefix.'_admin_notices',$seen_notices);
|
670 |
+
}
|
671 |
+
|
672 |
+
/**
|
673 |
+
* Prints javascript in footer to handle AJAX dismiss.
|
674 |
+
*/
|
675 |
+
static function print_footer_scripts() {
|
676 |
+
?>
|
677 |
+
<script type="text/javascript">
|
678 |
+
jQuery(document).ready(function ($){
|
679 |
+
var dismissClass = '<?php echo esc_js(self::$prefix."-dismiss");?>';
|
680 |
+
var ajaxaction = '<?php echo esc_js(self::$prefix."-dismiss-notice"); ?>';
|
681 |
+
var _wpnonce = '<?php echo wp_create_nonce(self::$prefix."-ajax-dismiss")?>';
|
682 |
+
var noticeClass = '<?php echo esc_js(self::$prefix."-notice");?>';
|
683 |
+
|
684 |
+
jQuery('.'+dismissClass).click(function(e){
|
685 |
+
e.preventDefault();
|
686 |
+
var noticeID= $(this).parents('.'+noticeClass).attr('id').substring(noticeClass.length+1);
|
687 |
+
|
688 |
+
$.post(ajaxurl, {
|
689 |
+
action: ajaxaction,
|
690 |
+
notice: noticeID,
|
691 |
+
_wpnonce: _wpnonce
|
692 |
+
}, function (response) {
|
693 |
+
if ('1' === response) {
|
694 |
+
$('#'+noticeClass+'-'+noticeID).fadeOut('slow');
|
695 |
+
} else {
|
696 |
+
$('#'+noticeClass+'-'+noticeID).removeClass('updated').addClass('error');
|
697 |
+
}
|
698 |
+
});
|
699 |
+
});
|
700 |
+
});
|
701 |
+
</script><?php
|
702 |
+
}
|
703 |
+
}//End EO_Admin_Notice_Handler
|
704 |
+
EO_Admin_Notice_Handler::load();
|
705 |
+
|
706 |
+
|
707 |
+
/**
|
708 |
+
* Handles city auto-fill request.
|
709 |
+
*
|
710 |
+
* Hooked onto admin_post_eo-autofillcity. Triggered when user clicks 'autofill' link.
|
711 |
+
* This routine goes through all the venues, reverse geocodes to find their city and
|
712 |
+
* autofills the city field (added in 1.7).
|
713 |
+
*
|
714 |
+
*@ignore
|
715 |
+
*@access private
|
716 |
+
*@link https://github.com/stephenh1988/Event-Organiser/issues/18
|
717 |
+
*@link http://open.mapquestapi.com/nominatim/ Nominatim Search Service
|
718 |
+
*/
|
719 |
+
function _eventorganiser_autofill_city(){
|
720 |
+
$seen_notices = get_option('eventorganiser_admin_notices',array());
|
721 |
+
|
722 |
+
if( in_array('autofillvenue17', $seen_notices) )
|
723 |
+
return;
|
724 |
+
|
725 |
+
EO_Admin_Notice_Handler::dismiss_notice('autofillvenue17');
|
726 |
+
|
727 |
+
$cities =array();
|
728 |
+
$venues = eo_get_venues();
|
729 |
+
|
730 |
+
foreach( $venues as $venue ){
|
731 |
+
$venue_id = (int) $venue->term_id;
|
732 |
+
$latlng =extract(eo_get_venue_latlng($venue_id));
|
733 |
+
|
734 |
+
If( eo_get_venue_meta($venue_id,'_city',true) )
|
735 |
+
continue;
|
736 |
+
|
737 |
+
$response=wp_remote_get("http://open.mapquestapi.com/nominatim/v1/reverse?format=json&lat={$lat}&lon={$lng}&osm_type=N&limit=1");
|
738 |
+
$geo = json_decode(wp_remote_retrieve_body( $response ));
|
739 |
+
if( isset($geo->address->city) ){
|
740 |
+
$cities[$venue_id] = $geo->address->city;
|
741 |
+
eo_update_venue_meta($venue_id, '_city', $geo->address->city);
|
742 |
+
}
|
743 |
+
if( isset($geo->address->country_code) && 'gb' == $geo->address->country_code ){
|
744 |
+
//For the UK use county not state.
|
745 |
+
if( isset($geo->address->county) ){
|
746 |
+
$cities[$venue_id] = $geo->address->county;
|
747 |
+
eo_update_venue_meta($venue_id, '_state', $geo->address->county);
|
748 |
+
}
|
749 |
+
}else{
|
750 |
+
if( isset($geo->address->state) ){
|
751 |
+
$cities[$venue_id] = $geo->address->state;
|
752 |
+
eo_update_venue_meta($venue_id, '_state', $geo->address->state);
|
753 |
+
}
|
754 |
+
}
|
755 |
+
}
|
756 |
+
|
757 |
+
wp_safe_redirect(admin_url('edit.php?post_type=event&page=venues'));
|
758 |
+
}
|
759 |
+
add_action('admin_post_eo-autofillcity','_eventorganiser_autofill_city');
|
760 |
+
|
761 |
+
function _eventorganiser_theme_check_results(){
|
762 |
+
delete_option( 'eo_wp_footer_present' );
|
763 |
+
delete_option( 'eo_sidebar_correct' );
|
764 |
+
}
|
765 |
+
add_action( 'switch_theme', '_eventorganiser_theme_check_results' );
|
766 |
+
|
767 |
+
function _eventorganiser_check_sidebars( $sidebar ){
|
768 |
+
$before_widget = $sidebar['before_widget'];
|
769 |
+
|
770 |
+
if( did_action( 'register_sidebar') > 1 && ( -1 == get_option( 'eo_sidebar_correct' ) ) )
|
771 |
+
return;
|
772 |
+
|
773 |
+
if( strpos( $before_widget, '%1$s' ) == false || strpos( $before_widget, '%2$s' ) == false ){
|
774 |
+
update_option( 'eo_sidebar_correct', -1 );
|
775 |
+
}else{
|
776 |
+
update_option( 'eo_sidebar_correct', 1 );
|
777 |
+
}
|
778 |
+
}
|
779 |
+
|
780 |
+
?>
|
includes/event-organiser-templates.php
ADDED
@@ -0,0 +1,269 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Template functions
|
4 |
+
*
|
5 |
+
* @package template-functions
|
6 |
+
*/
|
7 |
+
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Load a template part into a template
|
11 |
+
*
|
12 |
+
* Identical to {@see `get_template_part()`} except that it uses {@see `eo_locate_template()`}
|
13 |
+
* instead of {@see `locate_template()`}.
|
14 |
+
*
|
15 |
+
* Makes it easy for a theme to reuse sections of code in a easy to overload way
|
16 |
+
* for child themes. Looks for and includes templates {$slug}-{$name}.php
|
17 |
+
*
|
18 |
+
* You may include the same template part multiple times.
|
19 |
+
*
|
20 |
+
* @uses eo_locate_template()
|
21 |
+
* @since 1.7
|
22 |
+
* @uses do_action() Calls `get_template_part_{$slug}` action.
|
23 |
+
*
|
24 |
+
* @param string $slug The slug name for the generic template.
|
25 |
+
* @param string $name The name of the specialised template.
|
26 |
+
*/
|
27 |
+
function eo_get_template_part( $slug, $name = null ) {
|
28 |
+
do_action( "get_template_part_{$slug}", $slug, $name );
|
29 |
+
|
30 |
+
$templates = array();
|
31 |
+
if ( isset($name) )
|
32 |
+
$templates[] = "{$slug}-{$name}.php";
|
33 |
+
|
34 |
+
$templates[] = "{$slug}.php";
|
35 |
+
|
36 |
+
eo_locate_template($templates, true, false);
|
37 |
+
}
|
38 |
+
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Retrieve the name of the highest priority template file that exists.
|
42 |
+
*
|
43 |
+
* Searches the child theme first, then the parent theme before checking the plug-in templates folder.
|
44 |
+
* So parent themes can override the default plug-in templates, and child themes can over-ride both.
|
45 |
+
*
|
46 |
+
* Behaves almost identically to {@see locate_template()}
|
47 |
+
*
|
48 |
+
* @since 1.7
|
49 |
+
*
|
50 |
+
* @param string|array $template_names Template file(s) to search for, in order.
|
51 |
+
* @param bool $load If true the template file will be loaded if it is found.
|
52 |
+
* @param bool $require_once Whether to require_once or require. Default true. Has no effect if $load is false.
|
53 |
+
* @return string The template filename if one is located.
|
54 |
+
*/
|
55 |
+
function eo_locate_template($template_names, $load = false, $require_once = true ) {
|
56 |
+
$located = '';
|
57 |
+
|
58 |
+
$template_dir = get_stylesheet_directory(); //child theme
|
59 |
+
$parent_template_dir = get_template_directory(); //parent theme
|
60 |
+
|
61 |
+
$stack = apply_filters( 'eventorganiser_template_stack', array( $template_dir, $parent_template_dir, EVENT_ORGANISER_DIR . 'templates' ) );
|
62 |
+
|
63 |
+
foreach ( (array) $template_names as $template_name ) {
|
64 |
+
if ( !$template_name )
|
65 |
+
continue;
|
66 |
+
foreach ( $stack as $template_stack ){
|
67 |
+
if ( file_exists( trailingslashit( $template_stack ) . $template_name ) ) {
|
68 |
+
$located = trailingslashit( $template_stack ) . $template_name;
|
69 |
+
break;
|
70 |
+
}
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
if ( $load && '' != $located )
|
75 |
+
load_template( $located, $require_once );
|
76 |
+
|
77 |
+
return $located;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Whether an event archive is being viewed
|
82 |
+
*
|
83 |
+
* My specifying the type of archive ( e.g. 'day', 'month' or 'year'), we can check if its
|
84 |
+
* a day, month or year archive. By default, it will just return `is_post_type_archive('event')`
|
85 |
+
*
|
86 |
+
* You can get the date of the archive via {@see `eo_get_event_archive_date()`}
|
87 |
+
*
|
88 |
+
*@uses is_post_type_archive()
|
89 |
+
*@since 1.7
|
90 |
+
*@param string $type The type archive. 'day', 'month', or 'year'
|
91 |
+
*@return bool Whether an event archive is being viewed, where type is specified, if its an event archive of that type.
|
92 |
+
*/
|
93 |
+
function eo_is_event_archive( $type = false ){
|
94 |
+
|
95 |
+
if( !is_post_type_archive('event') )
|
96 |
+
return false;
|
97 |
+
|
98 |
+
$ondate = str_replace('/','-',get_query_var('ondate'));
|
99 |
+
|
100 |
+
switch( $type ){
|
101 |
+
case 'year':
|
102 |
+
if( _eventorganiser_check_datetime( $ondate.'-01-01 00:00', 'Y-m-d' ) )
|
103 |
+
return true;
|
104 |
+
return false;
|
105 |
+
|
106 |
+
case 'month':
|
107 |
+
if( _eventorganiser_check_datetime( $ondate.'-01 00:00', 'Y-m-d' ) )
|
108 |
+
return true;
|
109 |
+
return false;
|
110 |
+
|
111 |
+
case 'day':
|
112 |
+
if( _eventorganiser_check_datetime( $ondate.' 00:00', 'Y-m-d') )
|
113 |
+
return true;
|
114 |
+
return false;
|
115 |
+
|
116 |
+
default:
|
117 |
+
return true;
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Returns formatted date of an event archive.
|
123 |
+
*
|
124 |
+
* Returns the formatted ate of an event archive. E.g. for date archives, returns that date,
|
125 |
+
* for year archives returns 1st January of that year, for month archives 1st of that month.
|
126 |
+
* The date is formatted according to `$format` via {@see `eo_format_datetime()`}
|
127 |
+
*
|
128 |
+
* @since 1.7
|
129 |
+
* @uses is_post_type_archive()
|
130 |
+
* @uses eo_format_datetime()
|
131 |
+
* @link http://php.net/manual/en/function.date.php Formatting dates
|
132 |
+
* @param string|constant $format How to format the date, see http://php.net/manual/en/function.date.php or DATETIMEOBJ constant to return the datetime object.
|
133 |
+
* @return string|dateTime The formatted date
|
134 |
+
*/
|
135 |
+
function eo_get_event_archive_date( $format = DATETIMEOBJ ){
|
136 |
+
|
137 |
+
if( !is_post_type_archive('event') )
|
138 |
+
return false;
|
139 |
+
|
140 |
+
$ondate = str_replace('/','-',get_query_var('ondate'));
|
141 |
+
$parts = count(explode('-',$ondate));
|
142 |
+
|
143 |
+
if( $parts == 1 && is_numeric($ondate) ){
|
144 |
+
//Numeric - interpret as year
|
145 |
+
$ondate .= '-01-01';
|
146 |
+
}elseif( $parts == 2 ){
|
147 |
+
// 2012-01 format: interpret as month
|
148 |
+
$ondate .= '-01';
|
149 |
+
}
|
150 |
+
|
151 |
+
$ondate = _eventorganiser_check_datetime( $ondate.' 00:00', 'Y-m-d' );
|
152 |
+
return eo_format_datetime($ondate, $format);
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Checks if provided template path points to an 'event' template recognised by EO, given the context.
|
157 |
+
* This will one day ignore context, and if only the event archive template is present in theme folder
|
158 |
+
* it will use that regardless. If no event-archive tempate is present the plug-in will pick the most appropriate
|
159 |
+
* option, first from the theme/child-theme directory then the plugin.
|
160 |
+
*
|
161 |
+
* @ignore
|
162 |
+
* @since 1.3.1
|
163 |
+
*
|
164 |
+
* @param string $templatePath absolute path to template or filename (with .php extension)
|
165 |
+
* @param string $context What the template is for ('event','archive-event','event-venue', etc).
|
166 |
+
* @return (true|false) return true if template is recognised as an 'event' template. False otherwise.
|
167 |
+
*/
|
168 |
+
function eventorganiser_is_event_template($templatePath,$context=''){
|
169 |
+
|
170 |
+
$template = basename($templatePath);
|
171 |
+
|
172 |
+
switch($context):
|
173 |
+
case 'event';
|
174 |
+
return $template == 'single-event.php';
|
175 |
+
|
176 |
+
case 'archive':
|
177 |
+
return $template == 'archive-event.php';
|
178 |
+
|
179 |
+
case 'event-venue':
|
180 |
+
if((1 == preg_match('/^taxonomy-event-venue((-(\S*))?).php/',$template) || $template == 'venues-template.php'))
|
181 |
+
return true;
|
182 |
+
return false;
|
183 |
+
|
184 |
+
case 'event-category':
|
185 |
+
return (1 == preg_match('/^taxonomy-event-category((-(\S*))?).php/',$template));
|
186 |
+
|
187 |
+
case 'event-tag':
|
188 |
+
return (1 == preg_match('/^taxonomy-event-tag((-(\S*))?).php/',$template));
|
189 |
+
endswitch;
|
190 |
+
|
191 |
+
return false;
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Checks to see if appropriate templates are present in active template directory.
|
196 |
+
* Otherwises uses templates present in plugin's template directory.
|
197 |
+
* Hooked onto template_include'
|
198 |
+
*
|
199 |
+
* @ignore
|
200 |
+
* @since 1.0.0
|
201 |
+
* @param string $template Absolute path to template
|
202 |
+
* @return string Absolute path to template
|
203 |
+
*/
|
204 |
+
function eventorganiser_set_template( $template ){
|
205 |
+
|
206 |
+
//Has EO template handling been turned off?
|
207 |
+
if( !eventorganiser_get_option('templates') )
|
208 |
+
return $template;
|
209 |
+
|
210 |
+
//If WordPress couldn't find an 'event' template use plug-in instead:
|
211 |
+
|
212 |
+
if( is_post_type_archive('event') && !eventorganiser_is_event_template($template,'archive'))
|
213 |
+
$template = EVENT_ORGANISER_DIR.'templates/archive-event.php';
|
214 |
+
|
215 |
+
if( ( is_tax('event-venue') || eo_is_venue() ) && !eventorganiser_is_event_template($template,'event-venue'))
|
216 |
+
$template = EVENT_ORGANISER_DIR.'templates/taxonomy-event-venue.php';
|
217 |
+
|
218 |
+
if( is_tax('event-category') && !eventorganiser_is_event_template($template,'event-category'))
|
219 |
+
$template = EVENT_ORGANISER_DIR.'templates/taxonomy-event-category.php';
|
220 |
+
|
221 |
+
if( is_tax('event-tag') && eventorganiser_get_option('eventtag') && !eventorganiser_is_event_template($template,'event-tag') )
|
222 |
+
$template = EVENT_ORGANISER_DIR.'templates/taxonomy-event-tag.php';
|
223 |
+
|
224 |
+
/*
|
225 |
+
* In view of theme compatibility, if an event template isn't found
|
226 |
+
* rather than using our own single-event.php, we use ordinary single.php and
|
227 |
+
* add content in via the_content
|
228 |
+
*/
|
229 |
+
if( is_singular('event') && !eventorganiser_is_event_template($template,'event') ){
|
230 |
+
//Viewing a single event
|
231 |
+
|
232 |
+
//Hide next/previous post link
|
233 |
+
add_filter("next_post_link",'__return_false');
|
234 |
+
add_filter("previous_post_link",'__return_false');
|
235 |
+
|
236 |
+
//Prepend our event details
|
237 |
+
add_filter('the_content','_eventorganiser_single_event_content');
|
238 |
+
}
|
239 |
+
|
240 |
+
return $template;
|
241 |
+
}
|
242 |
+
add_filter('template_include', 'eventorganiser_set_template');
|
243 |
+
|
244 |
+
|
245 |
+
function _eventorganiser_single_event_content( $content ){
|
246 |
+
|
247 |
+
//Sanity check!
|
248 |
+
if( !is_singular('event') )
|
249 |
+
return $content;
|
250 |
+
|
251 |
+
global $eo_event_parsed;
|
252 |
+
if( !empty( $eo_event_parsed[get_the_ID()] ) ){
|
253 |
+
return $content;
|
254 |
+
}else{
|
255 |
+
$eo_event_parsed[get_the_ID()] = 1;
|
256 |
+
}
|
257 |
+
|
258 |
+
//Object buffering
|
259 |
+
ob_start();
|
260 |
+
eo_get_template_part('event-meta','event-single');
|
261 |
+
//include(EVENT_ORGANISER_DIR.'templates/event-meta-event-single.php');
|
262 |
+
$event_content = ob_get_contents();
|
263 |
+
ob_end_clean();
|
264 |
+
|
265 |
+
$event_content = apply_filters('eventorganiser_pre_event_content', $event_content, $content);
|
266 |
+
|
267 |
+
return $event_content.$content;
|
268 |
+
}
|
269 |
+
?>
|
includes/event-organiser-utility-functions.php
ADDED
@@ -0,0 +1,910 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Utility functions
|
4 |
+
*
|
5 |
+
* @package utility-functions
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Formats a datetime object into a specified format and handles translations.
|
10 |
+
* Used by
|
11 |
+
*
|
12 |
+
* * {@see `eo_get_the_start()`}
|
13 |
+
* * {@see `eo_get_the_end()`}
|
14 |
+
* * {@see `eo_get_schedule_start()`}
|
15 |
+
* * {@see `eo_get_schedule_last()`}
|
16 |
+
*
|
17 |
+
* The constant DATETIMEOBJ can be passed to them to get datetime objects
|
18 |
+
* Applies {@see `eventorganiser_format_datetime`} filter
|
19 |
+
*
|
20 |
+
* @since 1.2.0
|
21 |
+
* @link http://php.net/manual/en/function.date.php PHP Date
|
22 |
+
*
|
23 |
+
* @param dateTime $datetime The datetime to format
|
24 |
+
* @param string|constant $format How to format the date, see http://php.net/manual/en/function.date.php or DATETIMEOBJ constant to return the datetime object.
|
25 |
+
* @return string|dateTime The formatted date
|
26 |
+
*/
|
27 |
+
function eo_format_datetime($datetime,$format='d-m-Y'){
|
28 |
+
global $wp_locale;
|
29 |
+
|
30 |
+
if( DATETIMEOBJ == $format )
|
31 |
+
return $datetime;
|
32 |
+
|
33 |
+
if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) :
|
34 |
+
//Translate
|
35 |
+
$datemonth = $wp_locale->get_month($datetime->format('m'));
|
36 |
+
$datemonth_abbrev = $wp_locale->get_month_abbrev($datemonth);
|
37 |
+
$dateweekday = $wp_locale->get_weekday($datetime->format('w'));
|
38 |
+
$dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
|
39 |
+
$datemeridiem = trim($wp_locale->get_meridiem($datetime->format('a')));
|
40 |
+
$datemeridiem_capital =$wp_locale->get_meridiem($datetime->format('A'));
|
41 |
+
|
42 |
+
$datemeridiem = (empty($datemeridiem) ? $datetime->format('a') : $datemeridiem);
|
43 |
+
|
44 |
+
$dateformatstring = ' '.$format;
|
45 |
+
$dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
|
46 |
+
$dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
|
47 |
+
$dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
|
48 |
+
$dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
|
49 |
+
$dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
|
50 |
+
$dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
|
51 |
+
$dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
|
52 |
+
endif;
|
53 |
+
$formatted_datetime = $datetime->format($dateformatstring);
|
54 |
+
return apply_filters('eventorganiser_format_datetime', $formatted_datetime , $format, $datetime);
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Formats a date string in the format 'YYYY-MM-DD H:i:s' format or even
|
59 |
+
* relative strings like 'today' into a specified format.
|
60 |
+
*
|
61 |
+
* @uses eo_format_datetime()
|
62 |
+
* @since 1.2.0
|
63 |
+
* @link http://php.net/manual/en/function.date.php PHP Date
|
64 |
+
*
|
65 |
+
* @param string $dateString The date as a string
|
66 |
+
* @param string $format How to format the date. DATETIMEOBJ for datetime object.
|
67 |
+
* @return string|dateTime The formatted date
|
68 |
+
*/
|
69 |
+
function eo_format_date($dateString='',$format='d-m-Y'){
|
70 |
+
|
71 |
+
if($format!=''&& $dateString!=''){
|
72 |
+
$datetime = new DateTime($dateString, eo_get_blog_timezone());
|
73 |
+
$formated = eo_format_datetime($datetime,$format);
|
74 |
+
return $formated;
|
75 |
+
}
|
76 |
+
return false;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Returns the blog timezone
|
81 |
+
*
|
82 |
+
* Gets timezone settings from the db. If a timezone identifier is used just turns
|
83 |
+
* it into a DateTimeZone. If an offset is usd, it tries to find a suitable timezone.
|
84 |
+
* If all else fails it uses UTC.
|
85 |
+
*
|
86 |
+
* @since 1.3.0
|
87 |
+
*
|
88 |
+
* @return DateTimeZone The blog timezone
|
89 |
+
*/
|
90 |
+
function eo_get_blog_timezone(){
|
91 |
+
$tzstring = wp_cache_get( 'eventorganiser_timezone' );
|
92 |
+
|
93 |
+
if ( false === $tzstring ) {
|
94 |
+
|
95 |
+
$tzstring =get_option('timezone_string');
|
96 |
+
$offset = get_option('gmt_offset');
|
97 |
+
|
98 |
+
// Remove old Etc mappings. Fallback to gmt_offset.
|
99 |
+
if ( !empty($tz_string) && false !== strpos($tzstring,'Etc/GMT') )
|
100 |
+
$tzstring = '';
|
101 |
+
|
102 |
+
if( empty($tzstring) && $offset!=0 ):
|
103 |
+
//use offset
|
104 |
+
$offset *= 3600; // convert hour offset to seconds
|
105 |
+
$allowed_zones = timezone_abbreviations_list();
|
106 |
+
|
107 |
+
foreach ($allowed_zones as $abbr):
|
108 |
+
foreach ($abbr as $city):
|
109 |
+
if ($city['offset'] == $offset){
|
110 |
+
$tzstring=$city['timezone_id'];
|
111 |
+
break 2;
|
112 |
+
}
|
113 |
+
endforeach;
|
114 |
+
endforeach;
|
115 |
+
endif;
|
116 |
+
|
117 |
+
//Issue with the timezone selected, set to 'UTC'
|
118 |
+
if( empty($tzstring) ):
|
119 |
+
$tzstring = 'UTC';
|
120 |
+
endif;
|
121 |
+
|
122 |
+
//Cache timezone string not timezone object
|
123 |
+
//Thanks to Ben Huson http://wordpress.org/support/topic/plugin-event-organiser-getting-500-is-error-when-w3-total-cache-is-on
|
124 |
+
wp_cache_set( 'eventorganiser_timezone', $tzstring );
|
125 |
+
}
|
126 |
+
|
127 |
+
if( $tzstring instanceof DateTimeZone)
|
128 |
+
return $tzstring;
|
129 |
+
|
130 |
+
$timezone = new DateTimeZone($tzstring);
|
131 |
+
return $timezone;
|
132 |
+
}
|
133 |
+
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Calculates and formats an interval between two days, passed in any order.
|
137 |
+
* It's a PHP 5.2 workaround for {@link http://www.php.net/manual/en/dateinterval.format.php date interval format}
|
138 |
+
* @since 1.5
|
139 |
+
*
|
140 |
+
* @param dateTime $_date1 One date to compare
|
141 |
+
* @param dateTime $_date2 Second date to compare
|
142 |
+
* @param string $format Used to format the interval. See http://www.php.net/manual/en/dateinterval.format.php
|
143 |
+
* @return string Formatted interval.
|
144 |
+
*/
|
145 |
+
function eo_date_interval($_date1,$_date2, $format){
|
146 |
+
|
147 |
+
//Calculate R values (signs)
|
148 |
+
$R = ($_date1 <= $_date2 ? '+' : '-');
|
149 |
+
$r = ($_date1 <= $_date2 ? '' : '-');
|
150 |
+
|
151 |
+
//Make sure $date1 is ealier
|
152 |
+
$date1 = ($_date1 <= $_date2 ? $_date1 : $_date2);
|
153 |
+
$date2 = ($_date1 <= $_date2 ? $_date2 : $_date1);
|
154 |
+
|
155 |
+
//Calculate total days difference
|
156 |
+
$total_days = round(abs($date1->format('U') - $date2->format('U'))/86400);
|
157 |
+
|
158 |
+
//A leap year work around - consistent with DateInterval
|
159 |
+
$leap_year = ( $date1->format('m-d') == '02-29' ? true : false);
|
160 |
+
if( $leap_year ){
|
161 |
+
//This will only effect counting the number of days - and is corrected later.
|
162 |
+
//Otherwise incrementing $date1 by a year will overflow to March
|
163 |
+
$date1->modify('-1 day');
|
164 |
+
}
|
165 |
+
|
166 |
+
$periods = array( 'years'=>-1,'months'=>-1,'days'=>-1,'hours'=>-1);
|
167 |
+
|
168 |
+
foreach ($periods as $period => &$i ){
|
169 |
+
|
170 |
+
if($period == 'days' && $leap_year )
|
171 |
+
$date1->modify('+1 day');//Corrects earlier adjustment
|
172 |
+
|
173 |
+
while( $date1 <= $date2 ){
|
174 |
+
$date1->modify('+1 '.$period);
|
175 |
+
$i++;
|
176 |
+
}
|
177 |
+
|
178 |
+
//Reset date and record increments
|
179 |
+
$date1->modify('-1 '.$period);
|
180 |
+
}
|
181 |
+
extract($periods);
|
182 |
+
|
183 |
+
//Minutes, seconds
|
184 |
+
$seconds = round(abs($date1->format('U') - $date2->format('U')));
|
185 |
+
$minutes = floor($seconds/60);
|
186 |
+
$seconds = $seconds - $minutes*60;
|
187 |
+
|
188 |
+
$replace = array(
|
189 |
+
'/%y/' => $years,
|
190 |
+
'/%Y/' => zeroise($years,2),
|
191 |
+
'/%m/' => $months,
|
192 |
+
'/%M/' => zeroise($months,2),
|
193 |
+
'/%d/' => $days,
|
194 |
+
'/%D/' => zeroise($days,2),
|
195 |
+
'/%a/' => zeroise($total_days,2),
|
196 |
+
'/%h/' => $hours,
|
197 |
+
'/%H/' => zeroise($hours,2),
|
198 |
+
'/%i/' => $minutes,
|
199 |
+
'/%I/' =>zeroise($minutes,2),
|
200 |
+
'/%s/' => $seconds,
|
201 |
+
'/%S/' => zeroise($seconds,2),
|
202 |
+
'/%r/' => $r,
|
203 |
+
'/%R/' => $R
|
204 |
+
);
|
205 |
+
|
206 |
+
return preg_replace(array_keys($replace), array_values($replace), $format);
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Very basic class to convert php date format into xdate date format used for javascript.
|
211 |
+
*
|
212 |
+
* Takes a php date format and converts it to {@link http://arshaw.com/xdate/#Formatting xdate format} so
|
213 |
+
* that it can b used in javascript (notably the fullCalendar).
|
214 |
+
*
|
215 |
+
* Doesn't support
|
216 |
+
*L Whether it's a leap year
|
217 |
+
* N ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0)
|
218 |
+
* w Numeric representation of the day of the week (0=sun,...)
|
219 |
+
* z The day of the year (starting from 0)
|
220 |
+
* t Number of days in the given month
|
221 |
+
* B Swatch Internet time
|
222 |
+
* u microseconds
|
223 |
+
*
|
224 |
+
* e Timezone identifier (added in PHP 5.1.0) Examples: UTC, GMT, Atlantic/Azores
|
225 |
+
* I (capital i) Whether or not the date is in daylight saving time 1 if Daylight Saving Time, 0 otherwise.
|
226 |
+
* O Difference to Greenwich time (GMT) in hours Example: +0200
|
227 |
+
* T Timezone abbreviation Examples: EST, MDT ...
|
228 |
+
* Z Timezone offset in seconds. The offset for timezones west of UTC is always negative, and for those east of UTC is always positive.
|
229 |
+
|
230 |
+
* c ISO 8601 date (added in PHP 5) 2004-02-12T15:19:21+00:00
|
231 |
+
* r RFC 2822 formatted date Example: Thu, 21 Dec 2000 16:01:07 +0200
|
232 |
+
* U Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) See also time()
|
233 |
+
*
|
234 |
+
* @since 1.4
|
235 |
+
*
|
236 |
+
*@param string $phpformat Format according to http://php.net/manual/en/function.date.php
|
237 |
+
*@return string The format translated to xdate format: http://arshaw.com/xdate/#Formatting
|
238 |
+
*/
|
239 |
+
function eventorganiser_php2xdate($phpformat=""){
|
240 |
+
$php2xdate = array(
|
241 |
+
'Y'=>'yyyy','y'=>'yy','L'=>''/*Not Supported*/,'o'=>'I',
|
242 |
+
'j'=>'d','d'=>'dd','D'=>'ddd','l'=>'dddd','N'=>'', /*NS*/ 'S'=>'S',
|
243 |
+
'w'=>'', /*NS*/ 'z'=>'',/*NS*/ 'W'=>'w',
|
244 |
+
'F'=>'MMMM','m'=>'MM','M'=>'MMM','n'=>'M','t'=>'',/*NS*/
|
245 |
+
'a'=>'tt','A'=>'TT',
|
246 |
+
'B'=>'',/*NS*/'g'=>'h','G'=>'H','h'=>'hh','H'=>'HH','u'=>'fff',
|
247 |
+
'i'=>'mm','s'=>'ss',
|
248 |
+
'O'=>'zz ', 'P'=>'zzz',
|
249 |
+
'c'=>'u',
|
250 |
+
);
|
251 |
+
|
252 |
+
$xdateformat="";
|
253 |
+
|
254 |
+
for($i=0; $i< strlen($phpformat); $i++){
|
255 |
+
|
256 |
+
//Handle backslash excape
|
257 |
+
if($phpformat[$i]=="\\"){
|
258 |
+
$xdateformat .= "\\".$phpformat[$i+1];
|
259 |
+
$i++;
|
260 |
+
continue;
|
261 |
+
}
|
262 |
+
|
263 |
+
if(isset($php2xdate[$phpformat[$i]])){
|
264 |
+
$xdateformat .= $php2xdate[$phpformat[$i]];
|
265 |
+
}else{
|
266 |
+
$xdateformat .= $phpformat[$i];
|
267 |
+
}
|
268 |
+
}
|
269 |
+
return $xdateformat;
|
270 |
+
}
|
271 |
+
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Very basic class to convert php date format into jQuery UI date format used for javascript.
|
275 |
+
*
|
276 |
+
* Similar to {@see `eventorganiser_php2xdate()`} - but the format is slightly different for jQuery UI
|
277 |
+
* Takes a php date format and converts it to {@link http://docs.jquery.com/UI/Datepicker/formatDate} so
|
278 |
+
* that it can b used in javascript (notably by the datepicker).
|
279 |
+
*
|
280 |
+
* **Please note that this function does not convert time formats**
|
281 |
+
*
|
282 |
+
* @since 1.7
|
283 |
+
*
|
284 |
+
*@param string $phpformat Format according to http://php.net/manual/en/function.date.php
|
285 |
+
*@return string The format translated to xdate format: http://docs.jquery.com/UI/Datepicker/formatDate
|
286 |
+
*/
|
287 |
+
function eventorganiser_php2jquerydate($phpformat=""){
|
288 |
+
$php2jquerydate = array(
|
289 |
+
'Y'=>'yy','y'=>'y','L'=>''/*Not Supported*/,'o'=>'',/*Not Supported*/
|
290 |
+
'j'=>'d','d'=>'dd','D'=>'D','DD'=>'dddd','N'=>'',/*NS*/ 'S' => ''/*NS*/,
|
291 |
+
'w'=>'', /*NS*/ 'z'=>'o',/*NS*/ 'W'=>'w',
|
292 |
+
'F'=>'MM','m'=>'mm','M'=>'M','n'=>'m','t'=>'',/*NS*/
|
293 |
+
'a'=>''/*NS*/,'A'=>''/*NS*/,
|
294 |
+
'B'=>'',/*NS*/'g'=>''/*NS*/,'G'=>''/*NS*/,'h'=>''/*NS*/,'H'=>''/*NS*/,'u'=>'fff',
|
295 |
+
'i'=>''/*NS*/,'s'=>''/*NS*/,
|
296 |
+
'O'=>''/*NS*/, 'P'=>''/*NS*/,
|
297 |
+
);
|
298 |
+
|
299 |
+
$jqueryformat="";
|
300 |
+
|
301 |
+
for($i=0; $i< strlen($phpformat); $i++){
|
302 |
+
|
303 |
+
//Handle backslash excape
|
304 |
+
if($phpformat[$i]=="\\"){
|
305 |
+
$jqueryformat .= "\\".$phpformat[$i+1];
|
306 |
+
$i++;
|
307 |
+
continue;
|
308 |
+
}
|
309 |
+
|
310 |
+
if(isset($php2jquerydate[$phpformat[$i]])){
|
311 |
+
$jqueryformat .= $php2jquerydate[$phpformat[$i]];
|
312 |
+
}else{
|
313 |
+
$jqueryformat .= $phpformat[$i];
|
314 |
+
}
|
315 |
+
}
|
316 |
+
return $jqueryformat;
|
317 |
+
}
|
318 |
+
|
319 |
+
|
320 |
+
/**
|
321 |
+
* A utilty function intended for removing duplicate DateTime objects from array
|
322 |
+
* @since 1.5
|
323 |
+
*@access private
|
324 |
+
* @ignore
|
325 |
+
*
|
326 |
+
* @param array $array Array of DateTime objects (though can work for other objects)
|
327 |
+
* @return array A sub-array of the passed array, containing only unique elements.
|
328 |
+
*/
|
329 |
+
function _eventorganiser_remove_duplicates( $array=array() ){
|
330 |
+
//Do we need to worry about the times of the date-time objects?
|
331 |
+
|
332 |
+
if( empty($array) )
|
333 |
+
return $array;
|
334 |
+
|
335 |
+
$unique = array();
|
336 |
+
foreach ($array as $key=>$object){
|
337 |
+
if( !in_array($object, $unique) )
|
338 |
+
$unique[$key] = $object;
|
339 |
+
}
|
340 |
+
|
341 |
+
return $unique;
|
342 |
+
}
|
343 |
+
|
344 |
+
|
345 |
+
/**
|
346 |
+
* Utility function Compares two DateTime object,
|
347 |
+
* Returns +1 if the first date is after, -1 if its before or 0 if they're the same
|
348 |
+
* Note: does not compare *times*.
|
349 |
+
* Used to filter occurrances with udiff
|
350 |
+
*
|
351 |
+
* @access private
|
352 |
+
* @ignore
|
353 |
+
* @since 1.0.0
|
354 |
+
*
|
355 |
+
* @param dateTime $date1 The first date to compare
|
356 |
+
* @param dateTime $date2 The second date to compare
|
357 |
+
* @return int 1 | 0 | -1
|
358 |
+
*/
|
359 |
+
function _eventorganiser_compare_dates($date1,$date2){
|
360 |
+
//Don't wish to compare times
|
361 |
+
if($date1->format('Ymd') == $date2->format('Ymd'))
|
362 |
+
return 0;
|
363 |
+
|
364 |
+
return ($date1 > $date2)? 1:-1;
|
365 |
+
}
|
366 |
+
|
367 |
+
|
368 |
+
|
369 |
+
/**
|
370 |
+
* A workaround which handles "[ordinal] [day] of +(n) month" statements when
|
371 |
+
* using php 5.2.
|
372 |
+
*
|
373 |
+
* @access private
|
374 |
+
* @ignore
|
375 |
+
* @since 1.3
|
376 |
+
*
|
377 |
+
* @param dateTime $date dateTime object to modify
|
378 |
+
* @param string $modify How to modify the date: e.g. 'last Sunday of +2 month'
|
379 |
+
* @return dateTime the modified dateTime object. DateTime is set to blog tz.
|
380 |
+
*/
|
381 |
+
function _eventorganiser_php52_modify($date='',$modify=''){
|
382 |
+
|
383 |
+
//Expect e.g. 'Second Monday of +2 month
|
384 |
+
$pattern = '/([a-zA-Z]+)\s([a-zA-Z]+) of \+(\d+) month/';
|
385 |
+
preg_match($pattern, $modify, $matches);
|
386 |
+
|
387 |
+
$ordinal = array_search(strtolower($matches[1]), array('last','first','second','third','fourth') ); //0-4
|
388 |
+
$day = array_search(strtolower($matches[2]), array('sunday','monday','tuesday','wednesday','thursday','friday','saturday') ); //0-6
|
389 |
+
$freq = intval($matches[3]);
|
390 |
+
|
391 |
+
//set to first day of month
|
392 |
+
$date = date_create($date->format('Y-m-1'));
|
393 |
+
|
394 |
+
//first day of +$freq months
|
395 |
+
$date->modify('+'.$freq.' month');
|
396 |
+
|
397 |
+
//Calculate offset to day of week
|
398 |
+
if($ordinal >0):
|
399 |
+
$offset = ($day-intval($date->format('w')) +7)%7;//Offset to first weekday of that month (e.g. first Monday)
|
400 |
+
$d =($offset) +7*($ordinal-1) +1; //If wanting to get second, third or fourth monday add multiples of 7.
|
401 |
+
|
402 |
+
else:
|
403 |
+
//Ordinal is 'Last'
|
404 |
+
$date = date_create($date->format('Y-m-t'));//Last day
|
405 |
+
$offset = intval(($date->format('w')-$day+7)%7);//Find offset from last day to the last weekday of month (e.g. last Sunday)
|
406 |
+
$d = intval($date->format('t'))-$offset;
|
407 |
+
endif;
|
408 |
+
|
409 |
+
$date = date_create($date->format('Y-m-'.$d), eo_get_blog_timezone());
|
410 |
+
|
411 |
+
return $date;
|
412 |
+
}
|
413 |
+
|
414 |
+
/**
|
415 |
+
* Generates excerpt from contant if needed, and trims to a given length
|
416 |
+
*
|
417 |
+
* Is very simliar to wp_trim_excerpt. Doesn't apply excerpt_more filter
|
418 |
+
* Applies eventorganiser_trim_excerpt filter
|
419 |
+
* Must be used inside the loop
|
420 |
+
*
|
421 |
+
* @since 1.5
|
422 |
+
* @param string $text Optional. The excerpt. If set to empty, an excerpt is generated.
|
423 |
+
* @param int $excerpt_length The excerpt length if generated from content.
|
424 |
+
* @return string The excerpt.
|
425 |
+
*/
|
426 |
+
function eventorganiser_trim_excerpt($text = '', $excerpt_length=55) {
|
427 |
+
$raw_excerpt = $text;
|
428 |
+
if ( '' == $text ) {
|
429 |
+
$text = get_the_content('');
|
430 |
+
$text = strip_shortcodes( $text );
|
431 |
+
$text = apply_filters('the_content', $text);
|
432 |
+
$text = str_replace(']]>', ']]>', $text);
|
433 |
+
$text = wp_trim_words( $text, $excerpt_length, '...' );
|
434 |
+
}
|
435 |
+
return apply_filters('eventorganiser_trim_excerpt', $text, $raw_excerpt);
|
436 |
+
}
|
437 |
+
|
438 |
+
|
439 |
+
/**
|
440 |
+
* A helper function, creates a DateTime object from a date string and sets the timezone to the blog's current timezone
|
441 |
+
*
|
442 |
+
*@since 1.3
|
443 |
+
*@uses date_create()
|
444 |
+
*@param string $datetime_string A date-time in string format
|
445 |
+
*@return datetime The corresponding DateTime object.
|
446 |
+
*/
|
447 |
+
function eventorganiser_date_create($datetime_string){
|
448 |
+
$tz = eo_get_blog_timezone();
|
449 |
+
return date_create($datetime_string,$tz);
|
450 |
+
}
|
451 |
+
|
452 |
+
|
453 |
+
/**
|
454 |
+
* (Private) Utility function checks a date-time string is formatted correctly (according to the options)
|
455 |
+
* @access private
|
456 |
+
* @ignore
|
457 |
+
* @since 1.0.0
|
458 |
+
|
459 |
+
* @param datetime_string - a datetime string
|
460 |
+
* @param string $format - Format of the datetime string. One of 'd-m-Y', 'm-d-Y' and 'Y-m-d'.
|
461 |
+
* @return int DateTime| false - the parsed datetime string as a DateTime object or false on error (incorrectly formatted for example)
|
462 |
+
*/
|
463 |
+
function _eventorganiser_check_datetime( $datetime_string = '', $format = null ){
|
464 |
+
|
465 |
+
if( is_null( $format ) )
|
466 |
+
$format = eventorganiser_get_option('dateformat');
|
467 |
+
|
468 |
+
//Backwards compatible - can probably remove 2.1+
|
469 |
+
if( is_bool( $format ) ){
|
470 |
+
_deprecated_argument('_eventorganiser_check_datetime', '1.8', 'This function no longer accepts a boolean, pass the format of the passed date-time string.');
|
471 |
+
if( true === $format )
|
472 |
+
$format = 'Y-m-d';
|
473 |
+
else
|
474 |
+
$format = eventorganiser_get_option('dateformat');
|
475 |
+
}
|
476 |
+
|
477 |
+
//Get regular expression.
|
478 |
+
if( $format == 'Y-m-d' ){
|
479 |
+
$reg_exp = "/(?P<year>\d{4})[-.\/](?P<month>\d{1,})[-.\/](?P<day>\d{1,}) (?P<hour>\d{2}):(?P<minute>\d{2})/";
|
480 |
+
|
481 |
+
}elseif( $format == 'd-m-Y' ){
|
482 |
+
$reg_exp = "/(?P<day>\d{1,})[-.\/](?P<month>\d{1,})[-.\/](?P<year>\d{4}) (?P<hour>\d{2}):(?P<minute>\d{2})/";
|
483 |
+
|
484 |
+
}else{
|
485 |
+
$reg_exp = "/(?P<month>\d{1,})[-.\/](?P<day>\d{1,})[-.\/](?P<year>\d{4}) (?P<hour>\d{2}):(?P<minute>\d{2})/";
|
486 |
+
}
|
487 |
+
|
488 |
+
if( !preg_match($reg_exp, $datetime_string,$matches) )
|
489 |
+
return false;
|
490 |
+
|
491 |
+
extract(array_map('intval',$matches));
|
492 |
+
|
493 |
+
if ( !checkdate($month, $day, $year) || $hour < 0 || $hour > 23 || $minute < 0 || $minute > 59 )
|
494 |
+
return false;
|
495 |
+
|
496 |
+
$datetime = new DateTime(null, eo_get_blog_timezone());
|
497 |
+
$datetime->setDate($year, $month, $day);
|
498 |
+
$datetime->setTime($hour, $minute);
|
499 |
+
return $datetime;
|
500 |
+
}
|
501 |
+
|
502 |
+
/**
|
503 |
+
* Utility function for printing/returning radio boxes
|
504 |
+
*
|
505 |
+
* The $args array - excepts the following keys
|
506 |
+
*
|
507 |
+
* * **id** - The id of the radiobox (alias: label_for)
|
508 |
+
* * **name** - The name of the radiobox
|
509 |
+
* * **checked** - The the value to have checked
|
510 |
+
* * **options** - Array of options in 'value'=>'Label' format
|
511 |
+
* * **label** - The label for the radiobox field set
|
512 |
+
* * **class** - Class to be added to the radiobox field set
|
513 |
+
* * **echo** - Whether to print the mark-up or just return it
|
514 |
+
* * **help** - Optional, help text to accompany the field.
|
515 |
+
*
|
516 |
+
* @access private
|
517 |
+
* @param $args array The array of arguments
|
518 |
+
*/
|
519 |
+
function eventorganiser_radio_field( $args ){
|
520 |
+
|
521 |
+
$args = wp_parse_args($args,array(
|
522 |
+
'checked'=>'', 'help' => '', 'options'=>'', 'name'=>'', 'echo'=>1,
|
523 |
+
'class'=>'', 'label' => '','label_for'=>''
|
524 |
+
));
|
525 |
+
|
526 |
+
$id = ( !empty($args['id']) ? $args['id'] : $args['label_for']);
|
527 |
+
$name = isset($args['name']) ? $args['name'] : '';
|
528 |
+
$checked = $args['checked'];
|
529 |
+
$label = !empty($args['label']) ? '<legend><label>'.esc_html($args['label']).'</label></legend>' : '';
|
530 |
+
$class = !empty($args['class']) ? 'class="'.sanitize_html_class($args['class']).'"' : '';
|
531 |
+
|
532 |
+
$html = sprintf('<fieldset %s> %s', $class, $label);
|
533 |
+
if( !empty($args['options']) ){
|
534 |
+
foreach ($args['options'] as $value => $opt_label ){
|
535 |
+
$html .= sprintf('<label for="%1$s"><input type="radio" id="%1$s" name="%3$s" value="%4$s" %2$s> <span> %5$s </span></label><br>',
|
536 |
+
esc_attr($id.'_'.$value),
|
537 |
+
checked($value, $checked, false),
|
538 |
+
esc_attr($name),
|
539 |
+
esc_attr($value),
|
540 |
+
esc_html($opt_label));
|
541 |
+
}
|
542 |
+
}
|
543 |
+
if(!empty($args['help'])){
|
544 |
+
$html .= '<p class="description">'.esc_html($args['help']).'</p>';
|
545 |
+
}
|
546 |
+
$html .= '</fieldset>';
|
547 |
+
|
548 |
+
if( $args['echo'] )
|
549 |
+
echo $html;
|
550 |
+
|
551 |
+
return $html;
|
552 |
+
}
|
553 |
+
|
554 |
+
|
555 |
+
/**
|
556 |
+
* Utility function for printing/returning select field
|
557 |
+
*
|
558 |
+
* The $args array - excepts the following keys
|
559 |
+
*
|
560 |
+
* * **id** - The id of the select box (alias: label_for)
|
561 |
+
* * **name** - The name of the select box
|
562 |
+
* * **selected** - The the value to have selected
|
563 |
+
* * **options** - Array of options in 'value'=>'Label' format
|
564 |
+
* * **multiselect** True or False for multi-select
|
565 |
+
* * **label** - The label for the radiobox field set
|
566 |
+
* * **class** - Class to be added to the radiobox field set
|
567 |
+
* * **echo** - Whether to print the mark-up or just return it
|
568 |
+
* * **help** - Optional, help text to accompany the field.
|
569 |
+
*
|
570 |
+
* @access private
|
571 |
+
* @param $args array The array of arguments
|
572 |
+
*/
|
573 |
+
function eventorganiser_select_field($args){
|
574 |
+
|
575 |
+
$args = wp_parse_args($args,array(
|
576 |
+
'selected'=>'', 'help' => null, 'options'=>'', 'name'=>'', 'echo'=>1,
|
577 |
+
'label_for'=>'','class'=>'','disabled'=>false,'multiselect'=>false,
|
578 |
+
'inline_help' => false
|
579 |
+
));
|
580 |
+
|
581 |
+
$id = ( !empty($args['id']) ? $args['id'] : $args['label_for']);
|
582 |
+
$name = isset($args['name']) ? $args['name'] : '';
|
583 |
+
$selected = $args['selected'];
|
584 |
+
$classes = array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) );
|
585 |
+
$class = implode( ' ', $classes );
|
586 |
+
$multiselect = ($args['multiselect'] ? 'multiple' : '' );
|
587 |
+
$disabled = ($args['disabled'] ? 'disabled="disabled"' : '' );
|
588 |
+
|
589 |
+
$html = sprintf('<select %s name="%s" id="%s" %s>',
|
590 |
+
!empty( $class ) ? 'class="'.$class.'"' : '',
|
591 |
+
esc_attr($name),
|
592 |
+
esc_attr($id),
|
593 |
+
$multiselect.' '.$disabled
|
594 |
+
);
|
595 |
+
if( !empty( $args['show_option_all'] ) ){
|
596 |
+
$html .= sprintf('<option value="" %s> %s </option>',selected( empty($selected), true, false ), esc_html( $args['show_option_all'] ) );
|
597 |
+
}
|
598 |
+
|
599 |
+
if( !empty($args['options']) ){
|
600 |
+
foreach ($args['options'] as $value => $label ){
|
601 |
+
if( $args['multiselect'] && is_array($selected) )
|
602 |
+
$_selected = selected( in_array($value, $selected), true, false);
|
603 |
+
else
|
604 |
+
$_selected = selected($selected, $value, false);
|
605 |
+
|
606 |
+
$html .= sprintf('<option value="%s" %s> %s </option>',esc_attr($value),$_selected, esc_html($label));
|
607 |
+
}
|
608 |
+
}
|
609 |
+
$html .= '</select>'. $args['inline_help'];
|
610 |
+
|
611 |
+
if( isset( $args['help'] ) ){
|
612 |
+
$html .= '<p class="description">'.esc_html($args['help']).'</p>';
|
613 |
+
}
|
614 |
+
|
615 |
+
if( $args['echo'] )
|
616 |
+
echo $html;
|
617 |
+
|
618 |
+
return $html;
|
619 |
+
}
|
620 |
+
|
621 |
+
|
622 |
+
/**
|
623 |
+
* Utility function for printing/returning text field
|
624 |
+
*
|
625 |
+
* The $args array - excepts the following keys
|
626 |
+
*
|
627 |
+
* * **id** - The id of the select box (alias: label_for)
|
628 |
+
* * **name** - The name of the select box
|
629 |
+
* * **value** - The value of the text field
|
630 |
+
* * **type** - The type of the text field (e.g. 'text','hidden','password')
|
631 |
+
* * **options** - Array of options in 'value'=>'Label' format
|
632 |
+
* * **label** - The label for the radiobox field set
|
633 |
+
* * **class** - Class to be added to the radiobox field set
|
634 |
+
* * **echo** - Whether to print the mark-up or just return it
|
635 |
+
* * **help** - Optional, help text to accompany the field.
|
636 |
+
*
|
637 |
+
* @access private
|
638 |
+
* @param $args array The array of arguments
|
639 |
+
*/
|
640 |
+
function eventorganiser_text_field($args){
|
641 |
+
|
642 |
+
$args = wp_parse_args( $args,
|
643 |
+
array(
|
644 |
+
'type' => 'text', 'value'=>'', 'placeholder' => '','label_for'=>'', 'inline_help' => false,
|
645 |
+
'size'=>false, 'min' => false, 'max' => false, 'style'=>false, 'echo'=>true, 'data'=>false,
|
646 |
+
'class' => false,
|
647 |
+
)
|
648 |
+
);
|
649 |
+
|
650 |
+
$id = ( !empty($args['id']) ? $args['id'] : $args['label_for']);
|
651 |
+
$name = isset($args['name']) ? $args['name'] : '';
|
652 |
+
$value = $args['value'];
|
653 |
+
$type = $args['type'];
|
654 |
+
$classes = array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) );
|
655 |
+
$class = implode( ' ', $classes );
|
656 |
+
|
657 |
+
$min = ( $args['min'] !== false ? sprintf('min="%d"', $args['min']) : '' );
|
658 |
+
$max = ( $args['max'] !== false ? sprintf('max="%d"', $args['max']) : '' );
|
659 |
+
$size = ( !empty($args['size']) ? sprintf('size="%d"', $args['size']) : '' );
|
660 |
+
$style = ( !empty($args['style']) ? sprintf('style="%s"', $args['style']) : '' );
|
661 |
+
$placeholder = ( !empty($args['placeholder']) ? sprintf('placeholder="%s"', $args['placeholder']) : '');
|
662 |
+
$disabled = ( !empty($args['disabled']) ? 'disabled="disabled"' : '' );
|
663 |
+
|
664 |
+
//Custom data-* attributes
|
665 |
+
$data = '';
|
666 |
+
if( !empty( $args['data'] ) && is_array( $args['data'] ) ){
|
667 |
+
foreach( $args['data'] as $key => $attr_value ){
|
668 |
+
$data .= sprintf( 'data-%s="%s"', esc_attr( $key ), esc_attr( $attr_value ) );
|
669 |
+
}
|
670 |
+
}
|
671 |
+
|
672 |
+
$attributes = array_filter( array($min,$max,$size,$placeholder,$disabled, $style, $data ) );
|
673 |
+
|
674 |
+
$html = sprintf('<input type="%s" name="%s" class="%s regular-text ltr" id="%s" value="%s" autocomplete="off" %s /> %s',
|
675 |
+
esc_attr( $type ),
|
676 |
+
esc_attr( $name ),
|
677 |
+
$class,
|
678 |
+
esc_attr( $id ),
|
679 |
+
esc_attr( $value ),
|
680 |
+
implode(' ', $attributes),
|
681 |
+
$args['inline_help']
|
682 |
+
);
|
683 |
+
|
684 |
+
if( isset($args['help']) ){
|
685 |
+
$html .= '<p class="description">'.$args['help'].'</p>';
|
686 |
+
}
|
687 |
+
|
688 |
+
if( $args['echo'] )
|
689 |
+
echo $html;
|
690 |
+
|
691 |
+
return $html;
|
692 |
+
}
|
693 |
+
|
694 |
+
|
695 |
+
/**
|
696 |
+
* Utility function for printing/returning text field
|
697 |
+
*
|
698 |
+
* The $args array - excepts the following keys
|
699 |
+
*
|
700 |
+
* * **id** - The id of the checkbox (alias: label_for)
|
701 |
+
* * **name** - The name of the select box
|
702 |
+
* * **options** - Single or Array of options in 'value'=>'Label' format
|
703 |
+
* * **values** - The values of the text field
|
704 |
+
* * **type** - The type of the text field (e.g. 'text','hidden','password')
|
705 |
+
|
706 |
+
* * **label** - The label for the radiobox field set
|
707 |
+
* * **class** - Class to be added to the radiobox field set
|
708 |
+
* * **echo** - Whether to print the mark-up or just return it
|
709 |
+
* * **help** - Optional, help text to accompany the field.
|
710 |
+
*
|
711 |
+
* @access private
|
712 |
+
* @param $args array The array of arguments
|
713 |
+
*/
|
714 |
+
function eventorganiser_checkbox_field($args=array()){
|
715 |
+
|
716 |
+
$args = wp_parse_args($args,array(
|
717 |
+
'help' => '','name'=>'', 'class'=>'',
|
718 |
+
'checked'=>'', 'echo'=>true,'multiselect'=>false
|
719 |
+
));
|
720 |
+
|
721 |
+
$id = ( !empty($args['id']) ? $args['id'] : $args['label_for']);
|
722 |
+
$name = isset($args['name']) ? $args['name'] : '';
|
723 |
+
$class = ( $args['class'] ? "class='".sanitize_html_class($args['class'])."'" :"" );
|
724 |
+
|
725 |
+
/* $options and $checked are either both arrays or they are both strings. */
|
726 |
+
$options = isset($args['options']) ? $args['options'] : false;
|
727 |
+
$checked = isset($args['checked']) ? $args['checked'] : 1;
|
728 |
+
|
729 |
+
$html ='';
|
730 |
+
if( is_array($options) ){
|
731 |
+
foreach( $options as $value => $opt_label ){
|
732 |
+
$html .= sprintf('<label for="%1$s">
|
733 |
+
<input type="checkbox" name="%2$s" id="%1$s" value="%3$s" %4$s %5$s>
|
734 |
+
%6$s </br>
|
735 |
+
</label>',
|
736 |
+
esc_attr($id.'_'.$value),
|
737 |
+
esc_attr(trim($name).'[]'),
|
738 |
+
esc_attr($value),
|
739 |
+
checked( in_array($value, $checked), true, false ),
|
740 |
+
$class,
|
741 |
+
esc_attr($opt_label)
|
742 |
+
);
|
743 |
+
}
|
744 |
+
}else{
|
745 |
+
$html .= sprintf('<input type="checkbox" id="%1$s" name="%2$s" %3$s %4$s value="%5$s">',
|
746 |
+
esc_attr($id),
|
747 |
+
esc_attr($name),
|
748 |
+
checked( $checked, $options, false ),
|
749 |
+
$class,
|
750 |
+
esc_attr($options)
|
751 |
+
);
|
752 |
+
}
|
753 |
+
|
754 |
+
if(!empty($args['help'])){
|
755 |
+
$html .= '<p class="description">'.$args['help'].'</p>';
|
756 |
+
}
|
757 |
+
|
758 |
+
if( $args['echo'] )
|
759 |
+
echo $html;
|
760 |
+
|
761 |
+
return $html;
|
762 |
+
}
|
763 |
+
|
764 |
+
|
765 |
+
|
766 |
+
/**
|
767 |
+
* Utility function for printing/returning text area
|
768 |
+
*
|
769 |
+
* The $args array - excepts the following keys
|
770 |
+
*
|
771 |
+
* * **id** - The id of the checkbox (alias: label_for)
|
772 |
+
* * **name** - The name of the select box
|
773 |
+
* * **options** - Single or Array of options in 'value'=>'Label' format
|
774 |
+
* * **tinymce** Whether to use the TinyMCE editor. The TinyMCE prints directly.
|
775 |
+
* * **value** - The value of the text area
|
776 |
+
* * **rows** - The number of rows. Default 5.
|
777 |
+
* * **cols** - The number of columns. Default 50.
|
778 |
+
* * **class** - Class to be added to the textarea
|
779 |
+
* * **echo** - Whether to print the mark-up or just return it
|
780 |
+
* * **help** - Optional, help text to accompany the field.
|
781 |
+
*
|
782 |
+
* @access private
|
783 |
+
* @param $args array The array of arguments
|
784 |
+
*/
|
785 |
+
function eventorganiser_textarea_field($args){
|
786 |
+
|
787 |
+
$args = wp_parse_args($args,array(
|
788 |
+
'type' => 'text', 'value'=>'', 'tinymce' => '', 'help' => '',
|
789 |
+
'class'=>'large-text', 'echo'=>true,'rows'=>5, 'cols'=>50,
|
790 |
+
'readonly'=> false,
|
791 |
+
));
|
792 |
+
|
793 |
+
$id = ( !empty($args['id']) ? $args['id'] : $args['label_for']);
|
794 |
+
$name = isset($args['name']) ? $args['name'] : '';
|
795 |
+
$value = $args['value'];
|
796 |
+
$class = $args['class'];
|
797 |
+
$readonly = $args['readonly'] ? 'readonly' : '';
|
798 |
+
$html ='';
|
799 |
+
|
800 |
+
if( $args['tinymce'] ){
|
801 |
+
wp_editor( $value, esc_attr($id) ,array(
|
802 |
+
'textarea_name'=>$name,
|
803 |
+
'media_buttons'=>false,
|
804 |
+
));
|
805 |
+
}else{
|
806 |
+
$html .= sprintf('<textarea cols="%s" rows="%d" name="%s" class="%s large-text" id="%s" %s >%s</textarea>',
|
807 |
+
intval($args['cols']),
|
808 |
+
intval($args['rows']),
|
809 |
+
esc_attr($name),
|
810 |
+
sanitize_html_class($class),
|
811 |
+
esc_attr($id),
|
812 |
+
$readonly,
|
813 |
+
esc_textarea($value)
|
814 |
+
);
|
815 |
+
}
|
816 |
+
|
817 |
+
if(!empty($args['help'])){
|
818 |
+
$html .= '<p class="description">'.$args['help'].'</p>';
|
819 |
+
}
|
820 |
+
|
821 |
+
if( $args['echo'] )
|
822 |
+
echo $html;
|
823 |
+
|
824 |
+
return $html;
|
825 |
+
}
|
826 |
+
|
827 |
+
|
828 |
+
function eventorganiser_esc_printf($text){
|
829 |
+
return str_replace('%','%%',$text);
|
830 |
+
}
|
831 |
+
|
832 |
+
|
833 |
+
function eventorganiser_cache_get( $key, $group ){
|
834 |
+
|
835 |
+
$ns_key = wp_cache_get( 'eventorganiser_'.$group.'_key' );
|
836 |
+
|
837 |
+
// if not set, initialize it
|
838 |
+
if ( $ns_key === false )
|
839 |
+
wp_cache_set( 'eventorganiser_'.$group.'_key', 1 );
|
840 |
+
|
841 |
+
return wp_cache_get( "eo_".$ns_key."_".$key, $group );
|
842 |
+
}
|
843 |
+
|
844 |
+
|
845 |
+
function eventorganiser_clear_cache( $group, $key = false ){
|
846 |
+
|
847 |
+
if( $key == false ){
|
848 |
+
//If a key is not specified clear entire group by incrementing name space
|
849 |
+
return wp_cache_incr( 'eventorganiser_'.$group.'_key' );
|
850 |
+
|
851 |
+
}elseif( $ns_key = wp_cache_get( 'eventorganiser_'.$group.'_key' ) ){
|
852 |
+
//If key is specified - clear particular key from the group
|
853 |
+
return wp_cache_delete( "eo_".$ns_key."_".$key, $group );
|
854 |
+
}
|
855 |
+
}
|
856 |
+
|
857 |
+
|
858 |
+
function eventorganiser_cache_set( $key, $value, $group, $expire = 0 ){
|
859 |
+
$ns_key = wp_cache_get( 'eventorganiser_'.$group.'_key' );
|
860 |
+
|
861 |
+
// if not set, initialize it
|
862 |
+
if ( $ns_key === false )
|
863 |
+
wp_cache_set( 'eventorganiser_'.$group.'_key', 1 );
|
864 |
+
|
865 |
+
return wp_cache_add( "eo_".$ns_key."_".$key, $value, $group, $expire );
|
866 |
+
}
|
867 |
+
|
868 |
+
/**
|
869 |
+
* Display inline help via a qTip2 tooltip.
|
870 |
+
*
|
871 |
+
* The function handles the javascript/css loading and generates the link HTML which will trigger the tooltip.
|
872 |
+
* The HTML can be returned or printed using the fourth argument.
|
873 |
+
*
|
874 |
+
* @param string $title The title of the tooltip that will appear
|
875 |
+
* @param string $content The content of the tooltip
|
876 |
+
* @param bool $echo Whether the link HTML should be printed as well as returned.
|
877 |
+
* @return string
|
878 |
+
*/
|
879 |
+
function eventorganiser_inline_help( $title, $content, $echo = false, $type = 'help' ){
|
880 |
+
static $help = array();
|
881 |
+
|
882 |
+
$help[] = array(
|
883 |
+
'title' => $title,
|
884 |
+
'content' => $content,
|
885 |
+
);
|
886 |
+
|
887 |
+
wp_localize_script( 'eo-inline-help', 'eoHelp', $help );
|
888 |
+
|
889 |
+
//Ensure style is called after WP styles
|
890 |
+
add_action( 'admin_footer', '_eventorganiser_enqueue_inline_help_scripts', 100 );
|
891 |
+
|
892 |
+
$id = count($help)-1;
|
893 |
+
$src = EVENT_ORGANISER_URL."css/images/{$type}-14.png";
|
894 |
+
|
895 |
+
$link = sprintf( '<a href="#" id="%s" class="eo-inline-help eo-%s-inline"><img src="%s" width="16" height="16"></a>',
|
896 |
+
'eo-inline-help-' . $id,
|
897 |
+
$type,
|
898 |
+
$src
|
899 |
+
);
|
900 |
+
|
901 |
+
if( $echo )
|
902 |
+
echo $link;
|
903 |
+
|
904 |
+
return $link;
|
905 |
+
}
|
906 |
+
function _eventorganiser_enqueue_inline_help_scripts(){
|
907 |
+
wp_enqueue_script( 'eo-inline-help' );
|
908 |
+
wp_enqueue_style( 'eventorganiser-style' );
|
909 |
+
}
|
910 |
+
?>
|
includes/event-organiser-venue-functions.php
ADDED
@@ -0,0 +1,867 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Venue related functions
|
4 |
+
*@package venue-functions
|
5 |
+
*/
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Returns the ID of the venue of an event.
|
9 |
+
*
|
10 |
+
* Can be used inside the loop to output the
|
11 |
+
* venue id of the current event by not passing an ID.
|
12 |
+
*
|
13 |
+
* Otherwise it returns the venue ID of the passed event ID.
|
14 |
+
*
|
15 |
+
* @since 1.0.0
|
16 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
17 |
+
* @return int The corresponding venue (event-venue term) ID
|
18 |
+
*/
|
19 |
+
function eo_get_venue($event_id=''){
|
20 |
+
global $post;
|
21 |
+
$event = $post;
|
22 |
+
|
23 |
+
if( !empty($event_id) ){
|
24 |
+
$post_id = $event_id;
|
25 |
+
}else{
|
26 |
+
$post_id = (isset($post->ID) ? $post->ID : 0);
|
27 |
+
}
|
28 |
+
|
29 |
+
if( empty($post_id) )
|
30 |
+
return false;
|
31 |
+
|
32 |
+
$venue = get_the_terms($post_id,'event-venue');
|
33 |
+
|
34 |
+
if ( empty($venue) || is_wp_error( $venue ) )
|
35 |
+
return false;
|
36 |
+
|
37 |
+
$venue = array_pop($venue);
|
38 |
+
|
39 |
+
return (int) $venue->term_id;
|
40 |
+
}
|
41 |
+
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Returns the slug of the venue of an event.
|
45 |
+
*
|
46 |
+
* When used without an argument it uses the event specified in the global $post (e.g. current event in the loop).
|
47 |
+
* Can be used inside the loop to output the venue id of the current event.
|
48 |
+
* @since 1.0.0
|
49 |
+
*
|
50 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
51 |
+
* @return int The corresponding venue (event-venue term) slug
|
52 |
+
*/
|
53 |
+
function eo_get_venue_slug($event_id=''){
|
54 |
+
global $post;
|
55 |
+
$event = $post;
|
56 |
+
|
57 |
+
if( !empty($event_id) ){
|
58 |
+
$post_id = $event_id;
|
59 |
+
}else{
|
60 |
+
$post_id = (isset($post->ID) ? $post->ID : 0);
|
61 |
+
}
|
62 |
+
|
63 |
+
$venue = get_the_terms($post_id,'event-venue');
|
64 |
+
|
65 |
+
if ( empty($venue) || is_wp_error( $venue ) )
|
66 |
+
return false;
|
67 |
+
|
68 |
+
$venue = array_pop($venue);
|
69 |
+
|
70 |
+
return $venue->slug;
|
71 |
+
}
|
72 |
+
|
73 |
+
|
74 |
+
|
75 |
+
/**
|
76 |
+
* A utility function for getting the venue ID from a venue ID or slug.
|
77 |
+
* Useful for when we don't know which is being passed to us, but we want the ID.
|
78 |
+
* IDs **must** be cast as integers
|
79 |
+
* @since 1.6
|
80 |
+
*
|
81 |
+
* @param mixed $venue_slug_or_id The venue ID as an integer. Or Slug as string. Uses venue of current event if empty.
|
82 |
+
* @return int The corresponding venue (event-venue term) ID or false if not found.
|
83 |
+
*/
|
84 |
+
function eo_get_venue_id_by_slugorid($venue_slug_or_id=''){
|
85 |
+
|
86 |
+
$venue = $venue_slug_or_id;
|
87 |
+
|
88 |
+
if( empty($venue) )
|
89 |
+
return eo_get_venue();
|
90 |
+
|
91 |
+
if( is_int($venue) )
|
92 |
+
return (int) $venue;
|
93 |
+
|
94 |
+
$venue = eo_get_venue_by('slug', $venue);
|
95 |
+
|
96 |
+
if( $venue )
|
97 |
+
return (int) $venue->term_id;
|
98 |
+
|
99 |
+
return false;
|
100 |
+
}
|
101 |
+
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Get all venue data from database by venue field and data. This acts as a simple wrapper for {@see `get_term_by()`}
|
105 |
+
*
|
106 |
+
* Warning: `$value` is not escaped for 'name' `$field`. You must do it yourself, if required.
|
107 |
+
*
|
108 |
+
* If `$value` does not exist for that `$field`, the return value will be false other the term will be returned.
|
109 |
+
*
|
110 |
+
* ###Example
|
111 |
+
* Get the venue ID by slug (A better way is to use {@see `eo_get_venue_id_by_slugorid()`}
|
112 |
+
*
|
113 |
+
* $venue = eo_get_venue_by('slug','my-venue-slug');
|
114 |
+
* if( $venue )
|
115 |
+
* $venue_id = (int) $venue->term_id;
|
116 |
+
*
|
117 |
+
*
|
118 |
+
* @uses get_term_by()
|
119 |
+
* @since 1.6
|
120 |
+
*
|
121 |
+
* @param string $field Either 'slug', 'name', or 'id'
|
122 |
+
* @param string|int $value Search for this term value
|
123 |
+
* @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N
|
124 |
+
* @param string $filter Optional, default is raw or no WordPress defined filter will applied.
|
125 |
+
* @return mixed Term Row from database. Will return false if $taxonomy does not exist or $term was not found.
|
126 |
+
*/
|
127 |
+
function eo_get_venue_by($field,$value,$output = OBJECT, $filter = 'raw' ){
|
128 |
+
$venue = get_term_by($field, $value, 'event-venue',$output, $filter);
|
129 |
+
return $venue;
|
130 |
+
}
|
131 |
+
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Returns the name of the venue of an event.
|
135 |
+
* If used without any arguments uses the venue of the current event.
|
136 |
+
*
|
137 |
+
* Returns the name of a venue specified by it's slug or ID. If used inside the loop, it can return the name of the current post's venue. If specifying the venue by ID, **the ID must be an integer**.
|
138 |
+
*
|
139 |
+
* This function behaves differently to {@see `eo_get_venue_slug()`} which takes the event ID, rather than venue ID or slug, as an optional argument.
|
140 |
+
*
|
141 |
+
* @since 1.0.0
|
142 |
+
*
|
143 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
144 |
+
* @return string The name of the corresponding venue
|
145 |
+
*/
|
146 |
+
function eo_get_venue_name($venue_slug_or_id=''){
|
147 |
+
$venue_id = eo_get_venue_id_by_slugorid($venue_slug_or_id);
|
148 |
+
$venue = get_term($venue_id,'event-venue');
|
149 |
+
|
150 |
+
if ( empty($venue) || is_wp_error( $venue ) )
|
151 |
+
return false;
|
152 |
+
|
153 |
+
return $venue->name;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Echos the venue of the event
|
158 |
+
*
|
159 |
+
* @uses eo_get_venue_name()
|
160 |
+
* @param (int) venue id or (string) venue slug
|
161 |
+
*
|
162 |
+
* @since 1.0.0
|
163 |
+
*/
|
164 |
+
function eo_venue_name($venue_slug_or_id=''){
|
165 |
+
echo eo_get_venue_name($venue_slug_or_id);
|
166 |
+
}
|
167 |
+
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Returns the description of the description of an event.
|
171 |
+
* If used with any arguments uses the venue of the current event.
|
172 |
+
*
|
173 |
+
* Returns the description of a venue specified by it's slug or ID. When used without an argument it uses the event specified in the `global $post` (i.e. the current event in the Loop). If specifying the
|
174 |
+
* venue by ID, **the ID must be an integer**.
|
175 |
+
*
|
176 |
+
* @since 1.0.0
|
177 |
+
*
|
178 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
179 |
+
* @return string The description. of the corresponding venue
|
180 |
+
*/
|
181 |
+
function eo_get_venue_description($venue_slug_or_id=''){
|
182 |
+
$venue_id = eo_get_venue_id_by_slugorid($venue_slug_or_id);
|
183 |
+
$description = eo_get_venue_meta($venue_id,'_description');
|
184 |
+
$description = wptexturize($description);
|
185 |
+
$description = convert_chars($description);
|
186 |
+
$description = wpautop($description);
|
187 |
+
$description = shortcode_unautop($description);
|
188 |
+
$description = do_shortcode($description);
|
189 |
+
return $description;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Prints the name of the description of an event.
|
194 |
+
* Can be used inside the loop to output the
|
195 |
+
* venue id of the current event.
|
196 |
+
* @since 1.0.0
|
197 |
+
* @uses eo_get_venue_description()
|
198 |
+
*
|
199 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
200 |
+
*/
|
201 |
+
function eo_venue_description($venue_slug_or_id=''){
|
202 |
+
echo eo_get_venue_description($venue_slug_or_id);
|
203 |
+
}
|
204 |
+
|
205 |
+
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Returns an latitude-longtitude array (keys 'lat', 'lng')
|
209 |
+
* If used with any arguments uses the venue of the current event.
|
210 |
+
*
|
211 |
+
* Returns a latitude-longitude array of a venue specified by it's slug or ID. When used without an argument it uses the event specified in the `global $post` (i.e. the current event in the Loop). If
|
212 |
+
* specifying the venue by ID, **the ID must be an integer**.
|
213 |
+
* @since 1.0.0
|
214 |
+
*
|
215 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
216 |
+
* @return array Array with keys 'lat' and 'lng' with corresponding float values.
|
217 |
+
*/
|
218 |
+
function eo_get_venue_latlng($venue_slug_or_id=''){
|
219 |
+
$lat = eo_get_venue_lat($venue_slug_or_id);
|
220 |
+
$lng = eo_get_venue_lng($venue_slug_or_id);
|
221 |
+
return array('lat'=>$lat,'lng'=>$lng);
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Returns the latitude co-ordinate of a venue.
|
226 |
+
* If used with any arguments uses the venue of the current event.
|
227 |
+
*
|
228 |
+
* Returns the latitude of a venue specified by it's slug or ID. When used without an argument it uses the event specified in the `global $post` (i.e. the current event in the Loop). If specifying the
|
229 |
+
* specifying the venue by ID, **the ID must be an integer**.
|
230 |
+
* @since 1.0.0
|
231 |
+
*
|
232 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
233 |
+
* @return float The latitude of the venue as a float. 0 If it doesn't exist.
|
234 |
+
*/
|
235 |
+
function eo_get_venue_lat($venue_slug_or_id=''){
|
236 |
+
$venue_id = eo_get_venue_id_by_slugorid($venue_slug_or_id);
|
237 |
+
$lat = eo_get_venue_meta($venue_id,'_lat');
|
238 |
+
$lat = ! empty($lat) ? $lat : 0;
|
239 |
+
return $lat;
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Returns the longtitude co-ordinate of a venue.
|
244 |
+
* If used with any arguments uses the venue of the current event.
|
245 |
+
*
|
246 |
+
* Returns the longtitude of a venue specified by it's slug or ID. When used without an argument it uses the event specified in the `global $post` (i.e. the current event in the Loop). If specifying the
|
247 |
+
* specifying the venue by ID, **the ID must be an integer**.
|
248 |
+
* @since 1.0.0
|
249 |
+
*
|
250 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
251 |
+
* @return float The longtitude of the venue as a float. 0 If it doesn't exist.
|
252 |
+
*/
|
253 |
+
function eo_get_venue_lng($venue_slug_or_id=''){
|
254 |
+
$venue_id = eo_get_venue_id_by_slugorid($venue_slug_or_id);
|
255 |
+
$lng = eo_get_venue_meta($venue_id,'_lng');
|
256 |
+
$lng = ! empty($lng) ? $lng : 0;
|
257 |
+
return $lng;
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
/**
|
262 |
+
* Prints the latitude co-ordinate of a venue.
|
263 |
+
* If used with any arguments uses the venue of the current event.
|
264 |
+
* @uses eo_get_venue_lat()
|
265 |
+
* @since 1.0.0
|
266 |
+
*
|
267 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
268 |
+
*/
|
269 |
+
function eo_venue_lat($venue_slug_or_id=''){
|
270 |
+
echo eo_get_venue_lat($venue_slug_or_id);
|
271 |
+
}
|
272 |
+
|
273 |
+
|
274 |
+
/**
|
275 |
+
* Prints the longtitude co-ordinate of a venue.
|
276 |
+
* If used with any arguments uses the venue of the current event.
|
277 |
+
* @uses eo_get_venue_lng()
|
278 |
+
* @since 1.0.0
|
279 |
+
*
|
280 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
281 |
+
*/
|
282 |
+
function eo_venue_lng($venue_slug_or_id=''){
|
283 |
+
echo eo_get_venue_lng($venue_slug_or_id);
|
284 |
+
}
|
285 |
+
|
286 |
+
|
287 |
+
/**
|
288 |
+
* Returns the permalink of a venue
|
289 |
+
* If used with any arguments uses the venue of the current event.
|
290 |
+
* @uses get_term_link()
|
291 |
+
* @since 1.0.0
|
292 |
+
*
|
293 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
294 |
+
* @return string Link of the venue page
|
295 |
+
*/
|
296 |
+
function eo_get_venue_link($venue_slug_or_id=''){
|
297 |
+
$venue_id = eo_get_venue_id_by_slugorid($venue_slug_or_id);
|
298 |
+
return get_term_link( $venue_id, 'event-venue' );
|
299 |
+
}
|
300 |
+
|
301 |
+
|
302 |
+
/**
|
303 |
+
* Prints the permalink of a venue
|
304 |
+
* If used with any arguments uses the venue of the current event.
|
305 |
+
* @uses eo_get_venue_link()
|
306 |
+
* @since 1.0.0
|
307 |
+
*
|
308 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
309 |
+
*/
|
310 |
+
function eo_venue_link($venue_slug_or_id=''){
|
311 |
+
$venue_id = eo_get_venue_id_by_slugorid($venue_slug_or_id);
|
312 |
+
echo eo_get_venue_link($venue_slug_or_id);
|
313 |
+
}
|
314 |
+
|
315 |
+
|
316 |
+
/**
|
317 |
+
* Returns an array with address details of the event's venue.
|
318 |
+
* The keys consist of
|
319 |
+
*
|
320 |
+
* * 'address'
|
321 |
+
* * 'city'
|
322 |
+
* * 'state' - the state/province/county of the venue
|
323 |
+
* * 'postcode'
|
324 |
+
* * 'country'
|
325 |
+
*
|
326 |
+
* If used with any arguments uses the venue of the current event.
|
327 |
+
* @since 1.0.0
|
328 |
+
*
|
329 |
+
* @param int|string $venue_slug_or_id The venue ID (as an integer) or slug (as a string). Uses venue of current event if empty.
|
330 |
+
* @return array Array of venue address details
|
331 |
+
*/
|
332 |
+
function eo_get_venue_address($venue_slug_or_id=''){
|
333 |
+
$address=array();
|
334 |
+
$venue_id = eo_get_venue_id_by_slugorid($venue_slug_or_id);
|
335 |
+
$address_keys = array_keys(_eventorganiser_get_venue_address_fields());
|
336 |
+
foreach( $address_keys as $meta_key ){
|
337 |
+
$key = trim($meta_key,'_');
|
338 |
+
$address[$key] = eo_get_venue_meta($venue_id,$meta_key);
|
339 |
+
}
|
340 |
+
return $address;
|
341 |
+
}
|
342 |
+
|
343 |
+
|
344 |
+
/**
|
345 |
+
* Retrieve array of venues. Acts as a wrapper for {@link http://codex.wordpress.org/Function_Reference/get_terms get_terms()}, except hide_empty defaults to false.
|
346 |
+
*
|
347 |
+
* The list of arguments that `$args` can contain, which will overwrite the defaults:
|
348 |
+
*
|
349 |
+
* * **orderby** - Default is 'name'. Can be name, count, term_group, slug or nothing
|
350 |
+
* (will use venue/term ID), Passing a custom value other than these will cause it to
|
351 |
+
* order based on the custom value.
|
352 |
+
* * **order** - Default is ASC. Can use DESC.
|
353 |
+
* * **hide_empty** - Default is 0 (false)
|
354 |
+
* * **exclude** - Default is an empty array. An array, comma- or space-delimited string
|
355 |
+
* of term ids to exclude from the return array. If 'include' is non-empty,
|
356 |
+
* 'exclude' is ignored.
|
357 |
+
* * **include** - Default is an empty array. An array, comma- or space-delimited string
|
358 |
+
* of term ids to include in the return array.
|
359 |
+
* * **number** - The maximum number of terms to return. Default is to return them all.
|
360 |
+
* * **offset** - The number by which to offset the terms query.
|
361 |
+
* * **fields** - Default is 'all', which returns an array of term objects.
|
362 |
+
* If 'fields' is 'ids' or 'names', returns an array of integers or strings, respectively.
|
363 |
+
* * **slug** - Returns terms whose "slug" matches this value. Default is empty string.
|
364 |
+
* * **search** - Returned terms' names will contain the value of 'search',
|
365 |
+
* * **case-insensitive**. Default is an empty string.
|
366 |
+
*
|
367 |
+
* ###Example
|
368 |
+
*
|
369 |
+
* $venues = eo_get_venues();
|
370 |
+
*
|
371 |
+
* if( $venues ){
|
372 |
+
* echo '<ul>';
|
373 |
+
* foreach($venues as $venue):
|
374 |
+
* $venue_id = (int) $venue->term_id;
|
375 |
+
* printf('<li> <a href="%s">%s</a>', eo_get_venue_link($venue_id), esc_html($venue->name));
|
376 |
+
* endforeach;
|
377 |
+
* echo '</ul>';
|
378 |
+
* }
|
379 |
+
*
|
380 |
+
* @uses get_terms()
|
381 |
+
* @link https://gist.github.com/3902494 Gist for creating an archive page of all the venues
|
382 |
+
* @link http://codex.wordpress.org/Function_Reference/get_terms get_terms()
|
383 |
+
* @since 1.0.0
|
384 |
+
*
|
385 |
+
* @param string|array $args The values of what to search for when returning venues
|
386 |
+
* @return array List of Term (venue) Objects
|
387 |
+
*/
|
388 |
+
function eo_get_venues($args=array()){
|
389 |
+
$args = wp_parse_args( $args, array('hide_empty'=>0, 'fields'=>'all') );
|
390 |
+
$venues = get_terms('event-venue',$args);
|
391 |
+
if( $venues ){
|
392 |
+
//Ensure IDs are cast as integers {@link https://github.com/stephenh1988/Event-Organiser/issues/21}
|
393 |
+
if( $args['fields'] == 'ids' ){
|
394 |
+
$venues = array_map('intval', $venues);
|
395 |
+
}elseif( $args['fields'] == 'all' ){
|
396 |
+
foreach( $venues as $venue)
|
397 |
+
$venue->term_id = (int)$venue->term_id;
|
398 |
+
}
|
399 |
+
}
|
400 |
+
return $venues;
|
401 |
+
}
|
402 |
+
|
403 |
+
|
404 |
+
/**
|
405 |
+
* Updates new venue in the database.
|
406 |
+
*
|
407 |
+
* Calls {@see `wp_insert_term()`} to update the taxonomy term
|
408 |
+
* Updates venue meta data to database (for 'core' meta keys)
|
409 |
+
* The $args is an array - the same as that accepted by {@link http://codex.wordpress.org/Function_Reference/wp_update_term wp_update_term()}
|
410 |
+
* The $args array can also accept the following keys:
|
411 |
+
*
|
412 |
+
* * description
|
413 |
+
* * address
|
414 |
+
* * city
|
415 |
+
* * state
|
416 |
+
* * postcode
|
417 |
+
* * country
|
418 |
+
* * latitude
|
419 |
+
* * longtitude
|
420 |
+
*
|
421 |
+
* @since 1.4.0
|
422 |
+
*
|
423 |
+
* @uses wp_update_term() to update venue (taxonomy) term
|
424 |
+
* @uses do_action() Calls 'eventorganiser_save_venue' hook with the venue id
|
425 |
+
*
|
426 |
+
* @param int $venue_id The Term ID of the venue to update
|
427 |
+
* @param array $args Array as accepted by wp_update_term and including the 'core' metadata
|
428 |
+
* @return array|WP_Error Array of term ID and term-taxonomy ID or a WP_Error on error
|
429 |
+
*/
|
430 |
+
function eo_update_venue($venue_id, $args=array()){
|
431 |
+
|
432 |
+
$term_args = array_intersect_key($args, array('name'=>'','term_id'=>'','term_group'=>'','term_taxonomy_id'=>'','alias_of'=>'','parent'=>0,'slug'=>'','count'=>''));
|
433 |
+
$meta_args = array_intersect_key($args, array('description'=>'','address'=>'','postcode'=>'','city'=>'','state'=>'','country'=>'','latitude'=>'','longtitude'=>''));
|
434 |
+
$venue_id = (int) $venue_id;
|
435 |
+
|
436 |
+
|
437 |
+
//Update taxonomy table
|
438 |
+
$resp = wp_update_term($venue_id,'event-venue', $term_args);
|
439 |
+
|
440 |
+
if( is_wp_error($resp) ){
|
441 |
+
return $resp;
|
442 |
+
}
|
443 |
+
|
444 |
+
$venue_id = (int) $resp['term_id'];
|
445 |
+
|
446 |
+
foreach( $meta_args as $key => $value ){
|
447 |
+
switch($key):
|
448 |
+
case 'latitude':
|
449 |
+
$meta_key = '_lat';
|
450 |
+
break;
|
451 |
+
case 'longtitude':
|
452 |
+
$meta_key = '_lng';
|
453 |
+
break;
|
454 |
+
default:
|
455 |
+
$meta_key = '_'.$key;
|
456 |
+
break;
|
457 |
+
endswitch;
|
458 |
+
|
459 |
+
$validated_value = eventorganiser_sanitize_meta($meta_key, $value);
|
460 |
+
|
461 |
+
update_metadata('eo_venue', $venue_id, $meta_key, $validated_value);
|
462 |
+
}
|
463 |
+
do_action('eventorganiser_save_venue',$venue_id);
|
464 |
+
|
465 |
+
return array('term_id' => $venue_id, 'term_taxonomy_id' => $resp['term_taxonomy_id']);
|
466 |
+
}
|
467 |
+
|
468 |
+
|
469 |
+
/**
|
470 |
+
* Adds a new venue to the database.
|
471 |
+
*
|
472 |
+
* Calls {@see `wp_insert_term()`} to create the taxonomy term
|
473 |
+
* Adds venue meta data to database (for 'core' meta keys)
|
474 |
+
*
|
475 |
+
* The $args is an array - the same as that accepted by {@link http://codex.wordpress.org/Function_Reference/wp_update_term wp_update_term()}
|
476 |
+
* The $args array can also accept the following keys:
|
477 |
+
*
|
478 |
+
* * description
|
479 |
+
* * address
|
480 |
+
* * city
|
481 |
+
* * state
|
482 |
+
* * postcode
|
483 |
+
* * country
|
484 |
+
* * latitude
|
485 |
+
* * longtitude
|
486 |
+
*
|
487 |
+
* @since 1.4.0
|
488 |
+
*
|
489 |
+
* @uses `wp_insert_term()` to create venue (taxonomy) term
|
490 |
+
* @uses do_action() Calls 'eventorganiser_insert_venue' hook with the venue id
|
491 |
+
* @uses do_action() Calls 'eventorganiser_save_venue' hook with the venue id
|
492 |
+
* @link http://codex.wordpress.org/Function_Reference/wp_insert_term wp_insert_term()
|
493 |
+
*
|
494 |
+
* @param string $name the venue to insert
|
495 |
+
* @param array $args Array as accepted by wp_update_term and including the 'core' metadata
|
496 |
+
* @return array|WP_Error Array of term ID and term-taxonomy ID or a WP_Error on error
|
497 |
+
*/
|
498 |
+
function eo_insert_venue($name, $args=array()){
|
499 |
+
$term_args = array_intersect_key($args, array('name'=>'','term_id'=>'','term_group'=>'','term_taxonomy_id'=>'','alias_of'=>'','parent'=>0,'slug'=>'','count'=>''));
|
500 |
+
$meta_args = array_intersect_key($args, array('description'=>'','address'=>'','postcode'=>'','city'=>'','state'=>'','country'=>'','latitude'=>'','longtitude'=>''));
|
501 |
+
|
502 |
+
$resp = wp_insert_term($name,'event-venue',$term_args);
|
503 |
+
|
504 |
+
if(is_wp_error($resp)){
|
505 |
+
return $resp;
|
506 |
+
}
|
507 |
+
|
508 |
+
$venue_id = (int) $resp['term_id'];
|
509 |
+
|
510 |
+
foreach( $meta_args as $key => $value ){
|
511 |
+
switch($key):
|
512 |
+
case 'latitude':
|
513 |
+
$meta_key = '_lat';
|
514 |
+
break;
|
515 |
+
case 'longtitude':
|
516 |
+
$meta_key = '_lng';
|
517 |
+
break;
|
518 |
+
default:
|
519 |
+
$meta_key = '_'.$key;
|
520 |
+
break;
|
521 |
+
endswitch;
|
522 |
+
|
523 |
+
$validated_value = eventorganiser_sanitize_meta($meta_key, $value);
|
524 |
+
|
525 |
+
if( !empty($validated_value) )
|
526 |
+
add_metadata('eo_venue', $venue_id, $meta_key, $validated_value, true);
|
527 |
+
}
|
528 |
+
|
529 |
+
do_action('eventorganiser_insert_venue',$venue_id);
|
530 |
+
do_action('eventorganiser_save_venue',$venue_id);
|
531 |
+
|
532 |
+
return array('term_id' => $venue_id, 'term_taxonomy_id' => $resp['term_taxonomy_id']);
|
533 |
+
}
|
534 |
+
|
535 |
+
/**
|
536 |
+
* Deletes a venue in the database.
|
537 |
+
*
|
538 |
+
* Calls {@see `wp_delete_term()`} to delete the taxonomy term
|
539 |
+
* Deletes all the venue's meta
|
540 |
+
*
|
541 |
+
* @since 1.4.0
|
542 |
+
*
|
543 |
+
* @uses wp_delete_term to delete venue (taxonomy) term
|
544 |
+
* @uses do_action() Calls 'eventorganiser_delete_venue' hook with the venue id
|
545 |
+
*
|
546 |
+
* @param int $venue_id the Term ID of the venue to update
|
547 |
+
* @return bool|WP_Error false or error on failure. True after sucessfully deleting the venue and its meta data.
|
548 |
+
*/
|
549 |
+
function eo_delete_venue($venue_id){
|
550 |
+
global $wpdb;
|
551 |
+
$resp =wp_delete_term( $venue_id, 'event-venue');
|
552 |
+
if( is_wp_error($resp) || false === $resp ){
|
553 |
+
return $resp;
|
554 |
+
}
|
555 |
+
$venue_meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->eo_venuemeta WHERE eo_venue_id = %d ", $venue_id ));
|
556 |
+
|
557 |
+
if ( !empty($venue_meta_ids) ) {
|
558 |
+
$in_venue_meta_ids = "'" . implode("', '", $venue_meta_ids) . "'";
|
559 |
+
$wpdb->query( "DELETE FROM $wpdb->eo_venuemeta WHERE meta_id IN($in_venue_meta_ids)" );
|
560 |
+
}
|
561 |
+
do_action('eventorganiser_delete_venue',$venue_id);
|
562 |
+
|
563 |
+
return true;
|
564 |
+
}
|
565 |
+
|
566 |
+
/**
|
567 |
+
* Returns the mark-up for a Google map of the venue (and enqueues scripts).
|
568 |
+
* Accepts an arguments array corresponding to the attributes supported by the shortcode.
|
569 |
+
* @since 1.6
|
570 |
+
*
|
571 |
+
* @link http://www.stephenharris.info/2012/event-organiser-1-6-whats-new/ Examples of using eo_get_venue_map()
|
572 |
+
*
|
573 |
+
* @param mixed $venue_slug_or_id The venue ID as an integer. Or Slug as string. Uses venue of current event if empty.
|
574 |
+
* @return string The markup of the map. False is no venue found.
|
575 |
+
*/
|
576 |
+
function eo_get_venue_map($venue_slug_or_id='', $args=array()){
|
577 |
+
|
578 |
+
//Cast as array to allow multi venue support
|
579 |
+
if( $venue_slug_or_id == '%all%' || is_array($venue_slug_or_id) && in_array('%all%',$venue_slug_or_id) ){
|
580 |
+
$all_venues = eo_get_venues();
|
581 |
+
if( $all_venues )
|
582 |
+
$venue_slug_or_id = array_map('intval',wp_list_pluck($all_venues,'term_id'));
|
583 |
+
|
584 |
+
}
|
585 |
+
if( !is_array($venue_slug_or_id) )
|
586 |
+
$venue_slug_or_id = array( $venue_slug_or_id );
|
587 |
+
|
588 |
+
$venue_ids = array_map('eo_get_venue_id_by_slugorid',$venue_slug_or_id);
|
589 |
+
|
590 |
+
//Map properties
|
591 |
+
$args = shortcode_atts( array(
|
592 |
+
'zoom' => 15, 'scrollwheel'=>true, 'zoomcontrol'=>true, 'rotatecontrol'=>true,
|
593 |
+
'pancontrol'=>true, 'overviewmapcontrol'=>true, 'streetviewcontrol'=>true,
|
594 |
+
'maptypecontrol'=>true, 'draggable'=>true,'maptypeid' => 'ROADMAP',
|
595 |
+
'width' => '100%','height' => '200px','class' => '',
|
596 |
+
'tooltip'=>false
|
597 |
+
), $args );
|
598 |
+
|
599 |
+
//Cast zoom as integer
|
600 |
+
$args['zoom'] = (int) $args['zoom'];
|
601 |
+
|
602 |
+
//Escape attributes
|
603 |
+
$width = esc_attr($args['width']);
|
604 |
+
$height = esc_attr($args['height']);
|
605 |
+
$class = esc_attr($args['class']);
|
606 |
+
|
607 |
+
$args['maptypeid'] = strtoupper($args['maptypeid']);
|
608 |
+
|
609 |
+
//If class is selected use that style, otherwise use specified height and width
|
610 |
+
if( !empty($class) ){
|
611 |
+
$class .= " eo-venue-map googlemap";
|
612 |
+
$style = "";
|
613 |
+
}else{
|
614 |
+
$class = "eo-venue-map googlemap";
|
615 |
+
$style = "style='height:".$height.";width:".$width.";' ";
|
616 |
+
}
|
617 |
+
|
618 |
+
$venue_ids = array_filter($venue_ids);
|
619 |
+
|
620 |
+
if( empty($venue_ids) )
|
621 |
+
return false;
|
622 |
+
|
623 |
+
//Set up venue locations for map
|
624 |
+
foreach( $venue_ids as $venue_id ){
|
625 |
+
|
626 |
+
//Venue lat/lng array
|
627 |
+
$latlng = eo_get_venue_latlng($venue_id);
|
628 |
+
|
629 |
+
//Venue tooltip description
|
630 |
+
$tooltip_content = '<strong>'.eo_get_venue_name($venue_id).'</strong>';
|
631 |
+
$address = array_filter(eo_get_venue_address($venue_id));
|
632 |
+
if( !empty($address) )
|
633 |
+
$tooltip_content .='</br>'.implode(', ',$address);
|
634 |
+
|
635 |
+
$tooltip_content = apply_filters('eventorganiser_venue_tooltip',$tooltip_content,$venue_id);
|
636 |
+
|
637 |
+
$locations[] =array('lat'=>$latlng['lat'],'lng'=>$latlng['lng'], 'tooltipContent'=>$tooltip_content);
|
638 |
+
}
|
639 |
+
|
640 |
+
//This could be improved
|
641 |
+
EventOrganiser_Shortcodes::$map[] = array_merge($args, array('locations'=>$locations) );
|
642 |
+
EventOrganiser_Shortcodes::$add_script = true;
|
643 |
+
$id = count(EventOrganiser_Shortcodes::$map);
|
644 |
+
|
645 |
+
return "<div class='".$class."' id='eo_venue_map-{$id}' ".$style."></div>";
|
646 |
+
}
|
647 |
+
|
648 |
+
|
649 |
+
/**
|
650 |
+
* Retrieve post meta field for a venue.
|
651 |
+
*
|
652 |
+
* This function returns the values of the venue meta with the specified key from the specified venue. (Specified by the venue ID - the taxonomy term ID).
|
653 |
+
*
|
654 |
+
* @since 1.5.0
|
655 |
+
* @link http://wp-event-organiser.com/documentation/developers/venue-meta-data-and-metaboxes/ How to create custom fields for venues
|
656 |
+
*
|
657 |
+
* @param int $venue_id Venue (term) ID.
|
658 |
+
* @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
|
659 |
+
* @param bool $single Whether to return a single value.
|
660 |
+
* @return mixed Will be an array if $single is false. Will be value of meta data field if $single
|
661 |
+
* is true.
|
662 |
+
*/
|
663 |
+
function eo_get_venue_meta($venue_id, $key ='', $single=true){
|
664 |
+
return get_metadata('eo_venue', $venue_id, $key, $single);
|
665 |
+
}
|
666 |
+
|
667 |
+
|
668 |
+
/**
|
669 |
+
* Add meta data field to a venue
|
670 |
+
*
|
671 |
+
* You should avoid the following 'core' keys:
|
672 |
+
*
|
673 |
+
* * _description
|
674 |
+
* * _address
|
675 |
+
* * _city
|
676 |
+
* * _state
|
677 |
+
* * _postcode
|
678 |
+
* * _country
|
679 |
+
* * _latitude
|
680 |
+
* * _longtitude
|
681 |
+
*
|
682 |
+
* It is **strongly** recommended that you prefix your keys with and underscore.
|
683 |
+
*
|
684 |
+
* @since 1.5.0
|
685 |
+
* @link http://wp-event-organiser.com/documentation/developers/venue-meta-data-and-metaboxes/ How to create custom fields for venues
|
686 |
+
*
|
687 |
+
* @param int $venue_id Venue (term) ID.
|
688 |
+
* @param string $key Metadata name.
|
689 |
+
* @param mixed $value Metadata value.
|
690 |
+
* @param bool $unique Optional, default is false. Whether the same key should not be added.
|
691 |
+
* @return bool False for failure. True for success.
|
692 |
+
*/
|
693 |
+
function eo_add_venue_meta($venue_id, $key, $value, $unique = false ){
|
694 |
+
return add_metadata('eo_venue',$venue_id, $key, $value, $unique);
|
695 |
+
}
|
696 |
+
|
697 |
+
/**
|
698 |
+
* Update venue meta field based on venue (term) ID.
|
699 |
+
*
|
700 |
+
* Use the $prev_value parameter to differentiate between meta fields with the
|
701 |
+
* same key and venue ID. This may be used in place of {@see `eo_add_venue_meta()`} function. The first thing this function will do is make sure that `$meta_key` already exists on `$venue_id`. If it does not, `add_post_meta($venue_id, $meta_key, $meta_value)` is called instead and its result is returned. Returns meta_id if the meta doesn't exist, otherwise returns true on success and false on failure.
|
702 |
+
*
|
703 |
+
* If the meta field for the venue does not exist, it will be added.
|
704 |
+
*
|
705 |
+
* You should avoid the following 'core' keys:
|
706 |
+
*
|
707 |
+
* * _description
|
708 |
+
* * _address
|
709 |
+
* * _city
|
710 |
+
* * _state
|
711 |
+
* * _postcode
|
712 |
+
* * _country
|
713 |
+
* * _latitude
|
714 |
+
* * _longtitude
|
715 |
+
*
|
716 |
+
* It is **strongly** recommended that you prefix your keys with and underscore.
|
717 |
+
*
|
718 |
+
* @since 1.5.0
|
719 |
+
* @link http://wp-event-organiser.com/documentation/developers/venue-meta-data-and-metaboxes/ How to create custom fields for venues
|
720 |
+
*
|
721 |
+
* @param int $venue_id Venue (term) ID.
|
722 |
+
* @param string $key Metadata key.
|
723 |
+
* @param mixed $value Metadata value.
|
724 |
+
* @param mixed $prev_value Optional. Previous value to check before removing.
|
725 |
+
* @return bool False on failure, true if success.
|
726 |
+
*/
|
727 |
+
function eo_update_venue_meta($venue_id, $key, $value, $prev_value=''){
|
728 |
+
return update_metadata('eo_venue', $venue_id, $key, $value, $prev_value);
|
729 |
+
}
|
730 |
+
|
731 |
+
/**
|
732 |
+
* Remove metadata matching criteria from a venue.
|
733 |
+
*
|
734 |
+
* You can match based on the key, or key and value. Removing based on key and
|
735 |
+
* value, will keep from removing duplicate metadata with the same key. It also
|
736 |
+
* allows removing all metadata matching key, if needed.
|
737 |
+
*
|
738 |
+
* @since 1.5.0
|
739 |
+
* @link http://wp-event-organiser.com/documentation/developers/venue-meta-data-and-metaboxes/ How to create custom fields for venues
|
740 |
+
*
|
741 |
+
* @param int $venue_id Venue (term) ID.
|
742 |
+
* @param string $key Metadata name.
|
743 |
+
* @param mixed $value Optional. Metadata value.
|
744 |
+
* @return bool False for failure. True for success.
|
745 |
+
*/
|
746 |
+
function eo_delete_venue_meta($venue_id, $key, $value = '', $delete_all = false ){
|
747 |
+
return delete_metadata('eo_venue',$venue_id, $key, $value, $delete_all);
|
748 |
+
}
|
749 |
+
|
750 |
+
/**
|
751 |
+
* Sanitizes (or validates) the metadata (expects raw) before being inserted into the databse.
|
752 |
+
*
|
753 |
+
* @since 1.4.0
|
754 |
+
* @access private
|
755 |
+
*
|
756 |
+
* @param string The key of the meta data
|
757 |
+
* @param mixed The meta data being validated.
|
758 |
+
* @return mixed The validated value. False if the key is not recognised.
|
759 |
+
*/
|
760 |
+
function eventorganiser_sanitize_meta($key,$value){
|
761 |
+
|
762 |
+
switch($key):
|
763 |
+
case '_description':
|
764 |
+
$value = wp_filter_post_kses($value);
|
765 |
+
break;
|
766 |
+
case '_lat':
|
767 |
+
case '_lng':
|
768 |
+
//Cast as float and then string: make sure string uses . not , for decimal point
|
769 |
+
$value = floatval($value);
|
770 |
+
$value = number_format($value, 6);
|
771 |
+
break;
|
772 |
+
default:
|
773 |
+
$address_keys = _eventorganiser_get_venue_address_fields();
|
774 |
+
if( isset($address_keys[$key]) )
|
775 |
+
$value = sanitize_text_field($value);
|
776 |
+
else
|
777 |
+
$value = false;
|
778 |
+
endswitch;
|
779 |
+
|
780 |
+
return $value;
|
781 |
+
}
|
782 |
+
|
783 |
+
/**
|
784 |
+
*@ignore
|
785 |
+
*@access private
|
786 |
+
*/
|
787 |
+
function _eventorganiser_get_venue_address_fields(){
|
788 |
+
//Keys *must* be prefixed by a '_'.
|
789 |
+
$address_fields = array(
|
790 |
+
'_address'=> __('Address','eventorganiser'),
|
791 |
+
'_city'=> __('City','eventorganiser'),
|
792 |
+
'_state'=> __('State / Province','eventorganiser'),
|
793 |
+
'_postcode'=> __('Post Code','eventorganiser'),
|
794 |
+
'_country'=> __('Country','eventorganiser'),
|
795 |
+
);
|
796 |
+
|
797 |
+
return apply_filters('eventorganiser_venue_address_fields', $address_fields);
|
798 |
+
}
|
799 |
+
|
800 |
+
|
801 |
+
/**
|
802 |
+
*@ignore
|
803 |
+
*@access private
|
804 |
+
*/
|
805 |
+
function eventorganiser_venue_dropdown($post_id=0,$args){
|
806 |
+
$venues = get_terms('event-venue', array('hide_empty'=>false));
|
807 |
+
$current = (int) eo_get_venue($post_id);
|
808 |
+
|
809 |
+
$id = (!empty($args['id']) ? 'id="'.esc_attr($args['id']).'"' : '');
|
810 |
+
$name = (!empty($args['name']) ? 'name="'.esc_attr($args['name']).'"' : '');
|
811 |
+
?>
|
812 |
+
<select <?php echo $id.' '.$name; ?>>
|
813 |
+
<option><?php _e("Select a venue",'eventorganiser');?></option>
|
814 |
+
<?php foreach ($venues as $venue):?>
|
815 |
+
<option <?php selected($venue->term_id,$current);?> value="<?php echo $venue->term_id;?>"><?php echo $venue->name; ?></option>
|
816 |
+
<?php endforeach;?>
|
817 |
+
</select><?php
|
818 |
+
}
|
819 |
+
/**
|
820 |
+
*@ignore
|
821 |
+
*@access private
|
822 |
+
*/
|
823 |
+
function eo_event_venue_dropdown( $args = '' ) {
|
824 |
+
$defaults = array(
|
825 |
+
'show_option_all' =>'',
|
826 |
+
'echo' => 1,
|
827 |
+
'selected' => 0,
|
828 |
+
'name' => 'event-venue',
|
829 |
+
'id' => '',
|
830 |
+
'class' => 'postform event-organiser event-venue-dropdown event-dropdown',
|
831 |
+
'tab_index' => 0,
|
832 |
+
);
|
833 |
+
|
834 |
+
$defaults['selected'] = (is_tax('event-venue') ? get_query_var('event-venue') : 0);
|
835 |
+
$r = wp_parse_args( $args, $defaults );
|
836 |
+
$r['taxonomy']='event-venue';
|
837 |
+
extract( $r );
|
838 |
+
|
839 |
+
$tab_index_attribute = '';
|
840 |
+
if ( (int) $tab_index > 0 )
|
841 |
+
$tab_index_attribute = " tabindex=\"$tab_index\"";
|
842 |
+
|
843 |
+
$categories = get_terms($taxonomy, $r );
|
844 |
+
$name = esc_attr( $name );
|
845 |
+
$class = esc_attr( $class );
|
846 |
+
$id = $id ? esc_attr( $id ) : $name;
|
847 |
+
|
848 |
+
$output = "<select style='width:150px' name='$name' id='$id' class='$class' $tab_index_attribute>\n";
|
849 |
+
|
850 |
+
if ( $show_option_all ) {
|
851 |
+
$output .= '<option '.selected($selected,0,false).' value="0">'.$show_option_all.'</option>';
|
852 |
+
}
|
853 |
+
|
854 |
+
if ( ! empty( $categories ) ) {
|
855 |
+
foreach ($categories as $term):
|
856 |
+
$output .= '<option value="'.$term->slug.'"'.selected($selected,$term->slug,false).'>'.$term->name.'</option>';
|
857 |
+
endforeach;
|
858 |
+
}
|
859 |
+
$output .= "</select>\n";
|
860 |
+
|
861 |
+
if ( $echo )
|
862 |
+
echo $output;
|
863 |
+
|
864 |
+
return $output;
|
865 |
+
}
|
866 |
+
|
867 |
+
?>
|
includes/event.php
ADDED
@@ -0,0 +1,715 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
*@package event-functions
|
5 |
+
*/
|
6 |
+
/**
|
7 |
+
* This functions updates a post of event type, with data given in the $post_data
|
8 |
+
* and event data given in $event_data. Returns the post_id.
|
9 |
+
*
|
10 |
+
* Triggers {@see `eventorganiser_save_event`} passing event (post) ID
|
11 |
+
*
|
12 |
+
* The event data array can contain
|
13 |
+
*
|
14 |
+
* * `schedule` => (custom | once | daily | weekly | monthly | yearly) -- specifies the reoccurrence pattern
|
15 |
+
* * `schedule_meta` =>
|
16 |
+
* * For monthly schedules,
|
17 |
+
* * (string) BYMONTHDAY=XX to repeat on XXth day of month, e.g. BYMONTHDAY=01 to repeat on the first of every month.
|
18 |
+
* * (string) BYDAY=ND. N= 1|2|3|4|-1 (first, second, third, fourth, last). D is day of week SU|MO|TU|WE|TH|FR|SA. E.g. BYDAY=2TU (repeat on second tuesday)
|
19 |
+
* * For weekly schedules,
|
20 |
+
* * (array) Days to repeat on: (SU,MO,TU,WE,TH,FR,SA). e.g. set to array('SU','TU') to repeat on Tuesdays & Sundays.
|
21 |
+
* * Can be left blank to repeat weekly from the start date.
|
22 |
+
* * `frequency` => (int) positive integer, sets frequency of reoccurrence (every 2 days, or every 3 days etc)
|
23 |
+
* * `all_day` => 1 if its an all day event, 0 if not
|
24 |
+
* * `start` => start date (of first occurrence) as a datetime object
|
25 |
+
* * `end` => end date (of first occurrence) as a datetime object
|
26 |
+
* * `schedule_last` => **START** date of last occurrence (or upper-bound thereof) as a datetime object
|
27 |
+
* * `include` => array of datetime objects to include in the schedule
|
28 |
+
* * `exclude` => array of datetime objects to exclude in the schedule
|
29 |
+
*
|
30 |
+
* @since 1.5
|
31 |
+
* @uses wp_insert_post()
|
32 |
+
*
|
33 |
+
* @param int $post_id - the event (post) ID for the event you want to update
|
34 |
+
* @param array $event_data - array of event data
|
35 |
+
* @param array $post_data - array of data to be used by wp_update_post.
|
36 |
+
* @return int $post_id - the post ID of the updated event
|
37 |
+
*/
|
38 |
+
function eo_update_event($post_id, $event_data=array(), $post_data=array() ){
|
39 |
+
|
40 |
+
$post_id = (int) $post_id;
|
41 |
+
|
42 |
+
if( empty($post_id) )
|
43 |
+
return new WP_Error('eo_error','Empty post ID.');
|
44 |
+
|
45 |
+
if( !empty($event_data['venue']) || !empty($event_data['category']) ){
|
46 |
+
$post_data['taxonomy']['event-venue'] = isset($event_data['venue']) ? $event_data['venue'] : null;
|
47 |
+
$post_data['taxonomy']['event-category'] = isset($event_data['category']) ? $event_data['category'] : null;
|
48 |
+
unset($event_data['venue']);
|
49 |
+
unset($event_data['category']);
|
50 |
+
}
|
51 |
+
|
52 |
+
$event_data = apply_filters( 'eventorganiser_update_event_event_data', $event_data, $post_id, $post_data, $event_data );
|
53 |
+
$post_data = apply_filters( 'eventorganiser_update_event_post_data', $post_data, $post_id, $post_data, $event_data );
|
54 |
+
|
55 |
+
if( !empty($post_data) ){
|
56 |
+
$post_data['ID'] = $post_id;
|
57 |
+
wp_update_post( $post_data );
|
58 |
+
}
|
59 |
+
|
60 |
+
//Get previous data, parse with data to be updated
|
61 |
+
$prev = eo_get_event_schedule($post_id);
|
62 |
+
$event_data = wp_parse_args( $event_data, $prev );
|
63 |
+
|
64 |
+
//If schedule is 'once' and dates are included - set to 'custom':
|
65 |
+
if( ( empty($event_data['schedule']) || 'once' == $event_data['schedule'] ) && !empty($event_data['include']) ){
|
66 |
+
$event_data['schedule'] = 'custom';
|
67 |
+
}
|
68 |
+
|
69 |
+
//Do we need to delete existing dates from db?
|
70 |
+
$delete_existing = false;
|
71 |
+
$diff = array();
|
72 |
+
if( $prev ){
|
73 |
+
foreach ( $prev as $key => $prev_value ){
|
74 |
+
if( $event_data[$key] != $prev_value ){
|
75 |
+
if('monthly' == $event_data['schedule'] && $key =='schedule_meta'){
|
76 |
+
if( $event_data['occurs_by'] != $prev['occurs_by'] ){
|
77 |
+
$diff[]=$key;
|
78 |
+
$delete_existing = true;
|
79 |
+
break;
|
80 |
+
}
|
81 |
+
}else{
|
82 |
+
|
83 |
+
//If one off event / custom, don't worry about 'schedule_last'
|
84 |
+
if( $key == 'schedule_last' && in_array( $event_data['schedule'], array( 'once', 'custom' ) ) )
|
85 |
+
continue;
|
86 |
+
|
87 |
+
$diff[]=$key;
|
88 |
+
$delete_existing = true;
|
89 |
+
break;
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
//Need to replace occurrences
|
96 |
+
if( $delete_existing || !empty( $event_data['force_regenerate_dates'] ) ){
|
97 |
+
//Generate occurrences
|
98 |
+
$event_data = _eventorganiser_generate_occurrences($event_data);
|
99 |
+
|
100 |
+
if( is_wp_error($event_data) )
|
101 |
+
return $event_data;
|
102 |
+
|
103 |
+
//Delete old dates
|
104 |
+
eo_delete_event_occurrences($post_id);
|
105 |
+
|
106 |
+
//Insert new ones and update meta
|
107 |
+
$re = _eventorganiser_insert_occurrences($post_id,$event_data);
|
108 |
+
}
|
109 |
+
|
110 |
+
do_action( 'eventorganiser_save_event', $post_id );
|
111 |
+
return $post_id;
|
112 |
+
}
|
113 |
+
|
114 |
+
|
115 |
+
/**
|
116 |
+
* This functions inserts a post of event type, with data given in the $post_data
|
117 |
+
* and event data given in $event_data. Returns the post ID.
|
118 |
+
*
|
119 |
+
* Triggers {@see `eventorganiser_save_event`} passing event (post) ID
|
120 |
+
*
|
121 |
+
* The event data array can contain
|
122 |
+
*
|
123 |
+
* * `schedule` => (custom | once | daily | weekly | monthly | yearly) -- specifies the reoccurrence pattern
|
124 |
+
* * `schedule_meta` =>
|
125 |
+
* * For monthly schedules,
|
126 |
+
* * (string) BYMONTHDAY=XX to repeat on XXth day of month, e.g. BYMONTHDAY=01 to repeat on the first of every month.
|
127 |
+
* * (string) BYDAY=ND. N= 1|2|3|4|-1 (first, second, third, fourth, last). D is day of week SU|MO|TU|WE|TH|FR|SA. E.g. BYDAY=2TU (repeat on second tuesday)
|
128 |
+
* * For weekly schedules,
|
129 |
+
* * (array) Days to repeat on: (SU,MO,TU,WE,TH,FR,SA). e.g. set to array('SU','TU') to repeat on Tuesdays & Sundays.
|
130 |
+
* * Can be left blank to repeat weekly from the start date.
|
131 |
+
* * `frequency` => (int) positive integer, sets frequency of reoccurrence (every 2 days, or every 3 days etc)
|
132 |
+
* * `all_day` => 1 if its an all day event, 0 if not
|
133 |
+
* * `start` => start date (of first occurrence) as a datetime object
|
134 |
+
* * `end` => end date (of first occurrence) as a datetime object
|
135 |
+
* * `schedule_last` => **START** date of last occurrence (or upper-bound thereof) as a datetime object
|
136 |
+
* * `include` => array of datetime objects to include in the schedule
|
137 |
+
* * `exclude` => array of datetime objects to exclude in the schedule
|
138 |
+
*
|
139 |
+
* @since 1.5
|
140 |
+
* @link http://www.stephenharris.info/2012/front-end-event-posting/ Tutorial on front-end event posting
|
141 |
+
* @uses wp_insert_post()
|
142 |
+
*
|
143 |
+
* @param array $post_data array of data to be used by wp_insert_post.
|
144 |
+
* @param array $event_data array of event data
|
145 |
+
* @return int the post ID of the updated event
|
146 |
+
*/
|
147 |
+
function eo_insert_event($post_data=array(),$event_data=array()){
|
148 |
+
global $wpdb;
|
149 |
+
|
150 |
+
if( !empty($event_data['venue'] ) ){
|
151 |
+
$post_data['tax_input']['event-venue'] = $event_data['venue'];
|
152 |
+
unset($event_data['venue']);
|
153 |
+
}
|
154 |
+
if( !empty($event_data['category'] ) ){
|
155 |
+
$post_data['tax_input']['event-category'] = $event_data['category'];
|
156 |
+
unset($event_data['category']);
|
157 |
+
}
|
158 |
+
|
159 |
+
//If schedule is 'once' and dates are included - set to 'custom':
|
160 |
+
if( ( empty($event_data['schedule']) || 'once' == $event_data['schedule'] ) && !empty($event_data['include']) ){
|
161 |
+
$event_data['schedule'] = 'custom';
|
162 |
+
}
|
163 |
+
|
164 |
+
$event_data = _eventorganiser_generate_occurrences($event_data);
|
165 |
+
|
166 |
+
if( is_wp_error($event_data) )
|
167 |
+
return $event_data;
|
168 |
+
|
169 |
+
$event_data = apply_filters( 'eventorganiser_insert_event_event_data', $event_data, $post_data, $event_data );
|
170 |
+
$post_data = apply_filters( 'eventorganiser_insert_event_post_data', $post_data, $post_data, $event_data );
|
171 |
+
|
172 |
+
//Finally we create event (first create the post in WP)
|
173 |
+
$post_input = array_merge(array('post_title'=>'untitled event'), $post_data, array('post_type'=>'event'));
|
174 |
+
$post_id = wp_insert_post($post_input, true);
|
175 |
+
|
176 |
+
//Did the event insert correctly?
|
177 |
+
if ( is_wp_error( $post_id) )
|
178 |
+
return $post_id;
|
179 |
+
|
180 |
+
_eventorganiser_insert_occurrences($post_id, $event_data);
|
181 |
+
|
182 |
+
//Action used to break cache & trigger Pro actions (& by other plug-ins?)
|
183 |
+
do_action( 'eventorganiser_save_event', $post_id );
|
184 |
+
return $post_id;
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Deletes all occurrences for an event (removes them from the eo_events table).
|
189 |
+
* Triggers {@see `eventorganiser_delete_event`} (this action is used to break the caches).
|
190 |
+
* @since 1.5
|
191 |
+
*
|
192 |
+
* @param int $post_id the event's (post) ID to be deleted
|
193 |
+
*/
|
194 |
+
function eo_delete_event_occurrences($post_id){
|
195 |
+
global $wpdb;
|
196 |
+
|
197 |
+
do_action( 'eventorganiser_delete_event', $post_id ); //Deprecated - do not use!
|
198 |
+
do_action( 'eventorganiser_delete_event_occurrences', $post_id );
|
199 |
+
$del = $wpdb->get_results($wpdb->prepare("DELETE FROM $wpdb->eo_events WHERE post_id=%d",$post_id));
|
200 |
+
}
|
201 |
+
add_action( 'delete_post', 'eo_delete_event_occurrences', 10 );
|
202 |
+
|
203 |
+
/**
|
204 |
+
* This is a private function - handles the insertion of dates into the database. Use eo_insert_event or eo_update_event instead.
|
205 |
+
* @access private
|
206 |
+
* @ignore
|
207 |
+
*
|
208 |
+
* @param int $post_id The post ID of the event
|
209 |
+
* @param array $event_data Array of event data, including schedule meta (saved as post meta), duration and occurrences
|
210 |
+
* @return int $post_id
|
211 |
+
*/
|
212 |
+
function _eventorganiser_insert_occurrences($post_id, $event_data){
|
213 |
+
global $wpdb;
|
214 |
+
extract($event_data);
|
215 |
+
|
216 |
+
//Get duration
|
217 |
+
$duration=false;
|
218 |
+
if( function_exists('date_diff') ){
|
219 |
+
$duration = date_diff($start,$end);
|
220 |
+
|
221 |
+
/* Storing a DateInterval object can cause errors. Serialize it.
|
222 |
+
Thanks to Mathieu Parisot, Mathias & Dave Page */
|
223 |
+
$event_data['duration'] = maybe_serialize( $duration );
|
224 |
+
}
|
225 |
+
|
226 |
+
//Work around for PHP < 5.3
|
227 |
+
$seconds = round(abs($start->format('U') - $end->format('U')));
|
228 |
+
$days = floor($seconds/86400);// 86400 = 60*60*24 seconds in a normal day
|
229 |
+
$sec_diff = $seconds - $days*86400;
|
230 |
+
$duration_str = '+'.$days.'days '.$sec_diff.' seconds';
|
231 |
+
$event_data['duration_str'] =$duration_str;
|
232 |
+
|
233 |
+
$occurrence_array = array();
|
234 |
+
|
235 |
+
foreach( $occurrences as $counter=> $occurrence ):
|
236 |
+
$occurrence_end = clone $occurrence;
|
237 |
+
if( $duration ){
|
238 |
+
$occurrence_end->add($duration);
|
239 |
+
}else{
|
240 |
+
$occurrence_end->modify($duration_str);
|
241 |
+
}
|
242 |
+
|
243 |
+
$occurrence_input =array(
|
244 |
+
'post_id'=>$post_id,
|
245 |
+
'StartDate'=>$occurrence->format('Y-m-d'),
|
246 |
+
'StartTime'=>$occurrence->format('H:i:s'),
|
247 |
+
'EndDate'=>$occurrence_end->format('Y-m-d'),
|
248 |
+
'FinishTime'=>$end->format('H:i:s'),
|
249 |
+
'event_occurrence' => $counter,
|
250 |
+
);
|
251 |
+
|
252 |
+
$wpdb->insert($wpdb->eo_events, $occurrence_input);
|
253 |
+
$occurrence_array[$wpdb->insert_id] = $occurrence->format('Y-m-d H:i:s');
|
254 |
+
|
255 |
+
//Add to occurrence cache: TODO use post meta
|
256 |
+
$occurrence_cache[$wpdb->insert_id] = array(
|
257 |
+
'start' =>$occurrence,
|
258 |
+
'end' => new DateTime($occurrence_end->format('Y-m-d').' '.$end->format('H:i:s'), eo_get_blog_timezone())
|
259 |
+
);
|
260 |
+
endforeach;
|
261 |
+
|
262 |
+
//Set occurrence cache
|
263 |
+
wp_cache_set( 'eventorganiser_occurrences_'.$post_id, $occurrence_cache );
|
264 |
+
|
265 |
+
unset($event_data['occurrences']);
|
266 |
+
$event_data['_occurrences'] = $occurrence_array;
|
267 |
+
|
268 |
+
if( !empty($include) )
|
269 |
+
$event_data['include'] = array_map('eo_format_datetime', $include, array_fill(0, count($include), 'Y-m-d H:i:s') );
|
270 |
+
if( !empty($exclude) )
|
271 |
+
$event_data['exclude'] = array_map('eo_format_datetime', $exclude, array_fill(0, count($exclude), 'Y-m-d H:i:s') );
|
272 |
+
|
273 |
+
unset($event_data['start']);
|
274 |
+
unset($event_data['end']);
|
275 |
+
unset($event_data['schedule_start']);
|
276 |
+
unset($event_data['schedule_last']);
|
277 |
+
|
278 |
+
update_post_meta( $post_id,'_eventorganiser_event_schedule', $event_data);
|
279 |
+
update_post_meta( $post_id,'_eventorganiser_schedule_start_start', $start->format('Y-m-d H:i:s'));
|
280 |
+
update_post_meta( $post_id,'_eventorganiser_schedule_start_finish', $end->format('Y-m-d H:i:s'));
|
281 |
+
update_post_meta( $post_id,'_eventorganiser_schedule_last_start', $occurrence->format('Y-m-d H:i:s'));
|
282 |
+
update_post_meta( $post_id,'_eventorganiser_schedule_last_finish', $occurrence_end->format('Y-m-d H:i:s'));
|
283 |
+
return $post_id;
|
284 |
+
}
|
285 |
+
|
286 |
+
|
287 |
+
/**
|
288 |
+
* Gets schedule meta from the database (post meta)
|
289 |
+
* Datetimes are converted to DateTime objects, in blog's currenty timezone
|
290 |
+
*
|
291 |
+
* Event details include
|
292 |
+
*
|
293 |
+
* * `schedule` => (custom | once | daily | weekly | monthly | yearly) -- specifies the reoccurrence pattern
|
294 |
+
* * `schedule_meta` =>
|
295 |
+
* * For monthly schedules,
|
296 |
+
* * (string) BYMONTHDAY=XX to repeat on XXth day of month, e.g. BYMONTHDAY=01 to repeat on the first of every month.
|
297 |
+
* * (string) BYDAY=ND. N= 1|2|3|4|-1 (first, second, third, fourth, last). D is day of week SU|MO|TU|WE|TH|FR|SA. E.g. BYDAY=2TU (repeat on second tuesday)
|
298 |
+
* * For weekly schedules,
|
299 |
+
* * (array) Days to repeat on: (SU,MO,TU,WE,TH,FR,SA). e.g. set to array('SU','TU') to repeat on Tuesdays & Sundays.
|
300 |
+
* * `occurs_by` - For use with monthly schedules: how the event reoccurs: BYDAY or BYMONTHDAY
|
301 |
+
* * `frequency` => (int) positive integer, sets frequency of reoccurrence (every 2 days, or every 3 days etc)
|
302 |
+
* * `all_day` => 1 if its an all day event, 0 if not
|
303 |
+
* * `start` => start date (of first occurrence) as a datetime object
|
304 |
+
* * `end` => end date (of first occurrence) as a datetime object
|
305 |
+
* * `schedule_last` => **START** date of last occurrence as a datetime object
|
306 |
+
* * `include` => array of datetime objects to include in the schedule
|
307 |
+
* * `exclude` => array of datetime objects to exclude in the schedule
|
308 |
+
*
|
309 |
+
* @param int $post_id - The post ID of the event
|
310 |
+
* @return array event schedule details
|
311 |
+
*/
|
312 |
+
function eo_get_event_schedule( $post_id=0 ){
|
313 |
+
|
314 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
315 |
+
|
316 |
+
if( empty($post_id) )
|
317 |
+
return false;
|
318 |
+
|
319 |
+
$event_details = get_post_meta( $post_id,'_eventorganiser_event_schedule',true);
|
320 |
+
$event_details = wp_parse_args($event_details, array(
|
321 |
+
'schedule'=>'once',
|
322 |
+
'schedule_meta'=>'',
|
323 |
+
'frequency'=>1,
|
324 |
+
'all_day'=>0,
|
325 |
+
'duration_str'=>'',
|
326 |
+
'include'=>array(),
|
327 |
+
'exclude'=>array(),
|
328 |
+
'_occurrences'=>array(),
|
329 |
+
));
|
330 |
+
|
331 |
+
$tz = eo_get_blog_timezone();
|
332 |
+
$event_details['start'] = new DateTime(get_post_meta( $post_id,'_eventorganiser_schedule_start_start', true), $tz);
|
333 |
+
$event_details['end'] = new DateTime(get_post_meta( $post_id,'_eventorganiser_schedule_start_finish', true), $tz);
|
334 |
+
$event_details['schedule_start'] = clone $event_details['start'];
|
335 |
+
$event_details['schedule_last'] = new DateTime(get_post_meta( $post_id,'_eventorganiser_schedule_last_start', true), $tz);
|
336 |
+
$event_details['schedule_finish'] = new DateTime(get_post_meta( $post_id,'_eventorganiser_schedule_last_finish', true), $tz);
|
337 |
+
|
338 |
+
if( !empty($event_details['_occurrences']) ){
|
339 |
+
$event_details['_occurrences'] = array_map('eventorganiser_date_create', $event_details['_occurrences']);
|
340 |
+
}
|
341 |
+
|
342 |
+
if( !empty($event_details['include']) ){
|
343 |
+
$event_details['include'] = array_map('eventorganiser_date_create', $event_details['include'] );
|
344 |
+
}
|
345 |
+
if( !empty($event_details['exclude']) ){
|
346 |
+
$event_details['exclude'] = array_map('eventorganiser_date_create',$event_details['exclude'] );
|
347 |
+
}
|
348 |
+
|
349 |
+
if($event_details['schedule'] == 'weekly'){
|
350 |
+
$event_details['occurs_by'] = '';
|
351 |
+
}elseif($event_details['schedule'] == 'monthly'){
|
352 |
+
$bymonthday = preg_match('/BYMONTHDAY=/',$event_details['schedule_meta']);
|
353 |
+
$event_details['occurs_by'] = ($bymonthday ? 'BYMONTHDAY' : 'BYDAY');
|
354 |
+
}else{
|
355 |
+
$event_details['occurs_by'] ='';
|
356 |
+
}
|
357 |
+
|
358 |
+
return apply_filters( 'eventorganiser_get_event_schedule', $event_details, $post_id );
|
359 |
+
}
|
360 |
+
|
361 |
+
|
362 |
+
/**
|
363 |
+
* This is a private function - handles the generation of occurrence dates from the schedule data
|
364 |
+
* @access private
|
365 |
+
* @ignore
|
366 |
+
*
|
367 |
+
* @param array $event_data - Array containing the event's schedule data
|
368 |
+
* @return array $event_data - Array containing the event's schedule data including 'occurrences', an array of DateTimes
|
369 |
+
*/
|
370 |
+
function _eventorganiser_generate_occurrences( $event_data=array() ){
|
371 |
+
|
372 |
+
$event_defaults = array(
|
373 |
+
'start'=>'',
|
374 |
+
'end'=>'',
|
375 |
+
'all_day'=>0,
|
376 |
+
'schedule'=>'once',
|
377 |
+
'schedule_meta'=>'',
|
378 |
+
'frequency'=>1,
|
379 |
+
'schedule_last'=>'',
|
380 |
+
'exclude'=>array(),
|
381 |
+
'include'=>array(),
|
382 |
+
);
|
383 |
+
extract(wp_parse_args($event_data, $event_defaults));
|
384 |
+
|
385 |
+
$occurrences =array(); //occurrences array
|
386 |
+
|
387 |
+
//Make sure the same doesn't appear in both $include/$exclude. Is this really needed?
|
388 |
+
$exclude = array_udiff($exclude, $include, '_eventorganiser_compare_dates');
|
389 |
+
$include = array_udiff($include, $exclude, '_eventorganiser_compare_dates');
|
390 |
+
|
391 |
+
//Check dates are supplied and are valid
|
392 |
+
if( !($start instanceof DateTime) )
|
393 |
+
return new WP_Error('eo_error',__('Start date not provided.','eventorganiser'));
|
394 |
+
|
395 |
+
if( !($end instanceof DateTime) )
|
396 |
+
$end = clone $start;
|
397 |
+
|
398 |
+
if( !($schedule_last instanceof DateTime) )
|
399 |
+
$schedule_last = clone $start;
|
400 |
+
|
401 |
+
//Check dates are in chronological order
|
402 |
+
if($end < $start)
|
403 |
+
return new WP_Error('eo_error',__('Start date occurs after end date.','eventorganiser'));
|
404 |
+
|
405 |
+
if($schedule_last < $start)
|
406 |
+
return new WP_Error('eo_error',__('Schedule end date is before is before the start date.','eventorganiser'));
|
407 |
+
|
408 |
+
//Now set timezones
|
409 |
+
$timezone = eo_get_blog_timezone();
|
410 |
+
$start->setTimezone($timezone);
|
411 |
+
$end->setTimezone($timezone);
|
412 |
+
$schedule_last->setTimezone($timezone);
|
413 |
+
$H = intval($start->format('H'));
|
414 |
+
$i = intval($start->format('i'));
|
415 |
+
|
416 |
+
//White list schedule
|
417 |
+
if( !in_array($schedule, array('once','daily','weekly','monthly','yearly','custom')) )
|
418 |
+
return new WP_Error('eo_error',__('Schedule not recognised.','eventorganiser'));
|
419 |
+
|
420 |
+
//Ensure event frequency is a positive integer. Else set to 1.
|
421 |
+
$frequency = max(absint($frequency),1);
|
422 |
+
$all_day = (int) $all_day ;
|
423 |
+
|
424 |
+
$start_days =array();
|
425 |
+
$workaround='';
|
426 |
+
$icaldays = array('SU','MO','TU','WE','TH','FR','SA');
|
427 |
+
$weekdays = array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
|
428 |
+
$ical2day = array('SU'=>'Sunday','MO'=>'Monday','TU'=>'Tuesday',
|
429 |
+
'WE'=>'Wednesday','TH'=>'Thursday','FR'=>'Friday','SA'=>'Saturday',);
|
430 |
+
|
431 |
+
//Set up schedule
|
432 |
+
switch( $schedule ) :
|
433 |
+
case 'once':
|
434 |
+
case 'custom':
|
435 |
+
$frequency =1;
|
436 |
+
$schedule_meta ='';
|
437 |
+
$schedule_start = clone $start;
|
438 |
+
$schedule_last = clone $start;
|
439 |
+
$start_days[] = clone $start;
|
440 |
+
$workaround = 'once';//Not strictly a workaround.
|
441 |
+
break;
|
442 |
+
|
443 |
+
case 'daily':
|
444 |
+
$interval = "+".$frequency."day";
|
445 |
+
$start_days[] = clone $start;
|
446 |
+
break;
|
447 |
+
|
448 |
+
case 'weekly':
|
449 |
+
$schedule_meta = array_filter($schedule_meta);
|
450 |
+
if( !empty($schedule_meta) && is_array($schedule_meta) ):
|
451 |
+
foreach ($schedule_meta as $day):
|
452 |
+
$start_day = clone $start;
|
453 |
+
$start_day->modify($ical2day[$day]);
|
454 |
+
$start_days[] = $start_day;
|
455 |
+
endforeach;
|
456 |
+
else:
|
457 |
+
$start_days[] = clone $start;
|
458 |
+
endif;
|
459 |
+
|
460 |
+
$interval = "+".$frequency."week";
|
461 |
+
break;
|
462 |
+
|
463 |
+
case 'monthly':
|
464 |
+
$start_days[] = clone $start;
|
465 |
+
$rule_value = explode('=',$schedule_meta,2);
|
466 |
+
$rule =$rule_value[0];
|
467 |
+
$values = explode(',',$rule_value[1]);//Should only be one value, but may support more in future
|
468 |
+
$values = array_filter($values);
|
469 |
+
|
470 |
+
if( $rule=='BYMONTHDAY' ):
|
471 |
+
$date = (int) $start_days[0]->format('d');
|
472 |
+
$interval = "+".$frequency."month";
|
473 |
+
|
474 |
+
if($date >= 29)
|
475 |
+
$workaround = 'short months'; //This case deals with 29/30/31 of month
|
476 |
+
|
477 |
+
$schedule_meta = 'BYMONTHDAY='.$date;
|
478 |
+
|
479 |
+
else:
|
480 |
+
if( empty($values) ){
|
481 |
+
$date = (int) $start_days[0]->format('d');
|
482 |
+
$n = ceil($date/7); // nth weekday of month.
|
483 |
+
$day_num = intval($start_days[0]->format('w')); //0 (Sun) - 6(Sat)
|
484 |
+
|
485 |
+
}else{
|
486 |
+
//expect e.g. array( 2MO )
|
487 |
+
preg_match('/^(-?\d{1,2})([a-zA-Z]{2})/' ,$values[0],$matches);
|
488 |
+
$n=(int) $matches[1];
|
489 |
+
$day_num = array_search($matches[2],$icaldays);//(Sun) - 6(Sat)
|
490 |
+
}
|
491 |
+
|
492 |
+
if($n==5) $n= -1; //If 5th, interpret it as last.
|
493 |
+
$ordinal = array('1'=>"first",'2'=>"second",'3'=>"third",'4'=>"fourth",'-1'=>"last");
|
494 |
+
|
495 |
+
if( !isset($ordinal[$n]) )
|
496 |
+
return new WP_Error('eo_error',__('Invalid monthly schedule (invalid ordinal)','eventorganiser'));
|
497 |
+
|
498 |
+
$ical_day = $icaldays[$day_num]; //ical day from day_num (SU - SA)
|
499 |
+
$day = $weekdays[$day_num];//Full day name from day_num (Sunday -Monday)
|
500 |
+
$schedule_meta = 'BYDAY='.$n.$ical_day; //E.g. BYDAY=2MO
|
501 |
+
$interval = $ordinal[$n].' '.$day.' of +'.$frequency.' month'; //E.g. second monday of +1 month
|
502 |
+
|
503 |
+
//Work around for PHP <5.3
|
504 |
+
if(!function_exists('date_diff')){
|
505 |
+
$workaround = 'php5.2';
|
506 |
+
}
|
507 |
+
endif;
|
508 |
+
break;
|
509 |
+
|
510 |
+
case 'yearly':
|
511 |
+
$start_days[] = clone $start;
|
512 |
+
if( '29-02' == $start_days[0]->format('d-m') )
|
513 |
+
$workaround = 'leap year';
|
514 |
+
|
515 |
+
$interval = "+".$frequency."year";
|
516 |
+
break;
|
517 |
+
endswitch; //End $schedule switch
|
518 |
+
|
519 |
+
|
520 |
+
//Now we have setup and validated the schedules - loop through and generate occurrences
|
521 |
+
foreach($start_days as $index => $start_day):
|
522 |
+
$current = clone $start_day;
|
523 |
+
|
524 |
+
switch($workaround):
|
525 |
+
//Not really a workaround. Just add the occurrence and finish.
|
526 |
+
case 'once':
|
527 |
+
$current->setTime($H,$i );
|
528 |
+
$occurrences[] = clone $current;
|
529 |
+
break;
|
530 |
+
|
531 |
+
//Loops for monthly events that require php5.3 functionality
|
532 |
+
case 'php5.2':
|
533 |
+
while( $current <= $schedule_last ):
|
534 |
+
$current->setTime($H,$i );
|
535 |
+
$occurrences[] = clone $current;
|
536 |
+
$current = _eventorganiser_php52_modify($current,$interval);
|
537 |
+
endwhile;
|
538 |
+
break;
|
539 |
+
|
540 |
+
//Loops for monthly events on the 29th/30th/31st
|
541 |
+
case 'short months':
|
542 |
+
$day_int =intval($start_day->format('d'));
|
543 |
+
|
544 |
+
//Set the first month
|
545 |
+
$current_month= clone $start_day;
|
546 |
+
$current_month = date_create($current_month->format('Y-m-1'));
|
547 |
+
|
548 |
+
while( $current_month<=$schedule_last ):
|
549 |
+
$month_int = intval($current_month->format('m'));
|
550 |
+
$year_int = intval($current_month->format('Y'));
|
551 |
+
|
552 |
+
if( checkdate($month_int , $day_int , $year_int) ){
|
553 |
+
$current = new DateTime($day_int.'-'.$month_int.'-'.$year_int, $timezone);
|
554 |
+
$current->setTime($H,$i );
|
555 |
+
$occurrences[] = clone $current;
|
556 |
+
}
|
557 |
+
$current_month->modify($interval);
|
558 |
+
endwhile;
|
559 |
+
break;
|
560 |
+
|
561 |
+
//To be used for yearly events occuring on Feb 29
|
562 |
+
case 'leap year':
|
563 |
+
$current_year = clone $current;
|
564 |
+
$current_year->modify('-1 day');
|
565 |
+
|
566 |
+
while($current_year<=$schedule_last):
|
567 |
+
$is_leap_year = (int) $current_year->format('L');
|
568 |
+
|
569 |
+
if( $is_leap_year ){
|
570 |
+
$current = clone $current_year;
|
571 |
+
$current->modify('+1 day');
|
572 |
+
$current->setTime($H,$i );
|
573 |
+
$occurrences[] = clone $current;
|
574 |
+
}
|
575 |
+
|
576 |
+
$current_year->modify($interval);
|
577 |
+
endwhile;
|
578 |
+
break;
|
579 |
+
|
580 |
+
default:
|
581 |
+
while($current <= $schedule_last):
|
582 |
+
$current->setTime($H,$i );
|
583 |
+
$occurrences[] = clone $current;
|
584 |
+
$current->modify($interval);
|
585 |
+
endwhile;
|
586 |
+
break;
|
587 |
+
|
588 |
+
endswitch;//End 'workaround' switch;
|
589 |
+
endforeach;
|
590 |
+
|
591 |
+
//Now schedule meta is set up and occurrences are generated.
|
592 |
+
|
593 |
+
//Add inclusions, removes exceptions and duplicates
|
594 |
+
$occurrences = array_merge($occurrences, $include);
|
595 |
+
$occurrences = array_udiff($occurrences, $exclude, '_eventorganiser_compare_dates');
|
596 |
+
$occurrences = _eventorganiser_remove_duplicates($occurrences);
|
597 |
+
|
598 |
+
//Sort occurrences
|
599 |
+
sort($occurrences);
|
600 |
+
$schedule_start = clone $occurrences[0];
|
601 |
+
$schedule_last = clone end($occurrences);
|
602 |
+
|
603 |
+
$_event_data = array(
|
604 |
+
'start'=>$start,
|
605 |
+
'end'=>$end,
|
606 |
+
'all_day'=>$all_day,
|
607 |
+
'schedule'=>$schedule,
|
608 |
+
'schedule_meta'=>$schedule_meta,
|
609 |
+
'frequency'=>$frequency,
|
610 |
+
'schedule_start'=>$schedule_start,
|
611 |
+
'schedule_last'=>$schedule_last,
|
612 |
+
'exclude'=>$exclude,
|
613 |
+
'include'=>$include,
|
614 |
+
'occurrences'=>$occurrences
|
615 |
+
);
|
616 |
+
|
617 |
+
return apply_filters( 'eventorganiser_generate_occurrences', $_event_data, $event_details );
|
618 |
+
}
|
619 |
+
|
620 |
+
/**
|
621 |
+
* Generates the ICS RRULE fromthe event schedule data.
|
622 |
+
* @access private
|
623 |
+
* @ignore
|
624 |
+
* @since 1.0.0
|
625 |
+
*
|
626 |
+
* @param int $post_id The event (post) ID. Uses current event if empty.
|
627 |
+
* @return string The RRULE to be used in an ICS calendar
|
628 |
+
*/
|
629 |
+
function eventorganiser_generate_ics_rrule($post_id=0){
|
630 |
+
|
631 |
+
$post_id = (int) ( empty($post_id) ? get_the_ID() : $post_id);
|
632 |
+
|
633 |
+
$rrule = eo_get_event_schedule($post_id);
|
634 |
+
if( !$rrule )
|
635 |
+
return false;
|
636 |
+
|
637 |
+
extract($rrule);
|
638 |
+
|
639 |
+
$format = ( $all_day ? 'Ymd' : 'Ymd\THis\Z' );
|
640 |
+
|
641 |
+
$schedule_last->setTimezone(new DateTimeZone('UTC'));
|
642 |
+
$schedule_last = $schedule_last->format($format);
|
643 |
+
|
644 |
+
switch($schedule):
|
645 |
+
case 'once':
|
646 |
+
return false;
|
647 |
+
|
648 |
+
case 'yearly':
|
649 |
+
return "FREQ=YEARLY;INTERVAL=".$frequency.";UNTIL=".$schedule_last;
|
650 |
+
|
651 |
+
case 'monthly':
|
652 |
+
$reoccurrence_rule = "FREQ=MONTHLY;INTERVAL=".$frequency.";";
|
653 |
+
$reoccurrence_rule.=$schedule_meta.";";
|
654 |
+
$reoccurrence_rule.= "UNTIL=".$schedule_last;
|
655 |
+
return $reoccurrence_rule;
|
656 |
+
|
657 |
+
case 'weekly':
|
658 |
+
return "FREQ=WEEKLY;INTERVAL=".$frequency.";BYDAY=".implode(',',$schedule_meta).";UNTIL=".$schedule_last;
|
659 |
+
|
660 |
+
case 'daily':
|
661 |
+
return "FREQ=DAILY;INTERVAL=".$frequency.";UNTIL=".$schedule_last;
|
662 |
+
|
663 |
+
default:
|
664 |
+
endswitch;
|
665 |
+
return false;
|
666 |
+
}
|
667 |
+
|
668 |
+
/**
|
669 |
+
* Removes a single occurrence and adds it to the event's 'excluded' dates.
|
670 |
+
* @access private
|
671 |
+
* @ignore
|
672 |
+
* @since 1.5
|
673 |
+
*
|
674 |
+
* @param int $post_id The event (post) ID
|
675 |
+
* @param int $event_id The event occurrence ID
|
676 |
+
* @return bool|WP_Error True on success, WP_Error object on failure
|
677 |
+
*/
|
678 |
+
function _eventorganiser_remove_occurrence($post_id=0, $event_id=0){
|
679 |
+
global $wpdb;
|
680 |
+
|
681 |
+
$remove = $wpdb->get_row($wpdb->prepare(
|
682 |
+
"SELECT {$wpdb->eo_events}.StartDate, {$wpdb->eo_events}.StartTime
|
683 |
+
FROM {$wpdb->eo_events}
|
684 |
+
WHERE post_id=%d AND event_id=%d",$post_id,$event_id));
|
685 |
+
|
686 |
+
if( !$remove )
|
687 |
+
return new WP_Error('eo_notice', '<strong>'.__("Occurrence note deleted. Occurrence not found",'eventorganiser').'</strong>');
|
688 |
+
|
689 |
+
$date = trim($remove->StartDate).' '.trim($remove->StartTime);
|
690 |
+
|
691 |
+
$event_details = get_post_meta( $post_id,'_eventorganiser_event_schedule',true);
|
692 |
+
|
693 |
+
if( ($key = array_search($date,$event_details['include'])) === false){
|
694 |
+
//If the date was not manually included, add it to the 'exclude' array
|
695 |
+
$event_details['exclude'][] = $date;
|
696 |
+
}else{
|
697 |
+
//If the date was manually included, just remove it from the included dates
|
698 |
+
unset($event_details['include'][$key]);
|
699 |
+
}
|
700 |
+
|
701 |
+
//Remove the date from the occurrences
|
702 |
+
if( isset($event_details['_occurrences'][$event_id]) ){
|
703 |
+
unset($event_details['_occurrences'][$event_id]);
|
704 |
+
}
|
705 |
+
|
706 |
+
//Update post meta and delete date from events table
|
707 |
+
update_post_meta( $post_id,'_eventorganiser_event_schedule',$event_details);
|
708 |
+
$del = $wpdb->get_results($wpdb->prepare("DELETE FROM {$wpdb->eo_events} WHERE post_id=%d AND event_id=%d",$post_id,$event_id));
|
709 |
+
|
710 |
+
//Clear cache
|
711 |
+
_eventorganiser_delete_calendar_cache();
|
712 |
+
|
713 |
+
return true;
|
714 |
+
}
|
715 |
+
?>
|
js/admin-calendar.js
ADDED
@@ -0,0 +1,1199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
(function ($) {
|
2 |
+
$(document).ready(function () {
|
3 |
+
|
4 |
+
/* Calendar Dialogs */
|
5 |
+
$('#eo-dialog-tabs').tabs();
|
6 |
+
$('.eo-dialog').dialog({
|
7 |
+
autoOpen: false,
|
8 |
+
width: 527,
|
9 |
+
modal:true
|
10 |
+
});
|
11 |
+
$('#events-meta').parent().find('.ui-dialog-titlebar-close').appendTo('.ui-tabs-nav').closest('.ui-dialog').children('.ui-dialog-titlebar').remove();
|
12 |
+
|
13 |
+
/* Time Format from screen option */
|
14 |
+
var format = ($('#eofc_time_format').is(":checked") ? 'HH:mm' : 'h:mmtt');
|
15 |
+
if( $.cookie('eo_admin_cal_last_viewed_date') ){
|
16 |
+
var initial_date = new Date($.cookie('eo_admin_cal_last_viewed_date'));
|
17 |
+
}else{
|
18 |
+
var initial_date = new Date();
|
19 |
+
}
|
20 |
+
|
21 |
+
/* Calendar */
|
22 |
+
var calendar = jQuery('#eo_admin_calendar').fullCalendar({
|
23 |
+
firstDay: parseInt(EO_Ajax.startday),
|
24 |
+
date:initial_date.getDate(),
|
25 |
+
month:initial_date.getMonth(),
|
26 |
+
year: initial_date.getFullYear(),
|
27 |
+
defaultView: ($.cookie('eo_admin_cal_last_view') ? $.cookie('eo_admin_cal_last_view') : 'month'),
|
28 |
+
editable: false,
|
29 |
+
lazyFetching: 'true',
|
30 |
+
eventColor: '#21759B',
|
31 |
+
theme: true,
|
32 |
+
customButtons:{
|
33 |
+
category: eventorganiser_cat_dropdown,
|
34 |
+
venue: eventorganiser_venue_dropdown,
|
35 |
+
'goto': eventorganiser_mini_calendar
|
36 |
+
},
|
37 |
+
buttonText: {
|
38 |
+
today: EO_Ajax.locale.today,
|
39 |
+
month: EO_Ajax.locale.month,
|
40 |
+
week: EO_Ajax.locale.week,
|
41 |
+
day: EO_Ajax.locale.day,
|
42 |
+
cat: EO_Ajax.locale.cat,
|
43 |
+
venue: EO_Ajax.locale.venue
|
44 |
+
},
|
45 |
+
monthNames: EO_Ajax.locale.monthNames,
|
46 |
+
monthNamesShort: EO_Ajax.locale.monthAbbrev,
|
47 |
+
dayNames: EO_Ajax.locale.dayNames,
|
48 |
+
dayNamesShort: EO_Ajax.locale.dayAbbrev,
|
49 |
+
header: {
|
50 |
+
left: 'title',
|
51 |
+
center: 'category venue',
|
52 |
+
right: 'prev goto today next'
|
53 |
+
},
|
54 |
+
buttonIcons: false,
|
55 |
+
buttonui: true,
|
56 |
+
events: function (start, end, callback) {
|
57 |
+
jQuery.ajax({
|
58 |
+
url: EO_Ajax.ajaxurl + "?action=event-admin-cal",
|
59 |
+
dataType: 'JSON',
|
60 |
+
data: {
|
61 |
+
start: jQuery.fullCalendar.formatDate(start, 'yyyy-MM-dd'),
|
62 |
+
end: jQuery.fullCalendar.formatDate(end, 'yyyy-MM-dd')
|
63 |
+
},
|
64 |
+
success: function (data) {
|
65 |
+
callback(data)
|
66 |
+
}
|
67 |
+
})
|
68 |
+
},
|
69 |
+
categories: EO_Ajax.categories,
|
70 |
+
venues: EO_Ajax.venues,
|
71 |
+
selectable: true,
|
72 |
+
selectHelper: true,
|
73 |
+
eventRender: function (event, element) {
|
74 |
+
var cat = jQuery(".filter-category .eo-cal-filter").val();
|
75 |
+
var venue = jQuery(".filter-venue .eo-cal-filter").val();
|
76 |
+
if (typeof cat !== "undefined" && cat != '' && (jQuery.inArray(cat, event.category) < 0)) {
|
77 |
+
return '<div></div>'
|
78 |
+
}
|
79 |
+
if (typeof venue !== "undefined" && venue != '' && venue != event.venue) {
|
80 |
+
return '<div></div>'
|
81 |
+
}
|
82 |
+
},
|
83 |
+
viewDisplay: function (element) {
|
84 |
+
var date = jQuery.fullCalendar.formatDate( element.start,'yyyy-MM-dd');
|
85 |
+
var view = element.name;
|
86 |
+
|
87 |
+
//Expire cooke after 10 minutes
|
88 |
+
var expires_date = new Date();
|
89 |
+
expires_date = new Date(expires_date.getTime() + (10 * 60 * 1000));
|
90 |
+
$.cookie('eo_admin_cal_last_viewed_date', date,{ expires: expires_date });
|
91 |
+
$.cookie('eo_admin_cal_last_view', view,{ expires: expires_date });
|
92 |
+
},
|
93 |
+
weekMode: 'variable',
|
94 |
+
aspectRatio: 1.50,
|
95 |
+
loading: function (bool) {
|
96 |
+
if (bool) jQuery('#loading').show();
|
97 |
+
else jQuery('#loading').hide()
|
98 |
+
},
|
99 |
+
timeFormat:format,
|
100 |
+
axisFormat: format,
|
101 |
+
eventClick: function (event, jsevent, view) {
|
102 |
+
jsevent.preventDefault();
|
103 |
+
jQuery("#eo-dialog-tabs ul li").each(function(){
|
104 |
+
var id = $(this).attr('id').substring(14);
|
105 |
+
jQuery("#eo-dialog-tabs #"+$(this).attr('id')+'-content').html(event[id]);
|
106 |
+
});
|
107 |
+
|
108 |
+
$('#events-meta').dialog('open');
|
109 |
+
},
|
110 |
+
select: function (startDate, endDate, allDay, jsEvent, view) {
|
111 |
+
if (EO_Ajax.perm_edit) {
|
112 |
+
jsEvent.preventDefault();
|
113 |
+
var fc_format = 'yyyy-MM-dd';
|
114 |
+
var options = jQuery(this)[0].calendar.options;
|
115 |
+
var start_date = jQuery.fullCalendar.formatDate(startDate, fc_format);
|
116 |
+
var start_time = jQuery.fullCalendar.formatDate(startDate, 'HH:mm');
|
117 |
+
var end_date = jQuery.fullCalendar.formatDate(endDate, fc_format);
|
118 |
+
var end_time = jQuery.fullCalendar.formatDate(endDate, 'HH:mm');
|
119 |
+
if (allDay) {
|
120 |
+
format = 'ddd, dS MMMM';
|
121 |
+
allDay = 1
|
122 |
+
} else {
|
123 |
+
format = 'ddd, dS MMMM h(:mm)tt';
|
124 |
+
allDay = 0
|
125 |
+
}
|
126 |
+
if (start_date == end_date) {
|
127 |
+
var the_date = jQuery.fullCalendar.formatDate(startDate, format, options);
|
128 |
+
if (!allDay) {
|
129 |
+
the_date = the_date + ' — ' + jQuery.fullCalendar.formatDate(endDate, 'h(:mm)tt', options)
|
130 |
+
}
|
131 |
+
} else {
|
132 |
+
var the_date = jQuery.fullCalendar.formatDate(startDate, format, options) + ' — ' + jQuery.fullCalendar.formatDate(endDate, format, options)
|
133 |
+
}
|
134 |
+
$("#eo_event_create_cal input[name='eo_event[event_title]']").val('');
|
135 |
+
$("#eo_event_create_cal input.ui-autocomplete-input").val('');
|
136 |
+
$("#eo_event_create_cal textarea[name='eo_event[event_content]']").val('');
|
137 |
+
$("#eo_event_create_cal input[name='eo_event[StartDate]']").val(start_date);
|
138 |
+
$("#eo_event_create_cal input[name='eo_event[StartTime]']").val(start_time);
|
139 |
+
$("#eo_event_create_cal input[name='eo_event[EndDate]']").val(end_date);
|
140 |
+
$("#eo_event_create_cal input[name='eo_event[FinishTime]']").val(end_time);
|
141 |
+
$("#eo_event_create_cal input[name='eo_event[allday]']").val(allDay);
|
142 |
+
$("#eo_event_create_cal td#date").html(the_date);
|
143 |
+
$('#eo_event_create_cal').dialog('open');
|
144 |
+
$("form.eo_cal input[type='submit']").removeAttr('disabled');
|
145 |
+
$("form.eo_cal input#reset").click(function (event) {
|
146 |
+
$('#eo_event_create_cal').dialog('close');
|
147 |
+
})
|
148 |
+
}
|
149 |
+
}
|
150 |
+
});
|
151 |
+
|
152 |
+
/* Update time format screen option */
|
153 |
+
$('#eofc_time_format').change(function () {
|
154 |
+
format = ($('#eofc_time_format').is(":checked") ? 'HH:mm' : 'h:mmtt');
|
155 |
+
calendar.fullCalendar('option', 'timeFormat', format);
|
156 |
+
$.post(ajaxurl, {
|
157 |
+
action: 'eofc-format-time',
|
158 |
+
is24: $('#eofc_time_format').is(":checked")
|
159 |
+
});
|
160 |
+
});
|
161 |
+
|
162 |
+
|
163 |
+
/* View tabs */
|
164 |
+
$('.view-button').click(function (event) {
|
165 |
+
event.preventDefault();
|
166 |
+
$('.view-button').removeClass('active');
|
167 |
+
calendar.fullCalendar('changeView', $(this).attr('id'));
|
168 |
+
$(this).addClass('active')
|
169 |
+
});
|
170 |
+
|
171 |
+
/* GoTo 'mini calendar' */
|
172 |
+
function eventorganiser_mini_calendar(){
|
173 |
+
var element = $("<span class='fc-header-goto'><input type='hidden' id='miniCalendar'/></span>");
|
174 |
+
return element;
|
175 |
+
}
|
176 |
+
$('#miniCalendar').datepicker({
|
177 |
+
dateFormat: 'DD, d MM, yy',
|
178 |
+
firstDay: parseInt(EO_Ajax.startday),
|
179 |
+
changeMonth: true,
|
180 |
+
monthNamesShort: EO_Ajax.locale.monthAbbrev,
|
181 |
+
dayNamesMin: EO_Ajax.locale.dayAbbrev,
|
182 |
+
changeYear: true,
|
183 |
+
showOn: 'button',
|
184 |
+
buttonText: EO_Ajax.locale.gotodate,
|
185 |
+
onSelect: function (dateText, dp) {
|
186 |
+
calendar.fullCalendar('gotoDate', new Date(Date.parse(dateText)))
|
187 |
+
}
|
188 |
+
});
|
189 |
+
$('button.ui-datepicker-trigger').button();
|
190 |
+
|
191 |
+
/* Venue & Category Filters */
|
192 |
+
function eventorganiser_cat_dropdown(options){
|
193 |
+
|
194 |
+
var terms = options.categories;
|
195 |
+
|
196 |
+
var html="<select class='eo-cal-filter' id='eo-event-cat'>";
|
197 |
+
html+="<option value=''>"+options.buttonText.cat+"</option>";
|
198 |
+
for (var i=0;i<terms.length; i++) {
|
199 |
+
html+= "<option class='cat-slug-"+terms[i].slug+" cat' value='"+terms[i].slug+"'>"+terms[i].name+"</option>";
|
200 |
+
}
|
201 |
+
html+="</select>";
|
202 |
+
|
203 |
+
return $("<span class='fc-header-dropdown filter-category'></span>").append(html);
|
204 |
+
}
|
205 |
+
|
206 |
+
function eventorganiser_venue_dropdown(options){
|
207 |
+
|
208 |
+
var venues = options.venues;
|
209 |
+
|
210 |
+
var html="<select class='eo-cal-filter' id='eo-event-venue'>";
|
211 |
+
html+="<option value=''>"+options.buttonText.venue+"</option>";
|
212 |
+
|
213 |
+
for (var i=0; i<venues.length; i++){
|
214 |
+
html+= "<option value='"+venues[i].term_id+"'>"+venues[i].name+"</option>";
|
215 |
+
}
|
216 |
+
html+="</select>";
|
217 |
+
|
218 |
+
return $("<span class='fc-header-dropdown filter-venue'></span>").append(html);
|
219 |
+
}
|
220 |
+
$(".eo-cal-filter").change(function () {
|
221 |
+
calendar.fullCalendar('rerenderEvents')
|
222 |
+
});
|
223 |
+
$('.filter-venue .eo-cal-filter').selectmenu({
|
224 |
+
wrapperElement: "<span class='fc-header-filter'></span>"
|
225 |
+
});
|
226 |
+
$('.filter-category .eo-cal-filter').selectmenu({
|
227 |
+
wrapperElement: "<span class='fc-header-filter'></span>",
|
228 |
+
icons: [{find: '.cat'} ]
|
229 |
+
});
|
230 |
+
var w = $('#eo-event-venue-button').width() + 30;
|
231 |
+
$('#eo-event-venue-button').width(w + 'px');
|
232 |
+
$('#eo-event-venue-menu').width(w + 'px');
|
233 |
+
var w2 = $('#eo-event-cat-button').width() + 30;
|
234 |
+
$('#eo-event-cat-button').width(w2 + 'px');
|
235 |
+
$('#eo-event-cat-menu').width(w2 + 'px');
|
236 |
+
});
|
237 |
+
})(jQuery);
|
238 |
+
/*
|
239 |
+
* jQuery UI Selectmenu version 1.3.0
|
240 |
+
*
|
241 |
+
* Copyright (c) 2009-2010 filament group, http://filamentgroup.com
|
242 |
+
* Copyright (c) 2010-2012 Felix Nagel, http://www.felixnagel.com
|
243 |
+
* Licensed under the MIT (MIT-LICENSE.txt)
|
244 |
+
*
|
245 |
+
* https://github.com/fnagel/jquery-ui/wiki/Selectmenu
|
246 |
+
*/
|
247 |
+
|
248 |
+
(function($) {
|
249 |
+
/**
|
250 |
+
*@constructor
|
251 |
+
*/
|
252 |
+
$.widget("ui.selectmenu", {
|
253 |
+
options: {
|
254 |
+
appendTo: "body",
|
255 |
+
typeAhead: 1000,
|
256 |
+
style: 'dropdown',
|
257 |
+
positionOptions: {
|
258 |
+
my: "left top",
|
259 |
+
at: "left bottom",
|
260 |
+
offset: null
|
261 |
+
},
|
262 |
+
width: null,
|
263 |
+
menuWidth: null,
|
264 |
+
handleWidth: 26,
|
265 |
+
maxHeight: null,
|
266 |
+
icons: null,
|
267 |
+
format: null,
|
268 |
+
escapeHtml: false,
|
269 |
+
bgImage: function() {}
|
270 |
+
},
|
271 |
+
|
272 |
+
/**
|
273 |
+
*@constructor
|
274 |
+
*/
|
275 |
+
_create: function() {
|
276 |
+
var self = this, o = this.options;
|
277 |
+
|
278 |
+
// set a default id value, generate a new random one if not set by developer
|
279 |
+
var selectmenuId = (this.element.attr( 'id' ) || 'ui-selectmenu-' + Math.random().toString( 16 ).slice( 2, 10 )).replace(/(:|\.)/g,'')
|
280 |
+
|
281 |
+
// quick array of button and menu id's
|
282 |
+
this.ids = [ selectmenuId, selectmenuId + '-button', selectmenuId + '-menu' ];
|
283 |
+
|
284 |
+
// define safe mouseup for future toggling
|
285 |
+
this._safemouseup = true;
|
286 |
+
this.isOpen = false;
|
287 |
+
|
288 |
+
// create menu button wrapper
|
289 |
+
this.newelement = $( '<a />', {
|
290 |
+
'class': this.widgetBaseClass + ' ui-widget ui-state-default ui-corner-all',
|
291 |
+
'id' : this.ids[ 1 ],
|
292 |
+
'role': 'button',
|
293 |
+
'href': '#nogo',
|
294 |
+
'tabindex': this.element.attr( 'disabled' ) ? 1 : 0,
|
295 |
+
'aria-haspopup': true,
|
296 |
+
'aria-owns': this.ids[ 2 ]
|
297 |
+
});
|
298 |
+
this.newelementWrap = $( "<span />" )
|
299 |
+
.append( this.newelement )
|
300 |
+
.insertAfter( this.element );
|
301 |
+
|
302 |
+
// transfer tabindex
|
303 |
+
var tabindex = this.element.attr( 'tabindex' );
|
304 |
+
if ( tabindex ) {
|
305 |
+
this.newelement.attr( 'tabindex', tabindex );
|
306 |
+
}
|
307 |
+
|
308 |
+
// save reference to select in data for ease in calling methods
|
309 |
+
this.newelement.data( 'selectelement', this.element );
|
310 |
+
|
311 |
+
// menu icon
|
312 |
+
this.selectmenuIcon = $( '<span class="' + this.widgetBaseClass + '-icon ui-icon"></span>' )
|
313 |
+
.prependTo( this.newelement );
|
314 |
+
|
315 |
+
// append status span to button
|
316 |
+
this.newelement.prepend( '<span class="' + self.widgetBaseClass + '-status" />' );
|
317 |
+
|
318 |
+
// make associated form label trigger focus
|
319 |
+
this.element.bind({
|
320 |
+
'click.selectmenu': function( event ) {
|
321 |
+
self.newelement.focus();
|
322 |
+
event.preventDefault();
|
323 |
+
}
|
324 |
+
});
|
325 |
+
|
326 |
+
// click toggle for menu visibility
|
327 |
+
this.newelement
|
328 |
+
.bind('mousedown.selectmenu', function(event) {
|
329 |
+
self._toggle(event, true);
|
330 |
+
// make sure a click won't open/close instantly
|
331 |
+
if (o.style == "popup") {
|
332 |
+
self._safemouseup = false;
|
333 |
+
setTimeout(function() { self._safemouseup = true; }, 300);
|
334 |
+
}
|
335 |
+
return false;
|
336 |
+
})
|
337 |
+
.bind('click.selectmenu', function() {
|
338 |
+
return false;
|
339 |
+
})
|
340 |
+
.bind("keydown.selectmenu", function(event) {
|
341 |
+
var ret = false;
|
342 |
+
switch (event.keyCode) {
|
343 |
+
case $.ui.keyCode.ENTER:
|
344 |
+
ret = true;
|
345 |
+
break;
|
346 |
+
case $.ui.keyCode.SPACE:
|
347 |
+
self._toggle(event);
|
348 |
+
break;
|
349 |
+
case $.ui.keyCode.UP:
|
350 |
+
if (event.altKey) {
|
351 |
+
self.open(event);
|
352 |
+
} else {
|
353 |
+
self._moveSelection(-1);
|
354 |
+
}
|
355 |
+
break;
|
356 |
+
case $.ui.keyCode.DOWN:
|
357 |
+
if (event.altKey) {
|
358 |
+
self.open(event);
|
359 |
+
} else {
|
360 |
+
self._moveSelection(1);
|
361 |
+
}
|
362 |
+
break;
|
363 |
+
case $.ui.keyCode.LEFT:
|
364 |
+
self._moveSelection(-1);
|
365 |
+
break;
|
366 |
+
case $.ui.keyCode.RIGHT:
|
367 |
+
self._moveSelection(1);
|
368 |
+
break;
|
369 |
+
case $.ui.keyCode.TAB:
|
370 |
+
ret = true;
|
371 |
+
break;
|
372 |
+
case $.ui.keyCode.PAGE_UP:
|
373 |
+
case $.ui.keyCode.HOME:
|
374 |
+
self.index(0);
|
375 |
+
break;
|
376 |
+
case $.ui.keyCode.PAGE_DOWN:
|
377 |
+
case $.ui.keyCode.END:
|
378 |
+
self.index(self._optionLis.length);
|
379 |
+
break;
|
380 |
+
default:
|
381 |
+
ret = true;
|
382 |
+
}
|
383 |
+
return ret;
|
384 |
+
})
|
385 |
+
.bind('keypress.selectmenu', function(event) {
|
386 |
+
if (event.which > 0) {
|
387 |
+
self._typeAhead(event.which, 'mouseup');
|
388 |
+
}
|
389 |
+
return true;
|
390 |
+
})
|
391 |
+
.bind('mouseover.selectmenu', function() {
|
392 |
+
if (!o.disabled) $(this).addClass('ui-state-hover');
|
393 |
+
})
|
394 |
+
.bind('mouseout.selectmenu', function() {
|
395 |
+
if (!o.disabled) $(this).removeClass('ui-state-hover');
|
396 |
+
})
|
397 |
+
.bind('focus.selectmenu', function() {
|
398 |
+
if (!o.disabled) $(this).addClass('ui-state-focus');
|
399 |
+
})
|
400 |
+
.bind('blur.selectmenu', function() {
|
401 |
+
if (!o.disabled) $(this).removeClass('ui-state-focus');
|
402 |
+
});
|
403 |
+
|
404 |
+
// document click closes menu
|
405 |
+
$(document).bind("mousedown.selectmenu-" + this.ids[0], function(event) {
|
406 |
+
if ( self.isOpen ) {
|
407 |
+
self.close( event );
|
408 |
+
}
|
409 |
+
});
|
410 |
+
|
411 |
+
// change event on original selectmenu
|
412 |
+
this.element
|
413 |
+
.bind("click.selectmenu", function() {
|
414 |
+
self._refreshValue();
|
415 |
+
})
|
416 |
+
// FIXME: newelement can be null under unclear circumstances in IE8
|
417 |
+
// TODO not sure if this is still a problem (fnagel 20.03.11)
|
418 |
+
.bind("focus.selectmenu", function() {
|
419 |
+
if (self.newelement) {
|
420 |
+
self.newelement[0].focus();
|
421 |
+
}
|
422 |
+
});
|
423 |
+
|
424 |
+
// set width when not set via options
|
425 |
+
if (!o.width) {
|
426 |
+
o.width = this.element.outerWidth();
|
427 |
+
}
|
428 |
+
// set menu button width
|
429 |
+
this.newelement.width(o.width);
|
430 |
+
|
431 |
+
// hide original selectmenu element
|
432 |
+
this.element.hide();
|
433 |
+
|
434 |
+
// create menu portion, append to body
|
435 |
+
this.list = $( '<ul />', {
|
436 |
+
'class': 'ui-widget ui-widget-content',
|
437 |
+
'aria-hidden': true,
|
438 |
+
'role': 'listbox',
|
439 |
+
'aria-labelledby': this.ids[1],
|
440 |
+
'id': this.ids[2]
|
441 |
+
});
|
442 |
+
this.listWrap = $( "<div />", {
|
443 |
+
'class': self.widgetBaseClass + '-menu'
|
444 |
+
}).append( this.list ).appendTo( o.appendTo );
|
445 |
+
|
446 |
+
// transfer menu click to menu button
|
447 |
+
this.list
|
448 |
+
.bind("keydown.selectmenu", function(event) {
|
449 |
+
var ret = false;
|
450 |
+
switch (event.keyCode) {
|
451 |
+
case $.ui.keyCode.UP:
|
452 |
+
if (event.altKey) {
|
453 |
+
self.close(event, true);
|
454 |
+
} else {
|
455 |
+
self._moveFocus(-1);
|
456 |
+
}
|
457 |
+
break;
|
458 |
+
case $.ui.keyCode.DOWN:
|
459 |
+
if (event.altKey) {
|
460 |
+
self.close(event, true);
|
461 |
+
} else {
|
462 |
+
self._moveFocus(1);
|
463 |
+
}
|
464 |
+
break;
|
465 |
+
case $.ui.keyCode.LEFT:
|
466 |
+
self._moveFocus(-1);
|
467 |
+
break;
|
468 |
+
case $.ui.keyCode.RIGHT:
|
469 |
+
self._moveFocus(1);
|
470 |
+
break;
|
471 |
+
case $.ui.keyCode.HOME:
|
472 |
+
self._moveFocus(':first');
|
473 |
+
break;
|
474 |
+
case $.ui.keyCode.PAGE_UP:
|
475 |
+
self._scrollPage('up');
|
476 |
+
break;
|
477 |
+
case $.ui.keyCode.PAGE_DOWN:
|
478 |
+
self._scrollPage('down');
|
479 |
+
break;
|
480 |
+
case $.ui.keyCode.END:
|
481 |
+
self._moveFocus(':last');
|
482 |
+
break;
|
483 |
+
case $.ui.keyCode.ENTER:
|
484 |
+
case $.ui.keyCode.SPACE:
|
485 |
+
self.close(event, true);
|
486 |
+
$(event.target).parents('li:eq(0)').trigger('mouseup');
|
487 |
+
break;
|
488 |
+
case $.ui.keyCode.TAB:
|
489 |
+
ret = true;
|
490 |
+
self.close(event, true);
|
491 |
+
$(event.target).parents('li:eq(0)').trigger('mouseup');
|
492 |
+
break;
|
493 |
+
case $.ui.keyCode.ESCAPE:
|
494 |
+
self.close(event, true);
|
495 |
+
break;
|
496 |
+
default:
|
497 |
+
ret = true;
|
498 |
+
}
|
499 |
+
return ret;
|
500 |
+
})
|
501 |
+
.bind('keypress.selectmenu', function(event) {
|
502 |
+
if (event.which > 0) {
|
503 |
+
self._typeAhead(event.which, 'focus');
|
504 |
+
}
|
505 |
+
return true;
|
506 |
+
})
|
507 |
+
// this allows for using the scrollbar in an overflowed list
|
508 |
+
.bind( 'mousedown.selectmenu mouseup.selectmenu', function() { return false; });
|
509 |
+
|
510 |
+
// needed when window is resized
|
511 |
+
$(window).bind( "resize.selectmenu-" + this.ids[0], $.proxy( self.close, this ) );
|
512 |
+
},
|
513 |
+
|
514 |
+
/**
|
515 |
+
*@constructor
|
516 |
+
*/
|
517 |
+
_init: function() {
|
518 |
+
var self = this, o = this.options;
|
519 |
+
|
520 |
+
// serialize selectmenu element options
|
521 |
+
var selectOptionData = [];
|
522 |
+
this.element.find('option').each(function() {
|
523 |
+
var opt = $(this);
|
524 |
+
selectOptionData.push({
|
525 |
+
value: opt.attr('value'),
|
526 |
+
text: self._formatText(opt.text(), opt),
|
527 |
+
selected: opt.attr('selected'),
|
528 |
+
disabled: opt.attr('disabled'),
|
529 |
+
classes: opt.attr('class'),
|
530 |
+
typeahead: opt.attr('typeahead'),
|
531 |
+
parentOptGroup: opt.parent('optgroup'),
|
532 |
+
bgImage: o.bgImage.call(opt)
|
533 |
+
});
|
534 |
+
});
|
535 |
+
|
536 |
+
// active state class is only used in popup style
|
537 |
+
var activeClass = (self.options.style == "popup") ? " ui-state-active" : "";
|
538 |
+
|
539 |
+
// empty list so we can refresh the selectmenu via selectmenu()
|
540 |
+
this.list.html("");
|
541 |
+
|
542 |
+
// write li's
|
543 |
+
if (selectOptionData.length) {
|
544 |
+
for (var i = 0; i < selectOptionData.length; i++) {
|
545 |
+
var thisLiAttr = { role : 'presentation' };
|
546 |
+
if ( selectOptionData[ i ].disabled ) {
|
547 |
+
thisLiAttr[ 'class' ] = this.namespace + '-state-disabled';
|
548 |
+
}
|
549 |
+
var thisAAttr = {
|
550 |
+
html: selectOptionData[i].text || ' ',
|
551 |
+
href : '#nogo',
|
552 |
+
tabindex : -1,
|
553 |
+
role : 'option',
|
554 |
+
'aria-selected' : false
|
555 |
+
};
|
556 |
+
if ( selectOptionData[ i ].disabled ) {
|
557 |
+
thisAAttr[ 'aria-disabled' ] = selectOptionData[ i ].disabled;
|
558 |
+
}
|
559 |
+
if ( selectOptionData[ i ].typeahead ) {
|
560 |
+
thisAAttr[ 'typeahead' ] = selectOptionData[ i ].typeahead;
|
561 |
+
}
|
562 |
+
var thisA = $('<a/>', thisAAttr)
|
563 |
+
.bind('focus.selectmenu', function() {
|
564 |
+
$(this).parent().mouseover();
|
565 |
+
})
|
566 |
+
.bind('blur.selectmenu', function() {
|
567 |
+
$(this).parent().mouseout();
|
568 |
+
});
|
569 |
+
var thisLi = $('<li/>', thisLiAttr)
|
570 |
+
.append(thisA)
|
571 |
+
.data('index', i)
|
572 |
+
.addClass(selectOptionData[i].classes)
|
573 |
+
.data('optionClasses', selectOptionData[i].classes || '')
|
574 |
+
.bind("mouseup.selectmenu", function(event) {
|
575 |
+
if (self._safemouseup && !self._disabled(event.currentTarget) && !self._disabled($( event.currentTarget ).parents( "ul>li." + self.widgetBaseClass + "-group " )) ) {
|
576 |
+
self.index($(this).data('index'));
|
577 |
+
self.select(event);
|
578 |
+
self.close(event, true);
|
579 |
+
}
|
580 |
+
return false;
|
581 |
+
})
|
582 |
+
.bind("click.selectmenu", function() {
|
583 |
+
return false;
|
584 |
+
})
|
585 |
+
.bind('mouseover.selectmenu', function() {
|
586 |
+
// no hover if diabled
|
587 |
+
if (!$(this).hasClass(self.namespace + '-state-disabled') && !$(this).parent("ul").parent("li").hasClass(self.namespace + '-state-disabled')) {
|
588 |
+
self._selectedOptionLi().addClass(activeClass);
|
589 |
+
self._focusedOptionLi().removeClass(self.widgetBaseClass + '-item-focus ui-state-hover');
|
590 |
+
$(this).removeClass('ui-state-active').addClass(self.widgetBaseClass + '-item-focus ui-state-hover');
|
591 |
+
}
|
592 |
+
})
|
593 |
+
.bind('mouseout.selectmenu', function() {
|
594 |
+
if ($(this).is(self._selectedOptionLi())) {
|
595 |
+
$(this).addClass(activeClass);
|
596 |
+
}
|
597 |
+
$(this).removeClass(self.widgetBaseClass + '-item-focus ui-state-hover');
|
598 |
+
});
|
599 |
+
|
600 |
+
// optgroup or not...
|
601 |
+
if ( selectOptionData[i].parentOptGroup.length ) {
|
602 |
+
var optGroupName = self.widgetBaseClass + '-group-' + this.element.find( 'optgroup' ).index( selectOptionData[i].parentOptGroup );
|
603 |
+
if (this.list.find( 'li.' + optGroupName ).length ) {
|
604 |
+
this.list.find( 'li.' + optGroupName + ':last ul' ).append( thisLi );
|
605 |
+
} else {
|
606 |
+
$(' <li role="presentation" class="' + self.widgetBaseClass + '-group ' + optGroupName + (selectOptionData[i].parentOptGroup.attr("disabled") ? ' ' + this.namespace + '-state-disabled" aria-disabled="true"' : '"' ) + '><span class="' + self.widgetBaseClass + '-group-label">' + selectOptionData[i].parentOptGroup.attr('label') + '</span><ul></ul></li> ')
|
607 |
+
.appendTo( this.list )
|
608 |
+
.find( 'ul' )
|
609 |
+
.append( thisLi );
|
610 |
+
}
|
611 |
+
} else {
|
612 |
+
thisLi.appendTo(this.list);
|
613 |
+
}
|
614 |
+
|
615 |
+
// append icon if option is specified
|
616 |
+
if (o.icons) {
|
617 |
+
for (var j in o.icons) {
|
618 |
+
if (thisLi.is(o.icons[j].find)) {
|
619 |
+
thisLi
|
620 |
+
.data('optionClasses', selectOptionData[i].classes + ' ' + self.widgetBaseClass + '-hasIcon')
|
621 |
+
.addClass(self.widgetBaseClass + '-hasIcon');
|
622 |
+
var iconClass = o.icons[j].icon || "";
|
623 |
+
thisLi
|
624 |
+
.find('a:eq(0)')
|
625 |
+
.prepend('<span class="' + self.widgetBaseClass + '-item-icon ui-icon ' + iconClass + '"></span>');
|
626 |
+
if (selectOptionData[i].bgImage) {
|
627 |
+
thisLi.find('span').css('background-image', selectOptionData[i].bgImage);
|
628 |
+
}
|
629 |
+
}
|
630 |
+
}
|
631 |
+
}
|
632 |
+
}
|
633 |
+
} else {
|
634 |
+
$('<li role="presentation"><a href="#nogo" tabindex="-1" role="option"></a></li>').appendTo(this.list);
|
635 |
+
}
|
636 |
+
// we need to set and unset the CSS classes for dropdown and popup style
|
637 |
+
var isDropDown = ( o.style == 'dropdown' );
|
638 |
+
this.newelement
|
639 |
+
.toggleClass( self.widgetBaseClass + '-dropdown', isDropDown )
|
640 |
+
.toggleClass( self.widgetBaseClass + '-popup', !isDropDown );
|
641 |
+
this.list
|
642 |
+
.toggleClass( self.widgetBaseClass + '-menu-dropdown ui-corner-bottom', isDropDown )
|
643 |
+
.toggleClass( self.widgetBaseClass + '-menu-popup ui-corner-all', !isDropDown )
|
644 |
+
// add corners to top and bottom menu items
|
645 |
+
.find( 'li:first' )
|
646 |
+
.toggleClass( 'ui-corner-top', !isDropDown )
|
647 |
+
.end().find( 'li:last' )
|
648 |
+
.addClass( 'ui-corner-bottom' );
|
649 |
+
this.selectmenuIcon
|
650 |
+
.toggleClass( 'ui-icon-triangle-1-s', isDropDown )
|
651 |
+
.toggleClass( 'ui-icon-triangle-2-n-s', !isDropDown );
|
652 |
+
|
653 |
+
// set menu width to either menuWidth option value, width option value, or select width
|
654 |
+
if ( o.style == 'dropdown' ) {
|
655 |
+
this.list.width( o.menuWidth ? o.menuWidth : o.width );
|
656 |
+
} else {
|
657 |
+
this.list.width( o.menuWidth ? o.menuWidth : o.width - o.handleWidth );
|
658 |
+
}
|
659 |
+
|
660 |
+
// reset height to auto
|
661 |
+
this.list.css( 'height', 'auto' );
|
662 |
+
var listH = this.listWrap.height();
|
663 |
+
var winH = $( window ).height();
|
664 |
+
// calculate default max height
|
665 |
+
var maxH = o.maxHeight ? Math.min( o.maxHeight, winH ) : winH / 3;
|
666 |
+
if ( listH > maxH ) this.list.height( maxH );
|
667 |
+
|
668 |
+
// save reference to actionable li's (not group label li's)
|
669 |
+
this._optionLis = this.list.find( 'li:not(.' + self.widgetBaseClass + '-group)' );
|
670 |
+
|
671 |
+
// transfer disabled state
|
672 |
+
if ( this.element.attr( 'disabled' ) ) {
|
673 |
+
this.disable();
|
674 |
+
} else {
|
675 |
+
this.enable();
|
676 |
+
}
|
677 |
+
|
678 |
+
// update value
|
679 |
+
this._refreshValue();
|
680 |
+
|
681 |
+
// set selected item so movefocus has intial state
|
682 |
+
this._selectedOptionLi().addClass(this.widgetBaseClass + '-item-focus');
|
683 |
+
|
684 |
+
// needed when selectmenu is placed at the very bottom / top of the page
|
685 |
+
clearTimeout(this.refreshTimeout);
|
686 |
+
this.refreshTimeout = window.setTimeout(function () {
|
687 |
+
self._refreshPosition();
|
688 |
+
}, 200);
|
689 |
+
},
|
690 |
+
|
691 |
+
destroy: function() {
|
692 |
+
this.element.removeData( this.widgetName )
|
693 |
+
.removeClass( this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled' )
|
694 |
+
.removeAttr( 'aria-disabled' )
|
695 |
+
.unbind( ".selectmenu" );
|
696 |
+
|
697 |
+
$( window ).unbind( ".selectmenu-" + this.ids[0] );
|
698 |
+
$( document ).unbind( ".selectmenu-" + this.ids[0] );
|
699 |
+
|
700 |
+
this.newelementWrap.remove();
|
701 |
+
this.listWrap.remove();
|
702 |
+
|
703 |
+
// unbind click event and show original select
|
704 |
+
this.element
|
705 |
+
.unbind(".selectmenu")
|
706 |
+
.show();
|
707 |
+
|
708 |
+
// call widget destroy function
|
709 |
+
$.Widget.prototype.destroy.apply(this, arguments);
|
710 |
+
},
|
711 |
+
|
712 |
+
_typeAhead: function( code, eventType ) {
|
713 |
+
var self = this,
|
714 |
+
c = String.fromCharCode(code).toLowerCase(),
|
715 |
+
matchee = null,
|
716 |
+
nextIndex = null;
|
717 |
+
|
718 |
+
// Clear any previous timer if present
|
719 |
+
if ( self._typeAhead_timer ) {
|
720 |
+
window.clearTimeout( self._typeAhead_timer );
|
721 |
+
self._typeAhead_timer = undefined;
|
722 |
+
}
|
723 |
+
|
724 |
+
// Store the character typed
|
725 |
+
self._typeAhead_chars = (self._typeAhead_chars === undefined ? "" : self._typeAhead_chars).concat(c);
|
726 |
+
|
727 |
+
// Detect if we are in cyciling mode or direct selection mode
|
728 |
+
if ( self._typeAhead_chars.length < 2 ||
|
729 |
+
(self._typeAhead_chars.substr(-2, 1) === c && self._typeAhead_cycling) ) {
|
730 |
+
self._typeAhead_cycling = true;
|
731 |
+
|
732 |
+
// Match only the first character and loop
|
733 |
+
matchee = c;
|
734 |
+
}
|
735 |
+
else {
|
736 |
+
// We won't be cycling anymore until the timer expires
|
737 |
+
self._typeAhead_cycling = false;
|
738 |
+
|
739 |
+
// Match all the characters typed
|
740 |
+
matchee = self._typeAhead_chars;
|
741 |
+
}
|
742 |
+
|
743 |
+
// We need to determine the currently active index, but it depends on
|
744 |
+
// the used context: if it's in the element, we want the actual
|
745 |
+
// selected index, if it's in the menu, just the focused one
|
746 |
+
// I copied this code from _moveSelection() and _moveFocus()
|
747 |
+
// respectively --thg2k
|
748 |
+
var selectedIndex = (eventType !== 'focus' ?
|
749 |
+
this._selectedOptionLi().data('index') :
|
750 |
+
this._focusedOptionLi().data('index')) || 0;
|
751 |
+
|
752 |
+
for (var i = 0; i < this._optionLis.length; i++) {
|
753 |
+
var thisText = this._optionLis.eq(i).text().substr(0, matchee.length).toLowerCase();
|
754 |
+
|
755 |
+
if ( thisText === matchee ) {
|
756 |
+
if ( self._typeAhead_cycling ) {
|
757 |
+
if ( nextIndex === null )
|
758 |
+
nextIndex = i;
|
759 |
+
|
760 |
+
if ( i > selectedIndex ) {
|
761 |
+
nextIndex = i;
|
762 |
+
break;
|
763 |
+
}
|
764 |
+
} else {
|
765 |
+
nextIndex = i;
|
766 |
+
}
|
767 |
+
}
|
768 |
+
}
|
769 |
+
|
770 |
+
if ( nextIndex !== null ) {
|
771 |
+
// Why using trigger() instead of a direct method to select the
|
772 |
+
// index? Because we don't what is the exact action to do, it
|
773 |
+
// depends if the user is typing on the element or on the popped
|
774 |
+
// up menu
|
775 |
+
this._optionLis.eq(nextIndex).find("a").trigger( eventType );
|
776 |
+
}
|
777 |
+
|
778 |
+
self._typeAhead_timer = window.setTimeout(function() {
|
779 |
+
self._typeAhead_timer = undefined;
|
780 |
+
self._typeAhead_chars = undefined;
|
781 |
+
self._typeAhead_cycling = undefined;
|
782 |
+
}, self.options.typeAhead);
|
783 |
+
},
|
784 |
+
|
785 |
+
// returns some usefull information, called by callbacks only
|
786 |
+
_uiHash: function() {
|
787 |
+
var index = this.index();
|
788 |
+
return {
|
789 |
+
index: index,
|
790 |
+
option: $("option", this.element).get(index),
|
791 |
+
value: this.element[0].value
|
792 |
+
};
|
793 |
+
},
|
794 |
+
|
795 |
+
open: function(event) {
|
796 |
+
var self = this, o = this.options;
|
797 |
+
if ( self.newelement.attr("aria-disabled") != 'true' ) {
|
798 |
+
self._closeOthers(event);
|
799 |
+
self.newelement.addClass('ui-state-active');
|
800 |
+
|
801 |
+
self.list.attr('aria-hidden', false);
|
802 |
+
self.listWrap.addClass( self.widgetBaseClass + '-open' );
|
803 |
+
|
804 |
+
var selected = this._selectedOptionLi();
|
805 |
+
if ( o.style == "dropdown" ) {
|
806 |
+
self.newelement.removeClass('ui-corner-all').addClass('ui-corner-top');
|
807 |
+
} else {
|
808 |
+
// center overflow and avoid flickering
|
809 |
+
this.list
|
810 |
+
.css("left", -5000)
|
811 |
+
.scrollTop( this.list.scrollTop() + selected.position().top - this.list.outerHeight()/2 + selected.outerHeight()/2 )
|
812 |
+
.css("left","auto");
|
813 |
+
}
|
814 |
+
|
815 |
+
self._refreshPosition();
|
816 |
+
|
817 |
+
var link = selected.find("a");
|
818 |
+
if (link.length) link[0].focus();
|
819 |
+
|
820 |
+
self.isOpen = true;
|
821 |
+
self._trigger("open", event, self._uiHash());
|
822 |
+
}
|
823 |
+
},
|
824 |
+
/**
|
825 |
+
*@constructor
|
826 |
+
*/
|
827 |
+
close: function(event, retainFocus) {
|
828 |
+
if ( this.newelement.is('.ui-state-active') ) {
|
829 |
+
this.newelement
|
830 |
+
.removeClass('ui-state-active');
|
831 |
+
this.listWrap.removeClass(this.widgetBaseClass + '-open');
|
832 |
+
this.list.attr('aria-hidden', true);
|
833 |
+
if ( this.options.style == "dropdown" ) {
|
834 |
+
this.newelement.removeClass('ui-corner-top').addClass('ui-corner-all');
|
835 |
+
}
|
836 |
+
if ( retainFocus ) {
|
837 |
+
this.newelement.focus();
|
838 |
+
}
|
839 |
+
this.isOpen = false;
|
840 |
+
this._trigger("close", event, this._uiHash());
|
841 |
+
}
|
842 |
+
},
|
843 |
+
|
844 |
+
change: function(event) {
|
845 |
+
this.element.trigger("change");
|
846 |
+
this._trigger("change", event, this._uiHash());
|
847 |
+
},
|
848 |
+
|
849 |
+
select: function(event) {
|
850 |
+
if (this._disabled(event.currentTarget)) { return false; }
|
851 |
+
this._trigger("select", event, this._uiHash());
|
852 |
+
},
|
853 |
+
|
854 |
+
widget: function() {
|
855 |
+
return this.listWrap.add( this.newelementWrap );
|
856 |
+
},
|
857 |
+
|
858 |
+
_closeOthers: function(event) {
|
859 |
+
$('.' + this.widgetBaseClass + '.ui-state-active').not(this.newelement).each(function() {
|
860 |
+
$(this).data('selectelement').selectmenu('close', event);
|
861 |
+
});
|
862 |
+
$('.' + this.widgetBaseClass + '.ui-state-hover').trigger('mouseout');
|
863 |
+
},
|
864 |
+
|
865 |
+
_toggle: function(event, retainFocus) {
|
866 |
+
if ( this.isOpen ) {
|
867 |
+
this.close(event, retainFocus);
|
868 |
+
} else {
|
869 |
+
this.open(event);
|
870 |
+
}
|
871 |
+
},
|
872 |
+
|
873 |
+
_formatText: function(text, opt) {
|
874 |
+
if (this.options.format) {
|
875 |
+
text = this.options.format(text, opt);
|
876 |
+
} else if (this.options.escapeHtml) {
|
877 |
+
text = $('<div />').text(text).html();
|
878 |
+
}
|
879 |
+
return text;
|
880 |
+
},
|
881 |
+
|
882 |
+
_selectedIndex: function() {
|
883 |
+
return this.element[0].selectedIndex;
|
884 |
+
},
|
885 |
+
|
886 |
+
_selectedOptionLi: function() {
|
887 |
+
return this._optionLis.eq(this._selectedIndex());
|
888 |
+
},
|
889 |
+
|
890 |
+
_focusedOptionLi: function() {
|
891 |
+
return this.list.find('.' + this.widgetBaseClass + '-item-focus');
|
892 |
+
},
|
893 |
+
|
894 |
+
_moveSelection: function(amt, recIndex) {
|
895 |
+
// do nothing if disabled
|
896 |
+
if (!this.options.disabled) {
|
897 |
+
var currIndex = parseInt(this._selectedOptionLi().data('index') || 0, 10);
|
898 |
+
var newIndex = currIndex + amt;
|
899 |
+
// do not loop when using up key
|
900 |
+
|
901 |
+
if (newIndex < 0) {
|
902 |
+
newIndex = 0;
|
903 |
+
}
|
904 |
+
if (newIndex > this._optionLis.size() - 1) {
|
905 |
+
newIndex = this._optionLis.size() - 1;
|
906 |
+
}
|
907 |
+
// Occurs when a full loop has been made
|
908 |
+
if (newIndex === recIndex) { return false; }
|
909 |
+
|
910 |
+
if (this._optionLis.eq(newIndex).hasClass( this.namespace + '-state-disabled' )) {
|
911 |
+
// if option at newIndex is disabled, call _moveFocus, incrementing amt by one
|
912 |
+
(amt > 0) ? ++amt : --amt;
|
913 |
+
this._moveSelection(amt, newIndex);
|
914 |
+
} else {
|
915 |
+
this._optionLis.eq(newIndex).trigger('mouseover').trigger('mouseup');
|
916 |
+
}
|
917 |
+
}
|
918 |
+
},
|
919 |
+
/**
|
920 |
+
*@constructor
|
921 |
+
*/
|
922 |
+
_moveFocus: function(amt, recIndex) {
|
923 |
+
if (!isNaN(amt)) {
|
924 |
+
var currIndex = parseInt(this._focusedOptionLi().data('index') || 0, 10);
|
925 |
+
var newIndex = currIndex + amt;
|
926 |
+
} else {
|
927 |
+
var newIndex = parseInt(this._optionLis.filter(amt).data('index'), 10);
|
928 |
+
}
|
929 |
+
|
930 |
+
if (newIndex < 0) {
|
931 |
+
newIndex = 0;
|
932 |
+
}
|
933 |
+
if (newIndex > this._optionLis.size() - 1) {
|
934 |
+
newIndex = this._optionLis.size() - 1;
|
935 |
+
}
|
936 |
+
|
937 |
+
//Occurs when a full loop has been made
|
938 |
+
if (newIndex === recIndex) { return false; }
|
939 |
+
|
940 |
+
var activeID = this.widgetBaseClass + '-item-' + Math.round(Math.random() * 1000);
|
941 |
+
|
942 |
+
this._focusedOptionLi().find('a:eq(0)').attr('id', '');
|
943 |
+
|
944 |
+
if (this._optionLis.eq(newIndex).hasClass( this.namespace + '-state-disabled' )) {
|
945 |
+
// if option at newIndex is disabled, call _moveFocus, incrementing amt by one
|
946 |
+
(amt > 0) ? ++amt : --amt;
|
947 |
+
this._moveFocus(amt, newIndex);
|
948 |
+
} else {
|
949 |
+
this._optionLis.eq(newIndex).find('a:eq(0)').attr('id',activeID).focus();
|
950 |
+
}
|
951 |
+
|
952 |
+
this.list.attr('aria-activedescendant', activeID);
|
953 |
+
},
|
954 |
+
|
955 |
+
_scrollPage: function(direction) {
|
956 |
+
var numPerPage = Math.floor(this.list.outerHeight() / this._optionLis.first().outerHeight());
|
957 |
+
numPerPage = (direction == 'up' ? -numPerPage : numPerPage);
|
958 |
+
this._moveFocus(numPerPage);
|
959 |
+
},
|
960 |
+
/**
|
961 |
+
*@constructor
|
962 |
+
*/
|
963 |
+
_setOption: function(key, value) {
|
964 |
+
this.options[key] = value;
|
965 |
+
// set
|
966 |
+
if (key == 'disabled') {
|
967 |
+
if (value) this.close();
|
968 |
+
this.element
|
969 |
+
.add(this.newelement)
|
970 |
+
.add(this.list)[value ? 'addClass' : 'removeClass'](
|
971 |
+
this.widgetBaseClass + '-disabled' + ' ' +
|
972 |
+
this.namespace + '-state-disabled')
|
973 |
+
.attr("aria-disabled", value);
|
974 |
+
}
|
975 |
+
},
|
976 |
+
|
977 |
+
disable: function(index, type){
|
978 |
+
// if options is not provided, call the parents disable function
|
979 |
+
if ( typeof( index ) == 'undefined' ) {
|
980 |
+
this._setOption( 'disabled', true );
|
981 |
+
} else {
|
982 |
+
if ( type == "optgroup" ) {
|
983 |
+
this._disableOptgroup(index);
|
984 |
+
} else {
|
985 |
+
this._disableOption(index);
|
986 |
+
}
|
987 |
+
}
|
988 |
+
},
|
989 |
+
|
990 |
+
enable: function(index, type) {
|
991 |
+
// if options is not provided, call the parents enable function
|
992 |
+
if ( typeof( index ) == 'undefined' ) {
|
993 |
+
this._setOption('disabled', false);
|
994 |
+
} else {
|
995 |
+
if ( type == "optgroup" ) {
|
996 |
+
this._enableOptgroup(index);
|
997 |
+
} else {
|
998 |
+
this._enableOption(index);
|
999 |
+
}
|
1000 |
+
}
|
1001 |
+
},
|
1002 |
+
|
1003 |
+
_disabled: function(elem) {
|
1004 |
+
return $(elem).hasClass( this.namespace + '-state-disabled' );
|
1005 |
+
},
|
1006 |
+
|
1007 |
+
_disableOption: function(index) {
|
1008 |
+
var optionElem = this._optionLis.eq(index);
|
1009 |
+
if (optionElem) {
|
1010 |
+
optionElem.addClass(this.namespace + '-state-disabled')
|
1011 |
+
.find("a").attr("aria-disabled", true);
|
1012 |
+
this.element.find("option").eq(index).attr("disabled", "disabled");
|
1013 |
+
}
|
1014 |
+
},
|
1015 |
+
|
1016 |
+
_enableOption: function(index) {
|
1017 |
+
var optionElem = this._optionLis.eq(index);
|
1018 |
+
if (optionElem) {
|
1019 |
+
optionElem.removeClass( this.namespace + '-state-disabled' )
|
1020 |
+
.find("a").attr("aria-disabled", false);
|
1021 |
+
this.element.find("option").eq(index).removeAttr("disabled");
|
1022 |
+
}
|
1023 |
+
},
|
1024 |
+
|
1025 |
+
_disableOptgroup: function(index) {
|
1026 |
+
var optGroupElem = this.list.find( 'li.' + this.widgetBaseClass + '-group-' + index );
|
1027 |
+
if (optGroupElem) {
|
1028 |
+
optGroupElem.addClass(this.namespace + '-state-disabled')
|
1029 |
+
.attr("aria-disabled", true);
|
1030 |
+
this.element.find("optgroup").eq(index).attr("disabled", "disabled");
|
1031 |
+
}
|
1032 |
+
},
|
1033 |
+
|
1034 |
+
_enableOptgroup: function(index) {
|
1035 |
+
var optGroupElem = this.list.find( 'li.' + this.widgetBaseClass + '-group-' + index );
|
1036 |
+
if (optGroupElem) {
|
1037 |
+
optGroupElem.removeClass(this.namespace + '-state-disabled')
|
1038 |
+
.attr("aria-disabled", false);
|
1039 |
+
this.element.find("optgroup").eq(index).removeAttr("disabled");
|
1040 |
+
}
|
1041 |
+
},
|
1042 |
+
/**
|
1043 |
+
*@constructor
|
1044 |
+
*/
|
1045 |
+
index: function(newIndex) {
|
1046 |
+
if (arguments.length) {
|
1047 |
+
if (!this._disabled($(this._optionLis[newIndex])) && newIndex != this._selectedIndex()) {
|
1048 |
+
this.element[0].selectedIndex = newIndex;
|
1049 |
+
this._refreshValue();
|
1050 |
+
this.change();
|
1051 |
+
} else {
|
1052 |
+
return false;
|
1053 |
+
}
|
1054 |
+
} else {
|
1055 |
+
return this._selectedIndex();
|
1056 |
+
}
|
1057 |
+
},
|
1058 |
+
/**
|
1059 |
+
*@constructor
|
1060 |
+
*/
|
1061 |
+
value: function(newValue) {
|
1062 |
+
if (arguments.length && newValue != this.element[0].value) {
|
1063 |
+
this.element[0].value = newValue;
|
1064 |
+
this._refreshValue();
|
1065 |
+
this.change();
|
1066 |
+
} else {
|
1067 |
+
return this.element[0].value;
|
1068 |
+
}
|
1069 |
+
},
|
1070 |
+
|
1071 |
+
_refreshValue: function() {
|
1072 |
+
var activeClass = (this.options.style == "popup") ? " ui-state-active" : "";
|
1073 |
+
var activeID = this.widgetBaseClass + '-item-' + Math.round(Math.random() * 1000);
|
1074 |
+
// deselect previous
|
1075 |
+
this.list
|
1076 |
+
.find('.' + this.widgetBaseClass + '-item-selected')
|
1077 |
+
.removeClass(this.widgetBaseClass + "-item-selected" + activeClass)
|
1078 |
+
.find('a')
|
1079 |
+
.attr('aria-selected', 'false')
|
1080 |
+
.attr('id', '');
|
1081 |
+
// select new
|
1082 |
+
this._selectedOptionLi()
|
1083 |
+
.addClass(this.widgetBaseClass + "-item-selected" + activeClass)
|
1084 |
+
.find('a')
|
1085 |
+
.attr('aria-selected', 'true')
|
1086 |
+
.attr('id', activeID);
|
1087 |
+
|
1088 |
+
// toggle any class brought in from option
|
1089 |
+
var currentOptionClasses = (this.newelement.data('optionClasses') ? this.newelement.data('optionClasses') : "");
|
1090 |
+
var newOptionClasses = (this._selectedOptionLi().data('optionClasses') ? this._selectedOptionLi().data('optionClasses') : "");
|
1091 |
+
this.newelement
|
1092 |
+
.removeClass(currentOptionClasses)
|
1093 |
+
.data('optionClasses', newOptionClasses)
|
1094 |
+
.addClass( newOptionClasses )
|
1095 |
+
.find('.' + this.widgetBaseClass + '-status')
|
1096 |
+
.html(
|
1097 |
+
this._selectedOptionLi()
|
1098 |
+
.find('a:eq(0)')
|
1099 |
+
.html()
|
1100 |
+
);
|
1101 |
+
|
1102 |
+
this.list.attr('aria-activedescendant', activeID);
|
1103 |
+
},
|
1104 |
+
|
1105 |
+
_refreshPosition: function() {
|
1106 |
+
var o = this.options;
|
1107 |
+
|
1108 |
+
// if its a pop-up we need to calculate the position of the selected li
|
1109 |
+
if ( o.style == "popup" && !o.positionOptions.offset ) {
|
1110 |
+
var selected = this._selectedOptionLi();
|
1111 |
+
var _offset = "0 " + ( this.list.offset().top - selected.offset().top - ( this.newelement.outerHeight() + selected.outerHeight() ) / 2);
|
1112 |
+
}
|
1113 |
+
this.listWrap
|
1114 |
+
.removeAttr('style')
|
1115 |
+
.zIndex( this.element.zIndex() + 1 )
|
1116 |
+
.position({
|
1117 |
+
// set options for position plugin
|
1118 |
+
of: o.positionOptions.of || this.newelement,
|
1119 |
+
my: o.positionOptions.my,
|
1120 |
+
at: o.positionOptions.at,
|
1121 |
+
offset: o.positionOptions.offset || _offset,
|
1122 |
+
collision: o.positionOptions.collision || (o.style == "popup" ? 'fit' :'flip')
|
1123 |
+
});
|
1124 |
+
}
|
1125 |
+
});
|
1126 |
+
|
1127 |
+
})(jQuery);
|
1128 |
+
/*!
|
1129 |
+
* jQuery Cookie Plugin v1.3
|
1130 |
+
* https://github.com/carhartl/jquery-cookie
|
1131 |
+
*
|
1132 |
+
* Copyright 2011, Klaus Hartl
|
1133 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
1134 |
+
* http://www.opensource.org/licenses/mit-license.php
|
1135 |
+
* http://www.opensource.org/licenses/GPL-2.0
|
1136 |
+
*/
|
1137 |
+
(function ($, document, undefined) {
|
1138 |
+
|
1139 |
+
var pluses = /\+/g;
|
1140 |
+
|
1141 |
+
function raw(s) {
|
1142 |
+
return s;
|
1143 |
+
}
|
1144 |
+
|
1145 |
+
function decoded(s) {
|
1146 |
+
return decodeURIComponent(s.replace(pluses, ' '));
|
1147 |
+
}
|
1148 |
+
|
1149 |
+
var config = $.cookie = function (key, value, options) {
|
1150 |
+
|
1151 |
+
// write
|
1152 |
+
if (value !== undefined) {
|
1153 |
+
options = $.extend({}, config.defaults, options);
|
1154 |
+
|
1155 |
+
if (value === null) {
|
1156 |
+
options.expires = -1;
|
1157 |
+
}
|
1158 |
+
|
1159 |
+
if (typeof options.expires === 'number') {
|
1160 |
+
var days = options.expires, t = options.expires = new Date();
|
1161 |
+
t.setDate(t.getDate() + days);
|
1162 |
+
}
|
1163 |
+
|
1164 |
+
value = config.json ? JSON.stringify(value) : String(value);
|
1165 |
+
|
1166 |
+
return (document.cookie = [
|
1167 |
+
encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value),
|
1168 |
+
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
|
1169 |
+
options.path ? '; path=' + options.path : '',
|
1170 |
+
options.domain ? '; domain=' + options.domain : '',
|
1171 |
+
options.secure ? '; secure' : ''
|
1172 |
+
].join(''));
|
1173 |
+
}
|
1174 |
+
|
1175 |
+
// read
|
1176 |
+
var decode = config.raw ? raw : decoded;
|
1177 |
+
var cookies = document.cookie.split('; ');
|
1178 |
+
for (var i = 0, l = cookies.length; i < l; i++) {
|
1179 |
+
var parts = cookies[i].split('=');
|
1180 |
+
if (decode(parts.shift()) === key) {
|
1181 |
+
var cookie = decode(parts.join('='));
|
1182 |
+
return config.json ? JSON.parse(cookie) : cookie;
|
1183 |
+
}
|
1184 |
+
}
|
1185 |
+
|
1186 |
+
return null;
|
1187 |
+
};
|
1188 |
+
|
1189 |
+
config.defaults = {};
|
1190 |
+
|
1191 |
+
$.removeCookie = function (key, options) {
|
1192 |
+
if ($.cookie(key) !== null) {
|
1193 |
+
$.cookie(key, null, options);
|
1194 |
+
return true;
|
1195 |
+
}
|
1196 |
+
return false;
|
1197 |
+
};
|
1198 |
+
|
1199 |
+
})(jQuery, document);
|
js/admin-calendar.min.js
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
(function(b){b(document).ready(function(){function a(){return b("<span class='fc-header-goto'><input type='hidden' id='miniCalendar'/></span>")}function c(e){var i=e.categories,f="<select class='eo-cal-filter' id='eo-event-cat'>";f+="<option value=''>"+e.buttonText.cat+"</option>";for(e=0;e<i.length;e++)f+="<option class='cat-slug-"+i[e].slug+" cat' value='"+i[e].slug+"'>"+i[e].name+"</option>";f+="</select>";return b("<span class='fc-header-dropdown filter-category'></span>").append(f)}function d(e){var i=
|
2 |
+
e.venues,f="<select class='eo-cal-filter' id='eo-event-venue'>";f+="<option value=''>"+e.buttonText.venue+"</option>";for(e=0;e<i.length;e++)f+="<option value='"+i[e].term_id+"'>"+i[e].name+"</option>";f+="</select>";return b("<span class='fc-header-dropdown filter-venue'></span>").append(f)}b("#eo-dialog-tabs").tabs();b(".eo-dialog").dialog({autoOpen:false,width:527,modal:true});b("#events-meta").parent().find(".ui-dialog-titlebar-close").appendTo(".ui-tabs-nav").closest(".ui-dialog").children(".ui-dialog-titlebar").remove();
|
3 |
+
var h=b("#eofc_time_format").is(":checked")?"HH:mm":"h:mmtt",g=b.cookie("eo_admin_cal_last_viewed_date")?new Date(b.cookie("eo_admin_cal_last_viewed_date")):new Date,j=jQuery("#eo_admin_calendar").fullCalendar({firstDay:parseInt(EO_Ajax.startday),date:g.getDate(),month:g.getMonth(),year:g.getFullYear(),defaultView:b.cookie("eo_admin_cal_last_view")?b.cookie("eo_admin_cal_last_view"):"month",editable:false,lazyFetching:"true",eventColor:"#21759B",theme:true,customButtons:{category:c,venue:d,"goto":a},
|
4 |
+
buttonText:{today:EO_Ajax.locale.today,month:EO_Ajax.locale.month,week:EO_Ajax.locale.week,day:EO_Ajax.locale.day,cat:EO_Ajax.locale.cat,venue:EO_Ajax.locale.venue},monthNames:EO_Ajax.locale.monthNames,monthNamesShort:EO_Ajax.locale.monthAbbrev,dayNames:EO_Ajax.locale.dayNames,dayNamesShort:EO_Ajax.locale.dayAbbrev,header:{left:"title",center:"category venue",right:"prev goto today next"},buttonIcons:false,buttonui:true,events:function(e,i,f){jQuery.ajax({url:EO_Ajax.ajaxurl+"?action=event-admin-cal",
|
5 |
+
dataType:"JSON",data:{start:jQuery.fullCalendar.formatDate(e,"yyyy-MM-dd"),end:jQuery.fullCalendar.formatDate(i,"yyyy-MM-dd")},success:function(k){f(k)}})},categories:EO_Ajax.categories,venues:EO_Ajax.venues,selectable:true,selectHelper:true,eventRender:function(e){var i=jQuery(".filter-category .eo-cal-filter").val(),f=jQuery(".filter-venue .eo-cal-filter").val();if(typeof i!=="undefined"&&i!=""&&jQuery.inArray(i,e.category)<0)return"<div></div>";if(typeof f!=="undefined"&&f!=""&&f!=e.venue)return"<div></div>"},
|
6 |
+
viewDisplay:function(e){var i=jQuery.fullCalendar.formatDate(e.start,"yyyy-MM-dd");e=e.name;var f=new Date;f=new Date(f.getTime()+6E5);b.cookie("eo_admin_cal_last_viewed_date",i,{expires:f});b.cookie("eo_admin_cal_last_view",e,{expires:f})},weekMode:"variable",aspectRatio:1.5,loading:function(e){e?jQuery("#loading").show():jQuery("#loading").hide()},timeFormat:h,axisFormat:h,eventClick:function(e,i){i.preventDefault();jQuery("#eo-dialog-tabs ul li").each(function(){var f=b(this).attr("id").substring(14);
|
7 |
+
jQuery("#eo-dialog-tabs #"+b(this).attr("id")+"-content").html(e[f])});b("#events-meta").dialog("open")},select:function(e,i,f,k){if(EO_Ajax.perm_edit){k.preventDefault();k=jQuery(this)[0].calendar.options;var l=jQuery.fullCalendar.formatDate(e,"yyyy-MM-dd"),m=jQuery.fullCalendar.formatDate(e,"HH:mm"),n=jQuery.fullCalendar.formatDate(i,"yyyy-MM-dd"),o=jQuery.fullCalendar.formatDate(i,"HH:mm");if(f){h="ddd, dS MMMM";f=1}else{h="ddd, dS MMMM h(:mm)tt";f=0}if(l==n){e=jQuery.fullCalendar.formatDate(e,
|
8 |
+
h,k);f||(e=e+" — "+jQuery.fullCalendar.formatDate(i,"h(:mm)tt",k))}else e=jQuery.fullCalendar.formatDate(e,h,k)+" — "+jQuery.fullCalendar.formatDate(i,h,k);b("#eo_event_create_cal input[name='eo_event[event_title]']").val("");b("#eo_event_create_cal input.ui-autocomplete-input").val("");b("#eo_event_create_cal textarea[name='eo_event[event_content]']").val("");b("#eo_event_create_cal input[name='eo_event[StartDate]']").val(l);b("#eo_event_create_cal input[name='eo_event[StartTime]']").val(m);
|
9 |
+
b("#eo_event_create_cal input[name='eo_event[EndDate]']").val(n);b("#eo_event_create_cal input[name='eo_event[FinishTime]']").val(o);b("#eo_event_create_cal input[name='eo_event[allday]']").val(f);b("#eo_event_create_cal td#date").html(e);b("#eo_event_create_cal").dialog("open");b("form.eo_cal input[type='submit']").removeAttr("disabled");b("form.eo_cal input#reset").click(function(){b("#eo_event_create_cal").dialog("close")})}}});b("#eofc_time_format").change(function(){h=b("#eofc_time_format").is(":checked")?
|
10 |
+
"HH:mm":"h:mmtt";j.fullCalendar("option","timeFormat",h);b.post(ajaxurl,{action:"eofc-format-time",is24:b("#eofc_time_format").is(":checked")})});b(".view-button").click(function(e){e.preventDefault();b(".view-button").removeClass("active");j.fullCalendar("changeView",b(this).attr("id"));b(this).addClass("active")});b("#miniCalendar").datepicker({dateFormat:"DD, d MM, yy",firstDay:parseInt(EO_Ajax.startday),changeMonth:true,monthNamesShort:EO_Ajax.locale.monthAbbrev,dayNamesMin:EO_Ajax.locale.dayAbbrev,
|
11 |
+
changeYear:true,showOn:"button",buttonText:EO_Ajax.locale.gotodate,onSelect:function(e){j.fullCalendar("gotoDate",new Date(Date.parse(e)))}});b("button.ui-datepicker-trigger").button();b(".eo-cal-filter").change(function(){j.fullCalendar("rerenderEvents")});b(".filter-venue .eo-cal-filter").selectmenu({wrapperElement:"<span class='fc-header-filter'></span>"});b(".filter-category .eo-cal-filter").selectmenu({wrapperElement:"<span class='fc-header-filter'></span>",icons:[{find:".cat"}]});g=b("#eo-event-venue-button").width()+
|
12 |
+
30;b("#eo-event-venue-button").width(g+"px");b("#eo-event-venue-menu").width(g+"px");g=b("#eo-event-cat-button").width()+30;b("#eo-event-cat-button").width(g+"px");b("#eo-event-cat-menu").width(g+"px")})})(jQuery);
|
13 |
+
(function(b){b.widget("ui.selectmenu",{options:{appendTo:"body",typeAhead:1E3,style:"dropdown",positionOptions:{my:"left top",at:"left bottom",offset:null},width:null,menuWidth:null,handleWidth:26,maxHeight:null,icons:null,format:null,escapeHtml:false,bgImage:function(){}},_create:function(){var a=this,c=this.options,d=(this.element.attr("id")||"ui-selectmenu-"+Math.random().toString(16).slice(2,10)).replace(/(:|\.)/g,"");this.ids=[d,d+"-button",d+"-menu"];this._safemouseup=true;this.isOpen=false;
|
14 |
+
this.newelement=b("<a />",{"class":this.widgetBaseClass+" ui-widget ui-state-default ui-corner-all",id:this.ids[1],role:"button",href:"#nogo",tabindex:this.element.attr("disabled")?1:0,"aria-haspopup":true,"aria-owns":this.ids[2]});this.newelementWrap=b("<span />").append(this.newelement).insertAfter(this.element);(d=this.element.attr("tabindex"))&&this.newelement.attr("tabindex",d);this.newelement.data("selectelement",this.element);this.selectmenuIcon=b('<span class="'+this.widgetBaseClass+'-icon ui-icon"></span>').prependTo(this.newelement);
|
15 |
+
this.newelement.prepend('<span class="'+a.widgetBaseClass+'-status" />');this.element.bind({"click.selectmenu":function(h){a.newelement.focus();h.preventDefault()}});this.newelement.bind("mousedown.selectmenu",function(h){a._toggle(h,true);if(c.style=="popup"){a._safemouseup=false;setTimeout(function(){a._safemouseup=true},300)}return false}).bind("click.selectmenu",function(){return false}).bind("keydown.selectmenu",function(h){var g=false;switch(h.keyCode){case b.ui.keyCode.ENTER:g=true;break;case b.ui.keyCode.SPACE:a._toggle(h);
|
16 |
+
break;case b.ui.keyCode.UP:h.altKey?a.open(h):a._moveSelection(-1);break;case b.ui.keyCode.DOWN:h.altKey?a.open(h):a._moveSelection(1);break;case b.ui.keyCode.LEFT:a._moveSelection(-1);break;case b.ui.keyCode.RIGHT:a._moveSelection(1);break;case b.ui.keyCode.TAB:g=true;break;case b.ui.keyCode.PAGE_UP:case b.ui.keyCode.HOME:a.index(0);break;case b.ui.keyCode.PAGE_DOWN:case b.ui.keyCode.END:a.index(a._optionLis.length);break;default:g=true}return g}).bind("keypress.selectmenu",function(h){h.which>0&&
|
17 |
+
a._typeAhead(h.which,"mouseup");return true}).bind("mouseover.selectmenu",function(){c.disabled||b(this).addClass("ui-state-hover")}).bind("mouseout.selectmenu",function(){c.disabled||b(this).removeClass("ui-state-hover")}).bind("focus.selectmenu",function(){c.disabled||b(this).addClass("ui-state-focus")}).bind("blur.selectmenu",function(){c.disabled||b(this).removeClass("ui-state-focus")});b(document).bind("mousedown.selectmenu-"+this.ids[0],function(h){a.isOpen&&a.close(h)});this.element.bind("click.selectmenu",
|
18 |
+
function(){a._refreshValue()}).bind("focus.selectmenu",function(){a.newelement&&a.newelement[0].focus()});if(!c.width)c.width=this.element.outerWidth();this.newelement.width(c.width);this.element.hide();this.list=b("<ul />",{"class":"ui-widget ui-widget-content","aria-hidden":true,role:"listbox","aria-labelledby":this.ids[1],id:this.ids[2]});this.listWrap=b("<div />",{"class":a.widgetBaseClass+"-menu"}).append(this.list).appendTo(c.appendTo);this.list.bind("keydown.selectmenu",function(h){var g=false;
|
19 |
+
switch(h.keyCode){case b.ui.keyCode.UP:h.altKey?a.close(h,true):a._moveFocus(-1);break;case b.ui.keyCode.DOWN:h.altKey?a.close(h,true):a._moveFocus(1);break;case b.ui.keyCode.LEFT:a._moveFocus(-1);break;case b.ui.keyCode.RIGHT:a._moveFocus(1);break;case b.ui.keyCode.HOME:a._moveFocus(":first");break;case b.ui.keyCode.PAGE_UP:a._scrollPage("up");break;case b.ui.keyCode.PAGE_DOWN:a._scrollPage("down");break;case b.ui.keyCode.END:a._moveFocus(":last");break;case b.ui.keyCode.ENTER:case b.ui.keyCode.SPACE:a.close(h,
|
20 |
+
true);b(h.target).parents("li:eq(0)").trigger("mouseup");break;case b.ui.keyCode.TAB:g=true;a.close(h,true);b(h.target).parents("li:eq(0)").trigger("mouseup");break;case b.ui.keyCode.ESCAPE:a.close(h,true);break;default:g=true}return g}).bind("keypress.selectmenu",function(h){h.which>0&&a._typeAhead(h.which,"focus");return true}).bind("mousedown.selectmenu mouseup.selectmenu",function(){return false});b(window).bind("resize.selectmenu-"+this.ids[0],b.proxy(a.close,this))},_init:function(){var a=this,
|
21 |
+
c=this.options,d=[];this.element.find("option").each(function(){var f=b(this);d.push({value:f.attr("value"),text:a._formatText(f.text(),f),selected:f.attr("selected"),disabled:f.attr("disabled"),classes:f.attr("class"),typeahead:f.attr("typeahead"),parentOptGroup:f.parent("optgroup"),bgImage:c.bgImage.call(f)})});var h=a.options.style=="popup"?" ui-state-active":"";this.list.html("");if(d.length)for(var g=0;g<d.length;g++){var j={role:"presentation"};if(d[g].disabled)j["class"]=this.namespace+"-state-disabled";
|
22 |
+
var e={html:d[g].text||" ",href:"#nogo",tabindex:-1,role:"option","aria-selected":false};if(d[g].disabled)e["aria-disabled"]=d[g].disabled;if(d[g].typeahead)e.typeahead=d[g].typeahead;e=b("<a/>",e).bind("focus.selectmenu",function(){b(this).parent().mouseover()}).bind("blur.selectmenu",function(){b(this).parent().mouseout()});j=b("<li/>",j).append(e).data("index",g).addClass(d[g].classes).data("optionClasses",d[g].classes||"").bind("mouseup.selectmenu",function(f){if(a._safemouseup&&!a._disabled(f.currentTarget)&&
|
23 |
+
!a._disabled(b(f.currentTarget).parents("ul>li."+a.widgetBaseClass+"-group "))){a.index(b(this).data("index"));a.select(f);a.close(f,true)}return false}).bind("click.selectmenu",function(){return false}).bind("mouseover.selectmenu",function(){if(!b(this).hasClass(a.namespace+"-state-disabled")&&!b(this).parent("ul").parent("li").hasClass(a.namespace+"-state-disabled")){a._selectedOptionLi().addClass(h);a._focusedOptionLi().removeClass(a.widgetBaseClass+"-item-focus ui-state-hover");b(this).removeClass("ui-state-active").addClass(a.widgetBaseClass+
|
24 |
+
"-item-focus ui-state-hover")}}).bind("mouseout.selectmenu",function(){b(this).is(a._selectedOptionLi())&&b(this).addClass(h);b(this).removeClass(a.widgetBaseClass+"-item-focus ui-state-hover")});if(d[g].parentOptGroup.length){e=a.widgetBaseClass+"-group-"+this.element.find("optgroup").index(d[g].parentOptGroup);this.list.find("li."+e).length?this.list.find("li."+e+":last ul").append(j):b(' <li role="presentation" class="'+a.widgetBaseClass+"-group "+e+(d[g].parentOptGroup.attr("disabled")?" "+this.namespace+
|
25 |
+
'-state-disabled" aria-disabled="true"':'"')+'><span class="'+a.widgetBaseClass+'-group-label">'+d[g].parentOptGroup.attr("label")+"</span><ul></ul></li> ").appendTo(this.list).find("ul").append(j)}else j.appendTo(this.list);if(c.icons)for(var i in c.icons)if(j.is(c.icons[i].find)){j.data("optionClasses",d[g].classes+" "+a.widgetBaseClass+"-hasIcon").addClass(a.widgetBaseClass+"-hasIcon");e=c.icons[i].icon||"";j.find("a:eq(0)").prepend('<span class="'+a.widgetBaseClass+"-item-icon ui-icon "+e+'"></span>');
|
26 |
+
d[g].bgImage&&j.find("span").css("background-image",d[g].bgImage)}}else b('<li role="presentation"><a href="#nogo" tabindex="-1" role="option"></a></li>').appendTo(this.list);g=c.style=="dropdown";this.newelement.toggleClass(a.widgetBaseClass+"-dropdown",g).toggleClass(a.widgetBaseClass+"-popup",!g);this.list.toggleClass(a.widgetBaseClass+"-menu-dropdown ui-corner-bottom",g).toggleClass(a.widgetBaseClass+"-menu-popup ui-corner-all",!g).find("li:first").toggleClass("ui-corner-top",!g).end().find("li:last").addClass("ui-corner-bottom");
|
27 |
+
this.selectmenuIcon.toggleClass("ui-icon-triangle-1-s",g).toggleClass("ui-icon-triangle-2-n-s",!g);c.style=="dropdown"?this.list.width(c.menuWidth?c.menuWidth:c.width):this.list.width(c.menuWidth?c.menuWidth:c.width-c.handleWidth);this.list.css("height","auto");g=this.listWrap.height();i=b(window).height();i=c.maxHeight?Math.min(c.maxHeight,i):i/3;g>i&&this.list.height(i);this._optionLis=this.list.find("li:not(."+a.widgetBaseClass+"-group)");this.element.attr("disabled")?this.disable():this.enable();
|
28 |
+
this._refreshValue();this._selectedOptionLi().addClass(this.widgetBaseClass+"-item-focus");clearTimeout(this.refreshTimeout);this.refreshTimeout=window.setTimeout(function(){a._refreshPosition()},200)},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled").unbind(".selectmenu");b(window).unbind(".selectmenu-"+this.ids[0]);b(document).unbind(".selectmenu-"+this.ids[0]);this.newelementWrap.remove();
|
29 |
+
this.listWrap.remove();this.element.unbind(".selectmenu").show();b.Widget.prototype.destroy.apply(this,arguments)},_typeAhead:function(a,c){var d=this,h=String.fromCharCode(a).toLowerCase(),g=a=null;if(d._typeAhead_timer){window.clearTimeout(d._typeAhead_timer);d._typeAhead_timer=undefined}d._typeAhead_chars=(d._typeAhead_chars===undefined?"":d._typeAhead_chars).concat(h);if(d._typeAhead_chars.length<2||d._typeAhead_chars.substr(-2,1)===h&&d._typeAhead_cycling){d._typeAhead_cycling=true;a=h}else{d._typeAhead_cycling=
|
30 |
+
false;a=d._typeAhead_chars}h=(c!=="focus"?this._selectedOptionLi().data("index"):this._focusedOptionLi().data("index"))||0;for(var j=0;j<this._optionLis.length;j++)if(this._optionLis.eq(j).text().substr(0,a.length).toLowerCase()===a)if(d._typeAhead_cycling){if(g===null)g=j;if(j>h){g=j;break}}else g=j;g!==null&&this._optionLis.eq(g).find("a").trigger(c);d._typeAhead_timer=window.setTimeout(function(){d._typeAhead_timer=undefined;d._typeAhead_chars=undefined;d._typeAhead_cycling=undefined},d.options.typeAhead)},
|
31 |
+
_uiHash:function(){var a=this.index();return{index:a,option:b("option",this.element).get(a),value:this.element[0].value}},open:function(a){var c=this,d=this.options;if(c.newelement.attr("aria-disabled")!="true"){c._closeOthers(a);c.newelement.addClass("ui-state-active");c.list.attr("aria-hidden",false);c.listWrap.addClass(c.widgetBaseClass+"-open");var h=this._selectedOptionLi();d.style=="dropdown"?c.newelement.removeClass("ui-corner-all").addClass("ui-corner-top"):this.list.css("left",-5000).scrollTop(this.list.scrollTop()+
|
32 |
+
h.position().top-this.list.outerHeight()/2+h.outerHeight()/2).css("left","auto");c._refreshPosition();d=h.find("a");d.length&&d[0].focus();c.isOpen=true;c._trigger("open",a,c._uiHash())}},close:function(a,c){if(this.newelement.is(".ui-state-active")){this.newelement.removeClass("ui-state-active");this.listWrap.removeClass(this.widgetBaseClass+"-open");this.list.attr("aria-hidden",true);this.options.style=="dropdown"&&this.newelement.removeClass("ui-corner-top").addClass("ui-corner-all");c&&this.newelement.focus();
|
33 |
+
this.isOpen=false;this._trigger("close",a,this._uiHash())}},change:function(a){this.element.trigger("change");this._trigger("change",a,this._uiHash())},select:function(a){if(this._disabled(a.currentTarget))return false;this._trigger("select",a,this._uiHash())},widget:function(){return this.listWrap.add(this.newelementWrap)},_closeOthers:function(a){b("."+this.widgetBaseClass+".ui-state-active").not(this.newelement).each(function(){b(this).data("selectelement").selectmenu("close",a)});b("."+this.widgetBaseClass+
|
34 |
+
".ui-state-hover").trigger("mouseout")},_toggle:function(a,c){this.isOpen?this.close(a,c):this.open(a)},_formatText:function(a,c){if(this.options.format)a=this.options.format(a,c);else if(this.options.escapeHtml)a=b("<div />").text(a).html();return a},_selectedIndex:function(){return this.element[0].selectedIndex},_selectedOptionLi:function(){return this._optionLis.eq(this._selectedIndex())},_focusedOptionLi:function(){return this.list.find("."+this.widgetBaseClass+"-item-focus")},_moveSelection:function(a,
|
35 |
+
c){if(!this.options.disabled){var d=parseInt(this._selectedOptionLi().data("index")||0,10)+a;if(d<0)d=0;if(d>this._optionLis.size()-1)d=this._optionLis.size()-1;if(d===c)return false;if(this._optionLis.eq(d).hasClass(this.namespace+"-state-disabled")){a>0?++a:--a;this._moveSelection(a,d)}else this._optionLis.eq(d).trigger("mouseover").trigger("mouseup")}},_moveFocus:function(a,c){var d=isNaN(a)?parseInt(this._optionLis.filter(a).data("index"),10):parseInt(this._focusedOptionLi().data("index")||0,
|
36 |
+
10)+a;if(d<0)d=0;if(d>this._optionLis.size()-1)d=this._optionLis.size()-1;if(d===c)return false;c=this.widgetBaseClass+"-item-"+Math.round(Math.random()*1E3);this._focusedOptionLi().find("a:eq(0)").attr("id","");if(this._optionLis.eq(d).hasClass(this.namespace+"-state-disabled")){a>0?++a:--a;this._moveFocus(a,d)}else this._optionLis.eq(d).find("a:eq(0)").attr("id",c).focus();this.list.attr("aria-activedescendant",c)},_scrollPage:function(a){var c=Math.floor(this.list.outerHeight()/this._optionLis.first().outerHeight());
|
37 |
+
c=a=="up"?-c:c;this._moveFocus(c)},_setOption:function(a,c){this.options[a]=c;if(a=="disabled"){c&&this.close();this.element.add(this.newelement).add(this.list)[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",c)}},disable:function(a,c){if(typeof a=="undefined")this._setOption("disabled",true);else c=="optgroup"?this._disableOptgroup(a):this._disableOption(a)},enable:function(a,c){if(typeof a=="undefined")this._setOption("disabled",
|
38 |
+
false);else c=="optgroup"?this._enableOptgroup(a):this._enableOption(a)},_disabled:function(a){return b(a).hasClass(this.namespace+"-state-disabled")},_disableOption:function(a){var c=this._optionLis.eq(a);if(c){c.addClass(this.namespace+"-state-disabled").find("a").attr("aria-disabled",true);this.element.find("option").eq(a).attr("disabled","disabled")}},_enableOption:function(a){var c=this._optionLis.eq(a);if(c){c.removeClass(this.namespace+"-state-disabled").find("a").attr("aria-disabled",false);
|
39 |
+
this.element.find("option").eq(a).removeAttr("disabled")}},_disableOptgroup:function(a){var c=this.list.find("li."+this.widgetBaseClass+"-group-"+a);if(c){c.addClass(this.namespace+"-state-disabled").attr("aria-disabled",true);this.element.find("optgroup").eq(a).attr("disabled","disabled")}},_enableOptgroup:function(a){var c=this.list.find("li."+this.widgetBaseClass+"-group-"+a);if(c){c.removeClass(this.namespace+"-state-disabled").attr("aria-disabled",false);this.element.find("optgroup").eq(a).removeAttr("disabled")}},
|
40 |
+
index:function(a){if(arguments.length)if(!this._disabled(b(this._optionLis[a]))&&a!=this._selectedIndex()){this.element[0].selectedIndex=a;this._refreshValue();this.change()}else return false;else return this._selectedIndex()},value:function(a){if(arguments.length&&a!=this.element[0].value){this.element[0].value=a;this._refreshValue();this.change()}else return this.element[0].value},_refreshValue:function(){var a=this.options.style=="popup"?" ui-state-active":"",c=this.widgetBaseClass+"-item-"+Math.round(Math.random()*
|
41 |
+
1E3);this.list.find("."+this.widgetBaseClass+"-item-selected").removeClass(this.widgetBaseClass+"-item-selected"+a).find("a").attr("aria-selected","false").attr("id","");this._selectedOptionLi().addClass(this.widgetBaseClass+"-item-selected"+a).find("a").attr("aria-selected","true").attr("id",c);a=this.newelement.data("optionClasses")?this.newelement.data("optionClasses"):"";var d=this._selectedOptionLi().data("optionClasses")?this._selectedOptionLi().data("optionClasses"):"";this.newelement.removeClass(a).data("optionClasses",
|
42 |
+
d).addClass(d).find("."+this.widgetBaseClass+"-status").html(this._selectedOptionLi().find("a:eq(0)").html());this.list.attr("aria-activedescendant",c)},_refreshPosition:function(){var a=this.options;if(a.style=="popup"&&!a.positionOptions.offset){var c=this._selectedOptionLi();c="0 "+(this.list.offset().top-c.offset().top-(this.newelement.outerHeight()+c.outerHeight())/2)}this.listWrap.removeAttr("style").zIndex(this.element.zIndex()+1).position({of:a.positionOptions.of||this.newelement,my:a.positionOptions.my,
|
43 |
+
at:a.positionOptions.at,offset:a.positionOptions.offset||c,collision:a.positionOptions.collision||(a.style=="popup"?"fit":"flip")})}})})(jQuery);
|
44 |
+
(function(b,a,c){function d(e){return e}function h(e){return decodeURIComponent(e.replace(g," "))}var g=/\+/g,j=b.cookie=function(e,i,f){if(i!==c){f=b.extend({},j.defaults,f);if(i===null)f.expires=-1;if(typeof f.expires==="number"){var k=f.expires,l=f.expires=new Date;l.setDate(l.getDate()+k)}i=j.json?JSON.stringify(i):String(i);return a.cookie=[encodeURIComponent(e),"=",j.raw?i:encodeURIComponent(i),f.expires?"; expires="+f.expires.toUTCString():"",f.path?"; path="+f.path:"",f.domain?"; domain="+
|
45 |
+
f.domain:"",f.secure?"; secure":""].join("")}i=j.raw?d:h;f=a.cookie.split("; ");k=0;for(l=f.length;k<l;k++){var m=f[k].split("=");if(i(m.shift())===e){e=i(m.join("="));return j.json?JSON.parse(e):e}}return null};j.defaults={};b.removeCookie=function(e,i){if(b.cookie(e)!==null){b.cookie(e,null,i);return true}return false}})(jQuery,document);
|
js/event-manager.js
ADDED
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
( function( window, undefined ) {
|
2 |
+
"use strict";
|
3 |
+
var document = window.document;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Handles managing all events for whatever you plug it into. Priorities for hooks are based on lowest to highest in
|
7 |
+
* that, lowest priority hooks are fired first.
|
8 |
+
*/
|
9 |
+
var EventManager = function() {
|
10 |
+
/**
|
11 |
+
* Maintain a reference to the object scope so 'this' never becomes confusing.
|
12 |
+
*/
|
13 |
+
var SELF = this;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Contains the hooks that get registered with this EventManager. The array for storage utilizes a "flat"
|
17 |
+
* object literal such that looking up the hook utilizes the native object literal hash.
|
18 |
+
*/
|
19 |
+
var STORAGE = {
|
20 |
+
actions : {},
|
21 |
+
filters : {}
|
22 |
+
};
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Adds an action to the event manager.
|
26 |
+
*
|
27 |
+
* @param action Must contain namespace.identifier
|
28 |
+
* @param callback Must be a valid callback function before this action is added
|
29 |
+
* @param priority Defaults to 10
|
30 |
+
*/
|
31 |
+
SELF.addAction = function( action, callback, priority ) {
|
32 |
+
if( _validateNamespace( action ) === false || typeof callback !== 'function' ) {
|
33 |
+
return SELF;
|
34 |
+
}
|
35 |
+
|
36 |
+
priority = parseInt( ( priority || 10 ), 10 );
|
37 |
+
_addHook( 'actions', action, callback, priority );
|
38 |
+
return SELF;
|
39 |
+
};
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Performs an action if it exists. You can pass as many arguments as you want to this function; the only rule is
|
43 |
+
* that the first argument must always be the action.
|
44 |
+
*/
|
45 |
+
SELF.doAction = function( /* action, arg1, arg2, ... */ ) {
|
46 |
+
var args = Array.prototype.slice.call( arguments );
|
47 |
+
var action = args.shift();
|
48 |
+
|
49 |
+
if( _validateNamespace( action ) === false ) {
|
50 |
+
return SELF;
|
51 |
+
}
|
52 |
+
|
53 |
+
_runHook( 'actions', action, args );
|
54 |
+
|
55 |
+
return SELF;
|
56 |
+
};
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Removes the specified action if it contains a namespace.identifier & exists.
|
60 |
+
*
|
61 |
+
* @param action The action to remove
|
62 |
+
*/
|
63 |
+
SELF.removeAction = function( action ) {
|
64 |
+
if( _validateNamespace( action ) === false ) {
|
65 |
+
return SELF;
|
66 |
+
}
|
67 |
+
|
68 |
+
_removeHook( 'actions', action );
|
69 |
+
return SELF;
|
70 |
+
};
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Adds a filter to the event manager.
|
74 |
+
*
|
75 |
+
* @param filter Must contain namespace.identifier
|
76 |
+
* @param callback Must be a valid callback function before this action is added
|
77 |
+
* @param priority Defaults to 10
|
78 |
+
*/
|
79 |
+
SELF.addFilter = function( filter, callback, priority ) {
|
80 |
+
if( _validateNamespace( filter ) === false || typeof callback !== 'function' ) {
|
81 |
+
return SELF;
|
82 |
+
}
|
83 |
+
|
84 |
+
priority = parseInt( ( priority || 10 ), 10 );
|
85 |
+
_addHook( 'filters', filter, callback, priority );
|
86 |
+
return SELF;
|
87 |
+
};
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Performs a filter if it exists. You should only ever pass 1 argument to be filtered. The only rule is that
|
91 |
+
* the first argument must always be the filter.
|
92 |
+
*/
|
93 |
+
SELF.applyFilter = function( filter, param ) {
|
94 |
+
if( _validateNamespace( filter ) === false ) {
|
95 |
+
return SELF;
|
96 |
+
}
|
97 |
+
|
98 |
+
return _runHook( 'filters', filter, param );
|
99 |
+
};
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Removes the specified filter if it contains a namespace.identifier & exists.
|
103 |
+
*
|
104 |
+
* @param filter The action to remove
|
105 |
+
*/
|
106 |
+
SELF.removeFilter = function( filter ) {
|
107 |
+
if( _validateNamespace( filter ) === false ) {
|
108 |
+
return SELF;
|
109 |
+
}
|
110 |
+
|
111 |
+
_removeHook( 'filters', filter );
|
112 |
+
return SELF;
|
113 |
+
};
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Removes the specified hook by resetting the value of it.
|
117 |
+
*
|
118 |
+
* @param type Type of hook, either 'actions' or 'filters'
|
119 |
+
* @param hook The hook (namespace.identifier) to remove
|
120 |
+
* @private
|
121 |
+
*/
|
122 |
+
var _removeHook = function( type, hook ) {
|
123 |
+
if( STORAGE[ type ][ hook ] ) {
|
124 |
+
STORAGE[ type ][ hook ] = [];
|
125 |
+
}
|
126 |
+
};
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Validates that the hook has both a namespace and an identifier.
|
130 |
+
*
|
131 |
+
* @param hook The hook we are checking for namespace and identifier for.
|
132 |
+
* @return {Boolean} False if it does not contain both or is incorrect. True if it has an appropriate namespace & identifier.
|
133 |
+
* @private
|
134 |
+
*/
|
135 |
+
var _validateNamespace = function( hook ) {
|
136 |
+
if( typeof hook !== 'string' ) {
|
137 |
+
return false;
|
138 |
+
}
|
139 |
+
var identifier = hook.replace( /^\s+|\s+$/i, '' ).split( '.' );
|
140 |
+
var namespace = identifier.shift();
|
141 |
+
identifier = identifier.join( '.' );
|
142 |
+
|
143 |
+
return ( namespace !== '' && identifier !== '' );
|
144 |
+
};
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Adds the hook to the appropriate storage container
|
148 |
+
*
|
149 |
+
* @param type 'actions' or 'filters'
|
150 |
+
* @param hook The hook (namespace.identifier) to add to our event manager
|
151 |
+
* @param callback The function that will be called when the hook is executed.
|
152 |
+
* @param priority The priority of this hook. Must be an integer.
|
153 |
+
* @private
|
154 |
+
*/
|
155 |
+
var _addHook = function( type, hook, callback, priority ) {
|
156 |
+
var hookObject = {
|
157 |
+
callback : callback,
|
158 |
+
priority : priority
|
159 |
+
};
|
160 |
+
|
161 |
+
// Utilize 'prop itself' : http://jsperf.com/hasownproperty-vs-in-vs-undefined/19
|
162 |
+
var hooks = STORAGE[ type ][ hook ];
|
163 |
+
if( hooks ) {
|
164 |
+
hooks.push( hookObject );
|
165 |
+
hooks = _hookInsertSort( hooks );
|
166 |
+
}
|
167 |
+
else {
|
168 |
+
hooks = [ hookObject ];
|
169 |
+
}
|
170 |
+
|
171 |
+
STORAGE[ type ][ hook ] = hooks;
|
172 |
+
};
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Use an insert sort for keeping our hooks organized based on priority. This function is ridiculously faster
|
176 |
+
* than bubble sort, etc: http://jsperf.com/javascript-sort
|
177 |
+
*
|
178 |
+
* @param hooks The custom array containing all of the appropriate hooks to perform an insert sort on.
|
179 |
+
* @private
|
180 |
+
*/
|
181 |
+
var _hookInsertSort = function( hooks ) {
|
182 |
+
var tmpHook, j, prevHook;
|
183 |
+
for( var i = 1, len = hooks.length; i < len; i++ ) {
|
184 |
+
tmpHook = hooks[ i ];
|
185 |
+
j = i;
|
186 |
+
while( ( prevHook = hooks[ j - 1 ] ) && prevHook.priority > tmpHook.priority ) {
|
187 |
+
hooks[ j ] = hooks[ j - 1 ];
|
188 |
+
--j;
|
189 |
+
}
|
190 |
+
hooks[ j ] = tmpHook;
|
191 |
+
}
|
192 |
+
|
193 |
+
return hooks;
|
194 |
+
};
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Runs the specified hook. If it is an action, the value is not modified but if it is a filter, it is.
|
198 |
+
*
|
199 |
+
* @param type 'actions' or 'filters'
|
200 |
+
* @param hook The hook ( namespace.identifier ) to be ran.
|
201 |
+
* @param args Arguments to pass to the action/filter. If it's a filter, args is actually a single parameter.
|
202 |
+
* @private
|
203 |
+
*/
|
204 |
+
var _runHook = function( type, hook, args ) {
|
205 |
+
var hooks = STORAGE[ type ][ hook ];
|
206 |
+
if( typeof hooks === 'undefined' ) {
|
207 |
+
if( type === 'filters' ) {
|
208 |
+
return args;
|
209 |
+
}
|
210 |
+
return false;
|
211 |
+
}
|
212 |
+
|
213 |
+
for( var i = 0, len = hooks.length; i < len; i++ ) {
|
214 |
+
if( type === 'actions' ) {
|
215 |
+
hooks[ i ].callback.apply( undefined, args );
|
216 |
+
}
|
217 |
+
else {
|
218 |
+
args = hooks[ i ].callback.apply( undefined, [ args ] );
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
if( type === 'actions' ) {
|
223 |
+
return true;
|
224 |
+
}
|
225 |
+
|
226 |
+
return args;
|
227 |
+
};
|
228 |
+
|
229 |
+
};
|
230 |
+
|
231 |
+
window.wp = window.wp || {};
|
232 |
+
window.wp.hooks = new EventManager();
|
233 |
+
|
234 |
+
} )( window );
|
js/event-manager.min.js
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Module: WP-JS-Hooks
|
3 |
+
* Props: Carl Danley & 10up
|
4 |
+
*/
|
5 |
+
(function(t,n){"use strict";t.document;var r=function(){var t=this,r={actions:{},filters:{}};t.addAction=function(n,r,i){return o(n)===!1||"function"!=typeof r?t:(i=parseInt(i||10,10),e("actions",n,r,i),t)},t.doAction=function(){var n=Array.prototype.slice.call(arguments),r=n.shift();return o(r)===!1?t:(a("actions",r,n),t)},t.removeAction=function(n){return o(n)===!1?t:(i("actions",n),t)},t.addFilter=function(n,r,i){return o(n)===!1||"function"!=typeof r?t:(i=parseInt(i||10,10),e("filters",n,r,i),t)},t.applyFilter=function(n,r){return o(n)===!1?t:a("filters",n,r)},t.removeFilter=function(n){return o(n)===!1?t:(i("filters",n),t)};var i=function(t,n){r[t][n]&&(r[t][n]=[])},o=function(t){if("string"!=typeof t)return!1;var n=t.replace(/^\s+|\s+$/i,"").split("."),r=n.shift();return n=n.join("."),""!==r&&""!==n},e=function(t,n,i,o){var e={callback:i,priority:o},a=r[t][n];a?(a.push(e),a=c(a)):a=[e],r[t][n]=a},c=function(t){for(var n,r,i,o=1,e=t.length;e>o;o++){for(n=t[o],r=o;(i=t[r-1])&&i.priority>n.priority;)t[r]=t[r-1],--r;t[r]=n}return t},a=function(t,i,o){var e=r[t][i];if(e===n)return"filters"===t?o:!1;for(var c=0,a=e.length;a>c;c++)"actions"===t?e[c].callback.apply(n,o):o=e[c].callback.apply(n,[o]);return"actions"===t?!0:o}};t.wp=t.wp||{},t.wp.hooks=new r})(window);
|
js/event.js
ADDED
@@ -0,0 +1,2219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var eo_occurrences_by_rule = new Array;
|
2 |
+
jQuery(document).ready(function($) {
|
3 |
+
|
4 |
+
//Workaround for indexOf in IE 7&8
|
5 |
+
if (!Array.prototype.indexOf)
|
6 |
+
{
|
7 |
+
Array.prototype.indexOf = function(elt /*, from*/)
|
8 |
+
{
|
9 |
+
var len = this.length;
|
10 |
+
|
11 |
+
var from = Number(arguments[1]) || 0;
|
12 |
+
from = (from < 0)
|
13 |
+
? Math.ceil(from)
|
14 |
+
: Math.floor(from);
|
15 |
+
if (from < 0)
|
16 |
+
from += len;
|
17 |
+
|
18 |
+
for (; from < len; from++)
|
19 |
+
{
|
20 |
+
if (from in this &&
|
21 |
+
this[from] === elt)
|
22 |
+
return from;
|
23 |
+
}
|
24 |
+
return -1;
|
25 |
+
};
|
26 |
+
}
|
27 |
+
|
28 |
+
var eo_venue_obj;
|
29 |
+
if ($('#eo_occurrence_includes').length > 0) {
|
30 |
+
eo_include_dates = $('#eo_occurrence_includes').val().split(",");
|
31 |
+
eo_exclude_dates = $('#eo_occurrence_excludes').val().split(",");
|
32 |
+
}
|
33 |
+
|
34 |
+
// Update textareas to reflect inclusion, exclusion arrays
|
35 |
+
function eo_update_inc_ex_Input() {
|
36 |
+
$('#eo_occurrence_includes').val(eo_include_dates.join(',\r\n'));
|
37 |
+
$('#eo_occurrence_excludes').val(eo_exclude_dates.join(',\r\n'));
|
38 |
+
}
|
39 |
+
|
40 |
+
$(document).ready(function() {
|
41 |
+
//Venue picker - combobox
|
42 |
+
$.widget("ui.combobox", {
|
43 |
+
_create: function () {
|
44 |
+
var input;
|
45 |
+
var c = this.element.hide();
|
46 |
+
var d = c.children(":selected");
|
47 |
+
var e = d.val() ? d.text() : "";
|
48 |
+
var wrapper = $("<span>").addClass("ui-combobox eo-venue-input").insertAfter(c);
|
49 |
+
input = $("<input>").appendTo(wrapper).val(e).addClass("ui-combobox-input").autocomplete({
|
50 |
+
delay: 0,
|
51 |
+
minLength: 0,
|
52 |
+
source: function (a, b) {
|
53 |
+
$.getJSON(EO_Ajax_Event.ajaxurl + "?callback=?&action=eo-search-venue", a, function (a) {
|
54 |
+
var venues = $.map(a, function (a) {
|
55 |
+
a.label = a.name;
|
56 |
+
return a;
|
57 |
+
});
|
58 |
+
b(venues);
|
59 |
+
});
|
60 |
+
},
|
61 |
+
select: function (a, b) {
|
62 |
+
if ($("tr.venue_row").length > 0) {
|
63 |
+
if (b.item.term_id == 0) {
|
64 |
+
$("tr.venue_row").hide();
|
65 |
+
$("#eventorganiser_event_detail tr.eo-add-new-venue").hide();
|
66 |
+
} else {
|
67 |
+
$("tr.venue_row").show();
|
68 |
+
$("#eventorganiser_event_detail tr.eo-add-new-venue").hide();
|
69 |
+
}
|
70 |
+
eo_initialize_map(b.item.venue_lat, b.item.venue_lng)
|
71 |
+
$("#eo_venue_Lat").val(b.item.venue_lat);
|
72 |
+
$("#eo_venue_Lng").val(b.item.venue_lng);
|
73 |
+
}
|
74 |
+
$("#venue_select").removeAttr("selected");
|
75 |
+
$("#venue_select").val(b.item.term_id);
|
76 |
+
}
|
77 |
+
}).addClass("ui-widget-content ui-corner-left");
|
78 |
+
input.data("autocomplete")._renderItem = function (a, b) {
|
79 |
+
if (b.term_id == 0 ) {
|
80 |
+
return $("<li></li>").data("item.autocomplete", b).append("<a>" + b.label + "</a>").appendTo(a);
|
81 |
+
}
|
82 |
+
//Clean address
|
83 |
+
var address_array = [b.venue_address, b.venue_city, b.venue_state,b.venue_postcode,b.venue_country];
|
84 |
+
address_array = $.grep(address_array,function(n){
|
85 |
+
return(n);
|
86 |
+
});
|
87 |
+
|
88 |
+
return $("<li></li>").data("item.autocomplete", b)
|
89 |
+
.append("<a>" + b.label + "</br> <span style='font-size: 0.8em'><em>" +address_array.join(', ')+ "</span></em></a>")
|
90 |
+
.appendTo(a);
|
91 |
+
};
|
92 |
+
|
93 |
+
var button_wrappers = $("<span>").addClass("eo-venue-combobox-buttons").appendTo(wrapper);
|
94 |
+
$("<a style='vertical-align: top;margin: 0px -1px;padding: 0px;height: 21px;'>").attr("title", "Show All Items").appendTo(button_wrappers).button({
|
95 |
+
icons: {
|
96 |
+
primary: "ui-icon-triangle-1-s"
|
97 |
+
},
|
98 |
+
text: false
|
99 |
+
}).removeClass("ui-corner-all").addClass("ui-corner-right ui-combobox-toggle ui-combobox-button").click(function () {
|
100 |
+
if (input.autocomplete("widget").is(":visible")) {
|
101 |
+
input.autocomplete("close");
|
102 |
+
return
|
103 |
+
}
|
104 |
+
$(this).blur();
|
105 |
+
input.autocomplete("search", "");
|
106 |
+
input.focus();
|
107 |
+
});
|
108 |
+
|
109 |
+
if( 'event' == pagenow && EO_Ajax_Event.current_user_can.manage_venues ){
|
110 |
+
//Only add this on event edit page - i.e. not on calendar page.
|
111 |
+
$("<a style='vertical-align: top;margin: 0px -1px;padding: 0px;height: 21px;'>").attr("title", "Create New Venue").appendTo(button_wrappers).button({
|
112 |
+
icons: {
|
113 |
+
primary: "ui-icon-plus"
|
114 |
+
},
|
115 |
+
text: false
|
116 |
+
}).removeClass("ui-corner-all").addClass("ui-corner-right add-new-venue ui-combobox-button").click(function () {
|
117 |
+
$("#eventorganiser_event_detail tr.eo-add-new-venue").show();
|
118 |
+
$("tr.venue_row").show();
|
119 |
+
//Store existing venue details in case the user cancels creating a new on
|
120 |
+
eo_venue_obj={
|
121 |
+
id: $("#venue_select").val(),
|
122 |
+
label: $(".eo-venue-input input").val(),
|
123 |
+
lat: $("#eo_venue_Lat").val(),
|
124 |
+
lng: $("#eo_venue_Lng").val()
|
125 |
+
};
|
126 |
+
$("#venue_select").removeAttr("selected").val(0);
|
127 |
+
$('.eo-venue-combobox-select').hide();
|
128 |
+
$('.eo-venue-input input').val('');
|
129 |
+
eo_initialize_map(0,0);
|
130 |
+
var address = EO_Ajax_Event.location;
|
131 |
+
if( address ){
|
132 |
+
address =address.split("/");
|
133 |
+
address = address[address.length-1];
|
134 |
+
eventorganiser_code_address(address);
|
135 |
+
}else{
|
136 |
+
map.setZoom(1);
|
137 |
+
}
|
138 |
+
$(this).blur();
|
139 |
+
});
|
140 |
+
}
|
141 |
+
}
|
142 |
+
});
|
143 |
+
$("#venue_select").combobox();
|
144 |
+
});
|
145 |
+
|
146 |
+
|
147 |
+
$('.eo-add-new-venue-cancel').click(function(e){
|
148 |
+
e.preventDefault();
|
149 |
+
$('.eo-venue-combobox-select').show();
|
150 |
+
$('.eo-add-new-venue input').val('');
|
151 |
+
|
152 |
+
//Restore old venue details
|
153 |
+
eo_initialize_map(eo_venue_obj.lat,eo_venue_obj.lng);
|
154 |
+
$("#venue_select").val(eo_venue_obj.id);
|
155 |
+
$(".eo-venue-input input").val(eo_venue_obj.label);
|
156 |
+
|
157 |
+
$("#eventorganiser_event_detail tr.eo-add-new-venue").hide();
|
158 |
+
//$("#eventorganiser_event_detail tr.venue_row ").hide();
|
159 |
+
});
|
160 |
+
|
161 |
+
|
162 |
+
var locale = EO_Ajax_Event.locale;
|
163 |
+
function eo_update_event_form() {
|
164 |
+
var speed = 700;
|
165 |
+
var a = !$("#HWSEvent_rec").prop("checked");
|
166 |
+
$(".reoccurence .event-date :input").attr("disabled", a);
|
167 |
+
$(".reoccurence .event-date :input").toggleClass("ui-state-disabled", a);
|
168 |
+
a = !$("#eo_allday:checkbox").attr("checked");
|
169 |
+
$(".eo_time").attr("disabled", !a);
|
170 |
+
$(".eo_time").toggleClass("ui-state-disabled", !a);
|
171 |
+
switch ($("#HWSEventInput_Req").val()) {
|
172 |
+
case "once":
|
173 |
+
case "custom":
|
174 |
+
$("#HWSEvent_freq").val("1");
|
175 |
+
$(".reocurrence_row").hide();
|
176 |
+
$("#dayofweekrepeat").show();
|
177 |
+
$("#dayofmonthrepeat").show();
|
178 |
+
$(".reocurrence_row :input").attr("disabled", true);
|
179 |
+
break;
|
180 |
+
case "weekly":
|
181 |
+
$(".reocurrence_row :input").attr("disabled", false);
|
182 |
+
if ($("#HWSEvent_freq").val() > 1) {
|
183 |
+
$("#recpan").text(locale.weeks);
|
184 |
+
} else {
|
185 |
+
$("#recpan").text(locale.week);
|
186 |
+
}
|
187 |
+
$(".reocurrence_row").fadeIn(speed);
|
188 |
+
$("#dayofweekrepeat").fadeIn(speed);
|
189 |
+
$("#dayofweekrepeat :input").attr("disabled", false);
|
190 |
+
$("#dayofmonthrepeat").hide();
|
191 |
+
$("#dayofmonthrepeat :radio").attr("disabled", true);
|
192 |
+
break;
|
193 |
+
case "monthly":
|
194 |
+
$(".reocurrence_row :input").attr("disabled", false);
|
195 |
+
if ($("#HWSEvent_freq").val() > 1) {
|
196 |
+
$("#recpan").text(locale.months);
|
197 |
+
} else {
|
198 |
+
$("#recpan").text(locale.month);
|
199 |
+
}
|
200 |
+
$(".reocurrence_row").fadeIn(speed);
|
201 |
+
$("#dayofmonthrepeat").fadeIn(speed);
|
202 |
+
$("#dayofmonthrepeat :input").attr("disabled", false);
|
203 |
+
$("#dayofweekrepeat").hide();
|
204 |
+
$("#dayofweekrepeat :input").attr("disabled", true);
|
205 |
+
break;
|
206 |
+
case "daily":
|
207 |
+
$(".reocurrence_row :input").attr("disabled", false);
|
208 |
+
$(".reocurrence_row").fadeIn(speed);
|
209 |
+
if ($("#HWSEvent_freq").val() > 1) {
|
210 |
+
$("#recpan").text(locale.days);
|
211 |
+
} else {
|
212 |
+
$("#recpan").text(locale.day);
|
213 |
+
}
|
214 |
+
$("#dayofweekrepeat").hide();
|
215 |
+
$("#dayofweekrepeat :input").attr("disabled", true);
|
216 |
+
$("#dayofmonthrepeat").hide();
|
217 |
+
$("#dayofmonthrepeat :radio").attr("disabled", true);
|
218 |
+
break;
|
219 |
+
case "yearly":
|
220 |
+
$(".reocurrence_row :input").attr("disabled", false);
|
221 |
+
$(".reocurrence_row").fadeIn(speed);
|
222 |
+
if ($("#HWSEvent_freq").val() > 1) {
|
223 |
+
$("#recpan").text(locale.years);
|
224 |
+
} else {
|
225 |
+
$("#recpan").text(locale.year);
|
226 |
+
}
|
227 |
+
$("#dayofweekrepeat").hide();
|
228 |
+
$("#dayofweekrepeat :input").attr("disabled", true);
|
229 |
+
$("#dayofmonthrepeat").hide();
|
230 |
+
$("#dayofmonthrepeat :radio").attr("disabled", true);
|
231 |
+
break;
|
232 |
+
}
|
233 |
+
if ($("#venue_select").val() === null) {
|
234 |
+
$("tr.venue_row").hide();
|
235 |
+
}
|
236 |
+
eo_produce_summary();
|
237 |
+
}
|
238 |
+
|
239 |
+
function eo_produce_summary() {
|
240 |
+
if ($("#HWSEventInput_Req").val() == "once") {
|
241 |
+
$("#event_summary").html("This event will be a one-time event");
|
242 |
+
return
|
243 |
+
}
|
244 |
+
var a = $("#from_date").datepicker("getDate");
|
245 |
+
var b = EO_Ajax_Event.locale.weekDay;
|
246 |
+
var c = new Array("SU", "MO", "TU", "WE", "TH", "FR", "SA");
|
247 |
+
var options = {
|
248 |
+
monthNamesShort: EO_Ajax_Event.locale.monthAbbrev,
|
249 |
+
dayNamesMin: EO_Ajax_Event.locale.dayAbbrev,
|
250 |
+
monthNames: EO_Ajax_Event.locale.monthNames
|
251 |
+
};
|
252 |
+
|
253 |
+
var frequency = parseInt($("#HWSEvent_freq").val());
|
254 |
+
var summary = locale.summary + " ";
|
255 |
+
switch ($("#HWSEventInput_Req").val()) {
|
256 |
+
case "custom":
|
257 |
+
case "daily":
|
258 |
+
if (frequency > 1) {
|
259 |
+
summary += sprintf(locale.dayPlural, frequency);
|
260 |
+
} else {
|
261 |
+
summary += locale.daySingle;
|
262 |
+
}
|
263 |
+
break;
|
264 |
+
case "weekly":
|
265 |
+
if (frequency > 1) {
|
266 |
+
summary += sprintf(locale.weekPlural, frequency);
|
267 |
+
} else {
|
268 |
+
summary += locale.weekSingle;
|
269 |
+
}
|
270 |
+
var selected = $("#dayofweekrepeat :checkbox:checked");
|
271 |
+
if (selected.length == 0) {
|
272 |
+
var day = a.getDay();
|
273 |
+
$("#dayofweekrepeat :checkbox[value='" + c[day] + "']").attr("checked", true);
|
274 |
+
}
|
275 |
+
selected = $("#dayofweekrepeat :checkbox:checked");
|
276 |
+
selected.each(function(a) {
|
277 |
+
if (a == 0)
|
278 |
+
summary = summary + " " + b[c.indexOf($(this).val())];
|
279 |
+
if (a > 0)
|
280 |
+
summary = summary + ", " + b[c.indexOf($(this).val())];
|
281 |
+
});
|
282 |
+
break;
|
283 |
+
case "monthly":
|
284 |
+
if (frequency > 1) {
|
285 |
+
summary += sprintf(locale.monthPlural, frequency);
|
286 |
+
} else {
|
287 |
+
summary += locale.monthSingle;
|
288 |
+
}
|
289 |
+
if ($("#dayofmonthrepeat :radio:checked").val() == "BYMONTHDAY=") {
|
290 |
+
summary = summary + " " + a.getDate() + eo_date_suffix(a);
|
291 |
+
} else {
|
292 |
+
day = a.getDay() % 7;
|
293 |
+
var n = parseInt(Math.floor((a.getDate() - 1) / 7));
|
294 |
+
var occurrence = locale.occurrence;
|
295 |
+
summary = summary + " " + occurrence[n] + " " + b[day];
|
296 |
+
}
|
297 |
+
break;
|
298 |
+
case "yearly":
|
299 |
+
if (frequency > 1) {
|
300 |
+
summary += sprintf(locale.yearPlural, frequency);
|
301 |
+
} else {
|
302 |
+
summary += locale.yearSingle;
|
303 |
+
}
|
304 |
+
summary = summary + " " + $.datepicker.formatDate("MM d", a, options) + eo_date_suffix(a);
|
305 |
+
break;
|
306 |
+
}
|
307 |
+
var d = $("#recend").datepicker("getDate");
|
308 |
+
if (d != null) {
|
309 |
+
summary = summary + " " + locale.until + " " + $.datepicker.formatDate("MM d'" + eo_date_suffix(d) + "' yy", d, options);
|
310 |
+
}
|
311 |
+
$("#event_summary").html(summary);
|
312 |
+
}
|
313 |
+
|
314 |
+
function eo_date_suffix(date) {
|
315 |
+
var suffix = ["th", "st", "nd", "rd"];
|
316 |
+
if (3 < date.getDate() && date.getDate() < 20) {
|
317 |
+
var s = 0;
|
318 |
+
} else {
|
319 |
+
var s = Math.min(date.getDate() % 10, 4) % 4;
|
320 |
+
}
|
321 |
+
return suffix[s];
|
322 |
+
};
|
323 |
+
|
324 |
+
if ($("#eventorganiser_detail #from_date, #eventorganiser_detail #to_date").length > 0) {
|
325 |
+
var dates = $("#eventorganiser_detail #from_date, #eventorganiser_detail #to_date").datepicker({
|
326 |
+
dateFormat: EO_Ajax_Event.format,
|
327 |
+
changeMonth: true,
|
328 |
+
changeYear: true,
|
329 |
+
monthNamesShort: EO_Ajax_Event.locale.monthAbbrev,
|
330 |
+
dayNamesMin: EO_Ajax_Event.locale.dayAbbrev,
|
331 |
+
firstDay: parseInt(EO_Ajax_Event.startday),
|
332 |
+
buttonImage: 'images/ui-icon-calendar.png',
|
333 |
+
onSelect: function(selectedDate) {
|
334 |
+
var option = this.id == "from_date" ? "minDate": "maxDate",
|
335 |
+
instance = $(this).data("datepicker"),
|
336 |
+
date = $.datepicker.parseDate(instance.settings.dateFormat || $.datepicker._defaults.dateFormat, selectedDate, instance.settings);
|
337 |
+
dates.not(this).datepicker("option", option, date);
|
338 |
+
if (this.id == "from_date") {
|
339 |
+
$("#recend").datepicker("option", "minDate", date);
|
340 |
+
}
|
341 |
+
eo_update_occurrencepicker_rules();
|
342 |
+
eo_update_event_form()
|
343 |
+
}
|
344 |
+
});
|
345 |
+
$("#recend").datepicker({
|
346 |
+
dateFormat: EO_Ajax_Event.format,
|
347 |
+
monthNamesShort: EO_Ajax_Event.locale.monthAbbrev,
|
348 |
+
dayNamesMin: EO_Ajax_Event.locale.dayAbbrev,
|
349 |
+
changeMonth: true,
|
350 |
+
changeYear: true,
|
351 |
+
firstDay: parseInt(EO_Ajax_Event.startday)
|
352 |
+
});
|
353 |
+
$('#HWSEvent_time, #HWSEvent_time2').timepicker({
|
354 |
+
showPeriodLabels: false,
|
355 |
+
hourText: EO_Ajax_Event.locale.hour,
|
356 |
+
minuteText: EO_Ajax_Event.locale.minute
|
357 |
+
});
|
358 |
+
$("#HWSEvent_rec").click(function() {
|
359 |
+
eo_update_event_form();
|
360 |
+
});
|
361 |
+
$(".reoccurence .event-date :input, .onetime .event-date :input").not('.eo_time').change(function(o) {
|
362 |
+
eo_update_event_form();
|
363 |
+
if ($(this).attr('id') != 'eo_allday') {
|
364 |
+
eo_update_occurrencepicker_rules();
|
365 |
+
};
|
366 |
+
});
|
367 |
+
eo_update_event_form();
|
368 |
+
var bool = !$(this).prop("checked");
|
369 |
+
$(".reoccurence .event-date :input").attr('disabled', bool);
|
370 |
+
$(".reoccurence .event-date :input").toggleClass('ui-state-disabled', bool);
|
371 |
+
}
|
372 |
+
|
373 |
+
//When rule changes, wipe include/exclude dates clean
|
374 |
+
function eo_update_occurrencepicker_rules() {
|
375 |
+
eo_exclude_dates = new Array();
|
376 |
+
eo_include_dates = new Array();
|
377 |
+
eo_update_inc_ex_Input();
|
378 |
+
eo_generate_dates_by_rule(eo_viewing_month[0], eo_viewing_month[1], {});
|
379 |
+
dp.datepicker("refresh");
|
380 |
+
};
|
381 |
+
|
382 |
+
//Show/hide calendar
|
383 |
+
$('.eo_occurrence_toogle').click(function(e) {
|
384 |
+
e.preventDefault();
|
385 |
+
e.stopPropagation();
|
386 |
+
dp.toggle();
|
387 |
+
if( dp.is(":visible") ){
|
388 |
+
$('.eo_occurrence_toogle').val(EO_Ajax_Event.locale.hideDates);
|
389 |
+
}else{
|
390 |
+
$('.eo_occurrence_toogle').val(EO_Ajax_Event.locale.showDates);
|
391 |
+
}
|
392 |
+
});
|
393 |
+
|
394 |
+
//Fires before each date. Decides what classes to add
|
395 |
+
function eo_pre_show_date(date) {
|
396 |
+
var date_str = $.datepicker.formatDate('yy-mm-dd', date);
|
397 |
+
var isEventful = eo_is_date_eventful(date_str);
|
398 |
+
if (isEventful[0]) {
|
399 |
+
return [true, "ui-state-active", ""];
|
400 |
+
}
|
401 |
+
return [true, "ui-state-disabled", ''];
|
402 |
+
}
|
403 |
+
|
404 |
+
//Is given date an occurrence of the event?
|
405 |
+
function eo_is_date_eventful(date) {
|
406 |
+
var index = $.inArray(date, eo_occurrences_by_rule);
|
407 |
+
|
408 |
+
if (index > -1) {
|
409 |
+
//Occurs by rule - is it excluded manually?
|
410 |
+
var excluded = $.inArray(date, eo_exclude_dates);
|
411 |
+
if (excluded > -1) {
|
412 |
+
return [false, excluded];
|
413 |
+
} else {
|
414 |
+
return [true, -1];
|
415 |
+
}
|
416 |
+
} else {
|
417 |
+
//Doesn't occurs by rule - is it included manually?
|
418 |
+
var included = $.inArray(date, eo_include_dates);
|
419 |
+
if (included > -1) {
|
420 |
+
return [true, included];
|
421 |
+
} else {
|
422 |
+
return [false, -1];
|
423 |
+
}
|
424 |
+
}
|
425 |
+
}
|
426 |
+
|
427 |
+
//Generate array of eventful dates in given month by the event's current rule.
|
428 |
+
function eo_generate_dates_by_rule(year, month, inst) {
|
429 |
+
//month is 1-12.
|
430 |
+
eo_occurrences_by_rule = new Array();
|
431 |
+
eo_viewing_month = [year, month];
|
432 |
+
|
433 |
+
var schedule = $('#HWSEventInput_Req').val();
|
434 |
+
var frequency = parseInt($('#HWSEvent_freq').val());
|
435 |
+
|
436 |
+
var start = $("#from_date").datepicker("getDate");
|
437 |
+
var end = $("#recend").datepicker("getDate");
|
438 |
+
|
439 |
+
//Get month start/end dates. Date expects month 0-11.
|
440 |
+
month = month - 1;
|
441 |
+
var month_start = new Date(year, month, 1);
|
442 |
+
var nxt_mon = new Date(year, month + 1, 1);
|
443 |
+
var month_end = new Date(nxt_mon - 1);
|
444 |
+
|
445 |
+
if (end < month_start || start > month_end) {
|
446 |
+
return;
|
447 |
+
}
|
448 |
+
|
449 |
+
//If event starts in previous month - how many days from start to first occurrence in current month?
|
450 |
+
// Depends on occurrence (and 'stream' for weekly events.
|
451 |
+
switch (schedule) {
|
452 |
+
case 'once':
|
453 |
+
case 'custom':
|
454 |
+
var formateddate = $.datepicker.formatDate('yy-mm-dd', start);
|
455 |
+
eo_occurrences_by_rule.push(formateddate);
|
456 |
+
return;
|
457 |
+
break;
|
458 |
+
|
459 |
+
case 'daily':
|
460 |
+
if (start < month_start) {
|
461 |
+
var count_days = Math.abs((month_start - start) / (1000 * 60 * 60 * 24)) - 1;
|
462 |
+
count_days = count_days % frequency;
|
463 |
+
} else {
|
464 |
+
var count_days = parseInt(start.getDate());
|
465 |
+
}
|
466 |
+
var skip = frequency;
|
467 |
+
var streams = new Array();
|
468 |
+
var start_stream = new Date(month_start);
|
469 |
+
start_stream.setDate(month_start.getDate() + (count_days - 1));
|
470 |
+
streams.push(start_stream);
|
471 |
+
break;
|
472 |
+
|
473 |
+
case 'weekly':
|
474 |
+
var month_start_day = month_start.getDay();
|
475 |
+
var selected = $("#dayofweekrepeat :checkbox:checked");
|
476 |
+
|
477 |
+
var ical_weekdays = new Array("SU", "MO", "TU", "WE", "TH", "FR", "SA");
|
478 |
+
streams = new Array();
|
479 |
+
selected.each(function(index) {
|
480 |
+
index = ical_weekdays.indexOf($(this).val());
|
481 |
+
start_stream = new Date(start);
|
482 |
+
start_stream.setDate(start.getDate() + (index - start.getDay() + 7) % 7);
|
483 |
+
if (start_stream < month_start) {
|
484 |
+
count_days = Math.abs((month_start - start) / (1000 * 60 * 60 * 24));
|
485 |
+
count_days = count_days - count_days % (frequency * 7);
|
486 |
+
start_stream.setDate(start_stream.getDate() + count_days);
|
487 |
+
}
|
488 |
+
streams.push(start_stream);
|
489 |
+
});
|
490 |
+
skip = 7 * frequency;
|
491 |
+
break;
|
492 |
+
|
493 |
+
//These are easy
|
494 |
+
case 'monthly':
|
495 |
+
var month_difference = (year - start.getFullYear()) * 12 + month - (start.getMonth() + 1);
|
496 |
+
if (month_difference % frequency != 0) {
|
497 |
+
return;
|
498 |
+
}
|
499 |
+
var meta = $('input[name="eo_input[schedule_meta]"]:checked').val();
|
500 |
+
if (meta == 'BYMONTHDAY=') {
|
501 |
+
var day = start.getDate();
|
502 |
+
var daysinmonth = month_end.getDate();
|
503 |
+
if (day <= daysinmonth) {
|
504 |
+
//If valid date
|
505 |
+
var pointer = new Date(year, month, day);
|
506 |
+
}
|
507 |
+
|
508 |
+
} else {
|
509 |
+
//e.g. 3rd friday of month:
|
510 |
+
var n = Math.ceil(start.getDate() / 7);
|
511 |
+
var occurrence_day = start.getDay();
|
512 |
+
if (n >= 5) {
|
513 |
+
//Last day
|
514 |
+
var month_end_day = month_end.getDay();
|
515 |
+
var occurence_date = month_end.getDate() + (occurrence_day - month_end_day - 7) % 7;
|
516 |
+
} else {
|
517 |
+
month_start_day = month_start.getDay();
|
518 |
+
var offset = (occurrence_day - month_start_day + 7) % 7;
|
519 |
+
occurence_date = offset + (n - 1) * 7 + 1;
|
520 |
+
}
|
521 |
+
var pointer = new Date(month_start);
|
522 |
+
pointer.setDate(occurence_date);
|
523 |
+
}
|
524 |
+
if (pointer <= end) {
|
525 |
+
//If before end
|
526 |
+
formateddate = $.datepicker.formatDate('yy-mm-dd', pointer);
|
527 |
+
eo_occurrences_by_rule.push(formateddate);
|
528 |
+
}
|
529 |
+
return;
|
530 |
+
break;
|
531 |
+
|
532 |
+
case 'yearly':
|
533 |
+
var year_difference = (year - start.getFullYear());
|
534 |
+
if (year_difference % frequency != 0) {
|
535 |
+
return;
|
536 |
+
}
|
537 |
+
|
538 |
+
var dateCheck = new Date(year, start.getMonth(), start.getDate());
|
539 |
+
|
540 |
+
if (month == start.getMonth() && dateCheck.getMonth() == start.getMonth()) {
|
541 |
+
pointer = new Date(start);
|
542 |
+
pointer.setYear(year);
|
543 |
+
if (pointer <= end) {
|
544 |
+
//If before end
|
545 |
+
formateddate = $.datepicker.formatDate('yy-mm-dd', pointer);
|
546 |
+
eo_occurrences_by_rule.push(formateddate);
|
547 |
+
}
|
548 |
+
}
|
549 |
+
return;
|
550 |
+
break;
|
551 |
+
|
552 |
+
default:
|
553 |
+
return;
|
554 |
+
break;
|
555 |
+
|
556 |
+
}
|
557 |
+
//End switch
|
558 |
+
//While in current month, and event has not finished - generate occurrences.
|
559 |
+
for (var x in streams) {
|
560 |
+
pointer = new Date(streams[x]);
|
561 |
+
while (pointer <= month_end && pointer <= end) {
|
562 |
+
formateddate = $.datepicker.formatDate('yy-mm-dd', pointer);
|
563 |
+
eo_occurrences_by_rule.push(formateddate);
|
564 |
+
pointer.setDate(pointer.getDate() + skip);
|
565 |
+
}
|
566 |
+
}
|
567 |
+
}
|
568 |
+
|
569 |
+
//When a date is selected, add or remove it based on current state
|
570 |
+
function eo_addOrRemoveDate(date, inst) {
|
571 |
+
|
572 |
+
var isEventful = eo_is_date_eventful(date);
|
573 |
+
if (isEventful[0]) {
|
574 |
+
//Date is eventful. Remove date
|
575 |
+
var index = isEventful[1];
|
576 |
+
if (index > -1) {
|
577 |
+
//Date was manually included
|
578 |
+
eo_removeDateFromInclude(index);
|
579 |
+
} else {
|
580 |
+
//Date was eventful by rule
|
581 |
+
eo_addDateToExclude(date);
|
582 |
+
}
|
583 |
+
} else {
|
584 |
+
//Date is not eventful. Add date
|
585 |
+
index = isEventful[1];
|
586 |
+
if (index > -1) {
|
587 |
+
//Date was manually excluded
|
588 |
+
eo_removeDateFromExclude(index);
|
589 |
+
} else {
|
590 |
+
//Date was not an event by rule
|
591 |
+
eo_addDateToInclude(date);
|
592 |
+
}
|
593 |
+
}
|
594 |
+
//Update inclusion, exclusion textareas
|
595 |
+
eo_update_inc_ex_Input();
|
596 |
+
}
|
597 |
+
|
598 |
+
// Add/remove dates from inclusion, exclusion arrays
|
599 |
+
function eo_addDateToInclude(date) {
|
600 |
+
if ($.inArray(date, eo_include_dates) < 0)
|
601 |
+
eo_include_dates.push(date);
|
602 |
+
}
|
603 |
+
function eo_removeDateFromInclude(index) {
|
604 |
+
eo_include_dates.splice(index, 1);
|
605 |
+
}
|
606 |
+
function eo_addDateToExclude(date) {
|
607 |
+
if ($.inArray(date, eo_exclude_dates) < 0)
|
608 |
+
eo_exclude_dates.push(date);
|
609 |
+
}
|
610 |
+
function eo_removeDateFromExclude(index) {
|
611 |
+
eo_exclude_dates.splice(index, 1);
|
612 |
+
}
|
613 |
+
|
614 |
+
var now = new Date();
|
615 |
+
eo_generate_dates_by_rule(now.getFullYear(), now.getMonth() + 1, {});
|
616 |
+
|
617 |
+
var dp = $('#eo_occurrence_datepicker');
|
618 |
+
if (dp.length > 0) {
|
619 |
+
dp.datepicker({
|
620 |
+
dateFormat: "yy-mm-dd",
|
621 |
+
onSelect: eo_addOrRemoveDate,
|
622 |
+
beforeShowDay: eo_pre_show_date,
|
623 |
+
onChangeMonthYear: eo_generate_dates_by_rule,
|
624 |
+
changeMonth: true,
|
625 |
+
changeYear: true,
|
626 |
+
monthNamesShort: EO_Ajax_Event.locale.monthAbbrev,
|
627 |
+
dayNamesMin: EO_Ajax_Event.locale.dayAbbrev,
|
628 |
+
firstDay: parseInt(EO_Ajax_Event.startday)
|
629 |
+
}).hide();
|
630 |
+
}
|
631 |
+
$('html').click(function() {
|
632 |
+
dp.hide();
|
633 |
+
});
|
634 |
+
dp.find('.ui-datepicker-inline').click(function(e) {
|
635 |
+
if (!e)
|
636 |
+
e = window.event;
|
637 |
+
e.cancelBubble = true;
|
638 |
+
if (e.stopPropagation)
|
639 |
+
e.stopPropagation();
|
640 |
+
});
|
641 |
+
});
|
642 |
+
|
643 |
+
/**
|
644 |
+
sprintf() for JavaScript 0.7-beta1
|
645 |
+
http://www.diveintojavascript.com/projects/javascript-sprintf
|
646 |
+
|
647 |
+
Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
|
648 |
+
All rights reserved.
|
649 |
+
|
650 |
+
Redistribution and use in source and binary forms, with or without
|
651 |
+
modification, are permitted provided that the following conditions are met:
|
652 |
+
* Redistributions of source code must retain the above copyright
|
653 |
+
notice, this list of conditions and the following disclaimer.
|
654 |
+
* Redistributions in binary form must reproduce the above copyright
|
655 |
+
notice, this list of conditions and the following disclaimer in the
|
656 |
+
documentation and/or other materials provided with the distribution.
|
657 |
+
* Neither the name of sprintf() for JavaScript nor the
|
658 |
+
names of its contributors may be used to endorse or promote products
|
659 |
+
derived from this software without specific prior written permission.
|
660 |
+
|
661 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
662 |
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
663 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
664 |
+
DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY
|
665 |
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
666 |
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
667 |
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
668 |
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
669 |
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
670 |
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
671 |
+
|
672 |
+
|
673 |
+
Changelog:
|
674 |
+
2010.09.06 - 0.7-beta1
|
675 |
+
- features: vsprintf, support for named placeholders
|
676 |
+
- enhancements: format cache, reduced global namespace pollution
|
677 |
+
|
678 |
+
2010.05.22 - 0.6:
|
679 |
+
- reverted to 0.4 and fixed the bug regarding the sign of the number 0
|
680 |
+
Note:
|
681 |
+
Thanks to Raphael Pigulla <raph (at] n3rd [dot) org> (http://www.n3rd.org/)
|
682 |
+
who warned me about a bug in 0.5, I discovered that the last update was
|
683 |
+
a regress. I appologize for that.
|
684 |
+
|
685 |
+
2010.05.09 - 0.5:
|
686 |
+
- bug fix: 0 is now preceeded with a + sign
|
687 |
+
- bug fix: the sign was not at the right position on padded results (Kamal Abdali)
|
688 |
+
- switched from GPL to BSD license
|
689 |
+
|
690 |
+
2007.10.21 - 0.4:
|
691 |
+
- unit test and patch (David Baird)
|
692 |
+
|
693 |
+
2007.09.17 - 0.3:
|
694 |
+
- bug fix: no longer throws exception on empty paramenters (Hans Pufal)
|
695 |
+
|
696 |
+
2007.09.11 - 0.2:
|
697 |
+
- feature: added argument swapping
|
698 |
+
|
699 |
+
2007.04.03 - 0.1:
|
700 |
+
- initial release
|
701 |
+
**/
|
702 |
+
|
703 |
+
var sprintf = (function() {
|
704 |
+
function get_type(variable) {
|
705 |
+
return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
|
706 |
+
}
|
707 |
+
function str_repeat(input, multiplier) {
|
708 |
+
for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
|
709 |
+
return output.join('');
|
710 |
+
}
|
711 |
+
|
712 |
+
var str_format = function() {
|
713 |
+
if (!str_format.cache.hasOwnProperty(arguments[0])) {
|
714 |
+
str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
|
715 |
+
}
|
716 |
+
return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
|
717 |
+
};
|
718 |
+
|
719 |
+
str_format.format = function(parse_tree, argv) {
|
720 |
+
var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
|
721 |
+
for (i = 0; i < tree_length; i++) {
|
722 |
+
node_type = get_type(parse_tree[i]);
|
723 |
+
if (node_type === 'string') {
|
724 |
+
output.push(parse_tree[i]);
|
725 |
+
}
|
726 |
+
else if (node_type === 'array') {
|
727 |
+
match = parse_tree[i]; // convenience purposes only
|
728 |
+
if (match[2]) { // keyword argument
|
729 |
+
arg = argv[cursor];
|
730 |
+
for (k = 0; k < match[2].length; k++) {
|
731 |
+
if (!arg.hasOwnProperty(match[2][k])) {
|
732 |
+
throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
|
733 |
+
}
|
734 |
+
arg = arg[match[2][k]];
|
735 |
+
}
|
736 |
+
}
|
737 |
+
else if (match[1]) { // positional argument (explicit)
|
738 |
+
arg = argv[match[1]];
|
739 |
+
}
|
740 |
+
else { // positional argument (implicit)
|
741 |
+
arg = argv[cursor++];
|
742 |
+
}
|
743 |
+
|
744 |
+
if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
|
745 |
+
throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
|
746 |
+
}
|
747 |
+
switch (match[8]) {
|
748 |
+
case 'b': arg = arg.toString(2); break;
|
749 |
+
case 'c': arg = String.fromCharCode(arg); break;
|
750 |
+
case 'd': arg = parseInt(arg, 10); break;
|
751 |
+
case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
|
752 |
+
case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
|
753 |
+
case 'o': arg = arg.toString(8); break;
|
754 |
+
case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
|
755 |
+
case 'u': arg = Math.abs(arg); break;
|
756 |
+
case 'x': arg = arg.toString(16); break;
|
757 |
+
case 'X': arg = arg.toString(16).toUpperCase(); break;
|
758 |
+
}
|
759 |
+
arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
|
760 |
+
pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
|
761 |
+
pad_length = match[6] - String(arg).length;
|
762 |
+
pad = match[6] ? str_repeat(pad_character, pad_length) : '';
|
763 |
+
output.push(match[5] ? arg + pad : pad + arg);
|
764 |
+
}
|
765 |
+
}
|
766 |
+
return output.join('');
|
767 |
+
};
|
768 |
+
|
769 |
+
str_format.cache = {};
|
770 |
+
|
771 |
+
str_format.parse = function(fmt) {
|
772 |
+
var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
|
773 |
+
while (_fmt) {
|
774 |
+
if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
|
775 |
+
parse_tree.push(match[0]);
|
776 |
+
}
|
777 |
+
else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
|
778 |
+
parse_tree.push('%');
|
779 |
+
}
|
780 |
+
else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
|
781 |
+
if (match[2]) {
|
782 |
+
arg_names |= 1;
|
783 |
+
var field_list = [], replacement_field = match[2], field_match = [];
|
784 |
+
if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
|
785 |
+
field_list.push(field_match[1]);
|
786 |
+
while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
|
787 |
+
if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
|
788 |
+
field_list.push(field_match[1]);
|
789 |
+
}
|
790 |
+
else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
|
791 |
+
field_list.push(field_match[1]);
|
792 |
+
}
|
793 |
+
else {
|
794 |
+
throw('[sprintf] huh?');
|
795 |
+
}
|
796 |
+
}
|
797 |
+
}
|
798 |
+
else {
|
799 |
+
throw('[sprintf] huh?');
|
800 |
+
}
|
801 |
+
match[2] = field_list;
|
802 |
+
}
|
803 |
+
else {
|
804 |
+
arg_names |= 2;
|
805 |
+
}
|
806 |
+
if (arg_names === 3) {
|
807 |
+
throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
|
808 |
+
}
|
809 |
+
parse_tree.push(match);
|
810 |
+
}
|
811 |
+
else {
|
812 |
+
throw('[sprintf] huh?');
|
813 |
+
}
|
814 |
+
_fmt = _fmt.substring(match[0].length);
|
815 |
+
}
|
816 |
+
return parse_tree;
|
817 |
+
};
|
818 |
+
|
819 |
+
return str_format;
|
820 |
+
})();
|
821 |
+
|
822 |
+
var vsprintf = function(fmt, argv) {
|
823 |
+
argv.unshift(fmt);
|
824 |
+
return sprintf.apply(null, argv);
|
825 |
+
};
|
826 |
+
|
827 |
+
/*
|
828 |
+
* jQuery UI Timepicker 0.3.1
|
829 |
+
*
|
830 |
+
* Copyright 2010-2011, Francois Gelinas
|
831 |
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
832 |
+
* http://jquery.org/license
|
833 |
+
*
|
834 |
+
* http://fgelinas.com/code/timepicker
|
835 |
+
*
|
836 |
+
* Depends:
|
837 |
+
* jquery.ui.core.js
|
838 |
+
* jquery.ui.position.js (only if position settngs are used)
|
839 |
+
*
|
840 |
+
* Change version 0.1.0 - moved the t-rex up here
|
841 |
+
*
|
842 |
+
*/
|
843 |
+
|
844 |
+
(function ($) {
|
845 |
+
|
846 |
+
$.extend($.ui, { timepicker: { version: "0.3.1"} });
|
847 |
+
|
848 |
+
var PROP_NAME = 'timepicker',
|
849 |
+
tpuuid = new Date().getTime();
|
850 |
+
|
851 |
+
/**
|
852 |
+
* Time picker manager.
|
853 |
+
* Use the singleton instance of this class, $.timepicker, to interact with the time picker.
|
854 |
+
* Settings for (groups of) time pickers are maintained in an instance object,
|
855 |
+
* allowing multiple different settings on the same page.
|
856 |
+
* @constructor
|
857 |
+
*/
|
858 |
+
|
859 |
+
function Timepicker() {
|
860 |
+
this._curInst = null; // The current instance in use
|
861 |
+
this._disabledInputs = []; // List of time picker inputs that have been disabled
|
862 |
+
this._timepickerShowing = false; // True if the popup picker is showing , false if not
|
863 |
+
this._inDialog = false; // True if showing within a "dialog", false if not
|
864 |
+
this._dialogClass = 'ui-timepicker-dialog'; // The name of the dialog marker class
|
865 |
+
this._mainDivId = 'ui-timepicker-div'; // The ID of the main timepicker division
|
866 |
+
this._inlineClass = 'ui-timepicker-inline'; // The name of the inline marker class
|
867 |
+
this._currentClass = 'ui-timepicker-current'; // The name of the current hour / minutes marker class
|
868 |
+
this._dayOverClass = 'ui-timepicker-days-cell-over'; // The name of the day hover marker class
|
869 |
+
|
870 |
+
this.regional = []; // Available regional settings, indexed by language code
|
871 |
+
this.regional[''] = { // Default regional settings
|
872 |
+
hourText: 'Hour', // Display text for hours section
|
873 |
+
minuteText: 'Minute', // Display text for minutes link
|
874 |
+
amPmText: ['AM', 'PM'], // Display text for AM PM
|
875 |
+
closeButtonText: 'Done', // Text for the confirmation button (ok button)
|
876 |
+
nowButtonText: 'Now', // Text for the now button
|
877 |
+
deselectButtonText: 'Deselect' // Text for the deselect button
|
878 |
+
};
|
879 |
+
this._defaults = { // Global defaults for all the time picker instances
|
880 |
+
showOn: 'focus', // 'focus' for popup on focus,
|
881 |
+
// 'button' for trigger button, or 'both' for either (not yet implemented)
|
882 |
+
button: null, // 'button' element that will trigger the timepicker
|
883 |
+
showAnim: 'fadeIn', // Name of jQuery animation for popup
|
884 |
+
showOptions: {}, // Options for enhanced animations
|
885 |
+
appendText: '', // Display text following the input box, e.g. showing the format
|
886 |
+
|
887 |
+
beforeShow: null, // Define a callback function executed before the timepicker is shown
|
888 |
+
onSelect: null, // Define a callback function when a hour / minutes is selected
|
889 |
+
onClose: null, // Define a callback function when the timepicker is closed
|
890 |
+
|
891 |
+
timeSeparator: ':', // The character to use to separate hours and minutes.
|
892 |
+
periodSeparator: ' ', // The character to use to separate the time from the time period.
|
893 |
+
showPeriod: false, // Define whether or not to show AM/PM with selected time
|
894 |
+
showPeriodLabels: true, // Show the AM/PM labels on the left of the time picker
|
895 |
+
showLeadingZero: true, // Define whether or not to show a leading zero for hours < 10. [true/false]
|
896 |
+
showMinutesLeadingZero: true, // Define whether or not to show a leading zero for minutes < 10.
|
897 |
+
altField: '', // Selector for an alternate field to store selected time into
|
898 |
+
defaultTime: 'now', // Used as default time when input field is empty or for inline timePicker
|
899 |
+
// (set to 'now' for the current time, '' for no highlighted time)
|
900 |
+
myPosition: 'left top', // Position of the dialog relative to the input.
|
901 |
+
// see the position utility for more info : http://jqueryui.com/demos/position/
|
902 |
+
atPosition: 'left bottom', // Position of the input element to match
|
903 |
+
// Note : if the position utility is not loaded, the timepicker will attach left top to left bottom
|
904 |
+
//NEW: 2011-02-03
|
905 |
+
onHourShow: null, // callback for enabling / disabling on selectable hours ex : function(hour) { return true; }
|
906 |
+
onMinuteShow: null, // callback for enabling / disabling on time selection ex : function(hour,minute) { return true; }
|
907 |
+
|
908 |
+
hours: {
|
909 |
+
starts: 0, // first displayed hour
|
910 |
+
ends: 23 // last displayed hour
|
911 |
+
},
|
912 |
+
minutes: {
|
913 |
+
starts: 0, // first displayed minute
|
914 |
+
ends: 55, // last displayed minute
|
915 |
+
interval: 5 // interval of displayed minutes
|
916 |
+
},
|
917 |
+
rows: 4, // number of rows for the input tables, minimum 2, makes more sense if you use multiple of 2
|
918 |
+
// 2011-08-05 0.2.4
|
919 |
+
showHours: true, // display the hours section of the dialog
|
920 |
+
showMinutes: true, // display the minute section of the dialog
|
921 |
+
optionalMinutes: false, // optionally parse inputs of whole hours with minutes omitted
|
922 |
+
|
923 |
+
// buttons
|
924 |
+
showCloseButton: false, // shows an OK button to confirm the edit
|
925 |
+
showNowButton: false, // Shows the 'now' button
|
926 |
+
showDeselectButton: false // Shows the deselect time button
|
927 |
+
|
928 |
+
};
|
929 |
+
$.extend(this._defaults, this.regional['']);
|
930 |
+
|
931 |
+
this.tpDiv = $('<div id="' + this._mainDivId + '" class="ui-timepicker ui-widget ui-helper-clearfix ui-corner-all " style="display: none"></div>');
|
932 |
+
}
|
933 |
+
|
934 |
+
$.extend(Timepicker.prototype, {
|
935 |
+
/* Class name added to elements to indicate already configured with a time picker. */
|
936 |
+
markerClassName: 'hasTimepicker',
|
937 |
+
|
938 |
+
/* Debug logging (if enabled). */
|
939 |
+
log: function () {
|
940 |
+
},
|
941 |
+
|
942 |
+
_widgetTimepicker: function () {
|
943 |
+
return this.tpDiv;
|
944 |
+
},
|
945 |
+
|
946 |
+
/* Override the default settings for all instances of the time picker.
|
947 |
+
@param settings object - the new settings to use as defaults (anonymous object)
|
948 |
+
@return the manager object */
|
949 |
+
setDefaults: function (settings) {
|
950 |
+
extendRemove(this._defaults, settings || {});
|
951 |
+
return this;
|
952 |
+
},
|
953 |
+
|
954 |
+
/* Attach the time picker to a jQuery selection.
|
955 |
+
@param target element - the target input field or division or span
|
956 |
+
@param settings object - the new settings to use for this time picker instance (anonymous) */
|
957 |
+
_attachTimepicker: function (target, settings) {
|
958 |
+
// check for settings on the control itself - in namespace 'time:'
|
959 |
+
var inlineSettings = null;
|
960 |
+
for (var attrName in this._defaults) {
|
961 |
+
var attrValue = target.getAttribute('time:' + attrName);
|
962 |
+
if (attrValue) {
|
963 |
+
inlineSettings = inlineSettings || {};
|
964 |
+
try {
|
965 |
+
inlineSettings[attrName] = eval(attrValue);
|
966 |
+
} catch (err) {
|
967 |
+
inlineSettings[attrName] = attrValue;
|
968 |
+
}
|
969 |
+
}
|
970 |
+
}
|
971 |
+
var nodeName = target.nodeName.toLowerCase();
|
972 |
+
var inline = (nodeName == 'div' || nodeName == 'span');
|
973 |
+
|
974 |
+
if (!target.id) {
|
975 |
+
this.uuid += 1;
|
976 |
+
target.id = 'tp' + this.uuid;
|
977 |
+
}
|
978 |
+
var inst = this._newInst($(target), inline);
|
979 |
+
inst.settings = $.extend({}, settings || {}, inlineSettings || {});
|
980 |
+
if (nodeName == 'input') {
|
981 |
+
this._connectTimepicker(target, inst);
|
982 |
+
// init inst.hours and inst.minutes from the input value
|
983 |
+
this._setTimeFromField(inst);
|
984 |
+
} else if (inline) {
|
985 |
+
this._inlineTimepicker(target, inst);
|
986 |
+
}
|
987 |
+
|
988 |
+
|
989 |
+
},
|
990 |
+
|
991 |
+
/* Create a new instance object. */
|
992 |
+
_newInst: function (target, inline) {
|
993 |
+
var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
|
994 |
+
return {
|
995 |
+
id: id, input: target, // associated target
|
996 |
+
inline: inline, // is timepicker inline or not :
|
997 |
+
tpDiv: (!inline ? this.tpDiv : // presentation div
|
998 |
+
$('<div class="' + this._inlineClass + ' ui-timepicker ui-widget ui-helper-clearfix"></div>'))
|
999 |
+
};
|
1000 |
+
},
|
1001 |
+
|
1002 |
+
/* Attach the time picker to an input field. */
|
1003 |
+
_connectTimepicker: function (target, inst) {
|
1004 |
+
var input = $(target);
|
1005 |
+
inst.append = $([]);
|
1006 |
+
inst.trigger = $([]);
|
1007 |
+
if (input.hasClass(this.markerClassName)) { return; }
|
1008 |
+
this._attachments(input, inst);
|
1009 |
+
input.addClass(this.markerClassName).
|
1010 |
+
keydown(this._doKeyDown).
|
1011 |
+
keyup(this._doKeyUp).
|
1012 |
+
bind("setData.timepicker", function (event, key, value) {
|
1013 |
+
inst.settings[key] = value;
|
1014 |
+
}).
|
1015 |
+
bind("getData.timepicker", function (event, key) {
|
1016 |
+
return this._get(inst, key);
|
1017 |
+
});
|
1018 |
+
$.data(target, PROP_NAME, inst);
|
1019 |
+
},
|
1020 |
+
|
1021 |
+
/* Handle keystrokes. */
|
1022 |
+
_doKeyDown: function (event) {
|
1023 |
+
var inst = $.timepicker._getInst(event.target);
|
1024 |
+
var handled = true;
|
1025 |
+
inst._keyEvent = true;
|
1026 |
+
if ($.timepicker._timepickerShowing) {
|
1027 |
+
switch (event.keyCode) {
|
1028 |
+
case 9: $.timepicker._hideTimepicker();
|
1029 |
+
handled = false;
|
1030 |
+
break; // hide on tab out
|
1031 |
+
case 13:
|
1032 |
+
$.timepicker._updateSelectedValue(inst);
|
1033 |
+
$.timepicker._hideTimepicker();
|
1034 |
+
|
1035 |
+
return false; // don't submit the form
|
1036 |
+
break; // select the value on enter
|
1037 |
+
case 27: $.timepicker._hideTimepicker();
|
1038 |
+
break; // hide on escape
|
1039 |
+
default: handled = false;
|
1040 |
+
}
|
1041 |
+
}
|
1042 |
+
else if (event.keyCode == 36 && event.ctrlKey) { // display the time picker on ctrl+home
|
1043 |
+
$.timepicker._showTimepicker(this);
|
1044 |
+
}
|
1045 |
+
else {
|
1046 |
+
handled = false;
|
1047 |
+
}
|
1048 |
+
if (handled) {
|
1049 |
+
event.preventDefault();
|
1050 |
+
event.stopPropagation();
|
1051 |
+
}
|
1052 |
+
},
|
1053 |
+
|
1054 |
+
/* Update selected time on keyUp */
|
1055 |
+
/* Added verion 0.0.5 */
|
1056 |
+
_doKeyUp: function (event) {
|
1057 |
+
var inst = $.timepicker._getInst(event.target);
|
1058 |
+
$.timepicker._setTimeFromField(inst);
|
1059 |
+
$.timepicker._updateTimepicker(inst);
|
1060 |
+
},
|
1061 |
+
|
1062 |
+
/* Make attachments based on settings. */
|
1063 |
+
_attachments: function (input, inst) {
|
1064 |
+
var appendText = this._get(inst, 'appendText');
|
1065 |
+
var isRTL = this._get(inst, 'isRTL');
|
1066 |
+
if (inst.append) { inst.append.remove(); }
|
1067 |
+
if (appendText) {
|
1068 |
+
inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
|
1069 |
+
input[isRTL ? 'before' : 'after'](inst.append);
|
1070 |
+
}
|
1071 |
+
input.unbind('focus.timepicker', this._showTimepicker);
|
1072 |
+
input.unbind('click.timepicker', this._adjustZIndex);
|
1073 |
+
|
1074 |
+
if (inst.trigger) { inst.trigger.remove(); }
|
1075 |
+
|
1076 |
+
var showOn = this._get(inst, 'showOn');
|
1077 |
+
if (showOn == 'focus' || showOn == 'both') { // pop-up time picker when in the marked field
|
1078 |
+
input.bind("focus.timepicker", this._showTimepicker);
|
1079 |
+
input.bind("click.timepicker", this._adjustZIndex);
|
1080 |
+
}
|
1081 |
+
if (showOn == 'button' || showOn == 'both') { // pop-up time picker when 'button' element is clicked
|
1082 |
+
var button = this._get(inst, 'button');
|
1083 |
+
$(button).bind("click.timepicker", function () {
|
1084 |
+
if ($.timepicker._timepickerShowing && $.timepicker._lastInput == input[0]) {
|
1085 |
+
$.timepicker._hideTimepicker();
|
1086 |
+
} else if (!inst.input.is(':disabled')) {
|
1087 |
+
$.timepicker._showTimepicker(input[0]);
|
1088 |
+
}
|
1089 |
+
return false;
|
1090 |
+
});
|
1091 |
+
|
1092 |
+
}
|
1093 |
+
},
|
1094 |
+
|
1095 |
+
|
1096 |
+
/* Attach an inline time picker to a div. */
|
1097 |
+
_inlineTimepicker: function(target, inst) {
|
1098 |
+
var divSpan = $(target);
|
1099 |
+
if (divSpan.hasClass(this.markerClassName))
|
1100 |
+
return;
|
1101 |
+
divSpan.addClass(this.markerClassName).append(inst.tpDiv).
|
1102 |
+
bind("setData.timepicker", function(event, key, value){
|
1103 |
+
inst.settings[key] = value;
|
1104 |
+
}).bind("getData.timepicker", function(event, key){
|
1105 |
+
return this._get(inst, key);
|
1106 |
+
});
|
1107 |
+
$.data(target, PROP_NAME, inst);
|
1108 |
+
|
1109 |
+
this._setTimeFromField(inst);
|
1110 |
+
this._updateTimepicker(inst);
|
1111 |
+
inst.tpDiv.show();
|
1112 |
+
},
|
1113 |
+
|
1114 |
+
_adjustZIndex: function(input) {
|
1115 |
+
input = input.target || input;
|
1116 |
+
var inst = $.timepicker._getInst(input);
|
1117 |
+
inst.tpDiv.css('zIndex', $.timepicker._getZIndex(input) +1);
|
1118 |
+
},
|
1119 |
+
|
1120 |
+
/* Pop-up the time picker for a given input field.
|
1121 |
+
@param input element - the input field attached to the time picker or
|
1122 |
+
event - if triggered by focus */
|
1123 |
+
_showTimepicker: function (input) {
|
1124 |
+
input = input.target || input;
|
1125 |
+
if (input.nodeName.toLowerCase() != 'input') { input = $('input', input.parentNode)[0]; } // find from button/image trigger
|
1126 |
+
|
1127 |
+
if ($.timepicker._isDisabledTimepicker(input) || $.timepicker._lastInput == input) { return; } // already here
|
1128 |
+
|
1129 |
+
// fix v 0.0.8 - close current timepicker before showing another one
|
1130 |
+
$.timepicker._hideTimepicker();
|
1131 |
+
|
1132 |
+
var inst = $.timepicker._getInst(input);
|
1133 |
+
if ($.timepicker._curInst && $.timepicker._curInst != inst) {
|
1134 |
+
$.timepicker._curInst.tpDiv.stop(true, true);
|
1135 |
+
}
|
1136 |
+
var beforeShow = $.timepicker._get(inst, 'beforeShow');
|
1137 |
+
extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
|
1138 |
+
inst.lastVal = null;
|
1139 |
+
$.timepicker._lastInput = input;
|
1140 |
+
|
1141 |
+
$.timepicker._setTimeFromField(inst);
|
1142 |
+
|
1143 |
+
// calculate default position
|
1144 |
+
if ($.timepicker._inDialog) { input.value = ''; } // hide cursor
|
1145 |
+
if (!$.timepicker._pos) { // position below input
|
1146 |
+
$.timepicker._pos = $.timepicker._findPos(input);
|
1147 |
+
$.timepicker._pos[1] += input.offsetHeight; // add the height
|
1148 |
+
}
|
1149 |
+
var isFixed = false;
|
1150 |
+
$(input).parents().each(function () {
|
1151 |
+
isFixed |= $(this).css('position') == 'fixed';
|
1152 |
+
return !isFixed;
|
1153 |
+
});
|
1154 |
+
if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
|
1155 |
+
$.timepicker._pos[0] -= document.documentElement.scrollLeft;
|
1156 |
+
$.timepicker._pos[1] -= document.documentElement.scrollTop;
|
1157 |
+
}
|
1158 |
+
|
1159 |
+
var offset = { left: $.timepicker._pos[0], top: $.timepicker._pos[1] };
|
1160 |
+
|
1161 |
+
$.timepicker._pos = null;
|
1162 |
+
// determine sizing offscreen
|
1163 |
+
inst.tpDiv.css({ position: 'absolute', display: 'block', top: '-1000px' });
|
1164 |
+
$.timepicker._updateTimepicker(inst);
|
1165 |
+
|
1166 |
+
|
1167 |
+
// position with the ui position utility, if loaded
|
1168 |
+
if ( ( ! inst.inline ) && ( typeof $.ui.position == 'object' ) ) {
|
1169 |
+
inst.tpDiv.position({
|
1170 |
+
of: inst.input,
|
1171 |
+
my: $.timepicker._get( inst, 'myPosition' ),
|
1172 |
+
at: $.timepicker._get( inst, 'atPosition' ),
|
1173 |
+
// offset: $( "#offset" ).val(),
|
1174 |
+
// using: using,
|
1175 |
+
collision: 'flip'
|
1176 |
+
});
|
1177 |
+
offset = inst.tpDiv.offset();
|
1178 |
+
$.timepicker._pos = [offset.top, offset.left];
|
1179 |
+
}
|
1180 |
+
|
1181 |
+
|
1182 |
+
// reset clicked state
|
1183 |
+
inst._hoursClicked = false;
|
1184 |
+
inst._minutesClicked = false;
|
1185 |
+
|
1186 |
+
// fix width for dynamic number of time pickers
|
1187 |
+
// and adjust position before showing
|
1188 |
+
offset = $.timepicker._checkOffset(inst, offset, isFixed);
|
1189 |
+
inst.tpDiv.css({ position: ($.timepicker._inDialog && $.blockUI ?
|
1190 |
+
'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
|
1191 |
+
left: offset.left + 'px', top: offset.top + 'px'
|
1192 |
+
});
|
1193 |
+
if ( ! inst.inline ) {
|
1194 |
+
var showAnim = $.timepicker._get(inst, 'showAnim');
|
1195 |
+
var duration = $.timepicker._get(inst, 'duration');
|
1196 |
+
|
1197 |
+
var postProcess = function () {
|
1198 |
+
$.timepicker._timepickerShowing = true;
|
1199 |
+
var borders = $.timepicker._getBorders(inst.tpDiv);
|
1200 |
+
inst.tpDiv.find('iframe.ui-timepicker-cover'). // IE6- only
|
1201 |
+
css({ left: -borders[0], top: -borders[1],
|
1202 |
+
width: inst.tpDiv.outerWidth(), height: inst.tpDiv.outerHeight()
|
1203 |
+
});
|
1204 |
+
};
|
1205 |
+
|
1206 |
+
// Fixed the zIndex problem for real (I hope) - FG - v 0.2.9
|
1207 |
+
$.timepicker._adjustZIndex(input);
|
1208 |
+
//inst.tpDiv.css('zIndex', $.timepicker._getZIndex(input) +1);
|
1209 |
+
|
1210 |
+
if ($.effects && $.effects[showAnim]) {
|
1211 |
+
inst.tpDiv.show(showAnim, $.timepicker._get(inst, 'showOptions'), duration, postProcess);
|
1212 |
+
}
|
1213 |
+
else {
|
1214 |
+
inst.tpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
|
1215 |
+
}
|
1216 |
+
if (!showAnim || !duration) { postProcess(); }
|
1217 |
+
if (inst.input.is(':visible') && !inst.input.is(':disabled')) { inst.input.focus(); }
|
1218 |
+
$.timepicker._curInst = inst;
|
1219 |
+
}
|
1220 |
+
},
|
1221 |
+
|
1222 |
+
// This is a copy of the zIndex function of UI core 1.8.??
|
1223 |
+
// Copied in the timepicker to stay backward compatible.
|
1224 |
+
_getZIndex: function (target) {
|
1225 |
+
var elem = $( target ), position, value;
|
1226 |
+
while ( elem.length && elem[ 0 ] !== document ) {
|
1227 |
+
position = elem.css( "position" );
|
1228 |
+
if ( position === "absolute" || position === "relative" || position === "fixed" ) {
|
1229 |
+
value = parseInt( elem.css( "zIndex" ), 10 );
|
1230 |
+
if ( !isNaN( value ) && value !== 0 ) {
|
1231 |
+
return value;
|
1232 |
+
}
|
1233 |
+
}
|
1234 |
+
elem = elem.parent();
|
1235 |
+
}
|
1236 |
+
},
|
1237 |
+
|
1238 |
+
/* Refresh the time picker
|
1239 |
+
@param target element - The target input field or inline container element. */
|
1240 |
+
_refreshTimepicker: function(target) {
|
1241 |
+
var inst = this._getInst(target);
|
1242 |
+
if (inst) {
|
1243 |
+
this._updateTimepicker(inst);
|
1244 |
+
}
|
1245 |
+
},
|
1246 |
+
|
1247 |
+
|
1248 |
+
/* Generate the time picker content. */
|
1249 |
+
_updateTimepicker: function (inst) {
|
1250 |
+
inst.tpDiv.empty().append(this._generateHTML(inst));
|
1251 |
+
this._rebindDialogEvents(inst);
|
1252 |
+
|
1253 |
+
},
|
1254 |
+
|
1255 |
+
_rebindDialogEvents: function (inst) {
|
1256 |
+
var borders = $.timepicker._getBorders(inst.tpDiv),
|
1257 |
+
self = this;
|
1258 |
+
inst.tpDiv
|
1259 |
+
.find('iframe.ui-timepicker-cover') // IE6- only
|
1260 |
+
.css({ left: -borders[0], top: -borders[1],
|
1261 |
+
width: inst.tpDiv.outerWidth(), height: inst.tpDiv.outerHeight()
|
1262 |
+
})
|
1263 |
+
.end()
|
1264 |
+
// after the picker html is appended bind the click & double click events (faster in IE this way
|
1265 |
+
// then letting the browser interpret the inline events)
|
1266 |
+
// the binding for the minute cells also exists in _updateMinuteDisplay
|
1267 |
+
.find('.ui-timepicker-minute-cell')
|
1268 |
+
.unbind()
|
1269 |
+
.bind("click", { fromDoubleClick:false }, $.proxy($.timepicker.selectMinutes, this))
|
1270 |
+
.bind("dblclick", { fromDoubleClick:true }, $.proxy($.timepicker.selectMinutes, this))
|
1271 |
+
.end()
|
1272 |
+
.find('.ui-timepicker-hour-cell')
|
1273 |
+
.unbind()
|
1274 |
+
.bind("click", { fromDoubleClick:false }, $.proxy($.timepicker.selectHours, this))
|
1275 |
+
.bind("dblclick", { fromDoubleClick:true }, $.proxy($.timepicker.selectHours, this))
|
1276 |
+
.end()
|
1277 |
+
.find('.ui-timepicker td a')
|
1278 |
+
.unbind()
|
1279 |
+
.bind('mouseout', function () {
|
1280 |
+
$(this).removeClass('ui-state-hover');
|
1281 |
+
if (this.className.indexOf('ui-timepicker-prev') != -1) $(this).removeClass('ui-timepicker-prev-hover');
|
1282 |
+
if (this.className.indexOf('ui-timepicker-next') != -1) $(this).removeClass('ui-timepicker-next-hover');
|
1283 |
+
})
|
1284 |
+
.bind('mouseover', function () {
|
1285 |
+
if ( ! self._isDisabledTimepicker(inst.inline ? inst.tpDiv.parent()[0] : inst.input[0])) {
|
1286 |
+
$(this).parents('.ui-timepicker-calendar').find('a').removeClass('ui-state-hover');
|
1287 |
+
$(this).addClass('ui-state-hover');
|
1288 |
+
if (this.className.indexOf('ui-timepicker-prev') != -1) $(this).addClass('ui-timepicker-prev-hover');
|
1289 |
+
if (this.className.indexOf('ui-timepicker-next') != -1) $(this).addClass('ui-timepicker-next-hover');
|
1290 |
+
}
|
1291 |
+
})
|
1292 |
+
.end()
|
1293 |
+
.find('.' + this._dayOverClass + ' a')
|
1294 |
+
.trigger('mouseover')
|
1295 |
+
.end()
|
1296 |
+
.find('.ui-timepicker-now').bind("click", function(e) {
|
1297 |
+
$.timepicker.selectNow(e);
|
1298 |
+
}).end()
|
1299 |
+
.find('.ui-timepicker-deselect').bind("click",function(e) {
|
1300 |
+
$.timepicker.deselectTime(e);
|
1301 |
+
}).end()
|
1302 |
+
.find('.ui-timepicker-close').bind("click",function(e) {
|
1303 |
+
$.timepicker._hideTimepicker();
|
1304 |
+
}).end();
|
1305 |
+
},
|
1306 |
+
|
1307 |
+
/* Generate the HTML for the current state of the time picker. */
|
1308 |
+
_generateHTML: function (inst) {
|
1309 |
+
|
1310 |
+
var h, m, row, col, html, hoursHtml, minutesHtml = '',
|
1311 |
+
showPeriod = (this._get(inst, 'showPeriod') == true),
|
1312 |
+
showPeriodLabels = (this._get(inst, 'showPeriodLabels') == true),
|
1313 |
+
showLeadingZero = (this._get(inst, 'showLeadingZero') == true),
|
1314 |
+
showHours = (this._get(inst, 'showHours') == true),
|
1315 |
+
showMinutes = (this._get(inst, 'showMinutes') == true),
|
1316 |
+
amPmText = this._get(inst, 'amPmText'),
|
1317 |
+
rows = this._get(inst, 'rows'),
|
1318 |
+
amRows = 0,
|
1319 |
+
pmRows = 0,
|
1320 |
+
amItems = 0,
|
1321 |
+
pmItems = 0,
|
1322 |
+
amFirstRow = 0,
|
1323 |
+
pmFirstRow = 0,
|
1324 |
+
hours = Array(),
|
1325 |
+
hours_options = this._get(inst, 'hours'),
|
1326 |
+
hoursPerRow = null,
|
1327 |
+
hourCounter = 0,
|
1328 |
+
hourLabel = this._get(inst, 'hourText'),
|
1329 |
+
showCloseButton = this._get(inst, 'showCloseButton'),
|
1330 |
+
closeButtonText = this._get(inst, 'closeButtonText'),
|
1331 |
+
showNowButton = this._get(inst, 'showNowButton'),
|
1332 |
+
nowButtonText = this._get(inst, 'nowButtonText'),
|
1333 |
+
showDeselectButton = this._get(inst, 'showDeselectButton'),
|
1334 |
+
deselectButtonText = this._get(inst, 'deselectButtonText'),
|
1335 |
+
showButtonPanel = showCloseButton || showNowButton || showDeselectButton;
|
1336 |
+
|
1337 |
+
|
1338 |
+
|
1339 |
+
// prepare all hours and minutes, makes it easier to distribute by rows
|
1340 |
+
for (h = hours_options.starts; h <= hours_options.ends; h++) {
|
1341 |
+
hours.push (h);
|
1342 |
+
}
|
1343 |
+
hoursPerRow = Math.ceil(hours.length / rows); // always round up
|
1344 |
+
|
1345 |
+
if (showPeriodLabels) {
|
1346 |
+
for (hourCounter = 0; hourCounter < hours.length; hourCounter++) {
|
1347 |
+
if (hours[hourCounter] < 12) {
|
1348 |
+
amItems++;
|
1349 |
+
}
|
1350 |
+
else {
|
1351 |
+
pmItems++;
|
1352 |
+
}
|
1353 |
+
}
|
1354 |
+
hourCounter = 0;
|
1355 |
+
|
1356 |
+
amRows = Math.floor(amItems / hours.length * rows);
|
1357 |
+
pmRows = Math.floor(pmItems / hours.length * rows);
|
1358 |
+
|
1359 |
+
// assign the extra row to the period that is more densly populated
|
1360 |
+
if (rows != amRows + pmRows) {
|
1361 |
+
// Make sure: AM Has Items and either PM Does Not, AM has no rows yet, or AM is more dense
|
1362 |
+
if (amItems && (!pmItems || !amRows || (pmRows && amItems / amRows >= pmItems / pmRows))) {
|
1363 |
+
amRows++;
|
1364 |
+
} else {
|
1365 |
+
pmRows++;
|
1366 |
+
}
|
1367 |
+
}
|
1368 |
+
amFirstRow = Math.min(amRows, 1);
|
1369 |
+
pmFirstRow = amRows + 1;
|
1370 |
+
hoursPerRow = Math.ceil(Math.max(amItems / amRows, pmItems / pmRows));
|
1371 |
+
}
|
1372 |
+
|
1373 |
+
|
1374 |
+
html = '<table class="ui-timepicker-table ui-widget-content ui-corner-all"><tr>';
|
1375 |
+
|
1376 |
+
if (showHours) {
|
1377 |
+
|
1378 |
+
html += '<td class="ui-timepicker-hours">' +
|
1379 |
+
'<div class="ui-timepicker-title ui-widget-header ui-helper-clearfix ui-corner-all">' +
|
1380 |
+
hourLabel +
|
1381 |
+
'</div>' +
|
1382 |
+
'<table class="ui-timepicker">';
|
1383 |
+
|
1384 |
+
for (row = 1; row <= rows; row++) {
|
1385 |
+
html += '<tr>';
|
1386 |
+
// AM
|
1387 |
+
if (row == amFirstRow && showPeriodLabels) {
|
1388 |
+
html += '<th rowspan="' + amRows.toString() + '" class="periods" scope="row">' + amPmText[0] + '</th>';
|
1389 |
+
}
|
1390 |
+
// PM
|
1391 |
+
if (row == pmFirstRow && showPeriodLabels) {
|
1392 |
+
html += '<th rowspan="' + pmRows.toString() + '" class="periods" scope="row">' + amPmText[1] + '</th>';
|
1393 |
+
}
|
1394 |
+
for (col = 1; col <= hoursPerRow; col++) {
|
1395 |
+
if (showPeriodLabels && row < pmFirstRow && hours[hourCounter] >= 12) {
|
1396 |
+
html += this._generateHTMLHourCell(inst, undefined, showPeriod, showLeadingZero);
|
1397 |
+
} else {
|
1398 |
+
html += this._generateHTMLHourCell(inst, hours[hourCounter], showPeriod, showLeadingZero);
|
1399 |
+
hourCounter++;
|
1400 |
+
}
|
1401 |
+
}
|
1402 |
+
html += '</tr>';
|
1403 |
+
}
|
1404 |
+
html += '</tr></table>' + // Close the hours cells table
|
1405 |
+
'</td>'; // Close the Hour td
|
1406 |
+
}
|
1407 |
+
|
1408 |
+
if (showMinutes) {
|
1409 |
+
html += '<td class="ui-timepicker-minutes">';
|
1410 |
+
html += this._generateHTMLMinutes(inst);
|
1411 |
+
html += '</td>';
|
1412 |
+
}
|
1413 |
+
|
1414 |
+
html += '</tr>';
|
1415 |
+
|
1416 |
+
|
1417 |
+
if (showButtonPanel) {
|
1418 |
+
var buttonPanel = '<tr><td colspan="3"><div class="ui-timepicker-buttonpane ui-widget-content">';
|
1419 |
+
if (showNowButton) {
|
1420 |
+
buttonPanel += '<button type="button" class="ui-timepicker-now ui-state-default ui-corner-all" '
|
1421 |
+
+ ' data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" >'
|
1422 |
+
+ nowButtonText + '</button>';
|
1423 |
+
}
|
1424 |
+
if (showDeselectButton) {
|
1425 |
+
buttonPanel += '<button type="button" class="ui-timepicker-deselect ui-state-default ui-corner-all" '
|
1426 |
+
+ ' data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" >'
|
1427 |
+
+ deselectButtonText + '</button>';
|
1428 |
+
}
|
1429 |
+
if (showCloseButton) {
|
1430 |
+
buttonPanel += '<button type="button" class="ui-timepicker-close ui-state-default ui-corner-all" '
|
1431 |
+
+ ' data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" >'
|
1432 |
+
+ closeButtonText + '</button>';
|
1433 |
+
}
|
1434 |
+
|
1435 |
+
html += buttonPanel + '</div></td></tr>';
|
1436 |
+
}
|
1437 |
+
html += '</table>';
|
1438 |
+
|
1439 |
+
/* IE6 IFRAME FIX (taken from datepicker 1.5.3, fixed in 0.1.2 */
|
1440 |
+
html += ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
|
1441 |
+
'<iframe src="javascript:false;" class="ui-timepicker-cover" frameborder="0"></iframe>' : '');
|
1442 |
+
|
1443 |
+
return html;
|
1444 |
+
},
|
1445 |
+
|
1446 |
+
/* Special function that update the minutes selection in currently visible timepicker
|
1447 |
+
* called on hour selection when onMinuteShow is defined */
|
1448 |
+
_updateMinuteDisplay: function (inst) {
|
1449 |
+
var newHtml = this._generateHTMLMinutes(inst);
|
1450 |
+
inst.tpDiv.find('td.ui-timepicker-minutes').html(newHtml);
|
1451 |
+
this._rebindDialogEvents(inst);
|
1452 |
+
// after the picker html is appended bind the click & double click events (faster in IE this way
|
1453 |
+
// then letting the browser interpret the inline events)
|
1454 |
+
// yes I know, duplicate code, sorry
|
1455 |
+
/* .find('.ui-timepicker-minute-cell')
|
1456 |
+
.bind("click", { fromDoubleClick:false }, $.proxy($.timepicker.selectMinutes, this))
|
1457 |
+
.bind("dblclick", { fromDoubleClick:true }, $.proxy($.timepicker.selectMinutes, this));
|
1458 |
+
*/
|
1459 |
+
|
1460 |
+
},
|
1461 |
+
|
1462 |
+
/*
|
1463 |
+
* Generate the minutes table
|
1464 |
+
* This is separated from the _generateHTML function because is can be called separately (when hours changes)
|
1465 |
+
*/
|
1466 |
+
_generateHTMLMinutes: function (inst) {
|
1467 |
+
|
1468 |
+
var m, row, html = '',
|
1469 |
+
rows = this._get(inst, 'rows'),
|
1470 |
+
minutes = Array(),
|
1471 |
+
minutes_options = this._get(inst, 'minutes'),
|
1472 |
+
minutesPerRow = null,
|
1473 |
+
minuteCounter = 0,
|
1474 |
+
showMinutesLeadingZero = (this._get(inst, 'showMinutesLeadingZero') == true),
|
1475 |
+
onMinuteShow = this._get(inst, 'onMinuteShow'),
|
1476 |
+
minuteLabel = this._get(inst, 'minuteText');
|
1477 |
+
|
1478 |
+
if ( ! minutes_options.starts) {
|
1479 |
+
minutes_options.starts = 0;
|
1480 |
+
}
|
1481 |
+
if ( ! minutes_options.ends) {
|
1482 |
+
minutes_options.ends = 59;
|
1483 |
+
}
|
1484 |
+
for (m = minutes_options.starts; m <= minutes_options.ends; m += minutes_options.interval) {
|
1485 |
+
minutes.push(m);
|
1486 |
+
}
|
1487 |
+
minutesPerRow = Math.round(minutes.length / rows + 0.49); // always round up
|
1488 |
+
|
1489 |
+
/*
|
1490 |
+
* The minutes table
|
1491 |
+
*/
|
1492 |
+
// if currently selected minute is not enabled, we have a problem and need to select a new minute.
|
1493 |
+
if (onMinuteShow &&
|
1494 |
+
(onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours , inst.minutes]) == false) ) {
|
1495 |
+
// loop minutes and select first available
|
1496 |
+
for (minuteCounter = 0; minuteCounter < minutes.length; minuteCounter += 1) {
|
1497 |
+
m = minutes[minuteCounter];
|
1498 |
+
if (onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours, m])) {
|
1499 |
+
inst.minutes = m;
|
1500 |
+
break;
|
1501 |
+
}
|
1502 |
+
}
|
1503 |
+
}
|
1504 |
+
|
1505 |
+
|
1506 |
+
|
1507 |
+
html += '<div class="ui-timepicker-title ui-widget-header ui-helper-clearfix ui-corner-all">' +
|
1508 |
+
minuteLabel +
|
1509 |
+
'</div>' +
|
1510 |
+
'<table class="ui-timepicker">';
|
1511 |
+
|
1512 |
+
minuteCounter = 0;
|
1513 |
+
for (row = 1; row <= rows; row++) {
|
1514 |
+
html += '<tr>';
|
1515 |
+
while (minuteCounter < row * minutesPerRow) {
|
1516 |
+
m = minutes[minuteCounter];
|
1517 |
+
var displayText = '';
|
1518 |
+
if (m !== undefined ) {
|
1519 |
+
displayText = (m < 10) && showMinutesLeadingZero ? "0" + m.toString() : m.toString();
|
1520 |
+
}
|
1521 |
+
html += this._generateHTMLMinuteCell(inst, m, displayText);
|
1522 |
+
minuteCounter++;
|
1523 |
+
}
|
1524 |
+
html += '</tr>';
|
1525 |
+
}
|
1526 |
+
|
1527 |
+
html += '</table>';
|
1528 |
+
|
1529 |
+
return html;
|
1530 |
+
},
|
1531 |
+
|
1532 |
+
/* Generate the content of a "Hour" cell */
|
1533 |
+
_generateHTMLHourCell: function (inst, hour, showPeriod, showLeadingZero) {
|
1534 |
+
|
1535 |
+
var displayHour = hour;
|
1536 |
+
if ((hour > 12) && showPeriod) {
|
1537 |
+
displayHour = hour - 12;
|
1538 |
+
}
|
1539 |
+
if ((displayHour == 0) && showPeriod) {
|
1540 |
+
displayHour = 12;
|
1541 |
+
}
|
1542 |
+
if ((displayHour < 10) && showLeadingZero) {
|
1543 |
+
displayHour = '0' + displayHour;
|
1544 |
+
}
|
1545 |
+
|
1546 |
+
var html = "";
|
1547 |
+
var enabled = true;
|
1548 |
+
var onHourShow = this._get(inst, 'onHourShow'); //custom callback
|
1549 |
+
|
1550 |
+
if (hour == undefined) {
|
1551 |
+
html = '<td><span class="ui-state-default ui-state-disabled"> </span></td>';
|
1552 |
+
return html;
|
1553 |
+
}
|
1554 |
+
|
1555 |
+
if (onHourShow) {
|
1556 |
+
enabled = onHourShow.apply((inst.input ? inst.input[0] : null), [hour]);
|
1557 |
+
}
|
1558 |
+
|
1559 |
+
if (enabled) {
|
1560 |
+
html = '<td class="ui-timepicker-hour-cell" data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" data-hour="' + hour.toString() + '">' +
|
1561 |
+
'<a class="ui-state-default ' +
|
1562 |
+
(hour == inst.hours ? 'ui-state-active' : '') +
|
1563 |
+
'">' +
|
1564 |
+
displayHour.toString() +
|
1565 |
+
'</a></td>';
|
1566 |
+
}
|
1567 |
+
else {
|
1568 |
+
html =
|
1569 |
+
'<td>' +
|
1570 |
+
'<span class="ui-state-default ui-state-disabled ' +
|
1571 |
+
(hour == inst.hours ? ' ui-state-active ' : ' ') +
|
1572 |
+
'">' +
|
1573 |
+
displayHour.toString() +
|
1574 |
+
'</span>' +
|
1575 |
+
'</td>';
|
1576 |
+
}
|
1577 |
+
return html;
|
1578 |
+
},
|
1579 |
+
|
1580 |
+
/* Generate the content of a "Hour" cell */
|
1581 |
+
_generateHTMLMinuteCell: function (inst, minute, displayText) {
|
1582 |
+
var html = "";
|
1583 |
+
var enabled = true;
|
1584 |
+
var onMinuteShow = this._get(inst, 'onMinuteShow'); //custom callback
|
1585 |
+
if (onMinuteShow) {
|
1586 |
+
//NEW: 2011-02-03 we should give the hour as a parameter as well!
|
1587 |
+
enabled = onMinuteShow.apply((inst.input ? inst.input[0] : null), [inst.hours,minute]); //trigger callback
|
1588 |
+
}
|
1589 |
+
|
1590 |
+
if (minute == undefined) {
|
1591 |
+
html = '<td><span class="ui-state-default ui-state-disabled"> </span></td>';
|
1592 |
+
return html;
|
1593 |
+
}
|
1594 |
+
|
1595 |
+
if (enabled) {
|
1596 |
+
html = '<td class="ui-timepicker-minute-cell" data-timepicker-instance-id="#' + inst.id.replace(/\\\\/g,"\\") + '" data-minute="' + minute.toString() + '" >' +
|
1597 |
+
'<a class="ui-state-default ' +
|
1598 |
+
(minute == inst.minutes ? 'ui-state-active' : '') +
|
1599 |
+
'" >' +
|
1600 |
+
displayText +
|
1601 |
+
'</a></td>';
|
1602 |
+
}
|
1603 |
+
else {
|
1604 |
+
|
1605 |
+
html = '<td>' +
|
1606 |
+
'<span class="ui-state-default ui-state-disabled" >' +
|
1607 |
+
displayText +
|
1608 |
+
'</span>' +
|
1609 |
+
'</td>';
|
1610 |
+
}
|
1611 |
+
return html;
|
1612 |
+
},
|
1613 |
+
|
1614 |
+
|
1615 |
+
/* Detach a timepicker from its control.
|
1616 |
+
@param target element - the target input field or division or span */
|
1617 |
+
_destroyTimepicker: function(target) {
|
1618 |
+
var $target = $(target);
|
1619 |
+
var inst = $.data(target, PROP_NAME);
|
1620 |
+
if (!$target.hasClass(this.markerClassName)) {
|
1621 |
+
return;
|
1622 |
+
}
|
1623 |
+
var nodeName = target.nodeName.toLowerCase();
|
1624 |
+
$.removeData(target, PROP_NAME);
|
1625 |
+
if (nodeName == 'input') {
|
1626 |
+
inst.append.remove();
|
1627 |
+
inst.trigger.remove();
|
1628 |
+
$target.removeClass(this.markerClassName)
|
1629 |
+
.unbind('focus.timepicker', this._showTimepicker)
|
1630 |
+
.unbind('click.timepicker', this._adjustZIndex);
|
1631 |
+
} else if (nodeName == 'div' || nodeName == 'span')
|
1632 |
+
$target.removeClass(this.markerClassName).empty();
|
1633 |
+
},
|
1634 |
+
|
1635 |
+
/**
|
1636 |
+
Enable the date picker to a jQuery selection.
|
1637 |
+
@constructor
|
1638 |
+
@param target element - the target input field or division or span */
|
1639 |
+
_enableTimepicker: function(target) {
|
1640 |
+
var $target = $(target),
|
1641 |
+
target_id = $target.attr('id'),
|
1642 |
+
inst = $.data(target, PROP_NAME);
|
1643 |
+
|
1644 |
+
if (!$target.hasClass(this.markerClassName)) {
|
1645 |
+
return;
|
1646 |
+
}
|
1647 |
+
var nodeName = target.nodeName.toLowerCase();
|
1648 |
+
if (nodeName == 'input') {
|
1649 |
+
target.disabled = false;
|
1650 |
+
var button = this._get(inst, 'button');
|
1651 |
+
$(button).removeClass('ui-state-disabled').disabled = false;
|
1652 |
+
inst.trigger.filter('button').
|
1653 |
+
each(function() { this.disabled = false; }).end();
|
1654 |
+
}
|
1655 |
+
else if (nodeName == 'div' || nodeName == 'span') {
|
1656 |
+
var inline = $target.children('.' + this._inlineClass);
|
1657 |
+
inline.children().removeClass('ui-state-disabled');
|
1658 |
+
inline.find('button').each(
|
1659 |
+
function() { this.disabled = false }
|
1660 |
+
)
|
1661 |
+
}
|
1662 |
+
this._disabledInputs = $.map(this._disabledInputs,
|
1663 |
+
function(value) { return (value == target_id ? null : value); }); // delete entry
|
1664 |
+
},
|
1665 |
+
|
1666 |
+
/**
|
1667 |
+
Disable the time picker to a jQuery selection.
|
1668 |
+
@constructor
|
1669 |
+
@param target element - the target input field or division or span */
|
1670 |
+
_disableTimepicker: function(target) {
|
1671 |
+
var $target = $(target);
|
1672 |
+
var inst = $.data(target, PROP_NAME);
|
1673 |
+
if (!$target.hasClass(this.markerClassName)) {
|
1674 |
+
return;
|
1675 |
+
}
|
1676 |
+
var nodeName = target.nodeName.toLowerCase();
|
1677 |
+
if (nodeName == 'input') {
|
1678 |
+
var button = this._get(inst, 'button');
|
1679 |
+
|
1680 |
+
$(button).addClass('ui-state-disabled').disabled = true;
|
1681 |
+
target.disabled = true;
|
1682 |
+
|
1683 |
+
inst.trigger.filter('button').
|
1684 |
+
each(function() { this.disabled = true; }).end();
|
1685 |
+
|
1686 |
+
}
|
1687 |
+
else if (nodeName == 'div' || nodeName == 'span') {
|
1688 |
+
var inline = $target.children('.' + this._inlineClass);
|
1689 |
+
inline.children().addClass('ui-state-disabled');
|
1690 |
+
inline.find('button').each(
|
1691 |
+
function() { this.disabled = true }
|
1692 |
+
)
|
1693 |
+
|
1694 |
+
}
|
1695 |
+
this._disabledInputs = $.map(this._disabledInputs,
|
1696 |
+
function(value) { return (value == target ? null : value); }); // delete entry
|
1697 |
+
this._disabledInputs[this._disabledInputs.length] = $target.attr('id');
|
1698 |
+
},
|
1699 |
+
|
1700 |
+
/**
|
1701 |
+
Is the first field in a jQuery collection disabled as a timepicker?
|
1702 |
+
@constructor
|
1703 |
+
@param target_id element - the target input field or division or span
|
1704 |
+
@return boolean - true if disabled, false if enabled
|
1705 |
+
*/
|
1706 |
+
_isDisabledTimepicker: function (target_id) {
|
1707 |
+
if ( ! target_id) { return false; }
|
1708 |
+
for (var i = 0; i < this._disabledInputs.length; i++) {
|
1709 |
+
if (this._disabledInputs[i] == target_id) { return true; }
|
1710 |
+
}
|
1711 |
+
return false;
|
1712 |
+
},
|
1713 |
+
|
1714 |
+
/* Check positioning to remain on screen. */
|
1715 |
+
_checkOffset: function (inst, offset, isFixed) {
|
1716 |
+
var tpWidth = inst.tpDiv.outerWidth();
|
1717 |
+
var tpHeight = inst.tpDiv.outerHeight();
|
1718 |
+
var inputWidth = inst.input ? inst.input.outerWidth() : 0;
|
1719 |
+
var inputHeight = inst.input ? inst.input.outerHeight() : 0;
|
1720 |
+
var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
|
1721 |
+
var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
|
1722 |
+
|
1723 |
+
offset.left -= (this._get(inst, 'isRTL') ? (tpWidth - inputWidth) : 0);
|
1724 |
+
offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
|
1725 |
+
offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
|
1726 |
+
|
1727 |
+
// now check if datepicker is showing outside window viewport - move to a better place if so.
|
1728 |
+
offset.left -= Math.min(offset.left, (offset.left + tpWidth > viewWidth && viewWidth > tpWidth) ?
|
1729 |
+
Math.abs(offset.left + tpWidth - viewWidth) : 0);
|
1730 |
+
offset.top -= Math.min(offset.top, (offset.top + tpHeight > viewHeight && viewHeight > tpHeight) ?
|
1731 |
+
Math.abs(tpHeight + inputHeight) : 0);
|
1732 |
+
|
1733 |
+
return offset;
|
1734 |
+
},
|
1735 |
+
|
1736 |
+
/* Find an object's position on the screen. */
|
1737 |
+
_findPos: function (obj) {
|
1738 |
+
var inst = this._getInst(obj);
|
1739 |
+
var isRTL = this._get(inst, 'isRTL');
|
1740 |
+
while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
|
1741 |
+
obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
|
1742 |
+
}
|
1743 |
+
var position = $(obj).offset();
|
1744 |
+
return [position.left, position.top];
|
1745 |
+
},
|
1746 |
+
|
1747 |
+
/* Retrieve the size of left and top borders for an element.
|
1748 |
+
@param elem (jQuery object) the element of interest
|
1749 |
+
@return (number[2]) the left and top borders */
|
1750 |
+
_getBorders: function (elem) {
|
1751 |
+
var convert = function (value) {
|
1752 |
+
return { thin: 1, medium: 2, thick: 3}[value] || value;
|
1753 |
+
};
|
1754 |
+
return [parseFloat(convert(elem.css('border-left-width'))),
|
1755 |
+
parseFloat(convert(elem.css('border-top-width')))];
|
1756 |
+
},
|
1757 |
+
|
1758 |
+
|
1759 |
+
/* Close time picker if clicked elsewhere. */
|
1760 |
+
_checkExternalClick: function (event) {
|
1761 |
+
if (!$.timepicker._curInst) { return; }
|
1762 |
+
var $target = $(event.target);
|
1763 |
+
if ($target[0].id != $.timepicker._mainDivId &&
|
1764 |
+
$target.parents('#' + $.timepicker._mainDivId).length == 0 &&
|
1765 |
+
!$target.hasClass($.timepicker.markerClassName) &&
|
1766 |
+
!$target.hasClass($.timepicker._triggerClass) &&
|
1767 |
+
$.timepicker._timepickerShowing && !($.timepicker._inDialog && $.blockUI))
|
1768 |
+
$.timepicker._hideTimepicker();
|
1769 |
+
},
|
1770 |
+
|
1771 |
+
/**
|
1772 |
+
Hide the time picker from view.
|
1773 |
+
@param input element - the input field attached to the time picker
|
1774 |
+
* @constructor
|
1775 |
+
*/
|
1776 |
+
_hideTimepicker: function (input) {
|
1777 |
+
var inst = this._curInst;
|
1778 |
+
if (!inst || (input && inst != $.data(input, PROP_NAME))) { return; }
|
1779 |
+
if (this._timepickerShowing) {
|
1780 |
+
var showAnim = this._get(inst, 'showAnim');
|
1781 |
+
var duration = this._get(inst, 'duration');
|
1782 |
+
var postProcess = function () {
|
1783 |
+
$.timepicker._tidyDialog(inst);
|
1784 |
+
this._curInst = null;
|
1785 |
+
};
|
1786 |
+
if ($.effects && $.effects[showAnim]) {
|
1787 |
+
inst.tpDiv.hide(showAnim, $.timepicker._get(inst, 'showOptions'), duration, postProcess);
|
1788 |
+
}
|
1789 |
+
else {
|
1790 |
+
inst.tpDiv[(showAnim == 'slideDown' ? 'slideUp' :
|
1791 |
+
(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
|
1792 |
+
}
|
1793 |
+
if (!showAnim) { postProcess(); }
|
1794 |
+
|
1795 |
+
this._timepickerShowing = false;
|
1796 |
+
|
1797 |
+
this._lastInput = null;
|
1798 |
+
if (this._inDialog) {
|
1799 |
+
this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
|
1800 |
+
if ($.blockUI) {
|
1801 |
+
$.unblockUI();
|
1802 |
+
$('body').append(this.tpDiv);
|
1803 |
+
}
|
1804 |
+
}
|
1805 |
+
this._inDialog = false;
|
1806 |
+
|
1807 |
+
var onClose = this._get(inst, 'onClose');
|
1808 |
+
if (onClose) {
|
1809 |
+
onClose.apply(
|
1810 |
+
(inst.input ? inst.input[0] : null),
|
1811 |
+
[(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
|
1812 |
+
}
|
1813 |
+
|
1814 |
+
}
|
1815 |
+
},
|
1816 |
+
|
1817 |
+
|
1818 |
+
|
1819 |
+
/* Tidy up after a dialog display. */
|
1820 |
+
_tidyDialog: function (inst) {
|
1821 |
+
inst.tpDiv.removeClass(this._dialogClass).unbind('.ui-timepicker');
|
1822 |
+
},
|
1823 |
+
|
1824 |
+
/* Retrieve the instance data for the target control.
|
1825 |
+
@param target element - the target input field or division or span
|
1826 |
+
@return object - the associated instance data
|
1827 |
+
@throws error if a jQuery problem getting data */
|
1828 |
+
_getInst: function (target) {
|
1829 |
+
try {
|
1830 |
+
return $.data(target, PROP_NAME);
|
1831 |
+
}
|
1832 |
+
catch (err) {
|
1833 |
+
throw 'Missing instance data for this timepicker';
|
1834 |
+
}
|
1835 |
+
},
|
1836 |
+
|
1837 |
+
/* Get a setting value, defaulting if necessary. */
|
1838 |
+
_get: function (inst, name) {
|
1839 |
+
return inst.settings[name] !== undefined ?
|
1840 |
+
inst.settings[name] : this._defaults[name];
|
1841 |
+
},
|
1842 |
+
|
1843 |
+
/* Parse existing time and initialise time picker. */
|
1844 |
+
_setTimeFromField: function (inst) {
|
1845 |
+
if (inst.input.val() == inst.lastVal) { return; }
|
1846 |
+
var defaultTime = this._get(inst, 'defaultTime');
|
1847 |
+
|
1848 |
+
var timeToParse = defaultTime == 'now' ? this._getCurrentTimeRounded(inst) : defaultTime;
|
1849 |
+
if ((inst.inline == false) && (inst.input.val() != '')) { timeToParse = inst.input.val() }
|
1850 |
+
|
1851 |
+
if (timeToParse instanceof Date) {
|
1852 |
+
inst.hours = timeToParse.getHours();
|
1853 |
+
inst.minutes = timeToParse.getMinutes();
|
1854 |
+
} else {
|
1855 |
+
var timeVal = inst.lastVal = timeToParse;
|
1856 |
+
if (timeToParse == '') {
|
1857 |
+
inst.hours = -1;
|
1858 |
+
inst.minutes = -1;
|
1859 |
+
} else {
|
1860 |
+
var time = this.parseTime(inst, timeVal);
|
1861 |
+
inst.hours = time.hours;
|
1862 |
+
inst.minutes = time.minutes;
|
1863 |
+
}
|
1864 |
+
}
|
1865 |
+
|
1866 |
+
|
1867 |
+
$.timepicker._updateTimepicker(inst);
|
1868 |
+
},
|
1869 |
+
|
1870 |
+
/* Update or retrieve the settings for an existing time picker.
|
1871 |
+
@param target element - the target input field or division or span
|
1872 |
+
@param name object - the new settings to update or
|
1873 |
+
string - the name of the setting to change or retrieve,
|
1874 |
+
when retrieving also 'all' for all instance settings or
|
1875 |
+
'defaults' for all global defaults
|
1876 |
+
@param value any - the new value for the setting
|
1877 |
+
(omit if above is an object or to retrieve a value) */
|
1878 |
+
_optionTimepicker: function(target, name, value) {
|
1879 |
+
var inst = this._getInst(target);
|
1880 |
+
if (arguments.length == 2 && typeof name == 'string') {
|
1881 |
+
return (name == 'defaults' ? $.extend({}, $.timepicker._defaults) :
|
1882 |
+
(inst ? (name == 'all' ? $.extend({}, inst.settings) :
|
1883 |
+
this._get(inst, name)) : null));
|
1884 |
+
}
|
1885 |
+
var settings = name || {};
|
1886 |
+
if (typeof name == 'string') {
|
1887 |
+
settings = {};
|
1888 |
+
settings[name] = value;
|
1889 |
+
}
|
1890 |
+
if (inst) {
|
1891 |
+
if (this._curInst == inst) {
|
1892 |
+
this._hideTimepicker();
|
1893 |
+
}
|
1894 |
+
extendRemove(inst.settings, settings);
|
1895 |
+
this._updateTimepicker(inst);
|
1896 |
+
}
|
1897 |
+
},
|
1898 |
+
|
1899 |
+
|
1900 |
+
/* Set the time for a jQuery selection.
|
1901 |
+
@param target element - the target input field or division or span
|
1902 |
+
@param time String - the new time */
|
1903 |
+
_setTimeTimepicker: function(target, time) {
|
1904 |
+
var inst = this._getInst(target);
|
1905 |
+
if (inst) {
|
1906 |
+
this._setTime(inst, time);
|
1907 |
+
this._updateTimepicker(inst);
|
1908 |
+
this._updateAlternate(inst, time);
|
1909 |
+
}
|
1910 |
+
},
|
1911 |
+
|
1912 |
+
/* Set the time directly. */
|
1913 |
+
_setTime: function(inst, time, noChange) {
|
1914 |
+
var origHours = inst.hours;
|
1915 |
+
var origMinutes = inst.minutes;
|
1916 |
+
time = this.parseTime(inst, time);
|
1917 |
+
inst.hours = time.hours;
|
1918 |
+
inst.minutes = time.minutes;
|
1919 |
+
|
1920 |
+
if ((origHours != inst.hours || origMinutes != inst.minuts) && !noChange) {
|
1921 |
+
inst.input.trigger('change');
|
1922 |
+
}
|
1923 |
+
this._updateTimepicker(inst);
|
1924 |
+
this._updateSelectedValue(inst);
|
1925 |
+
},
|
1926 |
+
|
1927 |
+
/* Return the current time, ready to be parsed, rounded to the closest 5 minute */
|
1928 |
+
_getCurrentTimeRounded: function (inst) {
|
1929 |
+
var currentTime = new Date(),
|
1930 |
+
currentMinutes = currentTime.getMinutes(),
|
1931 |
+
// round to closest 5
|
1932 |
+
adjustedMinutes = Math.round( currentMinutes / 5 ) * 5;
|
1933 |
+
currentTime.setMinutes(adjustedMinutes);
|
1934 |
+
return currentTime;
|
1935 |
+
},
|
1936 |
+
|
1937 |
+
/*
|
1938 |
+
* Parse a time string into hours and minutes
|
1939 |
+
*/
|
1940 |
+
parseTime: function (inst, timeVal) {
|
1941 |
+
var retVal = new Object();
|
1942 |
+
retVal.hours = -1;
|
1943 |
+
retVal.minutes = -1;
|
1944 |
+
|
1945 |
+
var timeSeparator = this._get(inst, 'timeSeparator'),
|
1946 |
+
amPmText = this._get(inst, 'amPmText'),
|
1947 |
+
showHours = this._get(inst, 'showHours'),
|
1948 |
+
showMinutes = this._get(inst, 'showMinutes'),
|
1949 |
+
optionalMinutes = this._get(inst, 'optionalMinutes'),
|
1950 |
+
showPeriod = (this._get(inst, 'showPeriod') == true),
|
1951 |
+
p = timeVal.indexOf(timeSeparator);
|
1952 |
+
|
1953 |
+
// check if time separator found
|
1954 |
+
if (p != -1) {
|
1955 |
+
retVal.hours = parseInt(timeVal.substr(0, p), 10);
|
1956 |
+
retVal.minutes = parseInt(timeVal.substr(p + 1), 10);
|
1957 |
+
}
|
1958 |
+
// check for hours only
|
1959 |
+
else if ( (showHours) && ( !showMinutes || optionalMinutes ) ) {
|
1960 |
+
retVal.hours = parseInt(timeVal, 10);
|
1961 |
+
}
|
1962 |
+
// check for minutes only
|
1963 |
+
else if ( ( ! showHours) && (showMinutes) ) {
|
1964 |
+
retVal.minutes = parseInt(timeVal, 10);
|
1965 |
+
}
|
1966 |
+
|
1967 |
+
if (showHours) {
|
1968 |
+
var timeValUpper = timeVal.toUpperCase();
|
1969 |
+
if ((retVal.hours < 12) && (showPeriod) && (timeValUpper.indexOf(amPmText[1].toUpperCase()) != -1)) {
|
1970 |
+
retVal.hours += 12;
|
1971 |
+
}
|
1972 |
+
// fix for 12 AM
|
1973 |
+
if ((retVal.hours == 12) && (showPeriod) && (timeValUpper.indexOf(amPmText[0].toUpperCase()) != -1)) {
|
1974 |
+
retVal.hours = 0;
|
1975 |
+
}
|
1976 |
+
}
|
1977 |
+
|
1978 |
+
return retVal;
|
1979 |
+
},
|
1980 |
+
|
1981 |
+
selectNow: function(event) {
|
1982 |
+
var id = $(event.target).attr("data-timepicker-instance-id"),
|
1983 |
+
$target = $(id),
|
1984 |
+
inst = this._getInst($target[0]);
|
1985 |
+
//if (!inst || (input && inst != $.data(input, PROP_NAME))) { return; }
|
1986 |
+
var currentTime = new Date();
|
1987 |
+
inst.hours = currentTime.getHours();
|
1988 |
+
inst.minutes = currentTime.getMinutes();
|
1989 |
+
this._updateSelectedValue(inst);
|
1990 |
+
this._updateTimepicker(inst);
|
1991 |
+
this._hideTimepicker();
|
1992 |
+
},
|
1993 |
+
|
1994 |
+
deselectTime: function(event) {
|
1995 |
+
var id = $(event.target).attr("data-timepicker-instance-id"),
|
1996 |
+
$target = $(id),
|
1997 |
+
inst = this._getInst($target[0]);
|
1998 |
+
inst.hours = -1;
|
1999 |
+
inst.minutes = -1;
|
2000 |
+
this._updateSelectedValue(inst);
|
2001 |
+
this._hideTimepicker();
|
2002 |
+
},
|
2003 |
+
|
2004 |
+
|
2005 |
+
selectHours: function (event) {
|
2006 |
+
var $td = $(event.currentTarget),
|
2007 |
+
id = $td.attr("data-timepicker-instance-id"),
|
2008 |
+
newHours = parseInt($td.attr("data-hour")),
|
2009 |
+
fromDoubleClick = event.data.fromDoubleClick,
|
2010 |
+
$target = $(id),
|
2011 |
+
inst = this._getInst($target[0]),
|
2012 |
+
showMinutes = (this._get(inst, 'showMinutes') == true);
|
2013 |
+
|
2014 |
+
// don't select if disabled
|
2015 |
+
if ( $.timepicker._isDisabledTimepicker($target.attr('id')) ) { return false }
|
2016 |
+
|
2017 |
+
$td.parents('.ui-timepicker-hours:first').find('a').removeClass('ui-state-active');
|
2018 |
+
$td.children('a').addClass('ui-state-active');
|
2019 |
+
inst.hours = newHours;
|
2020 |
+
|
2021 |
+
// added for onMinuteShow callback
|
2022 |
+
var onMinuteShow = this._get(inst, 'onMinuteShow');
|
2023 |
+
if (onMinuteShow) {
|
2024 |
+
// this will trigger a callback on selected hour to make sure selected minute is allowed.
|
2025 |
+
this._updateMinuteDisplay(inst);
|
2026 |
+
}
|
2027 |
+
|
2028 |
+
this._updateSelectedValue(inst);
|
2029 |
+
|
2030 |
+
inst._hoursClicked = true;
|
2031 |
+
if ((inst._minutesClicked) || (fromDoubleClick) || (showMinutes == false)) {
|
2032 |
+
$.timepicker._hideTimepicker();
|
2033 |
+
}
|
2034 |
+
// return false because if used inline, prevent the url to change to a hashtag
|
2035 |
+
return false;
|
2036 |
+
},
|
2037 |
+
|
2038 |
+
selectMinutes: function (event) {
|
2039 |
+
var $td = $(event.currentTarget),
|
2040 |
+
id = $td.attr("data-timepicker-instance-id"),
|
2041 |
+
newMinutes = parseInt($td.attr("data-minute")),
|
2042 |
+
fromDoubleClick = event.data.fromDoubleClick,
|
2043 |
+
$target = $(id),
|
2044 |
+
inst = this._getInst($target[0]),
|
2045 |
+
showHours = (this._get(inst, 'showHours') == true);
|
2046 |
+
|
2047 |
+
// don't select if disabled
|
2048 |
+
if ( $.timepicker._isDisabledTimepicker($target.attr('id')) ) { return false }
|
2049 |
+
|
2050 |
+
$td.parents('.ui-timepicker-minutes:first').find('a').removeClass('ui-state-active');
|
2051 |
+
$td.children('a').addClass('ui-state-active');
|
2052 |
+
|
2053 |
+
inst.minutes = newMinutes;
|
2054 |
+
this._updateSelectedValue(inst);
|
2055 |
+
|
2056 |
+
inst._minutesClicked = true;
|
2057 |
+
if ((inst._hoursClicked) || (fromDoubleClick) || (showHours == false)) {
|
2058 |
+
$.timepicker._hideTimepicker();
|
2059 |
+
// return false because if used inline, prevent the url to change to a hashtag
|
2060 |
+
return false;
|
2061 |
+
}
|
2062 |
+
|
2063 |
+
// return false because if used inline, prevent the url to change to a hashtag
|
2064 |
+
return false;
|
2065 |
+
},
|
2066 |
+
|
2067 |
+
_updateSelectedValue: function (inst) {
|
2068 |
+
var newTime = this._getParsedTime(inst);
|
2069 |
+
if (inst.input) {
|
2070 |
+
inst.input.val(newTime);
|
2071 |
+
inst.input.trigger('change');
|
2072 |
+
}
|
2073 |
+
var onSelect = this._get(inst, 'onSelect');
|
2074 |
+
if (onSelect) { onSelect.apply((inst.input ? inst.input[0] : null), [newTime, inst]); } // trigger custom callback
|
2075 |
+
this._updateAlternate(inst, newTime);
|
2076 |
+
return newTime;
|
2077 |
+
},
|
2078 |
+
|
2079 |
+
/* this function process selected time and return it parsed according to instance options */
|
2080 |
+
_getParsedTime: function(inst) {
|
2081 |
+
|
2082 |
+
if (inst.hours == -1 && inst.minutes == -1) {
|
2083 |
+
return '';
|
2084 |
+
}
|
2085 |
+
|
2086 |
+
// default to 0 AM if hours is not valid
|
2087 |
+
if ((inst.hours < inst.hours.starts) || (inst.hours > inst.hours.ends )) { inst.hours = 0; }
|
2088 |
+
// default to 0 minutes if minute is not valid
|
2089 |
+
if ((inst.minutes < inst.minutes.starts) || (inst.minutes > inst.minutes.ends)) { inst.minutes = 0; }
|
2090 |
+
|
2091 |
+
var period = "",
|
2092 |
+
showPeriod = (this._get(inst, 'showPeriod') == true),
|
2093 |
+
showLeadingZero = (this._get(inst, 'showLeadingZero') == true),
|
2094 |
+
showHours = (this._get(inst, 'showHours') == true),
|
2095 |
+
showMinutes = (this._get(inst, 'showMinutes') == true),
|
2096 |
+
optionalMinutes = (this._get(inst, 'optionalMinutes') == true),
|
2097 |
+
amPmText = this._get(inst, 'amPmText'),
|
2098 |
+
selectedHours = inst.hours ? inst.hours : 0,
|
2099 |
+
selectedMinutes = inst.minutes ? inst.minutes : 0,
|
2100 |
+
displayHours = selectedHours ? selectedHours : 0,
|
2101 |
+
parsedTime = '';
|
2102 |
+
|
2103 |
+
if (showPeriod) {
|
2104 |
+
if (inst.hours == 0) {
|
2105 |
+
displayHours = 12;
|
2106 |
+
}
|
2107 |
+
if (inst.hours < 12) {
|
2108 |
+
period = amPmText[0];
|
2109 |
+
}
|
2110 |
+
else {
|
2111 |
+
period = amPmText[1];
|
2112 |
+
if (displayHours > 12) {
|
2113 |
+
displayHours -= 12;
|
2114 |
+
}
|
2115 |
+
}
|
2116 |
+
}
|
2117 |
+
|
2118 |
+
var h = displayHours.toString();
|
2119 |
+
if (showLeadingZero && (displayHours < 10)) { h = '0' + h; }
|
2120 |
+
|
2121 |
+
var m = selectedMinutes.toString();
|
2122 |
+
if (selectedMinutes < 10) { m = '0' + m; }
|
2123 |
+
|
2124 |
+
if (showHours) {
|
2125 |
+
parsedTime += h;
|
2126 |
+
}
|
2127 |
+
if (showHours && showMinutes && (!optionalMinutes || m != 0)) {
|
2128 |
+
parsedTime += this._get(inst, 'timeSeparator');
|
2129 |
+
}
|
2130 |
+
if (showMinutes && (!optionalMinutes || m != 0)) {
|
2131 |
+
parsedTime += m;
|
2132 |
+
}
|
2133 |
+
if (showHours) {
|
2134 |
+
if (period.length > 0) { parsedTime += this._get(inst, 'periodSeparator') + period; }
|
2135 |
+
}
|
2136 |
+
|
2137 |
+
return parsedTime;
|
2138 |
+
},
|
2139 |
+
|
2140 |
+
/* Update any alternate field to synchronise with the main field. */
|
2141 |
+
_updateAlternate: function(inst, newTime) {
|
2142 |
+
var altField = this._get(inst, 'altField');
|
2143 |
+
if (altField) { // update alternate field too
|
2144 |
+
$(altField).each(function(i,e) {
|
2145 |
+
$(e).val(newTime);
|
2146 |
+
});
|
2147 |
+
}
|
2148 |
+
},
|
2149 |
+
|
2150 |
+
/* This might look unused but it's called by the $.fn.timepicker function with param getTime */
|
2151 |
+
/* added v 0.2.3 - gitHub issue #5 - Thanks edanuff */
|
2152 |
+
_getTimeTimepicker : function(input) {
|
2153 |
+
var inst = this._getInst(input);
|
2154 |
+
return this._getParsedTime(inst);
|
2155 |
+
},
|
2156 |
+
_getHourTimepicker: function(input) {
|
2157 |
+
var inst = this._getInst(input);
|
2158 |
+
if ( inst == undefined) { return -1; }
|
2159 |
+
return inst.hours;
|
2160 |
+
},
|
2161 |
+
_getMinuteTimepicker: function(input) {
|
2162 |
+
var inst= this._getInst(input);
|
2163 |
+
if ( inst == undefined) { return -1; }
|
2164 |
+
return inst.minutes;
|
2165 |
+
}
|
2166 |
+
|
2167 |
+
});
|
2168 |
+
|
2169 |
+
|
2170 |
+
|
2171 |
+
/* Invoke the timepicker functionality.
|
2172 |
+
@param options string - a command, optionally followed by additional parameters or
|
2173 |
+
Object - settings for attaching new timepicker functionality
|
2174 |
+
@return jQuery object */
|
2175 |
+
$.fn.timepicker = function (options) {
|
2176 |
+
|
2177 |
+
/* Initialise the time picker. */
|
2178 |
+
if (!$.timepicker.initialized) {
|
2179 |
+
$(document).mousedown($.timepicker._checkExternalClick).
|
2180 |
+
find('body').append($.timepicker.tpDiv);
|
2181 |
+
$.timepicker.initialized = true;
|
2182 |
+
}
|
2183 |
+
|
2184 |
+
|
2185 |
+
|
2186 |
+
var otherArgs = Array.prototype.slice.call(arguments, 1);
|
2187 |
+
if (typeof options == 'string' && (options == 'getTime' || options == 'getHour' || options == 'getMinute' ))
|
2188 |
+
return $.timepicker['_' + options + 'Timepicker'].
|
2189 |
+
apply($.timepicker, [this[0]].concat(otherArgs));
|
2190 |
+
if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
|
2191 |
+
return $.timepicker['_' + options + 'Timepicker'].
|
2192 |
+
apply($.timepicker, [this[0]].concat(otherArgs));
|
2193 |
+
return this.each(function () {
|
2194 |
+
typeof options == 'string' ?
|
2195 |
+
$.timepicker['_' + options + 'Timepicker'].
|
2196 |
+
apply($.timepicker, [this].concat(otherArgs)) :
|
2197 |
+
$.timepicker._attachTimepicker(this, options);
|
2198 |
+
});
|
2199 |
+
};
|
2200 |
+
|
2201 |
+
/* jQuery extend now ignores nulls! */
|
2202 |
+
function extendRemove(target, props) {
|
2203 |
+
$.extend(target, props);
|
2204 |
+
for (var name in props)
|
2205 |
+
if (props[name] == null || props[name] == undefined)
|
2206 |
+
target[name] = props[name];
|
2207 |
+
return target;
|
2208 |
+
};
|
2209 |
+
|
2210 |
+
$.timepicker = new Timepicker(); // singleton instance
|
2211 |
+
$.timepicker.initialized = false;
|
2212 |
+
$.timepicker.uuid = new Date().getTime();
|
2213 |
+
$.timepicker.version = "0.3.1";
|
2214 |
+
|
2215 |
+
// Workaround for #4055
|
2216 |
+
// Add another global to avoid noConflict issues with inline event handlers
|
2217 |
+
window['TP_jQuery_' + tpuuid] = $;
|
2218 |
+
|
2219 |
+
})(jQuery);
|
js/event.min.js
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var eo_occurrences_by_rule=[];
|
2 |
+
jQuery(document).ready(function(b){function z(){b("#eo_occurrence_includes").val(eo_include_dates.join(",\r\n"));b("#eo_occurrence_excludes").val(eo_exclude_dates.join(",\r\n"))}function v(){var g=!b("#HWSEvent_rec").prop("checked");b(".reoccurence .event-date :input").attr("disabled",g);b(".reoccurence .event-date :input").toggleClass("ui-state-disabled",g);g=!b("#eo_allday:checkbox").attr("checked");b(".eo_time").attr("disabled",!g);b(".eo_time").toggleClass("ui-state-disabled",!g);switch(b("#HWSEventInput_Req").val()){case "once":case "custom":b("#HWSEvent_freq").val("1");
|
3 |
+
b(".reocurrence_row").hide();b("#dayofweekrepeat").show();b("#dayofmonthrepeat").show();b(".reocurrence_row :input").attr("disabled",true);break;case "weekly":b(".reocurrence_row :input").attr("disabled",false);b("#HWSEvent_freq").val()>1?b("#recpan").text(o.weeks):b("#recpan").text(o.week);b(".reocurrence_row").fadeIn(700);b("#dayofweekrepeat").fadeIn(700);b("#dayofweekrepeat :input").attr("disabled",false);b("#dayofmonthrepeat").hide();b("#dayofmonthrepeat :radio").attr("disabled",true);break;case "monthly":b(".reocurrence_row :input").attr("disabled",
|
4 |
+
false);b("#HWSEvent_freq").val()>1?b("#recpan").text(o.months):b("#recpan").text(o.month);b(".reocurrence_row").fadeIn(700);b("#dayofmonthrepeat").fadeIn(700);b("#dayofmonthrepeat :input").attr("disabled",false);b("#dayofweekrepeat").hide();b("#dayofweekrepeat :input").attr("disabled",true);break;case "daily":b(".reocurrence_row :input").attr("disabled",false);b(".reocurrence_row").fadeIn(700);b("#HWSEvent_freq").val()>1?b("#recpan").text(o.days):b("#recpan").text(o.day);b("#dayofweekrepeat").hide();
|
5 |
+
b("#dayofweekrepeat :input").attr("disabled",true);b("#dayofmonthrepeat").hide();b("#dayofmonthrepeat :radio").attr("disabled",true);break;case "yearly":b(".reocurrence_row :input").attr("disabled",false);b(".reocurrence_row").fadeIn(700);b("#HWSEvent_freq").val()>1?b("#recpan").text(o.years):b("#recpan").text(o.year);b("#dayofweekrepeat").hide();b("#dayofweekrepeat :input").attr("disabled",true);b("#dayofmonthrepeat").hide();b("#dayofmonthrepeat :radio").attr("disabled",true);break}b("#venue_select").val()===
|
6 |
+
null&&b("tr.venue_row").hide();q()}function q(){if(b("#HWSEventInput_Req").val()=="once")b("#event_summary").html("This event will be a one-time event");else{var g=b("#from_date").datepicker("getDate"),i=EO_Ajax_Event.locale.weekDay,t=new Array("SU","MO","TU","WE","TH","FR","SA"),m={monthNamesShort:EO_Ajax_Event.locale.monthAbbrev,dayNamesMin:EO_Ajax_Event.locale.dayAbbrev,monthNames:EO_Ajax_Event.locale.monthNames},h=parseInt(b("#HWSEvent_freq").val()),n=o.summary+" ";switch(b("#HWSEventInput_Req").val()){case "custom":case "daily":n+=
|
7 |
+
h>1?sprintf(o.dayPlural,h):o.daySingle;break;case "weekly":n+=h>1?sprintf(o.weekPlural,h):o.weekSingle;h=b("#dayofweekrepeat :checkbox:checked");if(h.length==0){h=g.getDay();b("#dayofweekrepeat :checkbox[value='"+t[h]+"']").attr("checked",true)}h=b("#dayofweekrepeat :checkbox:checked");h.each(function(p){if(p==0)n=n+" "+i[t.indexOf(b(this).val())];if(p>0)n=n+", "+i[t.indexOf(b(this).val())]});break;case "monthly":n+=h>1?sprintf(o.monthPlural,h):o.monthSingle;if(b("#dayofmonthrepeat :radio:checked").val()==
|
8 |
+
"BYMONTHDAY=")n=n+" "+g.getDate()+a(g);else{h=g.getDay()%7;g=parseInt(Math.floor((g.getDate()-1)/7));n=n+" "+o.occurrence[g]+" "+i[h]}break;case "yearly":n+=h>1?sprintf(o.yearPlural,h):o.yearSingle;n=n+" "+b.datepicker.formatDate("MM d",g,m)+a(g);break}g=b("#recend").datepicker("getDate");if(g!=null)n=n+" "+o.until+" "+b.datepicker.formatDate("MM d'"+a(g)+"' yy",g,m);b("#event_summary").html(n)}}function a(g){return["th","st","nd","rd"][3<g.getDate()&&g.getDate()<20?0:Math.min(g.getDate()%10,4)%4]}
|
9 |
+
function c(){eo_exclude_dates=[];eo_include_dates=[];z();f(eo_viewing_month[0],eo_viewing_month[1],{});A.datepicker("refresh")}function e(g){g=b.datepicker.formatDate("yy-mm-dd",g);if(d(g)[0])return[true,"ui-state-active",""];return[true,"ui-state-disabled",""]}function d(g){if(b.inArray(g,eo_occurrences_by_rule)>-1){g=b.inArray(g,eo_exclude_dates);return g>-1?[false,g]:[true,-1]}else{g=b.inArray(g,eo_include_dates);return g>-1?[true,g]:[false,-1]}}function f(g,i){eo_occurrences_by_rule=[];eo_viewing_month=
|
10 |
+
[g,i];var t=b("#HWSEventInput_Req").val(),m=parseInt(b("#HWSEvent_freq").val()),h=b("#from_date").datepicker("getDate"),n=b("#recend").datepicker("getDate");i-=1;var p=new Date(g,i,1),w=new Date(new Date(g,i+1,1)-1);if(!(n<p||h>w)){switch(t){case "once":case "custom":g=b.datepicker.formatDate("yy-mm-dd",h);eo_occurrences_by_rule.push(g);return;case "daily":if(h<p){var B=Math.abs((p-h)/864E5)-1;B%=m}else B=parseInt(h.getDate());i=m;var E=[],C=new Date(p);C.setDate(p.getDate()+(B-1));E.push(C);break;
|
11 |
+
case "weekly":var r=p.getDay();r=b("#dayofweekrepeat :checkbox:checked");var H=new Array("SU","MO","TU","WE","TH","FR","SA");E=[];r.each(function(G){G=H.indexOf(b(this).val());C=new Date(h);C.setDate(h.getDate()+(G-h.getDay()+7)%7);if(C<p){B=Math.abs((p-h)/864E5);B-=B%(m*7);C.setDate(C.getDate()+B)}E.push(C)});i=7*m;break;case "monthly":if(((g-h.getFullYear())*12+i-(h.getMonth()+1))%m!=0)return;if(b('input[name="eo_input[schedule_meta]"]:checked').val()=="BYMONTHDAY="){var F=h.getDate();w=w.getDate();
|
12 |
+
if(F<=w)r=new Date(g,i,F)}else{g=Math.ceil(h.getDate()/7);F=h.getDay();if(g>=5){r=w.getDay();w=w.getDate()+(F-r-7)%7}else{r=p.getDay();w=(F-r+7)%7+(g-1)*7+1}r=new Date(p);r.setDate(w)}if(r<=n){g=b.datepicker.formatDate("yy-mm-dd",r);eo_occurrences_by_rule.push(g)}return;case "yearly":if((g-h.getFullYear())%m!=0)return;w=new Date(g,h.getMonth(),h.getDate());if(i==h.getMonth()&&w.getMonth()==h.getMonth()){r=new Date(h);r.setYear(g);if(r<=n){g=b.datepicker.formatDate("yy-mm-dd",r);eo_occurrences_by_rule.push(g)}}return;
|
13 |
+
default:return}for(F in E)for(r=new Date(E[F]);r<=w&&r<=n;){g=b.datepicker.formatDate("yy-mm-dd",r);eo_occurrences_by_rule.push(g);r.setDate(r.getDate()+i)}}}function j(g){var i=d(g);if(i[0]){i=i[1];i>-1?k(i):s(g)}else{i=i[1];i>-1?x(i):l(g)}z()}function l(g){b.inArray(g,eo_include_dates)<0&&eo_include_dates.push(g)}function k(g){eo_include_dates.splice(g,1)}function s(g){b.inArray(g,eo_exclude_dates)<0&&eo_exclude_dates.push(g)}function x(g){eo_exclude_dates.splice(g,1)}if(!Array.prototype.indexOf)Array.prototype.indexOf=
|
14 |
+
function(g,i){var t=this.length;i=Number(i)||0;i=i<0?Math.ceil(i):Math.floor(i);if(i<0)i+=t;for(;i<t;i++)if(i in this&&this[i]===g)return i;return-1};var u;if(b("#eo_occurrence_includes").length>0){eo_include_dates=b("#eo_occurrence_includes").val().split(",");eo_exclude_dates=b("#eo_occurrence_excludes").val().split(",")}b(document).ready(function(){b.widget("ui.combobox",{_create:function(){var g,i=this.element.hide(),t=i.children(":selected");t=t.val()?t.text():"";i=b("<span>").addClass("ui-combobox eo-venue-input").insertAfter(i);
|
15 |
+
g=b("<input>").appendTo(i).val(t).addClass("ui-combobox-input").autocomplete({delay:0,minLength:0,source:function(m,h){b.getJSON(EO_Ajax_Event.ajaxurl+"?callback=?&action=eo-search-venue",m,function(n){n=b.map(n,function(p){p.label=p.name;return p});h(n)})},select:function(m,h){if(b("tr.venue_row").length>0){h.item.term_id==0?b("tr.venue_row").hide():b("tr.venue_row").show();b("#eventorganiser_event_detail tr.eo-add-new-venue").hide();eo_initialize_map(h.item.venue_lat,h.item.venue_lng);b("#eo_venue_Lat").val(h.item.venue_lat);
|
16 |
+
b("#eo_venue_Lng").val(h.item.venue_lng)}b("#venue_select").removeAttr("selected");b("#venue_select").val(h.item.term_id)}}).addClass("ui-widget-content ui-corner-left");g.data("autocomplete")._renderItem=function(m,h){if(h.term_id==0)return b("<li></li>").data("item.autocomplete",h).append("<a>"+h.label+"</a>").appendTo(m);var n=[h.venue_address,h.venue_city,h.venue_state,h.venue_postcode,h.venue_country];n=b.grep(n,function(p){return p});return b("<li></li>").data("item.autocomplete",h).append("<a>"+
|
17 |
+
h.label+"</br> <span style='font-size: 0.8em'><em>"+n.join(", ")+"</span></em></a>").appendTo(m)};i=b("<span>").addClass("eo-venue-combobox-buttons").appendTo(i);b("<a style='vertical-align: top;margin: 0px -1px;padding: 0px;height: 21px;'>").attr("title","Show All Items").appendTo(i).button({icons:{primary:"ui-icon-triangle-1-s"},text:false}).removeClass("ui-corner-all").addClass("ui-corner-right ui-combobox-toggle ui-combobox-button").click(function(){if(g.autocomplete("widget").is(":visible"))g.autocomplete("close");
|
18 |
+
else{b(this).blur();g.autocomplete("search","");g.focus()}});"event"==pagenow&&EO_Ajax_Event.current_user_can.manage_venues&&b("<a style='vertical-align: top;margin: 0px -1px;padding: 0px;height: 21px;'>").attr("title","Create New Venue").appendTo(i).button({icons:{primary:"ui-icon-plus"},text:false}).removeClass("ui-corner-all").addClass("ui-corner-right add-new-venue ui-combobox-button").click(function(){b("#eventorganiser_event_detail tr.eo-add-new-venue").show();b("tr.venue_row").show();u={id:b("#venue_select").val(),
|
19 |
+
label:b(".eo-venue-input input").val(),lat:b("#eo_venue_Lat").val(),lng:b("#eo_venue_Lng").val()};b("#venue_select").removeAttr("selected").val(0);b(".eo-venue-combobox-select").hide();b(".eo-venue-input input").val("");eo_initialize_map(0,0);var m=EO_Ajax_Event.location;if(m){m=m.split("/");m=m[m.length-1];eventorganiser_code_address(m)}else map.setZoom(1);b(this).blur()})}});b("#venue_select").combobox()});b(".eo-add-new-venue-cancel").click(function(g){g.preventDefault();b(".eo-venue-combobox-select").show();
|
20 |
+
b(".eo-add-new-venue input").val("");eo_initialize_map(u.lat,u.lng);b("#venue_select").val(u.id);b(".eo-venue-input input").val(u.label);b("#eventorganiser_event_detail tr.eo-add-new-venue").hide()});var o=EO_Ajax_Event.locale;if(b("#eventorganiser_detail #from_date, #eventorganiser_detail #to_date").length>0){var D=b("#eventorganiser_detail #from_date, #eventorganiser_detail #to_date").datepicker({dateFormat:EO_Ajax_Event.format,changeMonth:true,changeYear:true,monthNamesShort:EO_Ajax_Event.locale.monthAbbrev,
|
21 |
+
dayNamesMin:EO_Ajax_Event.locale.dayAbbrev,firstDay:parseInt(EO_Ajax_Event.startday),buttonImage:"images/ui-icon-calendar.png",onSelect:function(g){var i=this.id=="from_date"?"minDate":"maxDate",t=b(this).data("datepicker");g=b.datepicker.parseDate(t.settings.dateFormat||b.datepicker._defaults.dateFormat,g,t.settings);D.not(this).datepicker("option",i,g);this.id=="from_date"&&b("#recend").datepicker("option","minDate",g);c();v()}});b("#recend").datepicker({dateFormat:EO_Ajax_Event.format,monthNamesShort:EO_Ajax_Event.locale.monthAbbrev,
|
22 |
+
dayNamesMin:EO_Ajax_Event.locale.dayAbbrev,changeMonth:true,changeYear:true,firstDay:parseInt(EO_Ajax_Event.startday)});b("#HWSEvent_time, #HWSEvent_time2").timepicker({showPeriodLabels:false,hourText:EO_Ajax_Event.locale.hour,minuteText:EO_Ajax_Event.locale.minute});b("#HWSEvent_rec").click(function(){v()});b(".reoccurence .event-date :input, .onetime .event-date :input").not(".eo_time").change(function(){v();b(this).attr("id")!="eo_allday"&&c()});v();var y=!b(this).prop("checked");b(".reoccurence .event-date :input").attr("disabled",
|
23 |
+
y);b(".reoccurence .event-date :input").toggleClass("ui-state-disabled",y)}b(".eo_occurrence_toogle").click(function(g){g.preventDefault();g.stopPropagation();A.toggle();A.is(":visible")?b(".eo_occurrence_toogle").val(EO_Ajax_Event.locale.hideDates):b(".eo_occurrence_toogle").val(EO_Ajax_Event.locale.showDates)});y=new Date;f(y.getFullYear(),y.getMonth()+1,{});var A=b("#eo_occurrence_datepicker");A.length>0&&A.datepicker({dateFormat:"yy-mm-dd",onSelect:j,beforeShowDay:e,onChangeMonthYear:f,changeMonth:true,
|
24 |
+
changeYear:true,monthNamesShort:EO_Ajax_Event.locale.monthAbbrev,dayNamesMin:EO_Ajax_Event.locale.dayAbbrev,firstDay:parseInt(EO_Ajax_Event.startday)}).hide();b("html").click(function(){A.hide()});A.find(".ui-datepicker-inline").click(function(g){if(!g)g=window.event;g.cancelBubble=true;g.stopPropagation&&g.stopPropagation()})});
|
25 |
+
var sprintf=function(){function b(q){return Object.prototype.toString.call(q).slice(8,-1).toLowerCase()}function z(q,a){for(var c=[];a>0;c[--a]=q);return c.join("")}var v=function(){v.cache.hasOwnProperty(arguments[0])||(v.cache[arguments[0]]=v.parse(arguments[0]));return v.format.call(null,v.cache[arguments[0]],arguments)};v.format=function(q,a){var c=1,e=q.length,d="",f=[],j,l,k,s;for(j=0;j<e;j++){d=b(q[j]);if(d==="string")f.push(q[j]);else if(d==="array"){k=q[j];if(k[2]){d=a[c];for(l=0;l<k[2].length;l++){if(!d.hasOwnProperty(k[2][l]))throw sprintf('[sprintf] property "%s" does not exist',
|
26 |
+
k[2][l]);d=d[k[2][l]]}}else d=k[1]?a[k[1]]:a[c++];if(/[^s]/.test(k[8])&&b(d)!="number")throw sprintf("[sprintf] expecting number but found %s",b(d));switch(k[8]){case "b":d=d.toString(2);break;case "c":d=String.fromCharCode(d);break;case "d":d=parseInt(d,10);break;case "e":d=k[7]?d.toExponential(k[7]):d.toExponential();break;case "f":d=k[7]?parseFloat(d).toFixed(k[7]):parseFloat(d);break;case "o":d=d.toString(8);break;case "s":d=(d=String(d))&&k[7]?d.substring(0,k[7]):d;break;case "u":d=Math.abs(d);
|
27 |
+
break;case "x":d=d.toString(16);break;case "X":d=d.toString(16).toUpperCase();break}d=/[def]/.test(k[8])&&k[3]&&d>=0?"+"+d:d;l=k[4]?k[4]=="0"?"0":k[4].charAt(1):" ";s=k[6]-String(d).length;l=k[6]?z(l,s):"";f.push(k[5]?d+l:l+d)}}return f.join("")};v.cache={};v.parse=function(q){q=q;for(var a=[],c=[],e=0;q;){if((a=/^[^\x25]+/.exec(q))!==null)c.push(a[0]);else if((a=/^\x25{2}/.exec(q))!==null)c.push("%");else if((a=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(q))!==
|
28 |
+
null){if(a[2]){e|=1;var d=[],f=a[2],j=[];if((j=/^([a-z_][a-z_\d]*)/i.exec(f))!==null)for(d.push(j[1]);(f=f.substring(j[0].length))!=="";)if((j=/^\.([a-z_][a-z_\d]*)/i.exec(f))!==null)d.push(j[1]);else if((j=/^\[(\d+)\]/.exec(f))!==null)d.push(j[1]);else throw"[sprintf] huh?";else throw"[sprintf] huh?";a[2]=d}else e|=2;if(e===3)throw"[sprintf] mixing positional and named placeholders is not (yet) supported";c.push(a)}else throw"[sprintf] huh?";q=q.substring(a[0].length)}return c};return v}(),vsprintf=
|
29 |
+
function(b,z){z.unshift(b);return sprintf.apply(null,z)};
|
30 |
+
(function(b){function z(){this._curInst=null;this._disabledInputs=[];this._inDialog=this._timepickerShowing=false;this._dialogClass="ui-timepicker-dialog";this._mainDivId="ui-timepicker-div";this._inlineClass="ui-timepicker-inline";this._currentClass="ui-timepicker-current";this._dayOverClass="ui-timepicker-days-cell-over";this.regional=[];this.regional[""]={hourText:"Hour",minuteText:"Minute",amPmText:["AM","PM"],closeButtonText:"Done",nowButtonText:"Now",deselectButtonText:"Deselect"};this._defaults=
|
31 |
+
{showOn:"focus",button:null,showAnim:"fadeIn",showOptions:{},appendText:"",beforeShow:null,onSelect:null,onClose:null,timeSeparator:":",periodSeparator:" ",showPeriod:false,showPeriodLabels:true,showLeadingZero:true,showMinutesLeadingZero:true,altField:"",defaultTime:"now",myPosition:"left top",atPosition:"left bottom",onHourShow:null,onMinuteShow:null,hours:{starts:0,ends:23},minutes:{starts:0,ends:55,interval:5},rows:4,showHours:true,showMinutes:true,optionalMinutes:false,showCloseButton:false,
|
32 |
+
showNowButton:false,showDeselectButton:false};b.extend(this._defaults,this.regional[""]);this.tpDiv=b('<div id="'+this._mainDivId+'" class="ui-timepicker ui-widget ui-helper-clearfix ui-corner-all " style="display: none"></div>')}function v(a,c){b.extend(a,c);for(var e in c)if(c[e]==null||c[e]==undefined)a[e]=c[e];return a}b.extend(b.ui,{timepicker:{version:"0.3.1"}});var q=(new Date).getTime();b.extend(z.prototype,{markerClassName:"hasTimepicker",log:function(){},_widgetTimepicker:function(){return this.tpDiv},
|
33 |
+
setDefaults:function(a){v(this._defaults,a||{});return this},_attachTimepicker:function(a,c){var e=null;for(var d in this._defaults){var f=a.getAttribute("time:"+d);if(f){e=e||{};try{e[d]=eval(f)}catch(j){e[d]=f}}}d=a.nodeName.toLowerCase();f=d=="div"||d=="span";if(!a.id){this.uuid+=1;a.id="tp"+this.uuid}var l=this._newInst(b(a),f);l.settings=b.extend({},c||{},e||{});if(d=="input"){this._connectTimepicker(a,l);this._setTimeFromField(l)}else f&&this._inlineTimepicker(a,l)},_newInst:function(a,c){return{id:a[0].id.replace(/([^A-Za-z0-9_-])/g,
|
34 |
+
"\\\\$1"),input:a,inline:c,tpDiv:!c?this.tpDiv:b('<div class="'+this._inlineClass+' ui-timepicker ui-widget ui-helper-clearfix"></div>')}},_connectTimepicker:function(a,c){var e=b(a);c.append=b([]);c.trigger=b([]);if(!e.hasClass(this.markerClassName)){this._attachments(e,c);e.addClass(this.markerClassName).keydown(this._doKeyDown).keyup(this._doKeyUp).bind("setData.timepicker",function(d,f,j){c.settings[f]=j}).bind("getData.timepicker",function(d,f){return this._get(c,f)});b.data(a,"timepicker",
|
35 |
+
c)}},_doKeyDown:function(a){var c=b.timepicker._getInst(a.target),e=true;c._keyEvent=true;if(b.timepicker._timepickerShowing)switch(a.keyCode){case 9:b.timepicker._hideTimepicker();e=false;break;case 13:b.timepicker._updateSelectedValue(c);b.timepicker._hideTimepicker();return false;case 27:b.timepicker._hideTimepicker();break;default:e=false}else if(a.keyCode==36&&a.ctrlKey)b.timepicker._showTimepicker(this);else e=false;if(e){a.preventDefault();a.stopPropagation()}},_doKeyUp:function(a){a=b.timepicker._getInst(a.target);
|
36 |
+
b.timepicker._setTimeFromField(a);b.timepicker._updateTimepicker(a)},_attachments:function(a,c){var e=this._get(c,"appendText"),d=this._get(c,"isRTL");c.append&&c.append.remove();if(e){c.append=b('<span class="'+this._appendClass+'">'+e+"</span>");a[d?"before":"after"](c.append)}a.unbind("focus.timepicker",this._showTimepicker);a.unbind("click.timepicker",this._adjustZIndex);c.trigger&&c.trigger.remove();e=this._get(c,"showOn");if(e=="focus"||e=="both"){a.bind("focus.timepicker",this._showTimepicker);
|
37 |
+
a.bind("click.timepicker",this._adjustZIndex)}if(e=="button"||e=="both"){e=this._get(c,"button");b(e).bind("click.timepicker",function(){if(b.timepicker._timepickerShowing&&b.timepicker._lastInput==a[0])b.timepicker._hideTimepicker();else c.input.is(":disabled")||b.timepicker._showTimepicker(a[0]);return false})}},_inlineTimepicker:function(a,c){var e=b(a);if(!e.hasClass(this.markerClassName)){e.addClass(this.markerClassName).append(c.tpDiv).bind("setData.timepicker",function(d,f,j){c.settings[f]=
|
38 |
+
j}).bind("getData.timepicker",function(d,f){return this._get(c,f)});b.data(a,"timepicker",c);this._setTimeFromField(c);this._updateTimepicker(c);c.tpDiv.show()}},_adjustZIndex:function(a){a=a.target||a;b.timepicker._getInst(a).tpDiv.css("zIndex",b.timepicker._getZIndex(a)+1)},_showTimepicker:function(a){a=a.target||a;if(a.nodeName.toLowerCase()!="input")a=b("input",a.parentNode)[0];if(!(b.timepicker._isDisabledTimepicker(a)||b.timepicker._lastInput==a)){b.timepicker._hideTimepicker();var c=b.timepicker._getInst(a);
|
39 |
+
b.timepicker._curInst&&b.timepicker._curInst!=c&&b.timepicker._curInst.tpDiv.stop(true,true);var e=b.timepicker._get(c,"beforeShow");v(c.settings,e?e.apply(a,[a,c]):{});c.lastVal=null;b.timepicker._lastInput=a;b.timepicker._setTimeFromField(c);if(b.timepicker._inDialog)a.value="";if(!b.timepicker._pos){b.timepicker._pos=b.timepicker._findPos(a);b.timepicker._pos[1]+=a.offsetHeight}var d=false;b(a).parents().each(function(){d|=b(this).css("position")=="fixed";return!d});if(d&&b.browser.opera){b.timepicker._pos[0]-=
|
40 |
+
document.documentElement.scrollLeft;b.timepicker._pos[1]-=document.documentElement.scrollTop}e={left:b.timepicker._pos[0],top:b.timepicker._pos[1]};b.timepicker._pos=null;c.tpDiv.css({position:"absolute",display:"block",top:"-1000px"});b.timepicker._updateTimepicker(c);if(!c.inline&&typeof b.ui.position=="object"){c.tpDiv.position({of:c.input,my:b.timepicker._get(c,"myPosition"),at:b.timepicker._get(c,"atPosition"),collision:"flip"});e=c.tpDiv.offset();b.timepicker._pos=[e.top,e.left]}c._hoursClicked=
|
41 |
+
false;c._minutesClicked=false;e=b.timepicker._checkOffset(c,e,d);c.tpDiv.css({position:b.timepicker._inDialog&&b.blockUI?"static":d?"fixed":"absolute",display:"none",left:e.left+"px",top:e.top+"px"});if(!c.inline){e=b.timepicker._get(c,"showAnim");var f=b.timepicker._get(c,"duration"),j=function(){b.timepicker._timepickerShowing=true;var l=b.timepicker._getBorders(c.tpDiv);c.tpDiv.find("iframe.ui-timepicker-cover").css({left:-l[0],top:-l[1],width:c.tpDiv.outerWidth(),height:c.tpDiv.outerHeight()})};
|
42 |
+
b.timepicker._adjustZIndex(a);b.effects&&b.effects[e]?c.tpDiv.show(e,b.timepicker._get(c,"showOptions"),f,j):c.tpDiv[e||"show"](e?f:null,j);if(!e||!f)j();c.input.is(":visible")&&!c.input.is(":disabled")&&c.input.focus();b.timepicker._curInst=c}}},_getZIndex:function(a){a=b(a);for(var c;a.length&&a[0]!==document;){c=a.css("position");if(c==="absolute"||c==="relative"||c==="fixed"){c=parseInt(a.css("zIndex"),10);if(!isNaN(c)&&c!==0)return c}a=a.parent()}},_refreshTimepicker:function(a){(a=this._getInst(a))&&
|
43 |
+
this._updateTimepicker(a)},_updateTimepicker:function(a){a.tpDiv.empty().append(this._generateHTML(a));this._rebindDialogEvents(a)},_rebindDialogEvents:function(a){var c=b.timepicker._getBorders(a.tpDiv),e=this;a.tpDiv.find("iframe.ui-timepicker-cover").css({left:-c[0],top:-c[1],width:a.tpDiv.outerWidth(),height:a.tpDiv.outerHeight()}).end().find(".ui-timepicker-minute-cell").unbind().bind("click",{fromDoubleClick:false},b.proxy(b.timepicker.selectMinutes,this)).bind("dblclick",{fromDoubleClick:true},
|
44 |
+
b.proxy(b.timepicker.selectMinutes,this)).end().find(".ui-timepicker-hour-cell").unbind().bind("click",{fromDoubleClick:false},b.proxy(b.timepicker.selectHours,this)).bind("dblclick",{fromDoubleClick:true},b.proxy(b.timepicker.selectHours,this)).end().find(".ui-timepicker td a").unbind().bind("mouseout",function(){b(this).removeClass("ui-state-hover");this.className.indexOf("ui-timepicker-prev")!=-1&&b(this).removeClass("ui-timepicker-prev-hover");this.className.indexOf("ui-timepicker-next")!=-1&&
|
45 |
+
b(this).removeClass("ui-timepicker-next-hover")}).bind("mouseover",function(){if(!e._isDisabledTimepicker(a.inline?a.tpDiv.parent()[0]:a.input[0])){b(this).parents(".ui-timepicker-calendar").find("a").removeClass("ui-state-hover");b(this).addClass("ui-state-hover");this.className.indexOf("ui-timepicker-prev")!=-1&&b(this).addClass("ui-timepicker-prev-hover");this.className.indexOf("ui-timepicker-next")!=-1&&b(this).addClass("ui-timepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end().find(".ui-timepicker-now").bind("click",
|
46 |
+
function(d){b.timepicker.selectNow(d)}).end().find(".ui-timepicker-deselect").bind("click",function(d){b.timepicker.deselectTime(d)}).end().find(".ui-timepicker-close").bind("click",function(){b.timepicker._hideTimepicker()}).end()},_generateHTML:function(a){var c,e,d,f,j=this._get(a,"showPeriod")==true,l=this._get(a,"showPeriodLabels")==true,k=this._get(a,"showLeadingZero")==true;e=this._get(a,"showHours")==true;var s=this._get(a,"showMinutes")==true,x=this._get(a,"amPmText"),u=this._get(a,"rows"),
|
47 |
+
o=0,D=0,y=f=0,A=0,g=0,i=Array(),t=this._get(a,"hours");c=null;var m=0;d=this._get(a,"hourText");var h=this._get(a,"showCloseButton"),n=this._get(a,"closeButtonText"),p=this._get(a,"showNowButton"),w=this._get(a,"nowButtonText"),B=this._get(a,"showDeselectButton"),E=this._get(a,"deselectButtonText"),C=h||p||B;for(c=t.starts;c<=t.ends;c++)i.push(c);c=Math.ceil(i.length/u);if(l){for(m=0;m<i.length;m++)if(i[m]<12)f++;else y++;m=0;o=Math.floor(f/i.length*u);D=Math.floor(y/i.length*u);if(u!=o+D)if(f&&(!y||
|
48 |
+
!o||D&&f/o>=y/D))o++;else D++;A=Math.min(o,1);g=o+1;c=Math.ceil(Math.max(f/o,y/D))}f='<table class="ui-timepicker-table ui-widget-content ui-corner-all"><tr>';if(e){f+='<td class="ui-timepicker-hours"><div class="ui-timepicker-title ui-widget-header ui-helper-clearfix ui-corner-all">'+d+'</div><table class="ui-timepicker">';for(e=1;e<=u;e++){f+="<tr>";if(e==A&&l)f+='<th rowspan="'+o.toString()+'" class="periods" scope="row">'+x[0]+"</th>";if(e==g&&l)f+='<th rowspan="'+D.toString()+'" class="periods" scope="row">'+
|
49 |
+
x[1]+"</th>";for(d=1;d<=c;d++)if(l&&e<g&&i[m]>=12)f+=this._generateHTMLHourCell(a,undefined,j,k);else{f+=this._generateHTMLHourCell(a,i[m],j,k);m++}f+="</tr>"}f+="</tr></table></td>"}if(s){f+='<td class="ui-timepicker-minutes">';f+=this._generateHTMLMinutes(a);f+="</td>"}f+="</tr>";if(C){j='<tr><td colspan="3"><div class="ui-timepicker-buttonpane ui-widget-content">';if(p)j+='<button type="button" class="ui-timepicker-now ui-state-default ui-corner-all" data-timepicker-instance-id="#'+a.id.replace(/\\\\/g,
|
50 |
+
"\\")+'" >'+w+"</button>";if(B)j+='<button type="button" class="ui-timepicker-deselect ui-state-default ui-corner-all" data-timepicker-instance-id="#'+a.id.replace(/\\\\/g,"\\")+'" >'+E+"</button>";if(h)j+='<button type="button" class="ui-timepicker-close ui-state-default ui-corner-all" data-timepicker-instance-id="#'+a.id.replace(/\\\\/g,"\\")+'" >'+n+"</button>";f+=j+"</div></td></tr>"}f+="</table>";f+=b.browser.msie&&parseInt(b.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-timepicker-cover" frameborder="0"></iframe>':
|
51 |
+
"";return f},_updateMinuteDisplay:function(a){var c=this._generateHTMLMinutes(a);a.tpDiv.find("td.ui-timepicker-minutes").html(c);this._rebindDialogEvents(a)},_generateHTMLMinutes:function(a){var c,e,d="",f=this._get(a,"rows"),j=Array();e=this._get(a,"minutes");var l=null,k=0,s=this._get(a,"showMinutesLeadingZero")==true,x=this._get(a,"onMinuteShow"),u=this._get(a,"minuteText");if(!e.starts)e.starts=0;if(!e.ends)e.ends=59;for(c=e.starts;c<=e.ends;c+=e.interval)j.push(c);l=Math.round(j.length/f+0.49);
|
52 |
+
if(x&&x.apply(a.input?a.input[0]:null,[a.hours,a.minutes])==false)for(k=0;k<j.length;k+=1){c=j[k];if(x.apply(a.input?a.input[0]:null,[a.hours,c])){a.minutes=c;break}}d+='<div class="ui-timepicker-title ui-widget-header ui-helper-clearfix ui-corner-all">'+u+'</div><table class="ui-timepicker">';k=0;for(e=1;e<=f;e++){for(d+="<tr>";k<e*l;){c=j[k];x="";if(c!==undefined)x=c<10&&s?"0"+c.toString():c.toString();d+=this._generateHTMLMinuteCell(a,c,x);k++}d+="</tr>"}d+="</table>";return d},_generateHTMLHourCell:function(a,
|
53 |
+
c,e,d){var f=c;if(c>12&&e)f=c-12;if(f==0&&e)f=12;if(f<10&&d)f="0"+f;e="";e=true;d=this._get(a,"onHourShow");if(c==undefined)return e='<td><span class="ui-state-default ui-state-disabled"> </span></td>';if(d)e=d.apply(a.input?a.input[0]:null,[c]);return e=e?'<td class="ui-timepicker-hour-cell" data-timepicker-instance-id="#'+a.id.replace(/\\\\/g,"\\")+'" data-hour="'+c.toString()+'"><a class="ui-state-default '+(c==a.hours?"ui-state-active":"")+'">'+f.toString()+"</a></td>":'<td><span class="ui-state-default ui-state-disabled '+
|
54 |
+
(c==a.hours?" ui-state-active ":" ")+'">'+f.toString()+"</span></td>"},_generateHTMLMinuteCell:function(a,c,e){var d="";d=true;var f=this._get(a,"onMinuteShow");if(f)d=f.apply(a.input?a.input[0]:null,[a.hours,c]);if(c==undefined)return d='<td><span class="ui-state-default ui-state-disabled"> </span></td>';return d=d?'<td class="ui-timepicker-minute-cell" data-timepicker-instance-id="#'+a.id.replace(/\\\\/g,"\\")+'" data-minute="'+c.toString()+'" ><a class="ui-state-default '+(c==a.minutes?"ui-state-active":
|
55 |
+
"")+'" >'+e+"</a></td>":'<td><span class="ui-state-default ui-state-disabled" >'+e+"</span></td>"},_destroyTimepicker:function(a){var c=b(a),e=b.data(a,"timepicker");if(c.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();b.removeData(a,"timepicker");if(d=="input"){e.append.remove();e.trigger.remove();c.removeClass(this.markerClassName).unbind("focus.timepicker",this._showTimepicker).unbind("click.timepicker",this._adjustZIndex)}else if(d=="div"||d=="span")c.removeClass(this.markerClassName).empty()}},
|
56 |
+
_enableTimepicker:function(a){var c=b(a),e=c.attr("id"),d=b.data(a,"timepicker");if(c.hasClass(this.markerClassName)){var f=a.nodeName.toLowerCase();if(f=="input"){a.disabled=false;a=this._get(d,"button");b(a).removeClass("ui-state-disabled").disabled=false;d.trigger.filter("button").each(function(){this.disabled=false}).end()}else if(f=="div"||f=="span"){d=c.children("."+this._inlineClass);d.children().removeClass("ui-state-disabled");d.find("button").each(function(){this.disabled=false})}this._disabledInputs=
|
57 |
+
b.map(this._disabledInputs,function(j){return j==e?null:j})}},_disableTimepicker:function(a){var c=b(a),e=b.data(a,"timepicker");if(c.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();if(d=="input"){d=this._get(e,"button");b(d).addClass("ui-state-disabled").disabled=true;a.disabled=true;e.trigger.filter("button").each(function(){this.disabled=true}).end()}else if(d=="div"||d=="span"){e=c.children("."+this._inlineClass);e.children().addClass("ui-state-disabled");e.find("button").each(function(){this.disabled=
|
58 |
+
true})}this._disabledInputs=b.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=c.attr("id")}},_isDisabledTimepicker:function(a){if(!a)return false;for(var c=0;c<this._disabledInputs.length;c++)if(this._disabledInputs[c]==a)return true;return false},_checkOffset:function(a,c,e){var d=a.tpDiv.outerWidth(),f=a.tpDiv.outerHeight(),j=a.input?a.input.outerWidth():0,l=a.input?a.input.outerHeight():0,k=document.documentElement.clientWidth+b(document).scrollLeft(),
|
59 |
+
s=document.documentElement.clientHeight+b(document).scrollTop();c.left-=this._get(a,"isRTL")?d-j:0;c.left-=e&&c.left==a.input.offset().left?b(document).scrollLeft():0;c.top-=e&&c.top==a.input.offset().top+l?b(document).scrollTop():0;c.left-=Math.min(c.left,c.left+d>k&&k>d?Math.abs(c.left+d-k):0);c.top-=Math.min(c.top,c.top+f>s&&s>f?Math.abs(f+l):0);return c},_findPos:function(a){for(var c=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[c?"previousSibling":"nextSibling"];
|
60 |
+
a=b(a).offset();return[a.left,a.top]},_getBorders:function(a){var c=function(e){return{thin:1,medium:2,thick:3}[e]||e};return[parseFloat(c(a.css("border-left-width"))),parseFloat(c(a.css("border-top-width")))]},_checkExternalClick:function(a){if(b.timepicker._curInst){a=b(a.target);a[0].id!=b.timepicker._mainDivId&&a.parents("#"+b.timepicker._mainDivId).length==0&&!a.hasClass(b.timepicker.markerClassName)&&!a.hasClass(b.timepicker._triggerClass)&&b.timepicker._timepickerShowing&&!(b.timepicker._inDialog&&
|
61 |
+
b.blockUI)&&b.timepicker._hideTimepicker()}},_hideTimepicker:function(a){var c=this._curInst;if(!(!c||a&&c!=b.data(a,"timepicker")))if(this._timepickerShowing){a=this._get(c,"showAnim");var e=this._get(c,"duration"),d=function(){b.timepicker._tidyDialog(c);this._curInst=null};b.effects&&b.effects[a]?c.tpDiv.hide(a,b.timepicker._get(c,"showOptions"),e,d):c.tpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?e:null,d);a||d();this._timepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",
|
62 |
+
left:"0",top:"-100px"});if(b.blockUI){b.unblockUI();b("body").append(this.tpDiv)}}this._inDialog=false;if(a=this._get(c,"onClose"))a.apply(c.input?c.input[0]:null,[c.input?c.input.val():"",c])}},_tidyDialog:function(a){a.tpDiv.removeClass(this._dialogClass).unbind(".ui-timepicker")},_getInst:function(a){try{return b.data(a,"timepicker")}catch(c){throw"Missing instance data for this timepicker";}},_get:function(a,c){return a.settings[c]!==undefined?a.settings[c]:this._defaults[c]},_setTimeFromField:function(a){if(a.input.val()!=
|
63 |
+
a.lastVal){var c=this._get(a,"defaultTime");c=c=="now"?this._getCurrentTimeRounded(a):c;if(a.inline==false&&a.input.val()!="")c=a.input.val();if(c instanceof Date){a.hours=c.getHours();a.minutes=c.getMinutes()}else{var e=a.lastVal=c;if(c==""){a.hours=-1;a.minutes=-1}else{c=this.parseTime(a,e);a.hours=c.hours;a.minutes=c.minutes}}b.timepicker._updateTimepicker(a)}},_optionTimepicker:function(a,c,e){var d=this._getInst(a);if(arguments.length==2&&typeof c=="string")return c=="defaults"?b.extend({},b.timepicker._defaults):
|
64 |
+
d?c=="all"?b.extend({},d.settings):this._get(d,c):null;var f=c||{};if(typeof c=="string"){f={};f[c]=e}if(d){this._curInst==d&&this._hideTimepicker();v(d.settings,f);this._updateTimepicker(d)}},_setTimeTimepicker:function(a,c){if(a=this._getInst(a)){this._setTime(a,c);this._updateTimepicker(a);this._updateAlternate(a,c)}},_setTime:function(a,c,e){var d=a.hours,f=a.minutes;c=this.parseTime(a,c);a.hours=c.hours;a.minutes=c.minutes;if((d!=a.hours||f!=a.minuts)&&!e)a.input.trigger("change");this._updateTimepicker(a);
|
65 |
+
this._updateSelectedValue(a)},_getCurrentTimeRounded:function(){var a=new Date,c=a.getMinutes();c=Math.round(c/5)*5;a.setMinutes(c);return a},parseTime:function(a,c){var e={};e.hours=-1;e.minutes=-1;var d=this._get(a,"timeSeparator"),f=this._get(a,"amPmText"),j=this._get(a,"showHours"),l=this._get(a,"showMinutes"),k=this._get(a,"optionalMinutes");a=this._get(a,"showPeriod")==true;d=c.indexOf(d);if(d!=-1){e.hours=parseInt(c.substr(0,d),10);e.minutes=parseInt(c.substr(d+1),10)}else if(j&&(!l||k))e.hours=
|
66 |
+
parseInt(c,10);else if(!j&&l)e.minutes=parseInt(c,10);if(j){c=c.toUpperCase();if(e.hours<12&&a&&c.indexOf(f[1].toUpperCase())!=-1)e.hours+=12;if(e.hours==12&&a&&c.indexOf(f[0].toUpperCase())!=-1)e.hours=0}return e},selectNow:function(a){a=b(a.target).attr("data-timepicker-instance-id");a=this._getInst(b(a)[0]);var c=new Date;a.hours=c.getHours();a.minutes=c.getMinutes();this._updateSelectedValue(a);this._updateTimepicker(a);this._hideTimepicker()},deselectTime:function(a){a=b(a.target).attr("data-timepicker-instance-id");
|
67 |
+
a=this._getInst(b(a)[0]);a.hours=-1;a.minutes=-1;this._updateSelectedValue(a);this._hideTimepicker()},selectHours:function(a){var c=b(a.currentTarget),e=c.attr("data-timepicker-instance-id"),d=parseInt(c.attr("data-hour"));a=a.data.fromDoubleClick;e=b(e);var f=this._getInst(e[0]),j=this._get(f,"showMinutes")==true;if(b.timepicker._isDisabledTimepicker(e.attr("id")))return false;c.parents(".ui-timepicker-hours:first").find("a").removeClass("ui-state-active");c.children("a").addClass("ui-state-active");
|
68 |
+
f.hours=d;this._get(f,"onMinuteShow")&&this._updateMinuteDisplay(f);this._updateSelectedValue(f);f._hoursClicked=true;if(f._minutesClicked||a||j==false)b.timepicker._hideTimepicker();return false},selectMinutes:function(a){var c=b(a.currentTarget),e=c.attr("data-timepicker-instance-id"),d=parseInt(c.attr("data-minute"));a=a.data.fromDoubleClick;e=b(e);var f=this._getInst(e[0]),j=this._get(f,"showHours")==true;if(b.timepicker._isDisabledTimepicker(e.attr("id")))return false;c.parents(".ui-timepicker-minutes:first").find("a").removeClass("ui-state-active");
|
69 |
+
c.children("a").addClass("ui-state-active");f.minutes=d;this._updateSelectedValue(f);f._minutesClicked=true;if(f._hoursClicked||a||j==false){b.timepicker._hideTimepicker();return false}return false},_updateSelectedValue:function(a){var c=this._getParsedTime(a);if(a.input){a.input.val(c);a.input.trigger("change")}var e=this._get(a,"onSelect");if(e)e.apply(a.input?a.input[0]:null,[c,a]);this._updateAlternate(a,c);return c},_getParsedTime:function(a){if(a.hours==-1&&a.minutes==-1)return"";if(a.hours<
|
70 |
+
a.hours.starts||a.hours>a.hours.ends)a.hours=0;if(a.minutes<a.minutes.starts||a.minutes>a.minutes.ends)a.minutes=0;var c="",e=this._get(a,"showPeriod")==true,d=this._get(a,"showLeadingZero")==true,f=this._get(a,"showHours")==true,j=this._get(a,"showMinutes")==true,l=this._get(a,"optionalMinutes")==true,k=this._get(a,"amPmText"),s=a.hours?a.hours:0,x=a.minutes?a.minutes:0,u=s?s:0;s="";if(e){if(a.hours==0)u=12;if(a.hours<12)c=k[0];else{c=k[1];if(u>12)u-=12}}e=u.toString();if(d&&u<10)e="0"+e;d=x.toString();
|
71 |
+
if(x<10)d="0"+d;if(f)s+=e;if(f&&j&&(!l||d!=0))s+=this._get(a,"timeSeparator");if(j&&(!l||d!=0))s+=d;if(f)if(c.length>0)s+=this._get(a,"periodSeparator")+c;return s},_updateAlternate:function(a,c){(a=this._get(a,"altField"))&&b(a).each(function(e,d){b(d).val(c)})},_getTimeTimepicker:function(a){return this._getParsedTime(this._getInst(a))},_getHourTimepicker:function(a){a=this._getInst(a);if(a==undefined)return-1;return a.hours},_getMinuteTimepicker:function(a){a=this._getInst(a);if(a==undefined)return-1;
|
72 |
+
return a.minutes}});b.fn.timepicker=function(a){if(!b.timepicker.initialized){b(document).mousedown(b.timepicker._checkExternalClick).find("body").append(b.timepicker.tpDiv);b.timepicker.initialized=true}var c=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="getTime"||a=="getHour"||a=="getMinute"))return b.timepicker["_"+a+"Timepicker"].apply(b.timepicker,[this[0]].concat(c));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return b.timepicker["_"+a+"Timepicker"].apply(b.timepicker,
|
73 |
+
[this[0]].concat(c));return this.each(function(){typeof a=="string"?b.timepicker["_"+a+"Timepicker"].apply(b.timepicker,[this].concat(c)):b.timepicker._attachTimepicker(this,a)})};b.timepicker=new z;b.timepicker.initialized=false;b.timepicker.uuid=(new Date).getTime();b.timepicker.version="0.3.1";window["TP_jQuery_"+q]=b})(jQuery);
|
js/eventorganiser-pointer.js
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(document).ready( function($) {
|
2 |
+
eventorganiser_open_pointer(0);
|
3 |
+
function eventorganiser_open_pointer(i){
|
4 |
+
pointer = eventorganiserPointer.pointers[i];
|
5 |
+
options = jQuery.extend( pointer.options, {
|
6 |
+
close: function() {
|
7 |
+
jQuery.post( ajaxurl, {
|
8 |
+
pointer: pointer.pointer_id,
|
9 |
+
action: 'dismiss-wp-pointer'
|
10 |
+
});
|
11 |
+
},
|
12 |
+
});
|
13 |
+
|
14 |
+
jQuery(pointer.target).pointer( options ).pointer('open');
|
15 |
+
}
|
16 |
+
});
|
js/frontend.js
ADDED
@@ -0,0 +1,467 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
(function ($) {
|
2 |
+
jQuery(document).ready(function () {
|
3 |
+
|
4 |
+
function eventorganiser_cat_dropdown(options){
|
5 |
+
|
6 |
+
var terms = options.categories;
|
7 |
+
|
8 |
+
var html="<select class='eo-cal-filter' id='eo-event-cat'>";
|
9 |
+
html+="<option value=''>"+options.buttonText.cat+"</option>";
|
10 |
+
for (var i=0; i<terms.length; i++){
|
11 |
+
html+= "<option class='cat-colour-"+terms[i].colour+" cat' value='"+terms[i].slug+"'>"+terms[i].name+"</option>";
|
12 |
+
}
|
13 |
+
html+="</select>";
|
14 |
+
|
15 |
+
var element = $("<span class='fc-header-dropdown filter-category'></span>");
|
16 |
+
element.append(html);
|
17 |
+
return element;
|
18 |
+
}
|
19 |
+
|
20 |
+
function eventorganiser_mini_calendar(){
|
21 |
+
var element = $("<span class='fc-header-goto'><input type='hidden' class='eo-mini-calendar'/></span>");
|
22 |
+
return element;
|
23 |
+
}
|
24 |
+
|
25 |
+
function eventorganiser_venue_dropdown(options){
|
26 |
+
|
27 |
+
var venues = options.venues;
|
28 |
+
|
29 |
+
var html="<select class='eo-cal-filter' id='eo-event-venue'>";
|
30 |
+
html+="<option value=''>"+options.buttonText.venue+"</option>";
|
31 |
+
|
32 |
+
for (var i=0; i<venues.length; i++){
|
33 |
+
html+= "<option value='"+venues[i].term_id+"'>"+venues[i].name+"</option>";
|
34 |
+
}
|
35 |
+
html+="</select>";
|
36 |
+
var element = $("<span class='fc-header-dropdown filter-venue'></span>");
|
37 |
+
element.append(html);
|
38 |
+
return element;
|
39 |
+
}
|
40 |
+
|
41 |
+
|
42 |
+
if( $('#eo-upcoming-dates').length>0 && $('#eo-upcoming-dates').find('li:gt(4)').length > 0 ){
|
43 |
+
var eobloc = 5;
|
44 |
+
var locale = { more : EOAjaxFront.locale.ShowMore, less : EOAjaxFront.locale.ShowLess};
|
45 |
+
$('#eo-upcoming-dates').find('li:gt('+(eobloc-1)+')').hide().end().after(
|
46 |
+
$('<a href="#" id="eo-upcoming-dates-less">'+locale.less+'</a> <span id="eo-upcoming-dates-pipe">|</span> <a href="#" id="eo-upcoming-dates-more">'+locale.more+'</a>')
|
47 |
+
);
|
48 |
+
$('#eo-upcoming-dates-pipe').hide();
|
49 |
+
$('#eo-upcoming-dates-less').hide().click(function(e){
|
50 |
+
e.preventDefault();
|
51 |
+
var index = Math.floor( ($('#eo-upcoming-dates li:visible').length -1) / eobloc)*eobloc -1;
|
52 |
+
$('#eo-upcoming-dates li:gt('+index+')').hide();
|
53 |
+
$('#eo-upcoming-dates-more,#eo-upcoming-dates-pipe').show();
|
54 |
+
if( $('#eo-upcoming-dates li:visible').length <= eobloc ){
|
55 |
+
$('#eo-upcoming-dates-less,#eo-upcoming-dates-pipe').hide();
|
56 |
+
}
|
57 |
+
});
|
58 |
+
$('#eo-upcoming-dates-more').click(function(e){
|
59 |
+
e.preventDefault();
|
60 |
+
$('#eo-upcoming-dates-less,#eo-upcoming-dates-pipe, #eo-upcoming-dates li:hidden:lt('+eobloc+')').show();
|
61 |
+
var offset = $('#eo-upcoming-dates-pipe').offset();
|
62 |
+
$('html, body').animate({
|
63 |
+
scrollTop: Math.max( offset.top + 40 - $(window).height(),$(window).scrollTop())
|
64 |
+
});
|
65 |
+
if( $('#eo-upcoming-dates li:hidden').length == 0 ){
|
66 |
+
$('#eo-upcoming-dates-more,#eo-upcoming-dates-pipe').hide();
|
67 |
+
}
|
68 |
+
});
|
69 |
+
}
|
70 |
+
|
71 |
+
if ($(".eo-fullcalendar").length > 0) {
|
72 |
+
var calendars = EOAjax.calendars;
|
73 |
+
var loadingTimeOut;
|
74 |
+
for (var i = 0; i < calendars.length; i++) {
|
75 |
+
var calendar = "#eo_fullcalendar_" + (i + 1);
|
76 |
+
|
77 |
+
if (typeof calendars[i].category === "undefined") {
|
78 |
+
calendars[i].category ='';
|
79 |
+
}
|
80 |
+
if (typeof calendars[i].venue === "undefined") {
|
81 |
+
calendars[i].venue ='';
|
82 |
+
}
|
83 |
+
$(calendar).fullCalendar({
|
84 |
+
id: calendar,
|
85 |
+
year: calendars[i].year ? calendars[i].year : undefined,
|
86 |
+
month: calendars[i].month ? calendars[i].month : undefined,
|
87 |
+
date: calendars[i].date ? calendars[i].date : undefined,
|
88 |
+
category: calendars[i].event_category,
|
89 |
+
venue: calendars[i].event_venue,
|
90 |
+
customButtons:{
|
91 |
+
category: eventorganiser_cat_dropdown,
|
92 |
+
venue: eventorganiser_venue_dropdown,
|
93 |
+
'goto': eventorganiser_mini_calendar
|
94 |
+
},
|
95 |
+
theme: true,
|
96 |
+
categories: EOAjax.fullcal.categories,
|
97 |
+
venues: EOAjax.fullcal.venues,
|
98 |
+
timeFormatphp: calendars[i].timeformatphp,
|
99 |
+
timeFormat: calendars[i].timeformat,
|
100 |
+
editable: false,
|
101 |
+
tooltip: calendars[i].tooltip,
|
102 |
+
firstDay: parseInt(EOAjax.fullcal.firstDay),
|
103 |
+
weekends: calendars[i].weekends,
|
104 |
+
allDaySlot: calendars[i].alldayslot,
|
105 |
+
allDayText: calendars[i].alldaytext,
|
106 |
+
axisFormat: calendars[i].axisformat,
|
107 |
+
minTime: calendars[i].mintime,
|
108 |
+
maxTime:calendars[i].maxtime,
|
109 |
+
columnFormat: {
|
110 |
+
month: calendars[i].columnformatmonth,
|
111 |
+
week: calendars[i].columnformatweek,
|
112 |
+
day: calendars[i].columnformatday
|
113 |
+
},
|
114 |
+
titleFormat: {
|
115 |
+
month: calendars[i].titleformatmonth,
|
116 |
+
week: calendars[i].titleformatweek,
|
117 |
+
day: calendars[i].titleformatday
|
118 |
+
},
|
119 |
+
header: {
|
120 |
+
left: calendars[i].headerleft,
|
121 |
+
center: calendars[i].headercenter,
|
122 |
+
right: calendars[i].headerright
|
123 |
+
},
|
124 |
+
eventRender: function (a, b, v) {
|
125 |
+
var c = $(v.calendar.options.id).find(".filter-category .eo-cal-filter").val();
|
126 |
+
var d = $(v.calendar.options.id).find(".filter-venue .eo-cal-filter").val();
|
127 |
+
|
128 |
+
if (typeof c !== "undefined" && c != "" && $.inArray(c, a.category) < 0) {
|
129 |
+
return "<div></div>";
|
130 |
+
}
|
131 |
+
if (typeof d !== "undefined" && d != "" && d != a.venue) {
|
132 |
+
return "<div></div>";
|
133 |
+
}
|
134 |
+
if (! v.calendar.options.tooltip ) {
|
135 |
+
return
|
136 |
+
}
|
137 |
+
|
138 |
+
$(b).qtip({
|
139 |
+
content: {
|
140 |
+
text: a.description,
|
141 |
+
button: "x",
|
142 |
+
title: a.title
|
143 |
+
},
|
144 |
+
position: {
|
145 |
+
my: "top center",
|
146 |
+
at: "bottom center"
|
147 |
+
},
|
148 |
+
hide: {
|
149 |
+
fixed: true,
|
150 |
+
delay: 500,
|
151 |
+
effect: function (a) {
|
152 |
+
$(this).fadeOut("50")
|
153 |
+
}
|
154 |
+
},
|
155 |
+
border: {
|
156 |
+
radius: 4,
|
157 |
+
width: 3
|
158 |
+
},
|
159 |
+
style: {
|
160 |
+
classes: "ui-tooltip-shadow",
|
161 |
+
widget: true,
|
162 |
+
tip: "topMiddle"
|
163 |
+
}
|
164 |
+
})
|
165 |
+
},
|
166 |
+
buttonText: {
|
167 |
+
today: EOAjaxFront.locale.today,
|
168 |
+
month: EOAjaxFront.locale.month,
|
169 |
+
week: EOAjaxFront.locale.week,
|
170 |
+
day: EOAjaxFront.locale.day,
|
171 |
+
cat: EOAjaxFront.locale.cat,
|
172 |
+
venue: EOAjaxFront.locale.venue
|
173 |
+
},
|
174 |
+
monthNames: EOAjaxFront.locale.monthNames,
|
175 |
+
monthNamesShort: EOAjaxFront.locale.monthAbbrev,
|
176 |
+
dayNames: EOAjaxFront.locale.dayNames,
|
177 |
+
dayNamesShort: EOAjaxFront.locale.dayAbbrev,
|
178 |
+
eventColor: "#21759B",
|
179 |
+
defaultView: calendars[i].defaultview,
|
180 |
+
lazyFetching: "true",
|
181 |
+
events: function (a, b, c, d) {
|
182 |
+
var request = {
|
183 |
+
start: jQuery.fullCalendar.formatDate(a, "yyyy-MM-dd"),
|
184 |
+
end: jQuery.fullCalendar.formatDate(b, "yyyy-MM-dd"),
|
185 |
+
timeformat:d.timeFormatphp
|
186 |
+
};
|
187 |
+
if (typeof d.category !== "undefined" &&d.category != "") {
|
188 |
+
request.category = d.category
|
189 |
+
}
|
190 |
+
if (typeof d.venue !== "undefined" &&d.venue != "") {
|
191 |
+
request.venue = d.venue
|
192 |
+
}
|
193 |
+
jQuery.ajax({
|
194 |
+
url: EOAjax.ajaxurl + "?action=eventorganiser-fullcal",
|
195 |
+
dataType: "JSON",
|
196 |
+
data: request,
|
197 |
+
success: c
|
198 |
+
})
|
199 |
+
},
|
200 |
+
selectable: false,
|
201 |
+
weekMode: "variable",
|
202 |
+
aspectRatio: 1.5,
|
203 |
+
loading: function (a) {
|
204 |
+
var loading = $("#" + $(this).attr("id") + "_loading");
|
205 |
+
if (a) {
|
206 |
+
window.clearTimeout(loadingTimeOut);
|
207 |
+
loadingTimeOut = window.setTimeout(function () {
|
208 |
+
loading.show()
|
209 |
+
}, 1e3)
|
210 |
+
} else {
|
211 |
+
window.clearTimeout(loadingTimeOut);
|
212 |
+
loading.hide()
|
213 |
+
}
|
214 |
+
}
|
215 |
+
})
|
216 |
+
}
|
217 |
+
|
218 |
+
$(".eo-cal-filter").change(function () {
|
219 |
+
$(".eo-fullcalendar").fullCalendar("rerenderEvents")
|
220 |
+
})
|
221 |
+
|
222 |
+
$('.eo-mini-calendar').datepicker({
|
223 |
+
dateFormat: 'DD, d MM, yy',
|
224 |
+
changeMonth: true,
|
225 |
+
changeYear: true,
|
226 |
+
dateFormat: 'DD, d MM, yy',
|
227 |
+
firstDay: parseInt(EOAjax.fullcal.firstDay),
|
228 |
+
buttonText: EOAjaxFront.locale.gotodate,
|
229 |
+
monthNamesShort: EOAjaxFront.locale.monthAbbrev,
|
230 |
+
dayNamesMin: EOAjaxFront.locale.dayAbbrev,
|
231 |
+
showOn: 'button',
|
232 |
+
onSelect: function (dateText, dp) {
|
233 |
+
var cal_id = $(this).parents('div.eo-fullcalendar').attr('id');
|
234 |
+
$('#'+cal_id).fullCalendar('gotoDate', new Date(Date.parse(dateText)));
|
235 |
+
}
|
236 |
+
});
|
237 |
+
}
|
238 |
+
|
239 |
+
if ($(".eo_widget_calendar").length > 0 ) {
|
240 |
+
|
241 |
+
$(".eo_widget_calendar tfoot").unbind("click");
|
242 |
+
$(".eo_widget_calendar").off("click").on("click", 'tfoot a', function (a) {
|
243 |
+
a.preventDefault();
|
244 |
+
var b = $(this).closest(".eo_widget_calendar").attr("id");
|
245 |
+
|
246 |
+
//Defaults
|
247 |
+
var cal = {showpastevents: 1};
|
248 |
+
|
249 |
+
//Shortcode widget calendar
|
250 |
+
if( typeof EOAjax !== "undefined" && typeof EOAjax.widget_calendars !== "undefined" ){
|
251 |
+
cal = EOAjax.widget_calendars[b];
|
252 |
+
}
|
253 |
+
//Widget calendar
|
254 |
+
if (typeof eo_widget_cal !== "undefined") {
|
255 |
+
cal = eo_widget_cal[b];
|
256 |
+
}
|
257 |
+
|
258 |
+
//Set month
|
259 |
+
cal.eo_month = eveorg_getParameterByName("eo_month", $(this).attr("href"));
|
260 |
+
|
261 |
+
$.getJSON(EOAjaxFront.adminajax + "?action=eo_widget_cal", cal,function (a) {$("#" + b + "_content").html(a)})
|
262 |
+
})
|
263 |
+
}
|
264 |
+
|
265 |
+
if ($('.eo-agenda-widget').length > 0) {
|
266 |
+
function getEvents(a, b) {
|
267 |
+
$.ajax({
|
268 |
+
url: EOAjaxFront.adminajax,
|
269 |
+
dataType: "JSON",
|
270 |
+
data: {
|
271 |
+
action: "eo_widget_agenda",
|
272 |
+
instance_number: b["number"],
|
273 |
+
direction: a,
|
274 |
+
start: b.StartDate,
|
275 |
+
end: b.EndDate
|
276 |
+
},
|
277 |
+
success: function (a) {
|
278 |
+
if (!jQuery.isArray(a) || !a[0]) {
|
279 |
+
return false
|
280 |
+
} else {
|
281 |
+
b["StartDate"] = a[0].StartDate;
|
282 |
+
b["EndDate"] = a[a.length - 1].StartDate;
|
283 |
+
populateAgenda(a, b)
|
284 |
+
}
|
285 |
+
}
|
286 |
+
})
|
287 |
+
}
|
288 |
+
function populateAgenda(a, b) {
|
289 |
+
var agendaWidget = $("#" + b.id + "_container");
|
290 |
+
var dateList = agendaWidget.find("ul.dates");
|
291 |
+
var dates = dateList.find("li");
|
292 |
+
$(dates).remove();
|
293 |
+
var current = "";
|
294 |
+
for (i = 0; i < a.length; i++) {
|
295 |
+
var d = new Date(a[i].StartDate);
|
296 |
+
if (current == "" || current != a[i].StartDate && b
|
297 |
+
.mode == "day") {
|
298 |
+
current = a[i].StartDate;
|
299 |
+
var currentList = $('<li class="date" >' + a[i].display + '<ul class="a-date"></ul></li>');
|
300 |
+
dateList.append(currentList)
|
301 |
+
}
|
302 |
+
if( b.add_to_google ){
|
303 |
+
var c = $('<li class="event"></li>').append('<span class="cat"></span><span><strong>' + a[i].time + ": </strong></span>" + a[i]
|
304 |
+
.post_title)
|
305 |
+
.append('<div class="meta" style="display:none;"><span>' + a[i].link + "</span><span> </span><span>" + a[i]
|
306 |
+
.Glink + "</span></div>");
|
307 |
+
}else{
|
308 |
+
var c = $('<li class="event"></li>').append("<a class='eo-agenda-event-permalink' href='"+a[i].event_url+"'><span class='cat'></span><span><strong>" + a[i].time + ": </strong></span>" + a[i]
|
309 |
+
.post_title+"</a>")
|
310 |
+
}
|
311 |
+
c.find("span.cat")
|
312 |
+
.css({
|
313 |
+
background: a[i].color
|
314 |
+
});
|
315 |
+
currentList.append(c)
|
316 |
+
}
|
317 |
+
dates = dateList.find("li");
|
318 |
+
var events_el = agendaWidget.find("ul li.event");
|
319 |
+
events_el.on("click", function () {
|
320 |
+
$(this).find(".meta")
|
321 |
+
.toggle("400")
|
322 |
+
})
|
323 |
+
}
|
324 |
+
for (var agenda in eo_widget_agenda) {
|
325 |
+
agenda = eo_widget_agenda[agenda];
|
326 |
+
var d = new Date;
|
327 |
+
agenda.StartDate = $.fullCalendar.formatDate(d, "yyyy-MM-dd");
|
328 |
+
agenda.EndDate = agenda.StartDate;
|
329 |
+
getEvents(1, agenda)
|
330 |
+
}
|
331 |
+
$(".eo-agenda-widget .agenda-nav span.button").click(function (a) {
|
332 |
+
var id = $(this).parents(".eo-agenda-widget").attr("id");
|
333 |
+
agenda = eo_widget_agenda[id];
|
334 |
+
a.preventDefault();
|
335 |
+
if ($(this).hasClass("next")) {
|
336 |
+
var dir = "+1"
|
337 |
+
} else if ($(this).hasClass("prev")) {
|
338 |
+
var dir = "-1"
|
339 |
+
} else {
|
340 |
+
var par = $(this).parent();
|
341 |
+
if (par.hasClass("prev")) {
|
342 |
+
var dir = "-1"
|
343 |
+
} else {
|
344 |
+
var dir = "+1"
|
345 |
+
}
|
346 |
+
}
|
347 |
+
getEvents(dir, agenda)
|
348 |
+
})
|
349 |
+
}
|
350 |
+
});
|
351 |
+
})(jQuery);
|
352 |
+
|
353 |
+
function eveorg_getParameterByName(a, b) {
|
354 |
+
a = a.replace(/[\[]/, "\\[")
|
355 |
+
.replace(/[\]]/, "\\]");
|
356 |
+
var c = "[\\?&]" + a + "=([^&#]*)";
|
357 |
+
var d = new RegExp(c);
|
358 |
+
var e = d.exec(b);
|
359 |
+
if (e == null) return "";
|
360 |
+
else return decodeURIComponent(e[1].replace(/\+/g, " "))
|
361 |
+
}
|
362 |
+
|
363 |
+
function eo_load_map() {
|
364 |
+
var maps = EOAjax.map;
|
365 |
+
for (var i = 0; i < maps.length; i++) {
|
366 |
+
|
367 |
+
if ( null === document.getElementById( "eo_venue_map-" + (i + 1) ) )
|
368 |
+
continue;
|
369 |
+
|
370 |
+
var locations = maps[i].locations;
|
371 |
+
var b = {
|
372 |
+
zoom: maps[i].zoom,
|
373 |
+
scrollwheel: maps[i].scrollwheel,
|
374 |
+
zoomControl: maps[i].zoomcontrol,
|
375 |
+
rotateControl: maps[i].rotatecontrol,
|
376 |
+
panControl: maps[i].pancontrol,
|
377 |
+
overviewMapControl: maps[i].overviewmapcontrol,
|
378 |
+
streetViewControl: maps[i].streetviewcontrol,
|
379 |
+
draggable: maps[i].draggable,
|
380 |
+
mapTypeControl: maps[i].maptypecontrol,
|
381 |
+
mapTypeId: google.maps.MapTypeId[maps[i].maptypeid]
|
382 |
+
};
|
383 |
+
var map = new google.maps.Map(document.getElementById("eo_venue_map-" + (i + 1)), b);
|
384 |
+
|
385 |
+
// Create a new viewpoint bound
|
386 |
+
var bounds = new google.maps.LatLngBounds();
|
387 |
+
|
388 |
+
var LatLngList = new Array();
|
389 |
+
for( var j=0; j<locations.length; j++){
|
390 |
+
var lat = locations[j].lat;
|
391 |
+
var lng = locations[j].lng;
|
392 |
+
if (lat !== undefined && lng != undefined) {
|
393 |
+
LatLngList.push(new google.maps.LatLng(lat, lng));
|
394 |
+
bounds.extend (LatLngList[j]);
|
395 |
+
var c = new google.maps.Marker({
|
396 |
+
position: LatLngList[j],
|
397 |
+
map: map,
|
398 |
+
content:locations[j].tooltipContent
|
399 |
+
});
|
400 |
+
if( 'false' != maps[i].tooltip ){
|
401 |
+
google.maps.event.addListener(c, 'click',eventorganiser_venue_tooltip);
|
402 |
+
}
|
403 |
+
}
|
404 |
+
}
|
405 |
+
|
406 |
+
if( locations.length > 1 ){
|
407 |
+
// Fit these bounds to the map
|
408 |
+
map.fitBounds (bounds);
|
409 |
+
//google.maps.event.addListenerOnce(map, 'zoom_changed', function() {map.setZoom(zoom);});
|
410 |
+
}else{
|
411 |
+
map.setCenter ( LatLngList[0]);
|
412 |
+
}
|
413 |
+
|
414 |
+
}//Foreach map
|
415 |
+
}
|
416 |
+
/**
|
417 |
+
* @constructor
|
418 |
+
*/
|
419 |
+
function eventorganiser_venue_tooltip() {
|
420 |
+
|
421 |
+
// Grab marker position: convert world point into pixel point
|
422 |
+
var map = this.getMap();
|
423 |
+
var pixel = this.getMap().getProjection().fromLatLngToPoint(this.position);
|
424 |
+
var topRight=map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
|
425 |
+
var bottomLeft=map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
|
426 |
+
var scale=Math.pow(2,map.getZoom());
|
427 |
+
pixel= new google.maps.Point((pixel.x- bottomLeft.x)*scale,(pixel.y-topRight.y)*scale);
|
428 |
+
|
429 |
+
//var pixel = LatLngToPixel.fromLatLngToContainerPixel(this.position);
|
430 |
+
var pos = [ pixel.x, pixel.y ];
|
431 |
+
|
432 |
+
if(this.tooltip){
|
433 |
+
this.tooltip.qtip('api').set('position.target', pos);
|
434 |
+
this.tooltip.qtip('show');
|
435 |
+
return;
|
436 |
+
}
|
437 |
+
jQuery(this.getMap().getDiv()).css({overflow: 'visible'});
|
438 |
+
|
439 |
+
// Create the tooltip on a dummy div and store it on the marker
|
440 |
+
this.tooltip =jQuery('<div />').qtip({
|
441 |
+
content: {
|
442 |
+
text: this.content
|
443 |
+
},
|
444 |
+
border: {
|
445 |
+
radius: 4,
|
446 |
+
width: 3
|
447 |
+
},
|
448 |
+
style: {
|
449 |
+
classes: "ui-tooltip-shadow",
|
450 |
+
widget: true
|
451 |
+
},
|
452 |
+
position: {
|
453 |
+
at: "right center",
|
454 |
+
my: "top center",
|
455 |
+
target: pos,
|
456 |
+
container: jQuery(this.getMap().getDiv())
|
457 |
+
},
|
458 |
+
show: {
|
459 |
+
ready: true,
|
460 |
+
event: false,
|
461 |
+
solo: true
|
462 |
+
},
|
463 |
+
hide: {
|
464 |
+
event: 'mouseleave unfocus'
|
465 |
+
}
|
466 |
+
});
|
467 |
+
}
|
js/frontend.min.js
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
(function(a){jQuery(document).ready(function(){function f(b){var d=b.categories,g="<select class='eo-cal-filter' id='eo-event-cat'>";g+="<option value=''>"+b.buttonText.cat+"</option>";for(b=0;b<d.length;b++)g+="<option class='cat-colour-"+d[b].colour+" cat' value='"+d[b].slug+"'>"+d[b].name+"</option>";g+="</select>";d=a("<span class='fc-header-dropdown filter-category'></span>");d.append(g);return d}function j(){return a("<span class='fc-header-goto'><input type='hidden' class='eo-mini-calendar'/></span>")}
|
2 |
+
function k(b){var d=b.venues,g="<select class='eo-cal-filter' id='eo-event-venue'>";g+="<option value=''>"+b.buttonText.venue+"</option>";for(b=0;b<d.length;b++)g+="<option value='"+d[b].term_id+"'>"+d[b].name+"</option>";g+="</select>";d=a("<span class='fc-header-dropdown filter-venue'></span>");d.append(g);return d}if(a("#eo-upcoming-dates").length>0&&a("#eo-upcoming-dates").find("li:gt(4)").length>0){var e={more:EOAjaxFront.locale.ShowMore,less:EOAjaxFront.locale.ShowLess};a("#eo-upcoming-dates").find("li:gt(4)").hide().end().after(a('<a href="#" id="eo-upcoming-dates-less">'+
|
3 |
+
e.less+'</a> <span id="eo-upcoming-dates-pipe">|</span> <a href="#" id="eo-upcoming-dates-more">'+e.more+"</a>"));a("#eo-upcoming-dates-pipe").hide();a("#eo-upcoming-dates-less").hide().click(function(b){b.preventDefault();b=Math.floor((a("#eo-upcoming-dates li:visible").length-1)/5)*5-1;a("#eo-upcoming-dates li:gt("+b+")").hide();a("#eo-upcoming-dates-more,#eo-upcoming-dates-pipe").show();a("#eo-upcoming-dates li:visible").length<=5&&a("#eo-upcoming-dates-less,#eo-upcoming-dates-pipe").hide()});
|
4 |
+
a("#eo-upcoming-dates-more").click(function(b){b.preventDefault();a("#eo-upcoming-dates-less,#eo-upcoming-dates-pipe, #eo-upcoming-dates li:hidden:lt(5)").show();b=a("#eo-upcoming-dates-pipe").offset();a("html, body").animate({scrollTop:Math.max(b.top+40-a(window).height(),a(window).scrollTop())});a("#eo-upcoming-dates li:hidden").length==0&&a("#eo-upcoming-dates-more,#eo-upcoming-dates-pipe").hide()})}if(a(".eo-fullcalendar").length>0){e=EOAjax.calendars;for(var l,c=0;c<e.length;c++){var n="#eo_fullcalendar_"+
|
5 |
+
(c+1);if(typeof e[c].category==="undefined")e[c].category="";if(typeof e[c].venue==="undefined")e[c].venue="";a(n).fullCalendar({id:n,year:e[c].year?e[c].year:undefined,month:e[c].month?e[c].month:undefined,date:e[c].date?e[c].date:undefined,category:e[c].event_category,venue:e[c].event_venue,customButtons:{category:f,venue:k,"goto":j},theme:true,categories:EOAjax.fullcal.categories,venues:EOAjax.fullcal.venues,timeFormatphp:e[c].timeformatphp,timeFormat:e[c].timeformat,editable:false,tooltip:e[c].tooltip,
|
6 |
+
firstDay:parseInt(EOAjax.fullcal.firstDay),weekends:e[c].weekends,allDaySlot:e[c].alldayslot,allDayText:e[c].alldaytext,axisFormat:e[c].axisformat,minTime:e[c].mintime,maxTime:e[c].maxtime,columnFormat:{month:e[c].columnformatmonth,week:e[c].columnformatweek,day:e[c].columnformatday},titleFormat:{month:e[c].titleformatmonth,week:e[c].titleformatweek,day:e[c].titleformatday},header:{left:e[c].headerleft,center:e[c].headercenter,right:e[c].headerright},eventRender:function(b,d,g){var h=a(g.calendar.options.id).find(".filter-category .eo-cal-filter").val(),
|
7 |
+
i=a(g.calendar.options.id).find(".filter-venue .eo-cal-filter").val();if(typeof h!=="undefined"&&h!=""&&a.inArray(h,b.category)<0)return"<div></div>";if(typeof i!=="undefined"&&i!=""&&i!=b.venue)return"<div></div>";g.calendar.options.tooltip&&a(d).qtip({content:{text:b.description,button:"x",title:b.title},position:{my:"top center",at:"bottom center"},hide:{fixed:true,delay:500,effect:function(){a(this).fadeOut("50")}},border:{radius:4,width:3},style:{classes:"ui-tooltip-shadow",widget:true,tip:"topMiddle"}})},
|
8 |
+
buttonText:{today:EOAjaxFront.locale.today,month:EOAjaxFront.locale.month,week:EOAjaxFront.locale.week,day:EOAjaxFront.locale.day,cat:EOAjaxFront.locale.cat,venue:EOAjaxFront.locale.venue},monthNames:EOAjaxFront.locale.monthNames,monthNamesShort:EOAjaxFront.locale.monthAbbrev,dayNames:EOAjaxFront.locale.dayNames,dayNamesShort:EOAjaxFront.locale.dayAbbrev,eventColor:"#21759B",defaultView:e[c].defaultview,lazyFetching:"true",events:function(b,d,g,h){b={start:jQuery.fullCalendar.formatDate(b,"yyyy-MM-dd"),
|
9 |
+
end:jQuery.fullCalendar.formatDate(d,"yyyy-MM-dd"),timeformat:h.timeFormatphp};if(typeof h.category!=="undefined"&&h.category!="")b.category=h.category;if(typeof h.venue!=="undefined"&&h.venue!="")b.venue=h.venue;jQuery.ajax({url:EOAjax.ajaxurl+"?action=eventorganiser-fullcal",dataType:"JSON",data:b,success:g})},selectable:false,weekMode:"variable",aspectRatio:1.5,loading:function(b){var d=a("#"+a(this).attr("id")+"_loading");if(b){window.clearTimeout(l);l=window.setTimeout(function(){d.show()},1E3)}else{window.clearTimeout(l);
|
10 |
+
d.hide()}}})}a(".eo-cal-filter").change(function(){a(".eo-fullcalendar").fullCalendar("rerenderEvents")});a(".eo-mini-calendar").datepicker({dateFormat:"DD, d MM, yy",changeMonth:true,changeYear:true,dateFormat:"DD, d MM, yy",firstDay:parseInt(EOAjax.fullcal.firstDay),buttonText:EOAjaxFront.locale.gotodate,monthNamesShort:EOAjaxFront.locale.monthAbbrev,dayNamesMin:EOAjaxFront.locale.dayAbbrev,showOn:"button",onSelect:function(b){var d=a(this).parents("div.eo-fullcalendar").attr("id");a("#"+d).fullCalendar("gotoDate",
|
11 |
+
new Date(Date.parse(b)))}})}if(a(".eo_widget_calendar").length>0){a(".eo_widget_calendar tfoot").unbind("click");a(".eo_widget_calendar").off("click").on("click","tfoot a",function(b){b.preventDefault();var d=a(this).closest(".eo_widget_calendar").attr("id");b={showpastevents:1};if(typeof EOAjax!=="undefined"&&typeof EOAjax.widget_calendars!=="undefined")b=EOAjax.widget_calendars[d];if(typeof eo_widget_cal!=="undefined")b=eo_widget_cal[d];b.eo_month=eveorg_getParameterByName("eo_month",a(this).attr("href"));
|
12 |
+
a.getJSON(EOAjaxFront.adminajax+"?action=eo_widget_cal",b,function(g){a("#"+d+"_content").html(g)})})}if(a(".eo-agenda-widget").length>0){function o(b,d){a.ajax({url:EOAjaxFront.adminajax,dataType:"JSON",data:{action:"eo_widget_agenda",instance_number:d.number,direction:b,start:d.StartDate,end:d.EndDate},success:function(g){if(!jQuery.isArray(g)||!g[0])return false;else{d.StartDate=g[0].StartDate;d.EndDate=g[g.length-1].StartDate;r(g,d)}}})}function r(b,d){var g=a("#"+d.id+"_container"),h=g.find("ul.dates"),
|
13 |
+
i=h.find("li");a(i).remove();i="";for(c=0;c<b.length;c++){if(i==""||i!=b[c].StartDate&&d.mode=="day"){i=b[c].StartDate;var p=a('<li class="date" >'+b[c].display+'<ul class="a-date"></ul></li>');h.append(p)}var q=d.add_to_google?a('<li class="event"></li>').append('<span class="cat"></span><span><strong>'+b[c].time+": </strong></span>"+b[c].post_title).append('<div class="meta" style="display:none;"><span>'+b[c].link+"</span><span> \u00a0 </span><span>"+b[c].Glink+"</span></div>"):a('<li class="event"></li>').append("<a class='eo-agenda-event-permalink' href='"+
|
14 |
+
b[c].event_url+"'><span class='cat'></span><span><strong>"+b[c].time+": </strong></span>"+b[c].post_title+"</a>");q.find("span.cat").css({background:b[c].color});p.append(q)}i=h.find("li");g.find("ul li.event").on("click",function(){a(this).find(".meta").toggle("400")})}for(var m in eo_widget_agenda){m=eo_widget_agenda[m];m.StartDate=a.fullCalendar.formatDate(new Date,"yyyy-MM-dd");m.EndDate=m.StartDate;o(1,m)}a(".eo-agenda-widget .agenda-nav span.button").click(function(b){var d=a(this).parents(".eo-agenda-widget").attr("id");
|
15 |
+
m=eo_widget_agenda[d];b.preventDefault();b=a(this).hasClass("next")?"+1":a(this).hasClass("prev")?"-1":a(this).parent().hasClass("prev")?"-1":"+1";o(b,m)})}})})(jQuery);function eveorg_getParameterByName(a,f){a=a.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");a=(new RegExp("[\\?&]"+a+"=([^&#]*)")).exec(f);return a==null?"":decodeURIComponent(a[1].replace(/\+/g," "))}
|
16 |
+
function eo_load_map(){for(var a=EOAjax.map,f=0;f<a.length;f++)if(null!==document.getElementById("eo_venue_map-"+(f+1))){var j=a[f].locations,k={zoom:a[f].zoom,scrollwheel:a[f].scrollwheel,zoomControl:a[f].zoomcontrol,rotateControl:a[f].rotatecontrol,panControl:a[f].pancontrol,overviewMapControl:a[f].overviewmapcontrol,streetViewControl:a[f].streetviewcontrol,draggable:a[f].draggable,mapTypeControl:a[f].maptypecontrol,mapTypeId:google.maps.MapTypeId[a[f].maptypeid]};k=new google.maps.Map(document.getElementById("eo_venue_map-"+
|
17 |
+
(f+1)),k);for(var e=new google.maps.LatLngBounds,l=[],c=0;c<j.length;c++){var n=j[c].lat,o=j[c].lng;if(n!==undefined&&o!=undefined){l.push(new google.maps.LatLng(n,o));e.extend(l[c]);n=new google.maps.Marker({position:l[c],map:k,content:j[c].tooltipContent});"false"!=a[f].tooltip&&google.maps.event.addListener(n,"click",eventorganiser_venue_tooltip)}}j.length>1?k.fitBounds(e):k.setCenter(l[0])}}
|
18 |
+
function eventorganiser_venue_tooltip(){var a=this.getMap(),f=this.getMap().getProjection().fromLatLngToPoint(this.position),j=a.getProjection().fromLatLngToPoint(a.getBounds().getNorthEast()),k=a.getProjection().fromLatLngToPoint(a.getBounds().getSouthWest());a=Math.pow(2,a.getZoom());f=new google.maps.Point((f.x-k.x)*a,(f.y-j.y)*a);f=[f.x,f.y];if(this.tooltip){this.tooltip.qtip("api").set("position.target",f);this.tooltip.qtip("show")}else{jQuery(this.getMap().getDiv()).css({overflow:"visible"});
|
19 |
+
this.tooltip=jQuery("<div />").qtip({content:{text:this.content},border:{radius:4,width:3},style:{classes:"ui-tooltip-shadow",widget:true},position:{at:"right center",my:"top center",target:f,container:jQuery(this.getMap().getDiv())},show:{ready:true,event:false,solo:true},hide:{event:"mouseleave unfocus"}})}};
|
js/fullcalendar.js
ADDED
@@ -0,0 +1,5236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
- * NOTE: This is an edited version of the FullCalendar v1.5.4 (eventorganiser branch)
|
3 |
+
-*/
|
4 |
+
/**
|
5 |
+
* @preserve
|
6 |
+
* FullCalendar v1.5.4
|
7 |
+
* http://arshaw.com/fullcalendar/
|
8 |
+
*
|
9 |
+
* Use fullcalendar.css for basic styling.
|
10 |
+
* For event drag & drop, requires jQuery UI draggable.
|
11 |
+
* For event resizing, requires jQuery UI resizable.
|
12 |
+
*
|
13 |
+
* Copyright (c) 2011 Adam Shaw
|
14 |
+
* Dual licensed under the MIT and GPL licenses, located in
|
15 |
+
* MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
16 |
+
*
|
17 |
+
* Date: Sat Nov 3 20:29:34 2012 +0000
|
18 |
+
*
|
19 |
+
*/
|
20 |
+
|
21 |
+
(function($, undefined) {
|
22 |
+
|
23 |
+
|
24 |
+
var defaults = {
|
25 |
+
|
26 |
+
// display
|
27 |
+
defaultView: 'month',
|
28 |
+
aspectRatio: 1.35,
|
29 |
+
header: {
|
30 |
+
left: 'title',
|
31 |
+
center: '',
|
32 |
+
right: 'today prev,next'
|
33 |
+
},
|
34 |
+
weekends: true,
|
35 |
+
|
36 |
+
// editing
|
37 |
+
//editable: false,
|
38 |
+
//disableDragging: false,
|
39 |
+
//disableResizing: false,
|
40 |
+
|
41 |
+
allDayDefault: true,
|
42 |
+
ignoreTimezone: true,
|
43 |
+
|
44 |
+
// event ajax
|
45 |
+
lazyFetching: true,
|
46 |
+
startParam: 'start',
|
47 |
+
endParam: 'end',
|
48 |
+
|
49 |
+
// time formats
|
50 |
+
titleFormat: {
|
51 |
+
month: 'MMMM yyyy',
|
52 |
+
week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}",
|
53 |
+
day: 'dddd, MMM d, yyyy'
|
54 |
+
},
|
55 |
+
columnFormat: {
|
56 |
+
month: 'ddd',
|
57 |
+
week: 'ddd M/d',
|
58 |
+
day: 'dddd M/d'
|
59 |
+
},
|
60 |
+
timeFormat: { // for event elements
|
61 |
+
'': 'h(:mm)t' // default
|
62 |
+
},
|
63 |
+
|
64 |
+
// locale
|
65 |
+
isRTL: false,
|
66 |
+
firstDay: 0,
|
67 |
+
monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'],
|
68 |
+
monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
|
69 |
+
dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
|
70 |
+
dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
|
71 |
+
buttonText: {
|
72 |
+
prev: ' ◄ ',
|
73 |
+
next: ' ► ',
|
74 |
+
prevYear: ' << ',
|
75 |
+
nextYear: ' >> ',
|
76 |
+
today: 'today',
|
77 |
+
month: 'month',
|
78 |
+
week: 'week',
|
79 |
+
day: 'day'
|
80 |
+
},
|
81 |
+
|
82 |
+
// jquery-ui theming
|
83 |
+
theme: false,
|
84 |
+
buttonIcons: {
|
85 |
+
prev: 'circle-triangle-w',
|
86 |
+
next: 'circle-triangle-e'
|
87 |
+
},
|
88 |
+
|
89 |
+
//selectable: false,
|
90 |
+
unselectAuto: true,
|
91 |
+
|
92 |
+
dropAccept: '*'
|
93 |
+
|
94 |
+
};
|
95 |
+
|
96 |
+
// right-to-left defaults
|
97 |
+
var rtlDefaults = {
|
98 |
+
header: {
|
99 |
+
left: 'next,prev today',
|
100 |
+
center: '',
|
101 |
+
right: 'title'
|
102 |
+
},
|
103 |
+
buttonText: {
|
104 |
+
prev: ' ► ',
|
105 |
+
next: ' ◄ ',
|
106 |
+
prevYear: ' >> ',
|
107 |
+
nextYear: ' << '
|
108 |
+
},
|
109 |
+
buttonIcons: {
|
110 |
+
prev: 'circle-triangle-e',
|
111 |
+
next: 'circle-triangle-w'
|
112 |
+
}
|
113 |
+
};
|
114 |
+
|
115 |
+
|
116 |
+
|
117 |
+
var fc = $.fullCalendar = { version: "1.5.4" };
|
118 |
+
var fcViews = fc.views = {};
|
119 |
+
|
120 |
+
|
121 |
+
$.fn.fullCalendar = function(options) {
|
122 |
+
|
123 |
+
|
124 |
+
// method calling
|
125 |
+
if (typeof options == 'string') {
|
126 |
+
var args = Array.prototype.slice.call(arguments, 1);
|
127 |
+
var res;
|
128 |
+
this.each(function() {
|
129 |
+
var calendar = $.data(this, 'fullCalendar');
|
130 |
+
if (calendar && $.isFunction(calendar[options])) {
|
131 |
+
var r = calendar[options].apply(calendar, args);
|
132 |
+
if (res === undefined) {
|
133 |
+
res = r;
|
134 |
+
}
|
135 |
+
if (options == 'destroy') {
|
136 |
+
$.removeData(this, 'fullCalendar');
|
137 |
+
}
|
138 |
+
}
|
139 |
+
});
|
140 |
+
if (res !== undefined) {
|
141 |
+
return res;
|
142 |
+
}
|
143 |
+
return this;
|
144 |
+
}
|
145 |
+
|
146 |
+
|
147 |
+
// would like to have this logic in EventManager, but needs to happen before options are recursively extended
|
148 |
+
var eventSources = options.eventSources || [];
|
149 |
+
delete options.eventSources;
|
150 |
+
if (options.events) {
|
151 |
+
eventSources.push(options.events);
|
152 |
+
delete options.events;
|
153 |
+
}
|
154 |
+
|
155 |
+
|
156 |
+
options = $.extend(true, {},
|
157 |
+
defaults,
|
158 |
+
(options.isRTL || options.isRTL===undefined && defaults.isRTL) ? rtlDefaults : {},
|
159 |
+
options
|
160 |
+
);
|
161 |
+
|
162 |
+
|
163 |
+
this.each(function(i, _element) {
|
164 |
+
var element = $(_element);
|
165 |
+
var calendar = new Calendar(element, options, eventSources);
|
166 |
+
element.data('fullCalendar', calendar); // TODO: look into memory leak implications
|
167 |
+
calendar.render();
|
168 |
+
});
|
169 |
+
|
170 |
+
|
171 |
+
return this;
|
172 |
+
|
173 |
+
};
|
174 |
+
|
175 |
+
|
176 |
+
// function for adding/overriding defaults
|
177 |
+
function setDefaults(d) {
|
178 |
+
$.extend(true, defaults, d);
|
179 |
+
}
|
180 |
+
|
181 |
+
|
182 |
+
|
183 |
+
|
184 |
+
function Calendar(element, options, eventSources) {
|
185 |
+
var t = this;
|
186 |
+
|
187 |
+
|
188 |
+
// exports
|
189 |
+
t.options = options;
|
190 |
+
t.render = render;
|
191 |
+
t.destroy = destroy;
|
192 |
+
t.refetchEvents = refetchEvents;
|
193 |
+
t.reportEvents = reportEvents;
|
194 |
+
t.reportEventChange = reportEventChange;
|
195 |
+
t.rerenderEvents = rerenderEvents;
|
196 |
+
t.changeView = changeView;
|
197 |
+
t.select = select;
|
198 |
+
t.unselect = unselect;
|
199 |
+
t.prev = prev;
|
200 |
+
t.next = next;
|
201 |
+
t.prevYear = prevYear;
|
202 |
+
t.nextYear = nextYear;
|
203 |
+
t.today = today;
|
204 |
+
t.gotoDate = gotoDate;
|
205 |
+
t.incrementDate = incrementDate;
|
206 |
+
t.formatDate = function(format, date) { return formatDate(format, date, options) };
|
207 |
+
t.formatDates = function(format, date1, date2) { return formatDates(format, date1, date2, options) };
|
208 |
+
t.getDate = getDate;
|
209 |
+
t.getView = getView;
|
210 |
+
t.option = option;
|
211 |
+
t.trigger = trigger;
|
212 |
+
|
213 |
+
|
214 |
+
// imports
|
215 |
+
EventManager.call(t, options, eventSources);
|
216 |
+
var isFetchNeeded = t.isFetchNeeded;
|
217 |
+
var fetchEvents = t.fetchEvents;
|
218 |
+
|
219 |
+
|
220 |
+
// locals
|
221 |
+
var _element = element[0];
|
222 |
+
var header;
|
223 |
+
var headerElement;
|
224 |
+
var content;
|
225 |
+
var tm; // for making theme classes
|
226 |
+
var currentView;
|
227 |
+
var viewInstances = {};
|
228 |
+
var elementOuterWidth;
|
229 |
+
var suggestedViewHeight;
|
230 |
+
var absoluteViewElement;
|
231 |
+
var resizeUID = 0;
|
232 |
+
var ignoreWindowResize = 0;
|
233 |
+
var date = new Date();
|
234 |
+
var events = [];
|
235 |
+
var _dragElement;
|
236 |
+
|
237 |
+
|
238 |
+
|
239 |
+
/* Main Rendering
|
240 |
+
-----------------------------------------------------------------------------*/
|
241 |
+
|
242 |
+
|
243 |
+
setYMD(date, options.year, options.month, options.date);
|
244 |
+
|
245 |
+
|
246 |
+
function render(inc) {
|
247 |
+
if (!content) {
|
248 |
+
initialRender();
|
249 |
+
}else{
|
250 |
+
calcSize();
|
251 |
+
markSizesDirty();
|
252 |
+
markEventsDirty();
|
253 |
+
renderView(inc);
|
254 |
+
}
|
255 |
+
}
|
256 |
+
|
257 |
+
|
258 |
+
function initialRender() {
|
259 |
+
tm = options.theme ? 'ui' : 'fc';
|
260 |
+
element.addClass('fc');
|
261 |
+
if (options.isRTL) {
|
262 |
+
element.addClass('fc-rtl');
|
263 |
+
}
|
264 |
+
if (options.theme) {
|
265 |
+
element.addClass('ui-widget');
|
266 |
+
}
|
267 |
+
content = $("<div class='fc-content' style='position:relative'/>")
|
268 |
+
.prependTo(element);
|
269 |
+
header = new Header(t, options);
|
270 |
+
headerElement = header.render();
|
271 |
+
if (headerElement) {
|
272 |
+
element.prepend(headerElement);
|
273 |
+
}
|
274 |
+
changeView(options.defaultView);
|
275 |
+
$(window).resize(windowResize);
|
276 |
+
// needed for IE in a 0x0 iframe, b/c when it is resized, never triggers a windowResize
|
277 |
+
if (!bodyVisible()) {
|
278 |
+
lateRender();
|
279 |
+
}
|
280 |
+
}
|
281 |
+
|
282 |
+
|
283 |
+
// called when we know the calendar couldn't be rendered when it was initialized,
|
284 |
+
// but we think it's ready now
|
285 |
+
function lateRender() {
|
286 |
+
setTimeout(function() { // IE7 needs this so dimensions are calculated correctly
|
287 |
+
if (!currentView.start && bodyVisible()) { // !currentView.start makes sure this never happens more than once
|
288 |
+
renderView();
|
289 |
+
}
|
290 |
+
},0);
|
291 |
+
}
|
292 |
+
|
293 |
+
|
294 |
+
function destroy() {
|
295 |
+
$(window).unbind('resize', windowResize);
|
296 |
+
header.destroy();
|
297 |
+
content.remove();
|
298 |
+
element.removeClass('fc fc-rtl ui-widget');
|
299 |
+
}
|
300 |
+
|
301 |
+
|
302 |
+
|
303 |
+
function elementVisible() {
|
304 |
+
return _element.offsetWidth !== 0;
|
305 |
+
}
|
306 |
+
|
307 |
+
|
308 |
+
function bodyVisible() {
|
309 |
+
return $('body')[0].offsetWidth !== 0;
|
310 |
+
}
|
311 |
+
|
312 |
+
|
313 |
+
|
314 |
+
/* View Rendering
|
315 |
+
-----------------------------------------------------------------------------*/
|
316 |
+
|
317 |
+
// TODO: improve view switching (still weird transition in IE, and FF has whiteout problem)
|
318 |
+
|
319 |
+
function changeView(newViewName) {
|
320 |
+
if (!currentView || newViewName != currentView.name) {
|
321 |
+
ignoreWindowResize++; // because setMinHeight might change the height before render (and subsequently setSize) is reached
|
322 |
+
|
323 |
+
unselect();
|
324 |
+
|
325 |
+
var oldView = currentView;
|
326 |
+
var newViewElement;
|
327 |
+
|
328 |
+
if (oldView) {
|
329 |
+
(oldView.beforeHide || noop)(); // called before changing min-height. if called after, scroll state is reset (in Opera)
|
330 |
+
setMinHeight(content, content.height());
|
331 |
+
oldView.element.hide();
|
332 |
+
}else{
|
333 |
+
setMinHeight(content, 1); // needs to be 1 (not 0) for IE7, or else view dimensions miscalculated
|
334 |
+
}
|
335 |
+
content.css('overflow', 'hidden');
|
336 |
+
|
337 |
+
currentView = viewInstances[newViewName];
|
338 |
+
if (currentView) {
|
339 |
+
currentView.element.show();
|
340 |
+
}else{
|
341 |
+
currentView = viewInstances[newViewName] = new fcViews[newViewName](
|
342 |
+
newViewElement = absoluteViewElement =
|
343 |
+
$("<div class='fc-view fc-view-" + newViewName + "' style='position:absolute'/>")
|
344 |
+
.appendTo(content),
|
345 |
+
t // the calendar object
|
346 |
+
);
|
347 |
+
}
|
348 |
+
|
349 |
+
if (oldView) {
|
350 |
+
header.deactivateButton(oldView.name);
|
351 |
+
}
|
352 |
+
header.activateButton(newViewName);
|
353 |
+
|
354 |
+
renderView(); // after height has been set, will make absoluteViewElement's position=relative, then set to null
|
355 |
+
|
356 |
+
content.css('overflow', '');
|
357 |
+
if (oldView) {
|
358 |
+
setMinHeight(content, 1);
|
359 |
+
}
|
360 |
+
|
361 |
+
if (!newViewElement) {
|
362 |
+
(currentView.afterShow || noop)(); // called after setting min-height/overflow, so in final scroll state (for Opera)
|
363 |
+
}
|
364 |
+
|
365 |
+
ignoreWindowResize--;
|
366 |
+
}
|
367 |
+
}
|
368 |
+
|
369 |
+
|
370 |
+
|
371 |
+
function renderView(inc) {
|
372 |
+
if (elementVisible()) {
|
373 |
+
ignoreWindowResize++; // because renderEvents might temporarily change the height before setSize is reached
|
374 |
+
|
375 |
+
unselect();
|
376 |
+
|
377 |
+
if (suggestedViewHeight === undefined) {
|
378 |
+
calcSize();
|
379 |
+
}
|
380 |
+
|
381 |
+
var forceEventRender = false;
|
382 |
+
if (!currentView.start || inc || date < currentView.start || date >= currentView.end) {
|
383 |
+
// view must render an entire new date range (and refetch/render events)
|
384 |
+
currentView.render(date, inc || 0); // responsible for clearing events
|
385 |
+
setSize(true);
|
386 |
+
forceEventRender = true;
|
387 |
+
}
|
388 |
+
else if (currentView.sizeDirty) {
|
389 |
+
// view must resize (and rerender events)
|
390 |
+
currentView.clearEvents();
|
391 |
+
setSize();
|
392 |
+
forceEventRender = true;
|
393 |
+
}
|
394 |
+
else if (currentView.eventsDirty) {
|
395 |
+
currentView.clearEvents();
|
396 |
+
forceEventRender = true;
|
397 |
+
}
|
398 |
+
currentView.sizeDirty = false;
|
399 |
+
currentView.eventsDirty = false;
|
400 |
+
updateEvents(forceEventRender);
|
401 |
+
|
402 |
+
elementOuterWidth = element.outerWidth();
|
403 |
+
|
404 |
+
header.updateTitle(currentView.title);
|
405 |
+
var today = new Date();
|
406 |
+
if (today >= currentView.start && today < currentView.end) {
|
407 |
+
header.disableButton('today');
|
408 |
+
}else{
|
409 |
+
header.enableButton('today');
|
410 |
+
}
|
411 |
+
|
412 |
+
ignoreWindowResize--;
|
413 |
+
currentView.trigger('viewDisplay', _element);
|
414 |
+
}
|
415 |
+
}
|
416 |
+
|
417 |
+
|
418 |
+
|
419 |
+
/* Resizing
|
420 |
+
-----------------------------------------------------------------------------*/
|
421 |
+
|
422 |
+
|
423 |
+
function updateSize() {
|
424 |
+
markSizesDirty();
|
425 |
+
if (elementVisible()) {
|
426 |
+
calcSize();
|
427 |
+
setSize();
|
428 |
+
unselect();
|
429 |
+
currentView.clearEvents();
|
430 |
+
currentView.renderEvents(events);
|
431 |
+
currentView.sizeDirty = false;
|
432 |
+
}
|
433 |
+
}
|
434 |
+
|
435 |
+
|
436 |
+
function markSizesDirty() {
|
437 |
+
$.each(viewInstances, function(i, inst) {
|
438 |
+
inst.sizeDirty = true;
|
439 |
+
});
|
440 |
+
}
|
441 |
+
|
442 |
+
|
443 |
+
function calcSize() {
|
444 |
+
if (options.contentHeight) {
|
445 |
+
suggestedViewHeight = options.contentHeight;
|
446 |
+
}
|
447 |
+
else if (options.height) {
|
448 |
+
suggestedViewHeight = options.height - (headerElement ? headerElement.height() : 0) - vsides(content);
|
449 |
+
}
|
450 |
+
else {
|
451 |
+
suggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, .5));
|
452 |
+
}
|
453 |
+
}
|
454 |
+
|
455 |
+
|
456 |
+
function setSize(dateChanged) { // todo: dateChanged?
|
457 |
+
ignoreWindowResize++;
|
458 |
+
currentView.setHeight(suggestedViewHeight, dateChanged);
|
459 |
+
if (absoluteViewElement) {
|
460 |
+
absoluteViewElement.css('position', 'relative');
|
461 |
+
absoluteViewElement = null;
|
462 |
+
}
|
463 |
+
currentView.setWidth(content.width(), dateChanged);
|
464 |
+
ignoreWindowResize--;
|
465 |
+
}
|
466 |
+
|
467 |
+
|
468 |
+
function windowResize() {
|
469 |
+
if (!ignoreWindowResize) {
|
470 |
+
if (currentView.start) { // view has already been rendered
|
471 |
+
var uid = ++resizeUID;
|
472 |
+
setTimeout(function() { // add a delay
|
473 |
+
if (uid == resizeUID && !ignoreWindowResize && elementVisible()) {
|
474 |
+
if (elementOuterWidth != (elementOuterWidth = element.outerWidth())) {
|
475 |
+
ignoreWindowResize++; // in case the windowResize callback changes the height
|
476 |
+
updateSize();
|
477 |
+
currentView.trigger('windowResize', _element);
|
478 |
+
ignoreWindowResize--;
|
479 |
+
}
|
480 |
+
}
|
481 |
+
}, 200);
|
482 |
+
}else{
|
483 |
+
// calendar must have been initialized in a 0x0 iframe that has just been resized
|
484 |
+
lateRender();
|
485 |
+
}
|
486 |
+
}
|
487 |
+
}
|
488 |
+
|
489 |
+
|
490 |
+
|
491 |
+
/* Event Fetching/Rendering
|
492 |
+
-----------------------------------------------------------------------------*/
|
493 |
+
|
494 |
+
|
495 |
+
// fetches events if necessary, rerenders events if necessary (or if forced)
|
496 |
+
function updateEvents(forceRender) {
|
497 |
+
if (!options.lazyFetching || isFetchNeeded(currentView.visStart, currentView.visEnd)) {
|
498 |
+
refetchEvents();
|
499 |
+
}
|
500 |
+
else if (forceRender) {
|
501 |
+
rerenderEvents();
|
502 |
+
}
|
503 |
+
}
|
504 |
+
|
505 |
+
|
506 |
+
function refetchEvents() {
|
507 |
+
fetchEvents(currentView.visStart, currentView.visEnd, options); // will call reportEvents
|
508 |
+
}
|
509 |
+
|
510 |
+
|
511 |
+
// called when event data arrives
|
512 |
+
function reportEvents(_events) {
|
513 |
+
events = _events;
|
514 |
+
rerenderEvents();
|
515 |
+
}
|
516 |
+
|
517 |
+
|
518 |
+
// called when a single event's data has been changed
|
519 |
+
function reportEventChange(eventID) {
|
520 |
+
rerenderEvents(eventID);
|
521 |
+
}
|
522 |
+
|
523 |
+
|
524 |
+
// attempts to rerenderEvents
|
525 |
+
function rerenderEvents(modifiedEventID) {
|
526 |
+
markEventsDirty();
|
527 |
+
if (elementVisible()) {
|
528 |
+
currentView.clearEvents();
|
529 |
+
currentView.renderEvents(events, modifiedEventID);
|
530 |
+
currentView.eventsDirty = false;
|
531 |
+
}
|
532 |
+
}
|
533 |
+
|
534 |
+
|
535 |
+
function markEventsDirty() {
|
536 |
+
$.each(viewInstances, function(i, inst) {
|
537 |
+
inst.eventsDirty = true;
|
538 |
+
});
|
539 |
+
}
|
540 |
+
|
541 |
+
|
542 |
+
|
543 |
+
/* Selection
|
544 |
+
-----------------------------------------------------------------------------*/
|
545 |
+
|
546 |
+
|
547 |
+
function select(start, end, allDay) {
|
548 |
+
currentView.select(start, end, allDay===undefined ? true : allDay);
|
549 |
+
}
|
550 |
+
|
551 |
+
|
552 |
+
function unselect() { // safe to be called before renderView
|
553 |
+
if (currentView) {
|
554 |
+
currentView.unselect();
|
555 |
+
}
|
556 |
+
}
|
557 |
+
|
558 |
+
|
559 |
+
|
560 |
+
/* Date
|
561 |
+
-----------------------------------------------------------------------------*/
|
562 |
+
|
563 |
+
|
564 |
+
function prev() {
|
565 |
+
renderView(-1);
|
566 |
+
}
|
567 |
+
|
568 |
+
|
569 |
+
function next() {
|
570 |
+
renderView(1);
|
571 |
+
}
|
572 |
+
|
573 |
+
|
574 |
+
function prevYear() {
|
575 |
+
addYears(date, -1);
|
576 |
+
renderView();
|
577 |
+
}
|
578 |
+
|
579 |
+
|
580 |
+
function nextYear() {
|
581 |
+
addYears(date, 1);
|
582 |
+
renderView();
|
583 |
+
}
|
584 |
+
|
585 |
+
|
586 |
+
function today() {
|
587 |
+
date = new Date();
|
588 |
+
renderView();
|
589 |
+
}
|
590 |
+
|
591 |
+
|
592 |
+
function gotoDate(year, month, dateOfMonth) {
|
593 |
+
if (year instanceof Date) {
|
594 |
+
date = cloneDate(year); // provided 1 argument, a Date
|
595 |
+
}else{
|
596 |
+
setYMD(date, year, month, dateOfMonth);
|
597 |
+
}
|
598 |
+
renderView();
|
599 |
+
}
|
600 |
+
|
601 |
+
|
602 |
+
function incrementDate(years, months, days) {
|
603 |
+
if (years !== undefined) {
|
604 |
+
addYears(date, years);
|
605 |
+
}
|
606 |
+
if (months !== undefined) {
|
607 |
+
addMonths(date, months);
|
608 |
+
}
|
609 |
+
if (days !== undefined) {
|
610 |
+
addDays(date, days);
|
611 |
+
}
|
612 |
+
renderView();
|
613 |
+
}
|
614 |
+
|
615 |
+
|
616 |
+
function getDate() {
|
617 |
+
return cloneDate(date);
|
618 |
+
}
|
619 |
+
|
620 |
+
|
621 |
+
|
622 |
+
/* Misc
|
623 |
+
-----------------------------------------------------------------------------*/
|
624 |
+
|
625 |
+
|
626 |
+
function getView() {
|
627 |
+
return currentView;
|
628 |
+
}
|
629 |
+
|
630 |
+
|
631 |
+
function option(name, value) {
|
632 |
+
if (value === undefined) {
|
633 |
+
return options[name];
|
634 |
+
}
|
635 |
+
if (name == 'height' || name == 'contentHeight' || name == 'aspectRatio') {
|
636 |
+
options[name] = value;
|
637 |
+
updateSize();
|
638 |
+
}else{
|
639 |
+
options[name] = value;
|
640 |
+
rerenderEvents();
|
641 |
+
}
|
642 |
+
}
|
643 |
+
|
644 |
+
|
645 |
+
function trigger(name, thisObj) {
|
646 |
+
if (options[name]) {
|
647 |
+
return options[name].apply(
|
648 |
+
thisObj || _element,
|
649 |
+
Array.prototype.slice.call(arguments, 2)
|
650 |
+
);
|
651 |
+
}
|
652 |
+
}
|
653 |
+
|
654 |
+
|
655 |
+
|
656 |
+
/* External Dragging
|
657 |
+
------------------------------------------------------------------------*/
|
658 |
+
|
659 |
+
if (options.droppable) {
|
660 |
+
$(document)
|
661 |
+
.bind('dragstart', function(ev, ui) {
|
662 |
+
var _e = ev.target;
|
663 |
+
var e = $(_e);
|
664 |
+
if (!e.parents('.fc').length) { // not already inside a calendar
|
665 |
+
var accept = options.dropAccept;
|
666 |
+
if ($.isFunction(accept) ? accept.call(_e, e) : e.is(accept)) {
|
667 |
+
_dragElement = _e;
|
668 |
+
currentView.dragStart(_dragElement, ev, ui);
|
669 |
+
}
|
670 |
+
}
|
671 |
+
})
|
672 |
+
.bind('dragstop', function(ev, ui) {
|
673 |
+
if (_dragElement) {
|
674 |
+
currentView.dragStop(_dragElement, ev, ui);
|
675 |
+
_dragElement = null;
|
676 |
+
}
|
677 |
+
});
|
678 |
+
}
|
679 |
+
|
680 |
+
|
681 |
+
}
|
682 |
+
|
683 |
+
function Header(calendar, options) {
|
684 |
+
var t = this;
|
685 |
+
|
686 |
+
|
687 |
+
// exports
|
688 |
+
t.render = render;
|
689 |
+
t.destroy = destroy;
|
690 |
+
t.updateTitle = updateTitle;
|
691 |
+
t.activateButton = activateButton;
|
692 |
+
t.deactivateButton = deactivateButton;
|
693 |
+
t.disableButton = disableButton;
|
694 |
+
t.enableButton = enableButton;
|
695 |
+
|
696 |
+
|
697 |
+
// locals
|
698 |
+
var element = $([]);
|
699 |
+
var tm;
|
700 |
+
|
701 |
+
|
702 |
+
|
703 |
+
function render() {
|
704 |
+
tm = options.theme ? 'ui' : 'fc';
|
705 |
+
var sections = options.header;
|
706 |
+
if (sections) {
|
707 |
+
element = $("<table class='fc-header' style='width:100%'/>")
|
708 |
+
.append(
|
709 |
+
$("<tr/>")
|
710 |
+
.append(renderSection('left'))
|
711 |
+
.append(renderSection('center'))
|
712 |
+
.append(renderSection('right'))
|
713 |
+
);
|
714 |
+
return element;
|
715 |
+
}
|
716 |
+
}
|
717 |
+
|
718 |
+
|
719 |
+
function destroy() {
|
720 |
+
element.remove();
|
721 |
+
}
|
722 |
+
|
723 |
+
|
724 |
+
function renderSection(position) {
|
725 |
+
var e = $("<td class='fc-header-" + position + "'/>");
|
726 |
+
var buttonStr = options.header[position];
|
727 |
+
if (buttonStr) {
|
728 |
+
$.each(buttonStr.split(' '), function(i) {
|
729 |
+
if (i > 0) {
|
730 |
+
e.append("<span class='fc-header-space'/>");
|
731 |
+
}
|
732 |
+
var prevButton;
|
733 |
+
$.each(this.split(','), function(j, buttonName) {
|
734 |
+
if (buttonName == 'title') {
|
735 |
+
e.append("<span class='fc-header-title'><h2> </h2></span>");
|
736 |
+
if (prevButton) {
|
737 |
+
prevButton.addClass(tm + '-corner-right');
|
738 |
+
}
|
739 |
+
prevButton = null;
|
740 |
+
|
741 |
+
}else if( $.isFunction(options.customButtons[buttonName]) ){
|
742 |
+
var element = options.customButtons[buttonName](options);
|
743 |
+
e.append(element);
|
744 |
+
}else{
|
745 |
+
var buttonClick;
|
746 |
+
if (calendar[buttonName]) {
|
747 |
+
buttonClick = calendar[buttonName]; // calendar method
|
748 |
+
}
|
749 |
+
else if (fcViews[buttonName]) {
|
750 |
+
buttonClick = function() {
|
751 |
+
button.removeClass(tm + '-state-hover'); // forget why
|
752 |
+
calendar.changeView(buttonName);
|
753 |
+
};
|
754 |
+
}
|
755 |
+
if (buttonClick) {
|
756 |
+
var icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null; // why are we using smartProperty here?
|
757 |
+
var text = smartProperty(options.buttonText, buttonName); // why are we using smartProperty here?
|
758 |
+
|
759 |
+
if ( options.buttonui ){
|
760 |
+
var button = $("<span class='fc-button fc-button-" + buttonName + " " + tm + "-state-default'>" +text+"</span>");
|
761 |
+
button.button();
|
762 |
+
}else{
|
763 |
+
var button = $(
|
764 |
+
"<span class='fc-button fc-button-" + buttonName + " " + tm + "-state-default'>" +
|
765 |
+
"<span class='fc-button-inner'>" +
|
766 |
+
"<span class='fc-button-content'>" +
|
767 |
+
(icon ?
|
768 |
+
"<span class='fc-icon-wrap'>" +
|
769 |
+
"<span class='ui-icon ui-icon-" + icon + "'/>" +
|
770 |
+
"</span>" :
|
771 |
+
text
|
772 |
+
) +
|
773 |
+
"</span>" +
|
774 |
+
"<span class='fc-button-effect'><span></span></span>" +
|
775 |
+
"</span>" +
|
776 |
+
"</span>"
|
777 |
+
);
|
778 |
+
}
|
779 |
+
if (button) {
|
780 |
+
button
|
781 |
+
.click(function() {
|
782 |
+
if (!button.hasClass(tm + '-state-disabled')) {
|
783 |
+
buttonClick();
|
784 |
+
}
|
785 |
+
})
|
786 |
+
.mousedown(function() {
|
787 |
+
button
|
788 |
+
.not('.' + tm + '-state-active')
|
789 |
+
.not('.' + tm + '-state-disabled')
|
790 |
+
.addClass(tm + '-state-down');
|
791 |
+
})
|
792 |
+
.mouseup(function() {
|
793 |
+
button.removeClass(tm + '-state-down');
|
794 |
+
})
|
795 |
+
.hover(
|
796 |
+
function() {
|
797 |
+
button
|
798 |
+
.not('.' + tm + '-state-active')
|
799 |
+
.not('.' + tm + '-state-disabled')
|
800 |
+
.addClass(tm + '-state-hover');
|
801 |
+
},
|
802 |
+
function() {
|
803 |
+
button
|
804 |
+
.removeClass(tm + '-state-hover')
|
805 |
+
.removeClass(tm + '-state-down');
|
806 |
+
}
|
807 |
+
)
|
808 |
+
.appendTo(e);
|
809 |
+
if (!prevButton) {
|
810 |
+
button.addClass(tm + '-corner-left');
|
811 |
+
}
|
812 |
+
prevButton = button;
|
813 |
+
}
|
814 |
+
}
|
815 |
+
}
|
816 |
+
});
|
817 |
+
if (prevButton) {
|
818 |
+
prevButton.addClass(tm + '-corner-right');
|
819 |
+
}
|
820 |
+
});
|
821 |
+
}
|
822 |
+
return e;
|
823 |
+
}
|
824 |
+
|
825 |
+
|
826 |
+
function updateTitle(html) {
|
827 |
+
element.find('h2')
|
828 |
+
.html(html);
|
829 |
+
}
|
830 |
+
|
831 |
+
|
832 |
+
function activateButton(buttonName) {
|
833 |
+
element.find('span.fc-button-' + buttonName)
|
834 |
+
.addClass(tm + '-state-active');
|
835 |
+
}
|
836 |
+
|
837 |
+
|
838 |
+
function deactivateButton(buttonName) {
|
839 |
+
element.find('span.fc-button-' + buttonName)
|
840 |
+
.removeClass(tm + '-state-active');
|
841 |
+
}
|
842 |
+
|
843 |
+
|
844 |
+
function disableButton(buttonName) {
|
845 |
+
element.find('span.fc-button-' + buttonName)
|
846 |
+
.addClass(tm + '-state-disabled');
|
847 |
+
}
|
848 |
+
|
849 |
+
|
850 |
+
function enableButton(buttonName) {
|
851 |
+
element.find('span.fc-button-' + buttonName)
|
852 |
+
.removeClass(tm + '-state-disabled');
|
853 |
+
}
|
854 |
+
|
855 |
+
|
856 |
+
}
|
857 |
+
|
858 |
+
fc.sourceNormalizers = [];
|
859 |
+
fc.sourceFetchers = [];
|
860 |
+
|
861 |
+
var ajaxDefaults = {
|
862 |
+
dataType: 'json',
|
863 |
+
cache: false
|
864 |
+
};
|
865 |
+
|
866 |
+
var eventGUID = 1;
|
867 |
+
|
868 |
+
|
869 |
+
function EventManager(options, _sources) {
|
870 |
+
var t = this;
|
871 |
+
|
872 |
+
|
873 |
+
// exports
|
874 |
+
t.isFetchNeeded = isFetchNeeded;
|
875 |
+
t.fetchEvents = fetchEvents;
|
876 |
+
t.addEventSource = addEventSource;
|
877 |
+
t.removeEventSource = removeEventSource;
|
878 |
+
t.updateEvent = updateEvent;
|
879 |
+
t.renderEvent = renderEvent;
|
880 |
+
t.removeEvents = removeEvents;
|
881 |
+
t.clientEvents = clientEvents;
|
882 |
+
t.normalizeEvent = normalizeEvent;
|
883 |
+
|
884 |
+
|
885 |
+
// imports
|
886 |
+
var trigger = t.trigger;
|
887 |
+
var getView = t.getView;
|
888 |
+
var reportEvents = t.reportEvents;
|
889 |
+
|
890 |
+
|
891 |
+
// locals
|
892 |
+
var stickySource = { events: [] };
|
893 |
+
var sources = [ stickySource ];
|
894 |
+
var rangeStart, rangeEnd;
|
895 |
+
var currentFetchID = 0;
|
896 |
+
var pendingSourceCnt = 0;
|
897 |
+
var loadingLevel = 0;
|
898 |
+
var cache = [];
|
899 |
+
|
900 |
+
|
901 |
+
for (var i=0; i<_sources.length; i++) {
|
902 |
+
_addEventSource(_sources[i]);
|
903 |
+
}
|
904 |
+
|
905 |
+
|
906 |
+
|
907 |
+
/* Fetching
|
908 |
+
-----------------------------------------------------------------------------*/
|
909 |
+
|
910 |
+
|
911 |
+
function isFetchNeeded(start, end) {
|
912 |
+
return !rangeStart || start < rangeStart || end > rangeEnd;
|
913 |
+
}
|
914 |
+
|
915 |
+
|
916 |
+
function fetchEvents(start, end, options) {
|
917 |
+
rangeStart = start;
|
918 |
+
rangeEnd = end;
|
919 |
+
cache = [];
|
920 |
+
var fetchID = ++currentFetchID;
|
921 |
+
var len = sources.length;
|
922 |
+
pendingSourceCnt = len;
|
923 |
+
for (var i=0; i<len; i++) {
|
924 |
+
fetchEventSource(sources[i], fetchID, options);
|
925 |
+
}
|
926 |
+
}
|
927 |
+
|
928 |
+
|
929 |
+
function fetchEventSource(source, fetchID, options) {
|
930 |
+
_fetchEventSource(source, function(events) {
|
931 |
+
if (fetchID == currentFetchID) {
|
932 |
+
if (events) {
|
933 |
+
for (var i=0; i<events.length; i++) {
|
934 |
+
events[i].source = source;
|
935 |
+
normalizeEvent(events[i]);
|
936 |
+
}
|
937 |
+
cache = cache.concat(events);
|
938 |
+
}
|
939 |
+
pendingSourceCnt--;
|
940 |
+
if (!pendingSourceCnt) {
|
941 |
+
reportEvents(cache);
|
942 |
+
}
|
943 |
+
}
|
944 |
+
}, options);
|
945 |
+
}
|
946 |
+
|
947 |
+
|
948 |
+
function _fetchEventSource(source, callback) {
|
949 |
+
var i;
|
950 |
+
var fetchers = fc.sourceFetchers;
|
951 |
+
var res;
|
952 |
+
for (i=0; i<fetchers.length; i++) {
|
953 |
+
res = fetchers[i](source, rangeStart, rangeEnd, callback);
|
954 |
+
if (res === true) {
|
955 |
+
// the fetcher is in charge. made its own async request
|
956 |
+
return;
|
957 |
+
}
|
958 |
+
else if (typeof res == 'object') {
|
959 |
+
// the fetcher returned a new source. process it
|
960 |
+
_fetchEventSource(res, callback, options);
|
961 |
+
return;
|
962 |
+
}
|
963 |
+
}
|
964 |
+
var events = source.events;
|
965 |
+
if (events) {
|
966 |
+
if ($.isFunction(events)) {
|
967 |
+
pushLoading();
|
968 |
+
events(cloneDate(rangeStart), cloneDate(rangeEnd), function(events) {
|
969 |
+
callback(events);
|
970 |
+
popLoading();
|
971 |
+
}, options);
|
972 |
+
}
|
973 |
+
else if ($.isArray(events)) {
|
974 |
+
callback(events);
|
975 |
+
}
|
976 |
+
else {
|
977 |
+
callback();
|
978 |
+
}
|
979 |
+
}else{
|
980 |
+
var url = source.url;
|
981 |
+
if (url) {
|
982 |
+
var success = source.success;
|
983 |
+
var error = source.error;
|
984 |
+
var complete = source.complete;
|
985 |
+
var data = $.extend({}, source.data || {});
|
986 |
+
var startParam = firstDefined(source.startParam, options.startParam);
|
987 |
+
var endParam = firstDefined(source.endParam, options.endParam);
|
988 |
+
if (startParam) {
|
989 |
+
data[startParam] = Math.round(+rangeStart / 1000);
|
990 |
+
}
|
991 |
+
if (endParam) {
|
992 |
+
data[endParam] = Math.round(+rangeEnd / 1000);
|
993 |
+
}
|
994 |
+
pushLoading();
|
995 |
+
$.ajax($.extend({}, ajaxDefaults, source, {
|
996 |
+
data: data,
|
997 |
+
success: function(events) {
|
998 |
+
events = events || [];
|
999 |
+
var res = applyAll(success, this, arguments);
|
1000 |
+
if ($.isArray(res)) {
|
1001 |
+
events = res;
|
1002 |
+
}
|
1003 |
+
callback(events);
|
1004 |
+
},
|
1005 |
+
error: function() {
|
1006 |
+
applyAll(error, this, arguments);
|
1007 |
+
callback();
|
1008 |
+
},
|
1009 |
+
complete: function() {
|
1010 |
+
applyAll(complete, this, arguments);
|
1011 |
+
popLoading();
|
1012 |
+
}
|
1013 |
+
}));
|
1014 |
+
}else{
|
1015 |
+
callback();
|
1016 |
+
}
|
1017 |
+
}
|
1018 |
+
}
|
1019 |
+
|
1020 |
+
|
1021 |
+
|
1022 |
+
/* Sources
|
1023 |
+
-----------------------------------------------------------------------------*/
|
1024 |
+
|
1025 |
+
|
1026 |
+
function addEventSource(source) {
|
1027 |
+
source = _addEventSource(source);
|
1028 |
+
if (source) {
|
1029 |
+
pendingSourceCnt++;
|
1030 |
+
fetchEventSource(source, currentFetchID); // will eventually call reportEvents
|
1031 |
+
}
|
1032 |
+
}
|
1033 |
+
|
1034 |
+
|
1035 |
+
function _addEventSource(source) {
|
1036 |
+
if ($.isFunction(source) || $.isArray(source)) {
|
1037 |
+
source = { events: source };
|
1038 |
+
}
|
1039 |
+
else if (typeof source == 'string') {
|
1040 |
+
source = { url: source };
|
1041 |
+
}
|
1042 |
+
if (typeof source == 'object') {
|
1043 |
+
normalizeSource(source);
|
1044 |
+
sources.push(source);
|
1045 |
+
return source;
|
1046 |
+
}
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
|
1050 |
+
function removeEventSource(source) {
|
1051 |
+
sources = $.grep(sources, function(src) {
|
1052 |
+
return !isSourcesEqual(src, source);
|
1053 |
+
});
|
1054 |
+
// remove all client events from that source
|
1055 |
+
cache = $.grep(cache, function(e) {
|
1056 |
+
return !isSourcesEqual(e.source, source);
|
1057 |
+
});
|
1058 |
+
reportEvents(cache);
|
1059 |
+
}
|
1060 |
+
|
1061 |
+
|
1062 |
+
|
1063 |
+
/* Manipulation
|
1064 |
+
-----------------------------------------------------------------------------*/
|
1065 |
+
|
1066 |
+
|
1067 |
+
function updateEvent(event) { // update an existing event
|
1068 |
+
var i, len = cache.length, e,
|
1069 |
+
defaultEventEnd = getView().defaultEventEnd, // getView???
|
1070 |
+
startDelta = event.start - event._start,
|
1071 |
+
endDelta = event.end ?
|
1072 |
+
(event.end - (event._end || defaultEventEnd(event))) // event._end would be null if event.end
|
1073 |
+
: 0; // was null and event was just resized
|
1074 |
+
for (i=0; i<len; i++) {
|
1075 |
+
e = cache[i];
|
1076 |
+
if (e._id == event._id && e != event) {
|
1077 |
+
e.start = new Date(+e.start + startDelta);
|
1078 |
+
if (event.end) {
|
1079 |
+
if (e.end) {
|
1080 |
+
e.end = new Date(+e.end + endDelta);
|
1081 |
+
}else{
|
1082 |
+
e.end = new Date(+defaultEventEnd(e) + endDelta);
|
1083 |
+
}
|
1084 |
+
}else{
|
1085 |
+
e.end = null;
|
1086 |
+
}
|
1087 |
+
e.title = event.title;
|
1088 |
+
e.url = event.url;
|
1089 |
+
e.allDay = event.allDay;
|
1090 |
+
e.className = event.className;
|
1091 |
+
e.editable = event.editable;
|
1092 |
+
e.color = event.color;
|
1093 |
+
e.backgroudColor = event.backgroudColor;
|
1094 |
+
e.borderColor = event.borderColor;
|
1095 |
+
e.textColor = event.textColor;
|
1096 |
+
normalizeEvent(e);
|
1097 |
+
}
|
1098 |
+
}
|
1099 |
+
normalizeEvent(event);
|
1100 |
+
reportEvents(cache);
|
1101 |
+
}
|
1102 |
+
|
1103 |
+
|
1104 |
+
function renderEvent(event, stick) {
|
1105 |
+
normalizeEvent(event);
|
1106 |
+
if (!event.source) {
|
1107 |
+
if (stick) {
|
1108 |
+
stickySource.events.push(event);
|
1109 |
+
event.source = stickySource;
|
1110 |
+
}
|
1111 |
+
cache.push(event);
|
1112 |
+
}
|
1113 |
+
reportEvents(cache);
|
1114 |
+
}
|
1115 |
+
|
1116 |
+
|
1117 |
+
function removeEvents(filter) {
|
1118 |
+
if (!filter) { // remove all
|
1119 |
+
cache = [];
|
1120 |
+
// clear all array sources
|
1121 |
+
for (var i=0; i<sources.length; i++) {
|
1122 |
+
if ($.isArray(sources[i].events)) {
|
1123 |
+
sources[i].events = [];
|
1124 |
+
}
|
1125 |
+
}
|
1126 |
+
}else{
|
1127 |
+
if (!$.isFunction(filter)) { // an event ID
|
1128 |
+
var id = filter + '';
|
1129 |
+
filter = function(e) {
|
1130 |
+
return e._id == id;
|
1131 |
+
};
|
1132 |
+
}
|
1133 |
+
cache = $.grep(cache, filter, true);
|
1134 |
+
// remove events from array sources
|
1135 |
+
for (var i=0; i<sources.length; i++) {
|
1136 |
+
if ($.isArray(sources[i].events)) {
|
1137 |
+
sources[i].events = $.grep(sources[i].events, filter, true);
|
1138 |
+
}
|
1139 |
+
}
|
1140 |
+
}
|
1141 |
+
reportEvents(cache);
|
1142 |
+
}
|
1143 |
+
|
1144 |
+
|
1145 |
+
function clientEvents(filter) {
|
1146 |
+
if ($.isFunction(filter)) {
|
1147 |
+
return $.grep(cache, filter);
|
1148 |
+
}
|
1149 |
+
else if (filter) { // an event ID
|
1150 |
+
filter += '';
|
1151 |
+
return $.grep(cache, function(e) {
|
1152 |
+
return e._id == filter;
|
1153 |
+
});
|
1154 |
+
}
|
1155 |
+
return cache; // else, return all
|
1156 |
+
}
|
1157 |
+
|
1158 |
+
|
1159 |
+
|
1160 |
+
/* Loading State
|
1161 |
+
-----------------------------------------------------------------------------*/
|
1162 |
+
|
1163 |
+
|
1164 |
+
function pushLoading() {
|
1165 |
+
if (!loadingLevel++) {
|
1166 |
+
trigger('loading', null, true);
|
1167 |
+
}
|
1168 |
+
}
|
1169 |
+
|
1170 |
+
|
1171 |
+
function popLoading() {
|
1172 |
+
if (!--loadingLevel) {
|
1173 |
+
trigger('loading', null, false);
|
1174 |
+
}
|
1175 |
+
}
|
1176 |
+
|
1177 |
+
|
1178 |
+
|
1179 |
+
/* Event Normalization
|
1180 |
+
-----------------------------------------------------------------------------*/
|
1181 |
+
|
1182 |
+
|
1183 |
+
function normalizeEvent(event) {
|
1184 |
+
var source = event.source || {};
|
1185 |
+
var ignoreTimezone = firstDefined(source.ignoreTimezone, options.ignoreTimezone);
|
1186 |
+
event._id = event._id || (event.id === undefined ? '_fc' + eventGUID++ : event.id + '');
|
1187 |
+
if (event.date) {
|
1188 |
+
if (!event.start) {
|
1189 |
+
event.start = event.date;
|
1190 |
+
}
|
1191 |
+
delete event.date;
|
1192 |
+
}
|
1193 |
+
event._start = cloneDate(event.start = parseDate(event.start, ignoreTimezone));
|
1194 |
+
event.end = parseDate(event.end, ignoreTimezone);
|
1195 |
+
if (event.end && event.end <= event.start) {
|
1196 |
+
event.end = null;
|
1197 |
+
}
|
1198 |
+
event._end = event.end ? cloneDate(event.end) : null;
|
1199 |
+
if (event.allDay === undefined) {
|
1200 |
+
event.allDay = firstDefined(source.allDayDefault, options.allDayDefault);
|
1201 |
+
}
|
1202 |
+
if (event.className) {
|
1203 |
+
if (typeof event.className == 'string') {
|
1204 |
+
event.className = event.className.split(/\s+/);
|
1205 |
+
}
|
1206 |
+
}else{
|
1207 |
+
event.className = [];
|
1208 |
+
}
|
1209 |
+
// TODO: if there is no start date, return false to indicate an invalid event
|
1210 |
+
}
|
1211 |
+
|
1212 |
+
|
1213 |
+
|
1214 |
+
/* Utils
|
1215 |
+
------------------------------------------------------------------------------*/
|
1216 |
+
|
1217 |
+
|
1218 |
+
function normalizeSource(source) {
|
1219 |
+
if (source.className) {
|
1220 |
+
// TODO: repeat code, same code for event classNames
|
1221 |
+
if (typeof source.className == 'string') {
|
1222 |
+
source.className = source.className.split(/\s+/);
|
1223 |
+
}
|
1224 |
+
}else{
|
1225 |
+
source.className = [];
|
1226 |
+
}
|
1227 |
+
var normalizers = fc.sourceNormalizers;
|
1228 |
+
for (var i=0; i<normalizers.length; i++) {
|
1229 |
+
normalizers[i](source);
|
1230 |
+
}
|
1231 |
+
}
|
1232 |
+
|
1233 |
+
|
1234 |
+
function isSourcesEqual(source1, source2) {
|
1235 |
+
return source1 && source2 && getSourcePrimitive(source1) == getSourcePrimitive(source2);
|
1236 |
+
}
|
1237 |
+
|
1238 |
+
|
1239 |
+
function getSourcePrimitive(source) {
|
1240 |
+
return ((typeof source == 'object') ? (source.events || source.url) : '') || source;
|
1241 |
+
}
|
1242 |
+
|
1243 |
+
|
1244 |
+
}
|
1245 |
+
|
1246 |
+
|
1247 |
+
fc.addDays = addDays;
|
1248 |
+
fc.cloneDate = cloneDate;
|
1249 |
+
fc.parseDate = parseDate;
|
1250 |
+
fc.parseISO8601 = parseISO8601;
|
1251 |
+
fc.parseTime = parseTime;
|
1252 |
+
fc.formatDate = formatDate;
|
1253 |
+
fc.formatDates = formatDates;
|
1254 |
+
|
1255 |
+
|
1256 |
+
|
1257 |
+
/* Date Math
|
1258 |
+
-----------------------------------------------------------------------------*/
|
1259 |
+
|
1260 |
+
var dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'],
|
1261 |
+
DAY_MS = 86400000,
|
1262 |
+
HOUR_MS = 3600000,
|
1263 |
+
MINUTE_MS = 60000;
|
1264 |
+
|
1265 |
+
|
1266 |
+
function addYears(d, n, keepTime) {
|
1267 |
+
d.setFullYear(d.getFullYear() + n);
|
1268 |
+
if (!keepTime) {
|
1269 |
+
clearTime(d);
|
1270 |
+
}
|
1271 |
+
return d;
|
1272 |
+
}
|
1273 |
+
|
1274 |
+
|
1275 |
+
function addMonths(d, n, keepTime) { // prevents day overflow/underflow
|
1276 |
+
if (+d) { // prevent infinite looping on invalid dates
|
1277 |
+
var m = d.getMonth() + n,
|
1278 |
+
check = cloneDate(d);
|
1279 |
+
check.setDate(1);
|
1280 |
+
check.setMonth(m);
|
1281 |
+
d.setMonth(m);
|
1282 |
+
if (!keepTime) {
|
1283 |
+
clearTime(d);
|
1284 |
+
}
|
1285 |
+
while (d.getMonth() != check.getMonth()) {
|
1286 |
+
d.setDate(d.getDate() + (d < check ? 1 : -1));
|
1287 |
+
}
|
1288 |
+
}
|
1289 |
+
return d;
|
1290 |
+
}
|
1291 |
+
|
1292 |
+
|
1293 |
+
function addDays(d, n, keepTime) { // deals with daylight savings
|
1294 |
+
if (+d) {
|
1295 |
+
var dd = d.getDate() + n,
|
1296 |
+
check = cloneDate(d);
|
1297 |
+
check.setHours(9); // set to middle of day
|
1298 |
+
check.setDate(dd);
|
1299 |
+
d.setDate(dd);
|
1300 |
+
if (!keepTime) {
|
1301 |
+
clearTime(d);
|
1302 |
+
}
|
1303 |
+
fixDate(d, check);
|
1304 |
+
}
|
1305 |
+
return d;
|
1306 |
+
}
|
1307 |
+
|
1308 |
+
|
1309 |
+
function fixDate(d, check) { // force d to be on check's YMD, for daylight savings purposes
|
1310 |
+
if (+d) { // prevent infinite looping on invalid dates
|
1311 |
+
while (d.getDate() != check.getDate()) {
|
1312 |
+
d.setTime(+d + (d < check ? 1 : -1) * HOUR_MS);
|
1313 |
+
}
|
1314 |
+
}
|
1315 |
+
}
|
1316 |
+
|
1317 |
+
|
1318 |
+
function addMinutes(d, n) {
|
1319 |
+
d.setMinutes(d.getMinutes() + n);
|
1320 |
+
return d;
|
1321 |
+
}
|
1322 |
+
|
1323 |
+
|
1324 |
+
function clearTime(d) {
|
1325 |
+
d.setHours(0);
|
1326 |
+
d.setMinutes(0);
|
1327 |
+
d.setSeconds(0);
|
1328 |
+
d.setMilliseconds(0);
|
1329 |
+
return d;
|
1330 |
+
}
|
1331 |
+
|
1332 |
+
|
1333 |
+
function cloneDate(d, dontKeepTime) {
|
1334 |
+
if (dontKeepTime) {
|
1335 |
+
return clearTime(new Date(+d));
|
1336 |
+
}
|
1337 |
+
return new Date(+d);
|
1338 |
+
}
|
1339 |
+
|
1340 |
+
|
1341 |
+
function zeroDate() { // returns a Date with time 00:00:00 and dateOfMonth=1
|
1342 |
+
var i=0, d;
|
1343 |
+
do {
|
1344 |
+
d = new Date(1970, i++, 1);
|
1345 |
+
} while (d.getHours()); // != 0
|
1346 |
+
return d;
|
1347 |
+
}
|
1348 |
+
|
1349 |
+
|
1350 |
+
function skipWeekend(date, inc, excl) {
|
1351 |
+
inc = inc || 1;
|
1352 |
+
while (!date.getDay() || (excl && date.getDay()==1 || !excl && date.getDay()==6)) {
|
1353 |
+
addDays(date, inc);
|
1354 |
+
}
|
1355 |
+
return date;
|
1356 |
+
}
|
1357 |
+
|
1358 |
+
|
1359 |
+
function dayDiff(d1, d2) { // d1 - d2
|
1360 |
+
return Math.round((cloneDate(d1, true) - cloneDate(d2, true)) / DAY_MS);
|
1361 |
+
}
|
1362 |
+
|
1363 |
+
|
1364 |
+
function setYMD(date, y, m, d) {
|
1365 |
+
if (y !== undefined && y != date.getFullYear()) {
|
1366 |
+
date.setDate(1);
|
1367 |
+
date.setMonth(0);
|
1368 |
+
date.setFullYear(y);
|
1369 |
+
}
|
1370 |
+
if (m !== undefined && m != date.getMonth()) {
|
1371 |
+
date.setDate(1);
|
1372 |
+
date.setMonth(m);
|
1373 |
+
}
|
1374 |
+
if (d !== undefined) {
|
1375 |
+
date.setDate(d);
|
1376 |
+
}
|
1377 |
+
}
|
1378 |
+
|
1379 |
+
|
1380 |
+
|
1381 |
+
/* Date Parsing
|
1382 |
+
-----------------------------------------------------------------------------*/
|
1383 |
+
|
1384 |
+
|
1385 |
+
function parseDate(s, ignoreTimezone) { // ignoreTimezone defaults to true
|
1386 |
+
if (typeof s == 'object') { // already a Date object
|
1387 |
+
return s;
|
1388 |
+
}
|
1389 |
+
if (typeof s == 'number') { // a UNIX timestamp
|
1390 |
+
return new Date(s * 1000);
|
1391 |
+
}
|
1392 |
+
if (typeof s == 'string') {
|
1393 |
+
if (s.match(/^\d+(\.\d+)?$/)) { // a UNIX timestamp
|
1394 |
+
return new Date(parseFloat(s) * 1000);
|
1395 |
+
}
|
1396 |
+
if (ignoreTimezone === undefined) {
|
1397 |
+
ignoreTimezone = true;
|
1398 |
+
}
|
1399 |
+
return parseISO8601(s, ignoreTimezone) || (s ? new Date(s) : null);
|
1400 |
+
}
|
1401 |
+
// TODO: never return invalid dates (like from new Date(<string>)), return null instead
|
1402 |
+
return null;
|
1403 |
+
}
|
1404 |
+
|
1405 |
+
|
1406 |
+
function parseISO8601(s, ignoreTimezone) { // ignoreTimezone defaults to false
|
1407 |
+
// derived from http://delete.me.uk/2005/03/iso8601.html
|
1408 |
+
// TODO: for a know glitch/feature, read tests/issue_206_parseDate_dst.html
|
1409 |
+
var m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/);
|
1410 |
+
if (!m) {
|
1411 |
+
return null;
|
1412 |
+
}
|
1413 |
+
var date = new Date(m[1], 0, 1);
|
1414 |
+
if (ignoreTimezone || !m[13]) {
|
1415 |
+
var check = new Date(m[1], 0, 1, 9, 0);
|
1416 |
+
if (m[3]) {
|
1417 |
+
date.setMonth(m[3] - 1);
|
1418 |
+
check.setMonth(m[3] - 1);
|
1419 |
+
}
|
1420 |
+
if (m[5]) {
|
1421 |
+
date.setDate(m[5]);
|
1422 |
+
check.setDate(m[5]);
|
1423 |
+
}
|
1424 |
+
fixDate(date, check);
|
1425 |
+
if (m[7]) {
|
1426 |
+
date.setHours(m[7]);
|
1427 |
+
}
|
1428 |
+
if (m[8]) {
|
1429 |
+
date.setMinutes(m[8]);
|
1430 |
+
}
|
1431 |
+
if (m[10]) {
|
1432 |
+
date.setSeconds(m[10]);
|
1433 |
+
}
|
1434 |
+
if (m[12]) {
|
1435 |
+
date.setMilliseconds(Number("0." + m[12]) * 1000);
|
1436 |
+
}
|
1437 |
+
fixDate(date, check);
|
1438 |
+
}else{
|
1439 |
+
date.setUTCFullYear(
|
1440 |
+
m[1],
|
1441 |
+
m[3] ? m[3] - 1 : 0,
|
1442 |
+
m[5] || 1
|
1443 |
+
);
|
1444 |
+
date.setUTCHours(
|
1445 |
+
m[7] || 0,
|
1446 |
+
m[8] || 0,
|
1447 |
+
m[10] || 0,
|
1448 |
+
m[12] ? Number("0." + m[12]) * 1000 : 0
|
1449 |
+
);
|
1450 |
+
if (m[14]) {
|
1451 |
+
var offset = Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0);
|
1452 |
+
offset *= m[15] == '-' ? 1 : -1;
|
1453 |
+
date = new Date(+date + (offset * 60 * 1000));
|
1454 |
+
}
|
1455 |
+
}
|
1456 |
+
return date;
|
1457 |
+
}
|
1458 |
+
|
1459 |
+
|
1460 |
+
function parseTime(s) { // returns minutes since start of day
|
1461 |
+
if (typeof s == 'number') { // an hour
|
1462 |
+
return s * 60;
|
1463 |
+
}
|
1464 |
+
if (typeof s == 'object') { // a Date object
|
1465 |
+
return s.getHours() * 60 + s.getMinutes();
|
1466 |
+
}
|
1467 |
+
var m = s.match(/(\d+)(?::(\d+))?\s*(\w+)?/);
|
1468 |
+
if (m) {
|
1469 |
+
var h = parseInt(m[1], 10);
|
1470 |
+
if (m[3]) {
|
1471 |
+
h %= 12;
|
1472 |
+
if (m[3].toLowerCase().charAt(0) == 'p') {
|
1473 |
+
h += 12;
|
1474 |
+
}
|
1475 |
+
}
|
1476 |
+
return h * 60 + (m[2] ? parseInt(m[2], 10) : 0);
|
1477 |
+
}
|
1478 |
+
}
|
1479 |
+
|
1480 |
+
|
1481 |
+
|
1482 |
+
/* Date Formatting
|
1483 |
+
-----------------------------------------------------------------------------*/
|
1484 |
+
// TODO: use same function formatDate(date, [date2], format, [options])
|
1485 |
+
|
1486 |
+
|
1487 |
+
function formatDate(date, format, options) {
|
1488 |
+
return formatDates(date, null, format, options);
|
1489 |
+
}
|
1490 |
+
|
1491 |
+
|
1492 |
+
function formatDates(date1, date2, format, options) {
|
1493 |
+
options = options || defaults;
|
1494 |
+
var date = date1,
|
1495 |
+
otherDate = date2,
|
1496 |
+
i, len = format.length, c,
|
1497 |
+
i2, formatter,
|
1498 |
+
res = '';
|
1499 |
+
for (i=0; i<len; i++) {
|
1500 |
+
c = format.charAt(i);
|
1501 |
+
if (c == "'") {
|
1502 |
+
for (i2=i+1; i2<len; i2++) {
|
1503 |
+
if (format.charAt(i2) == "'") {
|
1504 |
+
if (date) {
|
1505 |
+
if (i2 == i+1) {
|
1506 |
+
res += "'";
|
1507 |
+
}else{
|
1508 |
+
res += format.substring(i+1, i2);
|
1509 |
+
}
|
1510 |
+
i = i2;
|
1511 |
+
}
|
1512 |
+
break;
|
1513 |
+
}
|
1514 |
+
}
|
1515 |
+
}
|
1516 |
+
else if (c == '(') {
|
1517 |
+
for (i2=i+1; i2<len; i2++) {
|
1518 |
+
if (format.charAt(i2) == ')') {
|
1519 |
+
var subres = formatDate(date, format.substring(i+1, i2), options);
|
1520 |
+
if (parseInt(subres.replace(/\D/, ''), 10)) {
|
1521 |
+
res += subres;
|
1522 |
+
}
|
1523 |
+
i = i2;
|
1524 |
+
break;
|
1525 |
+
}
|
1526 |
+
}
|
1527 |
+
}
|
1528 |
+
else if (c == '[') {
|
1529 |
+
for (i2=i+1; i2<len; i2++) {
|
1530 |
+
if (format.charAt(i2) == ']') {
|
1531 |
+
var subformat = format.substring(i+1, i2);
|
1532 |
+
var subres = formatDate(date, subformat, options);
|
1533 |
+
if (subres != formatDate(otherDate, subformat, options)) {
|
1534 |
+
res += subres;
|
1535 |
+
}
|
1536 |
+
i = i2;
|
1537 |
+
break;
|
1538 |
+
}
|
1539 |
+
}
|
1540 |
+
}
|
1541 |
+
else if (c == '{') {
|
1542 |
+
date = date2;
|
1543 |
+
otherDate = date1;
|
1544 |
+
}
|
1545 |
+
else if (c == '}') {
|
1546 |
+
date = date1;
|
1547 |
+
otherDate = date2;
|
1548 |
+
}
|
1549 |
+
else {
|
1550 |
+
for (i2=len; i2>i; i2--) {
|
1551 |
+
if (formatter = dateFormatters[format.substring(i, i2)]) {
|
1552 |
+
if (date) {
|
1553 |
+
res += formatter(date, options);
|
1554 |
+
}
|
1555 |
+
i = i2 - 1;
|
1556 |
+
break;
|
1557 |
+
}
|
1558 |
+
}
|
1559 |
+
if (i2 == i) {
|
1560 |
+
if (date) {
|
1561 |
+
res += c;
|
1562 |
+
}
|
1563 |
+
}
|
1564 |
+
}
|
1565 |
+
}
|
1566 |
+
return res;
|
1567 |
+
};
|
1568 |
+
|
1569 |
+
|
1570 |
+
var dateFormatters = {
|
1571 |
+
s : function(d) { return d.getSeconds() },
|
1572 |
+
ss : function(d) { return zeroPad(d.getSeconds()) },
|
1573 |
+
m : function(d) { return d.getMinutes() },
|
1574 |
+
mm : function(d) { return zeroPad(d.getMinutes()) },
|
1575 |
+
h : function(d) { return d.getHours() % 12 || 12 },
|
1576 |
+
hh : function(d) { return zeroPad(d.getHours() % 12 || 12) },
|
1577 |
+
H : function(d) { return d.getHours() },
|
1578 |
+
HH : function(d) { return zeroPad(d.getHours()) },
|
1579 |
+
d : function(d) { return d.getDate() },
|
1580 |
+
dd : function(d) { return zeroPad(d.getDate()) },
|
1581 |
+
ddd : function(d,o) { return o.dayNamesShort[d.getDay()] },
|
1582 |
+
dddd: function(d,o) { return o.dayNames[d.getDay()] },
|
1583 |
+
M : function(d) { return d.getMonth() + 1 },
|
1584 |
+
MM : function(d) { return zeroPad(d.getMonth() + 1) },
|
1585 |
+
MMM : function(d,o) { return o.monthNamesShort[d.getMonth()] },
|
1586 |
+
MMMM: function(d,o) { return o.monthNames[d.getMonth()] },
|
1587 |
+
yy : function(d) { return (d.getFullYear()+'').substring(2) },
|
1588 |
+
yyyy: function(d) { return d.getFullYear() },
|
1589 |
+
t : function(d) { return d.getHours() < 12 ? 'a' : 'p' },
|
1590 |
+
tt : function(d) { return d.getHours() < 12 ? 'am' : 'pm' },
|
1591 |
+
T : function(d) { return d.getHours() < 12 ? 'A' : 'P' },
|
1592 |
+
TT : function(d) { return d.getHours() < 12 ? 'AM' : 'PM' },
|
1593 |
+
u : function(d) { return formatDate(d, "yyyy-MM-dd'T'HH:mm:ss'Z'") },
|
1594 |
+
S : function(d) {
|
1595 |
+
var date = d.getDate();
|
1596 |
+
if (date > 10 && date < 20) {
|
1597 |
+
return 'th';
|
1598 |
+
}
|
1599 |
+
return ['st', 'nd', 'rd'][date%10-1] || 'th';
|
1600 |
+
}
|
1601 |
+
};
|
1602 |
+
|
1603 |
+
|
1604 |
+
|
1605 |
+
fc.applyAll = applyAll;
|
1606 |
+
|
1607 |
+
|
1608 |
+
/* Event Date Math
|
1609 |
+
-----------------------------------------------------------------------------*/
|
1610 |
+
|
1611 |
+
|
1612 |
+
function exclEndDay(event) {
|
1613 |
+
if (event.end) {
|
1614 |
+
return _exclEndDay(event.end, event.allDay);
|
1615 |
+
}else{
|
1616 |
+
return addDays(cloneDate(event.start), 1);
|
1617 |
+
}
|
1618 |
+
}
|
1619 |
+
|
1620 |
+
|
1621 |
+
function _exclEndDay(end, allDay) {
|
1622 |
+
end = cloneDate(end);
|
1623 |
+
return allDay || end.getHours() || end.getMinutes() ? addDays(end, 1) : clearTime(end);
|
1624 |
+
}
|
1625 |
+
|
1626 |
+
|
1627 |
+
function segCmp(a, b) {
|
1628 |
+
return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start);
|
1629 |
+
}
|
1630 |
+
|
1631 |
+
|
1632 |
+
function segsCollide(seg1, seg2) {
|
1633 |
+
return seg1.end > seg2.start && seg1.start < seg2.end;
|
1634 |
+
}
|
1635 |
+
|
1636 |
+
|
1637 |
+
|
1638 |
+
/* Event Sorting
|
1639 |
+
-----------------------------------------------------------------------------*/
|
1640 |
+
|
1641 |
+
|
1642 |
+
// event rendering utilities
|
1643 |
+
function sliceSegs(events, visEventEnds, start, end) {
|
1644 |
+
var segs = [],
|
1645 |
+
i, len=events.length, event,
|
1646 |
+
eventStart, eventEnd,
|
1647 |
+
segStart, segEnd,
|
1648 |
+
isStart, isEnd;
|
1649 |
+
for (i=0; i<len; i++) {
|
1650 |
+
event = events[i];
|
1651 |
+
eventStart = event.start;
|
1652 |
+
eventEnd = visEventEnds[i];
|
1653 |
+
if (eventEnd > start && eventStart < end) {
|
1654 |
+
if (eventStart < start) {
|
1655 |
+
segStart = cloneDate(start);
|
1656 |
+
isStart = false;
|
1657 |
+
}else{
|
1658 |
+
segStart = eventStart;
|
1659 |
+
isStart = true;
|
1660 |
+
}
|
1661 |
+
if (eventEnd > end) {
|
1662 |
+
segEnd = cloneDate(end);
|
1663 |
+
isEnd = false;
|
1664 |
+
}else{
|
1665 |
+
segEnd = eventEnd;
|
1666 |
+
isEnd = true;
|
1667 |
+
}
|
1668 |
+
segs.push({
|
1669 |
+
event: event,
|
1670 |
+
start: segStart,
|
1671 |
+
end: segEnd,
|
1672 |
+
isStart: isStart,
|
1673 |
+
isEnd: isEnd,
|
1674 |
+
msLength: segEnd - segStart
|
1675 |
+
});
|
1676 |
+
}
|
1677 |
+
}
|
1678 |
+
return segs.sort(segCmp);
|
1679 |
+
}
|
1680 |
+
|
1681 |
+
|
1682 |
+
// event rendering calculation utilities
|
1683 |
+
function stackSegs(segs) {
|
1684 |
+
var levels = [],
|
1685 |
+
i, len = segs.length, seg,
|
1686 |
+
j, collide, k;
|
1687 |
+
for (i=0; i<len; i++) {
|
1688 |
+
seg = segs[i];
|
1689 |
+
j = 0; // the level index where seg should belong
|
1690 |
+
while (true) {
|
1691 |
+
collide = false;
|
1692 |
+
if (levels[j]) {
|
1693 |
+
for (k=0; k<levels[j].length; k++) {
|
1694 |
+
if (segsCollide(levels[j][k], seg)) {
|
1695 |
+
collide = true;
|
1696 |
+
break;
|
1697 |
+
}
|
1698 |
+
}
|
1699 |
+
}
|
1700 |
+
if (collide) {
|
1701 |
+
j++;
|
1702 |
+
}else{
|
1703 |
+
break;
|
1704 |
+
}
|
1705 |
+
}
|
1706 |
+
if (levels[j]) {
|
1707 |
+
levels[j].push(seg);
|
1708 |
+
}else{
|
1709 |
+
levels[j] = [seg];
|
1710 |
+
}
|
1711 |
+
}
|
1712 |
+
return levels;
|
1713 |
+
}
|
1714 |
+
|
1715 |
+
|
1716 |
+
|
1717 |
+
/* Event Element Binding
|
1718 |
+
-----------------------------------------------------------------------------*/
|
1719 |
+
|
1720 |
+
|
1721 |
+
function lazySegBind(container, segs, bindHandlers) {
|
1722 |
+
container.unbind('mouseover').mouseover(function(ev) {
|
1723 |
+
var parent=ev.target, e,
|
1724 |
+
i, seg;
|
1725 |
+
while (parent != this) {
|
1726 |
+
e = parent;
|
1727 |
+
parent = parent.parentNode;
|
1728 |
+
}
|
1729 |
+
if ((i = e._fci) !== undefined) {
|
1730 |
+
e._fci = undefined;
|
1731 |
+
seg = segs[i];
|
1732 |
+
bindHandlers(seg.event, seg.element, seg);
|
1733 |
+
$(ev.target).trigger(ev);
|
1734 |
+
}
|
1735 |
+
ev.stopPropagation();
|
1736 |
+
});
|
1737 |
+
}
|
1738 |
+
|
1739 |
+
|
1740 |
+
|
1741 |
+
/* Element Dimensions
|
1742 |
+
-----------------------------------------------------------------------------*/
|
1743 |
+
|
1744 |
+
|
1745 |
+
function setOuterWidth(element, width, includeMargins) {
|
1746 |
+
for (var i=0, e; i<element.length; i++) {
|
1747 |
+
e = $(element[i]);
|
1748 |
+
e.width(Math.max(0, width - hsides(e, includeMargins)));
|
1749 |
+
}
|
1750 |
+
}
|
1751 |
+
|
1752 |
+
|
1753 |
+
function setOuterHeight(element, height, includeMargins) {
|
1754 |
+
for (var i=0, e; i<element.length; i++) {
|
1755 |
+
e = $(element[i]);
|
1756 |
+
e.height(Math.max(0, height - vsides(e, includeMargins)));
|
1757 |
+
}
|
1758 |
+
}
|
1759 |
+
|
1760 |
+
|
1761 |
+
function hsides(element, includeMargins) {
|
1762 |
+
return hpadding(element) + hborders(element) + (includeMargins ? hmargins(element) : 0);
|
1763 |
+
}
|
1764 |
+
|
1765 |
+
|
1766 |
+
function hpadding(element) {
|
1767 |
+
return (parseFloat($.css(element[0], 'paddingLeft', true)) || 0) +
|
1768 |
+
(parseFloat($.css(element[0], 'paddingRight', true)) || 0);
|
1769 |
+
}
|
1770 |
+
|
1771 |
+
|
1772 |
+
function hmargins(element) {
|
1773 |
+
return (parseFloat($.css(element[0], 'marginLeft', true)) || 0) +
|
1774 |
+
(parseFloat($.css(element[0], 'marginRight', true)) || 0);
|
1775 |
+
}
|
1776 |
+
|
1777 |
+
|
1778 |
+
function hborders(element) {
|
1779 |
+
return (parseFloat($.css(element[0], 'borderLeftWidth', true)) || 0) +
|
1780 |
+
(parseFloat($.css(element[0], 'borderRightWidth', true)) || 0);
|
1781 |
+
}
|
1782 |
+
|
1783 |
+
|
1784 |
+
function vsides(element, includeMargins) {
|
1785 |
+
return vpadding(element) + vborders(element) + (includeMargins ? vmargins(element) : 0);
|
1786 |
+
}
|
1787 |
+
|
1788 |
+
|
1789 |
+
function vpadding(element) {
|
1790 |
+
return (parseFloat($.css(element[0], 'paddingTop', true)) || 0) +
|
1791 |
+
(parseFloat($.css(element[0], 'paddingBottom', true)) || 0);
|
1792 |
+
}
|
1793 |
+
|
1794 |
+
|
1795 |
+
function vmargins(element) {
|
1796 |
+
return (parseFloat($.css(element[0], 'marginTop', true)) || 0) +
|
1797 |
+
(parseFloat($.css(element[0], 'marginBottom', true)) || 0);
|
1798 |
+
}
|
1799 |
+
|
1800 |
+
|
1801 |
+
function vborders(element) {
|
1802 |
+
return (parseFloat($.css(element[0], 'borderTopWidth', true)) || 0) +
|
1803 |
+
(parseFloat($.css(element[0], 'borderBottomWidth', true)) || 0);
|
1804 |
+
}
|
1805 |
+
|
1806 |
+
|
1807 |
+
function setMinHeight(element, height) {
|
1808 |
+
height = (typeof height == 'number' ? height + 'px' : height);
|
1809 |
+
element.each(function(i, _element) {
|
1810 |
+
_element.style.cssText += ';min-height:' + height + ';_height:' + height;
|
1811 |
+
// why can't we just use .css() ? i forget
|
1812 |
+
});
|
1813 |
+
}
|
1814 |
+
|
1815 |
+
|
1816 |
+
|
1817 |
+
/* Misc Utils
|
1818 |
+
-----------------------------------------------------------------------------*/
|
1819 |
+
|
1820 |
+
|
1821 |
+
//TODO: arraySlice
|
1822 |
+
//TODO: isFunction, grep ?
|
1823 |
+
|
1824 |
+
|
1825 |
+
function noop() { }
|
1826 |
+
|
1827 |
+
|
1828 |
+
function cmp(a, b) {
|
1829 |
+
return a - b;
|
1830 |
+
}
|
1831 |
+
|
1832 |
+
|
1833 |
+
function arrayMax(a) {
|
1834 |
+
return Math.max.apply(Math, a);
|
1835 |
+
}
|
1836 |
+
|
1837 |
+
|
1838 |
+
function zeroPad(n) {
|
1839 |
+
return (n < 10 ? '0' : '') + n;
|
1840 |
+
}
|
1841 |
+
|
1842 |
+
|
1843 |
+
function smartProperty(obj, name) { // get a camel-cased/namespaced property of an object
|
1844 |
+
if (obj[name] !== undefined) {
|
1845 |
+
return obj[name];
|
1846 |
+
}
|
1847 |
+
var parts = name.split(/(?=[A-Z])/),
|
1848 |
+
i=parts.length-1, res;
|
1849 |
+
for (; i>=0; i--) {
|
1850 |
+
res = obj[parts[i].toLowerCase()];
|
1851 |
+
if (res !== undefined) {
|
1852 |
+
return res;
|
1853 |
+
}
|
1854 |
+
}
|
1855 |
+
return obj[''];
|
1856 |
+
}
|
1857 |
+
|
1858 |
+
|
1859 |
+
function htmlEscape(s) {
|
1860 |
+
return s.replace(/&/g, '&')
|
1861 |
+
.replace(/</g, '<')
|
1862 |
+
.replace(/>/g, '>')
|
1863 |
+
.replace(/'/g, ''')
|
1864 |
+
.replace(/"/g, '"')
|
1865 |
+
.replace(/\n/g, '<br />');
|
1866 |
+
}
|
1867 |
+
|
1868 |
+
|
1869 |
+
function cssKey(_element) {
|
1870 |
+
return _element.id + '/' + _element.className + '/' + _element.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig, '');
|
1871 |
+
}
|
1872 |
+
|
1873 |
+
|
1874 |
+
function disableTextSelection(element) {
|
1875 |
+
element
|
1876 |
+
.attr('unselectable', 'on')
|
1877 |
+
.css('MozUserSelect', 'none')
|
1878 |
+
.bind('selectstart.ui', function() { return false; });
|
1879 |
+
}
|
1880 |
+
|
1881 |
+
|
1882 |
+
/*
|
1883 |
+
function enableTextSelection(element) {
|
1884 |
+
element
|
1885 |
+
.attr('unselectable', 'off')
|
1886 |
+
.css('MozUserSelect', '')
|
1887 |
+
.unbind('selectstart.ui');
|
1888 |
+
}
|
1889 |
+
*/
|
1890 |
+
|
1891 |
+
|
1892 |
+
function markFirstLast(e) {
|
1893 |
+
e.children()
|
1894 |
+
.removeClass('fc-first fc-last')
|
1895 |
+
.filter(':first-child')
|
1896 |
+
.addClass('fc-first')
|
1897 |
+
.end()
|
1898 |
+
.filter(':last-child')
|
1899 |
+
.addClass('fc-last');
|
1900 |
+
}
|
1901 |
+
|
1902 |
+
|
1903 |
+
function setDayID(cell, date) {
|
1904 |
+
cell.each(function(i, _cell) {
|
1905 |
+
_cell.className = _cell.className.replace(/^fc-\w*/, 'fc-' + dayIDs[date.getDay()]);
|
1906 |
+
// TODO: make a way that doesn't rely on order of classes
|
1907 |
+
});
|
1908 |
+
}
|
1909 |
+
|
1910 |
+
|
1911 |
+
function getSkinCss(event, opt) {
|
1912 |
+
var source = event.source || {};
|
1913 |
+
var eventColor = event.color;
|
1914 |
+
var sourceColor = source.color;
|
1915 |
+
var optionColor = opt('eventColor');
|
1916 |
+
var backgroundColor =
|
1917 |
+
event.backgroundColor ||
|
1918 |
+
eventColor ||
|
1919 |
+
source.backgroundColor ||
|
1920 |
+
sourceColor ||
|
1921 |
+
opt('eventBackgroundColor') ||
|
1922 |
+
optionColor;
|
1923 |
+
var borderColor =
|
1924 |
+
event.borderColor ||
|
1925 |
+
eventColor ||
|
1926 |
+
source.borderColor ||
|
1927 |
+
sourceColor ||
|
1928 |
+
opt('eventBorderColor') ||
|
1929 |
+
optionColor;
|
1930 |
+
var textColor =
|
1931 |
+
event.textColor ||
|
1932 |
+
source.textColor ||
|
1933 |
+
opt('eventTextColor');
|
1934 |
+
var statements = [];
|
1935 |
+
if (backgroundColor) {
|
1936 |
+
statements.push('background-color:' + backgroundColor);
|
1937 |
+
}
|
1938 |
+
if (borderColor) {
|
1939 |
+
statements.push('border-color:' + borderColor);
|
1940 |
+
}
|
1941 |
+
if (textColor) {
|
1942 |
+
statements.push('color:' + textColor);
|
1943 |
+
}
|
1944 |
+
return statements.join(';');
|
1945 |
+
}
|
1946 |
+
|
1947 |
+
|
1948 |
+
function applyAll(functions, thisObj, args) {
|
1949 |
+
if ($.isFunction(functions)) {
|
1950 |
+
functions = [ functions ];
|
1951 |
+
}
|
1952 |
+
if (functions) {
|
1953 |
+
var i;
|
1954 |
+
var ret;
|
1955 |
+
for (i=0; i<functions.length; i++) {
|
1956 |
+
ret = functions[i].apply(thisObj, args) || ret;
|
1957 |
+
}
|
1958 |
+
return ret;
|
1959 |
+
}
|
1960 |
+
}
|
1961 |
+
|
1962 |
+
|
1963 |
+
function firstDefined() {
|
1964 |
+
for (var i=0; i<arguments.length; i++) {
|
1965 |
+
if (arguments[i] !== undefined) {
|
1966 |
+
return arguments[i];
|
1967 |
+
}
|
1968 |
+
}
|
1969 |
+
}
|
1970 |
+
|
1971 |
+
|
1972 |
+
fcViews.month = MonthView;
|
1973 |
+
|
1974 |
+
function MonthView(element, calendar) {
|
1975 |
+
var t = this;
|
1976 |
+
|
1977 |
+
|
1978 |
+
// exports
|
1979 |
+
t.render = render;
|
1980 |
+
|
1981 |
+
|
1982 |
+
// imports
|
1983 |
+
BasicView.call(t, element, calendar, 'month');
|
1984 |
+
var opt = t.opt;
|
1985 |
+
var renderBasic = t.renderBasic;
|
1986 |
+
var formatDate = calendar.formatDate;
|
1987 |
+
|
1988 |
+
|
1989 |
+
|
1990 |
+
function render(date, delta) {
|
1991 |
+
if (delta) {
|
1992 |
+
addMonths(date, delta);
|
1993 |
+
date.setDate(1);
|
1994 |
+
}
|
1995 |
+
var start = cloneDate(date, true);
|
1996 |
+
start.setDate(1);
|
1997 |
+
var end = addMonths(cloneDate(start), 1);
|
1998 |
+
var visStart = cloneDate(start);
|
1999 |
+
var visEnd = cloneDate(end);
|
2000 |
+
var firstDay = opt('firstDay');
|
2001 |
+
var nwe = opt('weekends') ? 0 : 1;
|
2002 |
+
if (nwe) {
|
2003 |
+
skipWeekend(visStart);
|
2004 |
+
skipWeekend(visEnd, -1, true);
|
2005 |
+
}
|
2006 |
+
addDays(visStart, -((visStart.getDay() - Math.max(firstDay, nwe) + 7) % 7));
|
2007 |
+
addDays(visEnd, (7 - visEnd.getDay() + Math.max(firstDay, nwe)) % 7);
|
2008 |
+
var rowCnt = Math.round((visEnd - visStart) / (DAY_MS * 7));
|
2009 |
+
if (opt('weekMode') == 'fixed') {
|
2010 |
+
addDays(visEnd, (6 - rowCnt) * 7);
|
2011 |
+
rowCnt = 6;
|
2012 |
+
}
|
2013 |
+
t.title = formatDate(start, opt('titleFormat'));
|
2014 |
+
t.start = start;
|
2015 |
+
t.end = end;
|
2016 |
+
t.visStart = visStart;
|
2017 |
+
t.visEnd = visEnd;
|
2018 |
+
renderBasic(6, rowCnt, nwe ? 5 : 7, true);
|
2019 |
+
}
|
2020 |
+
|
2021 |
+
|
2022 |
+
}
|
2023 |
+
|
2024 |
+
fcViews.basicWeek = BasicWeekView;
|
2025 |
+
|
2026 |
+
function BasicWeekView(element, calendar) {
|
2027 |
+
var t = this;
|
2028 |
+
|
2029 |
+
|
2030 |
+
// exports
|
2031 |
+
t.render = render;
|
2032 |
+
|
2033 |
+
|
2034 |
+
// imports
|
2035 |
+
BasicView.call(t, element, calendar, 'basicWeek');
|
2036 |
+
var opt = t.opt;
|
2037 |
+
var renderBasic = t.renderBasic;
|
2038 |
+
var formatDates = calendar.formatDates;
|
2039 |
+
|
2040 |
+
|
2041 |
+
|
2042 |
+
function render(date, delta) {
|
2043 |
+
if (delta) {
|
2044 |
+
addDays(date, delta * 7);
|
2045 |
+
}
|
2046 |
+
var start = addDays(cloneDate(date), -((date.getDay() - opt('firstDay') + 7) % 7));
|
2047 |
+
var end = addDays(cloneDate(start), 7);
|
2048 |
+
var visStart = cloneDate(start);
|
2049 |
+
var visEnd = cloneDate(end);
|
2050 |
+
var weekends = opt('weekends');
|
2051 |
+
if (!weekends) {
|
2052 |
+
skipWeekend(visStart);
|
2053 |
+
skipWeekend(visEnd, -1, true);
|
2054 |
+
}
|
2055 |
+
t.title = formatDates(
|
2056 |
+
visStart,
|
2057 |
+
addDays(cloneDate(visEnd), -1),
|
2058 |
+
opt('titleFormat')
|
2059 |
+
);
|
2060 |
+
t.start = start;
|
2061 |
+
t.end = end;
|
2062 |
+
t.visStart = visStart;
|
2063 |
+
t.visEnd = visEnd;
|
2064 |
+
renderBasic(1, 1, weekends ? 7 : 5, false);
|
2065 |
+
}
|
2066 |
+
|
2067 |
+
|
2068 |
+
}
|
2069 |
+
|
2070 |
+
fcViews.basicDay = BasicDayView;
|
2071 |
+
|
2072 |
+
//TODO: when calendar's date starts out on a weekend, shouldn't happen
|
2073 |
+
|
2074 |
+
|
2075 |
+
function BasicDayView(element, calendar) {
|
2076 |
+
var t = this;
|
2077 |
+
|
2078 |
+
|
2079 |
+
// exports
|
2080 |
+
t.render = render;
|
2081 |
+
|
2082 |
+
|
2083 |
+
// imports
|
2084 |
+
BasicView.call(t, element, calendar, 'basicDay');
|
2085 |
+
var opt = t.opt;
|
2086 |
+
var renderBasic = t.renderBasic;
|
2087 |
+
var formatDate = calendar.formatDate;
|
2088 |
+
|
2089 |
+
|
2090 |
+
|
2091 |
+
function render(date, delta) {
|
2092 |
+
if (delta) {
|
2093 |
+
addDays(date, delta);
|
2094 |
+
if (!opt('weekends')) {
|
2095 |
+
skipWeekend(date, delta < 0 ? -1 : 1);
|
2096 |
+
}
|
2097 |
+
}
|
2098 |
+
t.title = formatDate(date, opt('titleFormat'));
|
2099 |
+
t.start = t.visStart = cloneDate(date, true);
|
2100 |
+
t.end = t.visEnd = addDays(cloneDate(t.start), 1);
|
2101 |
+
renderBasic(1, 1, 1, false);
|
2102 |
+
}
|
2103 |
+
|
2104 |
+
|
2105 |
+
}
|
2106 |
+
|
2107 |
+
setDefaults({
|
2108 |
+
weekMode: 'fixed'
|
2109 |
+
});
|
2110 |
+
|
2111 |
+
|
2112 |
+
function BasicView(element, calendar, viewName) {
|
2113 |
+
var t = this;
|
2114 |
+
|
2115 |
+
|
2116 |
+
// exports
|
2117 |
+
t.renderBasic = renderBasic;
|
2118 |
+
t.setHeight = setHeight;
|
2119 |
+
t.setWidth = setWidth;
|
2120 |
+
t.renderDayOverlay = renderDayOverlay;
|
2121 |
+
t.defaultSelectionEnd = defaultSelectionEnd;
|
2122 |
+
t.renderSelection = renderSelection;
|
2123 |
+
t.clearSelection = clearSelection;
|
2124 |
+
t.reportDayClick = reportDayClick; // for selection (kinda hacky)
|
2125 |
+
t.dragStart = dragStart;
|
2126 |
+
t.dragStop = dragStop;
|
2127 |
+
t.defaultEventEnd = defaultEventEnd;
|
2128 |
+
t.getHoverListener = function() { return hoverListener };
|
2129 |
+
t.colContentLeft = colContentLeft;
|
2130 |
+
t.colContentRight = colContentRight;
|
2131 |
+
t.dayOfWeekCol = dayOfWeekCol;
|
2132 |
+
t.dateCell = dateCell;
|
2133 |
+
t.cellDate = cellDate;
|
2134 |
+
t.cellIsAllDay = function() { return true };
|
2135 |
+
t.allDayRow = allDayRow;
|
2136 |
+
t.allDayBounds = allDayBounds;
|
2137 |
+
t.getRowCnt = function() { return rowCnt };
|
2138 |
+
t.getColCnt = function() { return colCnt };
|
2139 |
+
t.getColWidth = function() { return colWidth };
|
2140 |
+
t.getDaySegmentContainer = function() { return daySegmentContainer };
|
2141 |
+
|
2142 |
+
|
2143 |
+
// imports
|
2144 |
+
View.call(t, element, calendar, viewName);
|
2145 |
+
OverlayManager.call(t);
|
2146 |
+
SelectionManager.call(t);
|
2147 |
+
BasicEventRenderer.call(t);
|
2148 |
+
var opt = t.opt;
|
2149 |
+
var trigger = t.trigger;
|
2150 |
+
var clearEvents = t.clearEvents;
|
2151 |
+
var renderOverlay = t.renderOverlay;
|
2152 |
+
var clearOverlays = t.clearOverlays;
|
2153 |
+
var daySelectionMousedown = t.daySelectionMousedown;
|
2154 |
+
var formatDate = calendar.formatDate;
|
2155 |
+
|
2156 |
+
|
2157 |
+
// locals
|
2158 |
+
|
2159 |
+
var head;
|
2160 |
+
var headCells;
|
2161 |
+
var body;
|
2162 |
+
var bodyRows;
|
2163 |
+
var bodyCells;
|
2164 |
+
var bodyFirstCells;
|
2165 |
+
var bodyCellTopInners;
|
2166 |
+
var daySegmentContainer;
|
2167 |
+
|
2168 |
+
var viewWidth;
|
2169 |
+
var viewHeight;
|
2170 |
+
var colWidth;
|
2171 |
+
|
2172 |
+
var rowCnt, colCnt;
|
2173 |
+
var coordinateGrid;
|
2174 |
+
var hoverListener;
|
2175 |
+
var colContentPositions;
|
2176 |
+
|
2177 |
+
var rtl, dis, dit;
|
2178 |
+
var firstDay;
|
2179 |
+
var nwe;
|
2180 |
+
var tm;
|
2181 |
+
var colFormat;
|
2182 |
+
|
2183 |
+
|
2184 |
+
|
2185 |
+
/* Rendering
|
2186 |
+
------------------------------------------------------------*/
|
2187 |
+
|
2188 |
+
|
2189 |
+
disableTextSelection(element.addClass('fc-grid'));
|
2190 |
+
|
2191 |
+
|
2192 |
+
function renderBasic(maxr, r, c, showNumbers) {
|
2193 |
+
rowCnt = r;
|
2194 |
+
colCnt = c;
|
2195 |
+
updateOptions();
|
2196 |
+
var firstTime = !body;
|
2197 |
+
if (firstTime) {
|
2198 |
+
buildSkeleton(maxr, showNumbers);
|
2199 |
+
}else{
|
2200 |
+
clearEvents();
|
2201 |
+
}
|
2202 |
+
updateCells(firstTime);
|
2203 |
+
}
|
2204 |
+
|
2205 |
+
|
2206 |
+
|
2207 |
+
function updateOptions() {
|
2208 |
+
rtl = opt('isRTL');
|
2209 |
+
if (rtl) {
|
2210 |
+
dis = -1;
|
2211 |
+
dit = colCnt - 1;
|
2212 |
+
}else{
|
2213 |
+
dis = 1;
|
2214 |
+
dit = 0;
|
2215 |
+
}
|
2216 |
+
firstDay = opt('firstDay');
|
2217 |
+
nwe = opt('weekends') ? 0 : 1;
|
2218 |
+
tm = opt('theme') ? 'ui' : 'fc';
|
2219 |
+
colFormat = opt('columnFormat');
|
2220 |
+
}
|
2221 |
+
|
2222 |
+
|
2223 |
+
|
2224 |
+
function buildSkeleton(maxRowCnt, showNumbers) {
|
2225 |
+
var s;
|
2226 |
+
var headerClass = tm + "-widget-header";
|
2227 |
+
var contentClass = tm + "-widget-content";
|
2228 |
+
var i, j;
|
2229 |
+
var table;
|
2230 |
+
|
2231 |
+
s =
|
2232 |
+
"<table class='fc-border-separate' style='width:100%' cellspacing='0'>" +
|
2233 |
+
"<thead>" +
|
2234 |
+
"<tr>";
|
2235 |
+
for (i=0; i<colCnt; i++) {
|
2236 |
+
s +=
|
2237 |
+
"<th class='fc- " + headerClass + "'/>"; // need fc- for setDayID
|
2238 |
+
}
|
2239 |
+
s +=
|
2240 |
+
"</tr>" +
|
2241 |
+
"</thead>" +
|
2242 |
+
"<tbody>";
|
2243 |
+
for (i=0; i<maxRowCnt; i++) {
|
2244 |
+
s +=
|
2245 |
+
"<tr class='fc-week" + i + "'>";
|
2246 |
+
for (j=0; j<colCnt; j++) {
|
2247 |
+
s +=
|
2248 |
+
"<td class='fc- " + contentClass + " fc-day" + (i*colCnt+j) + "'>" + // need fc- for setDayID
|
2249 |
+
"<div>" +
|
2250 |
+
(showNumbers ?
|
2251 |
+
"<div class='fc-day-number'/>" :
|
2252 |
+
''
|
2253 |
+
) +
|
2254 |
+
"<div class='fc-day-content'>" +
|
2255 |
+
"<div style='position:relative'> </div>" +
|
2256 |
+
"</div>" +
|
2257 |
+
"</div>" +
|
2258 |
+
"</td>";
|
2259 |
+
}
|
2260 |
+
s +=
|
2261 |
+
"</tr>";
|
2262 |
+
}
|
2263 |
+
s +=
|
2264 |
+
"</tbody>" +
|
2265 |
+
"</table>";
|
2266 |
+
table = $(s).appendTo(element);
|
2267 |
+
|
2268 |
+
head = table.find('thead');
|
2269 |
+
headCells = head.find('th');
|
2270 |
+
body = table.find('tbody');
|
2271 |
+
bodyRows = body.find('tr');
|
2272 |
+
bodyCells = body.find('td');
|
2273 |
+
bodyFirstCells = bodyCells.filter(':first-child');
|
2274 |
+
bodyCellTopInners = bodyRows.eq(0).find('div.fc-day-content div');
|
2275 |
+
|
2276 |
+
markFirstLast(head.add(head.find('tr'))); // marks first+last tr/th's
|
2277 |
+
markFirstLast(bodyRows); // marks first+last td's
|
2278 |
+
bodyRows.eq(0).addClass('fc-first'); // fc-last is done in updateCells
|
2279 |
+
|
2280 |
+
dayBind(bodyCells);
|
2281 |
+
|
2282 |
+
daySegmentContainer =
|
2283 |
+
$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
|
2284 |
+
.appendTo(element);
|
2285 |
+
}
|
2286 |
+
|
2287 |
+
|
2288 |
+
|
2289 |
+
function updateCells(firstTime) {
|
2290 |
+
var dowDirty = firstTime || rowCnt == 1; // could the cells' day-of-weeks need updating?
|
2291 |
+
var month = t.start.getMonth();
|
2292 |
+
var today = clearTime(new Date());
|
2293 |
+
var cell;
|
2294 |
+
var date;
|
2295 |
+
var row;
|
2296 |
+
|
2297 |
+
if (dowDirty) {
|
2298 |
+
headCells.each(function(i, _cell) {
|
2299 |
+
cell = $(_cell);
|
2300 |
+
date = indexDate(i);
|
2301 |
+
cell.html(formatDate(date, colFormat));
|
2302 |
+
setDayID(cell, date);
|
2303 |
+
});
|
2304 |
+
}
|
2305 |
+
|
2306 |
+
bodyCells.each(function(i, _cell) {
|
2307 |
+
cell = $(_cell);
|
2308 |
+
date = indexDate(i);
|
2309 |
+
if (date.getMonth() == month) {
|
2310 |
+
cell.removeClass('fc-other-month');
|
2311 |
+
}else{
|
2312 |
+
cell.addClass('fc-other-month');
|
2313 |
+
}
|
2314 |
+
if (+date == +today) {
|
2315 |
+
cell.addClass(tm + '-state-highlight fc-today');
|
2316 |
+
}else{
|
2317 |
+
cell.removeClass(tm + '-state-highlight fc-today');
|
2318 |
+
}
|
2319 |
+
cell.find('div.fc-day-number').text(date.getDate());
|
2320 |
+
if (dowDirty) {
|
2321 |
+
setDayID(cell, date);
|
2322 |
+
}
|
2323 |
+
});
|
2324 |
+
|
2325 |
+
bodyRows.each(function(i, _row) {
|
2326 |
+
row = $(_row);
|
2327 |
+
if (i < rowCnt) {
|
2328 |
+
row.show();
|
2329 |
+
if (i == rowCnt-1) {
|
2330 |
+
row.addClass('fc-last');
|
2331 |
+
}else{
|
2332 |
+
row.removeClass('fc-last');
|
2333 |
+
}
|
2334 |
+
}else{
|
2335 |
+
row.hide();
|
2336 |
+
}
|
2337 |
+
});
|
2338 |
+
}
|
2339 |
+
|
2340 |
+
|
2341 |
+
|
2342 |
+
function setHeight(height) {
|
2343 |
+
viewHeight = height;
|
2344 |
+
|
2345 |
+
var bodyHeight = viewHeight - head.height();
|
2346 |
+
var rowHeight;
|
2347 |
+
var rowHeightLast;
|
2348 |
+
var cell;
|
2349 |
+
|
2350 |
+
if (opt('weekMode') == 'variable') {
|
2351 |
+
rowHeight = rowHeightLast = Math.floor(bodyHeight / (rowCnt==1 ? 2 : 6));
|
2352 |
+
}else{
|
2353 |
+
rowHeight = Math.floor(bodyHeight / rowCnt);
|
2354 |
+
rowHeightLast = bodyHeight - rowHeight * (rowCnt-1);
|
2355 |
+
}
|
2356 |
+
|
2357 |
+
bodyFirstCells.each(function(i, _cell) {
|
2358 |
+
if (i < rowCnt) {
|
2359 |
+
cell = $(_cell);
|
2360 |
+
setMinHeight(
|
2361 |
+
cell.find('> div'),
|
2362 |
+
(i==rowCnt-1 ? rowHeightLast : rowHeight) - vsides(cell)
|
2363 |
+
);
|
2364 |
+
}
|
2365 |
+
});
|
2366 |
+
|
2367 |
+
}
|
2368 |
+
|
2369 |
+
|
2370 |
+
function setWidth(width) {
|
2371 |
+
viewWidth = width;
|
2372 |
+
colContentPositions.clear();
|
2373 |
+
colWidth = Math.floor(viewWidth / colCnt);
|
2374 |
+
setOuterWidth(headCells.slice(0, -1), colWidth);
|
2375 |
+
}
|
2376 |
+
|
2377 |
+
|
2378 |
+
|
2379 |
+
/* Day clicking and binding
|
2380 |
+
-----------------------------------------------------------*/
|
2381 |
+
|
2382 |
+
|
2383 |
+
function dayBind(days) {
|
2384 |
+
days.click(dayClick)
|
2385 |
+
.mousedown(daySelectionMousedown);
|
2386 |
+
}
|
2387 |
+
|
2388 |
+
|
2389 |
+
function dayClick(ev) {
|
2390 |
+
if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick
|
2391 |
+
var index = parseInt(this.className.match(/fc\-day(\d+)/)[1]); // TODO: maybe use .data
|
2392 |
+
var date = indexDate(index);
|
2393 |
+
trigger('dayClick', this, date, true, ev);
|
2394 |
+
}
|
2395 |
+
}
|
2396 |
+
|
2397 |
+
|
2398 |
+
|
2399 |
+
/* Semi-transparent Overlay Helpers
|
2400 |
+
------------------------------------------------------*/
|
2401 |
+
|
2402 |
+
|
2403 |
+
function renderDayOverlay(overlayStart, overlayEnd, refreshCoordinateGrid) { // overlayEnd is exclusive
|
2404 |
+
if (refreshCoordinateGrid) {
|
2405 |
+
coordinateGrid.build();
|
2406 |
+
}
|
2407 |
+
var rowStart = cloneDate(t.visStart);
|
2408 |
+
var rowEnd = addDays(cloneDate(rowStart), colCnt);
|
2409 |
+
for (var i=0; i<rowCnt; i++) {
|
2410 |
+
var stretchStart = new Date(Math.max(rowStart, overlayStart));
|
2411 |
+
var stretchEnd = new Date(Math.min(rowEnd, overlayEnd));
|
2412 |
+
if (stretchStart < stretchEnd) {
|
2413 |
+
var colStart, colEnd;
|
2414 |
+
if (rtl) {
|
2415 |
+
colStart = dayDiff(stretchEnd, rowStart)*dis+dit+1;
|
2416 |
+
colEnd = dayDiff(stretchStart, rowStart)*dis+dit+1;
|
2417 |
+
}else{
|
2418 |
+
colStart = dayDiff(stretchStart, rowStart);
|
2419 |
+
colEnd = dayDiff(stretchEnd, rowStart);
|
2420 |
+
}
|
2421 |
+
dayBind(
|
2422 |
+
renderCellOverlay(i, colStart, i, colEnd-1)
|
2423 |
+
);
|
2424 |
+
}
|
2425 |
+
addDays(rowStart, 7);
|
2426 |
+
addDays(rowEnd, 7);
|
2427 |
+
}
|
2428 |
+
}
|
2429 |
+
|
2430 |
+
|
2431 |
+
function renderCellOverlay(row0, col0, row1, col1) { // row1,col1 is inclusive
|
2432 |
+
var rect = coordinateGrid.rect(row0, col0, row1, col1, element);
|
2433 |
+
return renderOverlay(rect, element);
|
2434 |
+
}
|
2435 |
+
|
2436 |
+
|
2437 |
+
|
2438 |
+
/* Selection
|
2439 |
+
-----------------------------------------------------------------------*/
|
2440 |
+
|
2441 |
+
|
2442 |
+
function defaultSelectionEnd(startDate, allDay) {
|
2443 |
+
return cloneDate(startDate);
|
2444 |
+
}
|
2445 |
+
|
2446 |
+
|
2447 |
+
function renderSelection(startDate, endDate, allDay) {
|
2448 |
+
renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true); // rebuild every time???
|
2449 |
+
}
|
2450 |
+
|
2451 |
+
|
2452 |
+
function clearSelection() {
|
2453 |
+
clearOverlays();
|
2454 |
+
}
|
2455 |
+
|
2456 |
+
|
2457 |
+
function reportDayClick(date, allDay, ev) {
|
2458 |
+
var cell = dateCell(date);
|
2459 |
+
var _element = bodyCells[cell.row*colCnt + cell.col];
|
2460 |
+
trigger('dayClick', _element, date, allDay, ev);
|
2461 |
+
}
|
2462 |
+
|
2463 |
+
|
2464 |
+
|
2465 |
+
/* External Dragging
|
2466 |
+
-----------------------------------------------------------------------*/
|
2467 |
+
|
2468 |
+
|
2469 |
+
function dragStart(_dragElement, ev, ui) {
|
2470 |
+
hoverListener.start(function(cell) {
|
2471 |
+
clearOverlays();
|
2472 |
+
if (cell) {
|
2473 |
+
renderCellOverlay(cell.row, cell.col, cell.row, cell.col);
|
2474 |
+
}
|
2475 |
+
}, ev);
|
2476 |
+
}
|
2477 |
+
|
2478 |
+
|
2479 |
+
function dragStop(_dragElement, ev, ui) {
|
2480 |
+
var cell = hoverListener.stop();
|
2481 |
+
clearOverlays();
|
2482 |
+
if (cell) {
|
2483 |
+
var d = cellDate(cell);
|
2484 |
+
trigger('drop', _dragElement, d, true, ev, ui);
|
2485 |
+
}
|
2486 |
+
}
|
2487 |
+
|
2488 |
+
|
2489 |
+
|
2490 |
+
/* Utilities
|
2491 |
+
--------------------------------------------------------*/
|
2492 |
+
|
2493 |
+
|
2494 |
+
function defaultEventEnd(event) {
|
2495 |
+
return cloneDate(event.start);
|
2496 |
+
}
|
2497 |
+
|
2498 |
+
|
2499 |
+
coordinateGrid = new CoordinateGrid(function(rows, cols) {
|
2500 |
+
var e, n, p;
|
2501 |
+
headCells.each(function(i, _e) {
|
2502 |
+
e = $(_e);
|
2503 |
+
n = e.offset().left;
|
2504 |
+
if (i) {
|
2505 |
+
p[1] = n;
|
2506 |
+
}
|
2507 |
+
p = [n];
|
2508 |
+
cols[i] = p;
|
2509 |
+
});
|
2510 |
+
p[1] = n + e.outerWidth();
|
2511 |
+
bodyRows.each(function(i, _e) {
|
2512 |
+
if (i < rowCnt) {
|
2513 |
+
e = $(_e);
|
2514 |
+
n = e.offset().top;
|
2515 |
+
if (i) {
|
2516 |
+
p[1] = n;
|
2517 |
+
}
|
2518 |
+
p = [n];
|
2519 |
+
rows[i] = p;
|
2520 |
+
}
|
2521 |
+
});
|
2522 |
+
p[1] = n + e.outerHeight();
|
2523 |
+
});
|
2524 |
+
|
2525 |
+
|
2526 |
+
hoverListener = new HoverListener(coordinateGrid);
|
2527 |
+
|
2528 |
+
|
2529 |
+
colContentPositions = new HorizontalPositionCache(function(col) {
|
2530 |
+
return bodyCellTopInners.eq(col);
|
2531 |
+
});
|
2532 |
+
|
2533 |
+
|
2534 |
+
function colContentLeft(col) {
|
2535 |
+
return colContentPositions.left(col);
|
2536 |
+
}
|
2537 |
+
|
2538 |
+
|
2539 |
+
function colContentRight(col) {
|
2540 |
+
return colContentPositions.right(col);
|
2541 |
+
}
|
2542 |
+
|
2543 |
+
|
2544 |
+
|
2545 |
+
|
2546 |
+
function dateCell(date) {
|
2547 |
+
return {
|
2548 |
+
row: Math.floor(dayDiff(date, t.visStart) / 7),
|
2549 |
+
col: dayOfWeekCol(date.getDay())
|
2550 |
+
};
|
2551 |
+
}
|
2552 |
+
|
2553 |
+
|
2554 |
+
function cellDate(cell) {
|
2555 |
+
return _cellDate(cell.row, cell.col);
|
2556 |
+
}
|
2557 |
+
|
2558 |
+
|
2559 |
+
function _cellDate(row, col) {
|
2560 |
+
return addDays(cloneDate(t.visStart), row*7 + col*dis+dit);
|
2561 |
+
// what about weekends in middle of week?
|
2562 |
+
}
|
2563 |
+
|
2564 |
+
|
2565 |
+
function indexDate(index) {
|
2566 |
+
return _cellDate(Math.floor(index/colCnt), index%colCnt);
|
2567 |
+
}
|
2568 |
+
|
2569 |
+
|
2570 |
+
function dayOfWeekCol(dayOfWeek) {
|
2571 |
+
return ((dayOfWeek - Math.max(firstDay, nwe) + colCnt) % colCnt) * dis + dit;
|
2572 |
+
}
|
2573 |
+
|
2574 |
+
|
2575 |
+
|
2576 |
+
|
2577 |
+
function allDayRow(i) {
|
2578 |
+
return bodyRows.eq(i);
|
2579 |
+
}
|
2580 |
+
|
2581 |
+
|
2582 |
+
function allDayBounds(i) {
|
2583 |
+
return {
|
2584 |
+
left: 0,
|
2585 |
+
right: viewWidth
|
2586 |
+
};
|
2587 |
+
}
|
2588 |
+
|
2589 |
+
|
2590 |
+
}
|
2591 |
+
|
2592 |
+
function BasicEventRenderer() {
|
2593 |
+
var t = this;
|
2594 |
+
|
2595 |
+
|
2596 |
+
// exports
|
2597 |
+
t.renderEvents = renderEvents;
|
2598 |
+
t.compileDaySegs = compileSegs; // for DayEventRenderer
|
2599 |
+
t.clearEvents = clearEvents;
|
2600 |
+
t.bindDaySeg = bindDaySeg;
|
2601 |
+
|
2602 |
+
|
2603 |
+
// imports
|
2604 |
+
DayEventRenderer.call(t);
|
2605 |
+
var opt = t.opt;
|
2606 |
+
var trigger = t.trigger;
|
2607 |
+
//var setOverflowHidden = t.setOverflowHidden;
|
2608 |
+
var isEventDraggable = t.isEventDraggable;
|
2609 |
+
var isEventResizable = t.isEventResizable;
|
2610 |
+
var reportEvents = t.reportEvents;
|
2611 |
+
var reportEventClear = t.reportEventClear;
|
2612 |
+
var eventElementHandlers = t.eventElementHandlers;
|
2613 |
+
var showEvents = t.showEvents;
|
2614 |
+
var hideEvents = t.hideEvents;
|
2615 |
+
var eventDrop = t.eventDrop;
|
2616 |
+
var getDaySegmentContainer = t.getDaySegmentContainer;
|
2617 |
+
var getHoverListener = t.getHoverListener;
|
2618 |
+
var renderDayOverlay = t.renderDayOverlay;
|
2619 |
+
var clearOverlays = t.clearOverlays;
|
2620 |
+
var getRowCnt = t.getRowCnt;
|
2621 |
+
var getColCnt = t.getColCnt;
|
2622 |
+
var renderDaySegs = t.renderDaySegs;
|
2623 |
+
var resizableDayEvent = t.resizableDayEvent;
|
2624 |
+
|
2625 |
+
|
2626 |
+
|
2627 |
+
/* Rendering
|
2628 |
+
--------------------------------------------------------------------*/
|
2629 |
+
|
2630 |
+
|
2631 |
+
function renderEvents(events, modifiedEventId) {
|
2632 |
+
reportEvents(events);
|
2633 |
+
renderDaySegs(compileSegs(events), modifiedEventId);
|
2634 |
+
}
|
2635 |
+
|
2636 |
+
|
2637 |
+
function clearEvents() {
|
2638 |
+
reportEventClear();
|
2639 |
+
getDaySegmentContainer().empty();
|
2640 |
+
}
|
2641 |
+
|
2642 |
+
|
2643 |
+
function compileSegs(events) {
|
2644 |
+
var rowCnt = getRowCnt(),
|
2645 |
+
colCnt = getColCnt(),
|
2646 |
+
d1 = cloneDate(t.visStart),
|
2647 |
+
d2 = addDays(cloneDate(d1), colCnt),
|
2648 |
+
visEventsEnds = $.map(events, exclEndDay),
|
2649 |
+
i, row,
|
2650 |
+
j, level,
|
2651 |
+
k, seg,
|
2652 |
+
segs=[];
|
2653 |
+
for (i=0; i<rowCnt; i++) {
|
2654 |
+
row = stackSegs(sliceSegs(events, visEventsEnds, d1, d2));
|
2655 |
+
for (j=0; j<row.length; j++) {
|
2656 |
+
level = row[j];
|
2657 |
+
for (k=0; k<level.length; k++) {
|
2658 |
+
seg = level[k];
|
2659 |
+
seg.row = i;
|
2660 |
+
seg.level = j; // not needed anymore
|
2661 |
+
segs.push(seg);
|
2662 |
+
}
|
2663 |
+
}
|
2664 |
+
addDays(d1, 7);
|
2665 |
+
addDays(d2, 7);
|
2666 |
+
}
|
2667 |
+
return segs;
|
2668 |
+
}
|
2669 |
+
|
2670 |
+
|
2671 |
+
function bindDaySeg(event, eventElement, seg) {
|
2672 |
+
if (isEventDraggable(event)) {
|
2673 |
+
draggableDayEvent(event, eventElement);
|
2674 |
+
}
|
2675 |
+
if (seg.isEnd && isEventResizable(event)) {
|
2676 |
+
resizableDayEvent(event, eventElement, seg);
|
2677 |
+
}
|
2678 |
+
eventElementHandlers(event, eventElement);
|
2679 |
+
// needs to be after, because resizableDayEvent might stopImmediatePropagation on click
|
2680 |
+
}
|
2681 |
+
|
2682 |
+
|
2683 |
+
|
2684 |
+
/* Dragging
|
2685 |
+
----------------------------------------------------------------------------*/
|
2686 |
+
|
2687 |
+
|
2688 |
+
function draggableDayEvent(event, eventElement) {
|
2689 |
+
var hoverListener = getHoverListener();
|
2690 |
+
var dayDelta;
|
2691 |
+
eventElement.draggable({
|
2692 |
+
zIndex: 9,
|
2693 |
+
delay: 50,
|
2694 |
+
opacity: opt('dragOpacity'),
|
2695 |
+
revertDuration: opt('dragRevertDuration'),
|
2696 |
+
start: function(ev, ui) {
|
2697 |
+
trigger('eventDragStart', eventElement, event, ev, ui);
|
2698 |
+
hideEvents(event, eventElement);
|
2699 |
+
hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
2700 |
+
eventElement.draggable('option', 'revert', !cell || !rowDelta && !colDelta);
|
2701 |
+
clearOverlays();
|
2702 |
+
if (cell) {
|
2703 |
+
//setOverflowHidden(true);
|
2704 |
+
dayDelta = rowDelta*7 + colDelta * (opt('isRTL') ? -1 : 1);
|
2705 |
+
renderDayOverlay(
|
2706 |
+
addDays(cloneDate(event.start), dayDelta),
|
2707 |
+
addDays(exclEndDay(event), dayDelta)
|
2708 |
+
);
|
2709 |
+
}else{
|
2710 |
+
//setOverflowHidden(false);
|
2711 |
+
dayDelta = 0;
|
2712 |
+
}
|
2713 |
+
}, ev, 'drag');
|
2714 |
+
},
|
2715 |
+
stop: function(ev, ui) {
|
2716 |
+
hoverListener.stop();
|
2717 |
+
clearOverlays();
|
2718 |
+
trigger('eventDragStop', eventElement, event, ev, ui);
|
2719 |
+
if (dayDelta) {
|
2720 |
+
eventDrop(this, event, dayDelta, 0, event.allDay, ev, ui);
|
2721 |
+
}else{
|
2722 |
+
eventElement.css('filter', ''); // clear IE opacity side-effects
|
2723 |
+
showEvents(event, eventElement);
|
2724 |
+
}
|
2725 |
+
//setOverflowHidden(false);
|
2726 |
+
}
|
2727 |
+
});
|
2728 |
+
}
|
2729 |
+
|
2730 |
+
|
2731 |
+
}
|
2732 |
+
|
2733 |
+
fcViews.agendaWeek = AgendaWeekView;
|
2734 |
+
|
2735 |
+
function AgendaWeekView(element, calendar) {
|
2736 |
+
var t = this;
|
2737 |
+
|
2738 |
+
|
2739 |
+
// exports
|
2740 |
+
t.render = render;
|
2741 |
+
|
2742 |
+
|
2743 |
+
// imports
|
2744 |
+
AgendaView.call(t, element, calendar, 'agendaWeek');
|
2745 |
+
var opt = t.opt;
|
2746 |
+
var renderAgenda = t.renderAgenda;
|
2747 |
+
var formatDates = calendar.formatDates;
|
2748 |
+
|
2749 |
+
|
2750 |
+
|
2751 |
+
function render(date, delta) {
|
2752 |
+
if (delta) {
|
2753 |
+
addDays(date, delta * 7);
|
2754 |
+
}
|
2755 |
+
var start = addDays(cloneDate(date), -((date.getDay() - opt('firstDay') + 7) % 7));
|
2756 |
+
var end = addDays(cloneDate(start), 7);
|
2757 |
+
var visStart = cloneDate(start);
|
2758 |
+
var visEnd = cloneDate(end);
|
2759 |
+
var weekends = opt('weekends');
|
2760 |
+
if (!weekends) {
|
2761 |
+
skipWeekend(visStart);
|
2762 |
+
skipWeekend(visEnd, -1, true);
|
2763 |
+
}
|
2764 |
+
t.title = formatDates(
|
2765 |
+
visStart,
|
2766 |
+
addDays(cloneDate(visEnd), -1),
|
2767 |
+
opt('titleFormat')
|
2768 |
+
);
|
2769 |
+
t.start = start;
|
2770 |
+
t.end = end;
|
2771 |
+
t.visStart = visStart;
|
2772 |
+
t.visEnd = visEnd;
|
2773 |
+
renderAgenda(weekends ? 7 : 5);
|
2774 |
+
}
|
2775 |
+
|
2776 |
+
|
2777 |
+
}
|
2778 |
+
|
2779 |
+
fcViews.agendaDay = AgendaDayView;
|
2780 |
+
|
2781 |
+
function AgendaDayView(element, calendar) {
|
2782 |
+
var t = this;
|
2783 |
+
|
2784 |
+
|
2785 |
+
// exports
|
2786 |
+
t.render = render;
|
2787 |
+
|
2788 |
+
|
2789 |
+
// imports
|
2790 |
+
AgendaView.call(t, element, calendar, 'agendaDay');
|
2791 |
+
var opt = t.opt;
|
2792 |
+
var renderAgenda = t.renderAgenda;
|
2793 |
+
var formatDate = calendar.formatDate;
|
2794 |
+
|
2795 |
+
|
2796 |
+
|
2797 |
+
function render(date, delta) {
|
2798 |
+
if (delta) {
|
2799 |
+
addDays(date, delta);
|
2800 |
+
if (!opt('weekends')) {
|
2801 |
+
skipWeekend(date, delta < 0 ? -1 : 1);
|
2802 |
+
}
|
2803 |
+
}
|
2804 |
+
var start = cloneDate(date, true);
|
2805 |
+
var end = addDays(cloneDate(start), 1);
|
2806 |
+
t.title = formatDate(date, opt('titleFormat'));
|
2807 |
+
t.start = t.visStart = start;
|
2808 |
+
t.end = t.visEnd = end;
|
2809 |
+
renderAgenda(1);
|
2810 |
+
}
|
2811 |
+
|
2812 |
+
|
2813 |
+
}
|
2814 |
+
|
2815 |
+
setDefaults({
|
2816 |
+
allDaySlot: true,
|
2817 |
+
allDayText: 'all-day',
|
2818 |
+
firstHour: 6,
|
2819 |
+
slotMinutes: 30,
|
2820 |
+
defaultEventMinutes: 120,
|
2821 |
+
axisFormat: 'h(:mm)tt',
|
2822 |
+
timeFormat: {
|
2823 |
+
agenda: 'h:mm{ - h:mm}'
|
2824 |
+
},
|
2825 |
+
dragOpacity: {
|
2826 |
+
agenda: .5
|
2827 |
+
},
|
2828 |
+
minTime: 0,
|
2829 |
+
maxTime: 24
|
2830 |
+
});
|
2831 |
+
|
2832 |
+
|
2833 |
+
// TODO: make it work in quirks mode (event corners, all-day height)
|
2834 |
+
// TODO: test liquid width, especially in IE6
|
2835 |
+
|
2836 |
+
|
2837 |
+
function AgendaView(element, calendar, viewName) {
|
2838 |
+
var t = this;
|
2839 |
+
|
2840 |
+
|
2841 |
+
// exports
|
2842 |
+
t.renderAgenda = renderAgenda;
|
2843 |
+
t.setWidth = setWidth;
|
2844 |
+
t.setHeight = setHeight;
|
2845 |
+
t.beforeHide = beforeHide;
|
2846 |
+
t.afterShow = afterShow;
|
2847 |
+
t.defaultEventEnd = defaultEventEnd;
|
2848 |
+
t.timePosition = timePosition;
|
2849 |
+
t.dayOfWeekCol = dayOfWeekCol;
|
2850 |
+
t.dateCell = dateCell;
|
2851 |
+
t.cellDate = cellDate;
|
2852 |
+
t.cellIsAllDay = cellIsAllDay;
|
2853 |
+
t.allDayRow = getAllDayRow;
|
2854 |
+
t.allDayBounds = allDayBounds;
|
2855 |
+
t.getHoverListener = function() { return hoverListener };
|
2856 |
+
t.colContentLeft = colContentLeft;
|
2857 |
+
t.colContentRight = colContentRight;
|
2858 |
+
t.getDaySegmentContainer = function() { return daySegmentContainer };
|
2859 |
+
t.getSlotSegmentContainer = function() { return slotSegmentContainer };
|
2860 |
+
t.getMinMinute = function() { return minMinute };
|
2861 |
+
t.getMaxMinute = function() { return maxMinute };
|
2862 |
+
t.getBodyContent = function() { return slotContent }; // !!??
|
2863 |
+
t.getRowCnt = function() { return 1 };
|
2864 |
+
t.getColCnt = function() { return colCnt };
|
2865 |
+
t.getColWidth = function() { return colWidth };
|
2866 |
+
t.getSlotHeight = function() { return slotHeight };
|
2867 |
+
t.defaultSelectionEnd = defaultSelectionEnd;
|
2868 |
+
t.renderDayOverlay = renderDayOverlay;
|
2869 |
+
t.renderSelection = renderSelection;
|
2870 |
+
t.clearSelection = clearSelection;
|
2871 |
+
t.reportDayClick = reportDayClick; // selection mousedown hack
|
2872 |
+
t.dragStart = dragStart;
|
2873 |
+
t.dragStop = dragStop;
|
2874 |
+
|
2875 |
+
|
2876 |
+
// imports
|
2877 |
+
View.call(t, element, calendar, viewName);
|
2878 |
+
OverlayManager.call(t);
|
2879 |
+
SelectionManager.call(t);
|
2880 |
+
AgendaEventRenderer.call(t);
|
2881 |
+
var opt = t.opt;
|
2882 |
+
var trigger = t.trigger;
|
2883 |
+
var clearEvents = t.clearEvents;
|
2884 |
+
var renderOverlay = t.renderOverlay;
|
2885 |
+
var clearOverlays = t.clearOverlays;
|
2886 |
+
var reportSelection = t.reportSelection;
|
2887 |
+
var unselect = t.unselect;
|
2888 |
+
var daySelectionMousedown = t.daySelectionMousedown;
|
2889 |
+
var slotSegHtml = t.slotSegHtml;
|
2890 |
+
var formatDate = calendar.formatDate;
|
2891 |
+
|
2892 |
+
|
2893 |
+
// locals
|
2894 |
+
|
2895 |
+
var dayTable;
|
2896 |
+
var dayHead;
|
2897 |
+
var dayHeadCells;
|
2898 |
+
var dayBody;
|
2899 |
+
var dayBodyCells;
|
2900 |
+
var dayBodyCellInners;
|
2901 |
+
var dayBodyFirstCell;
|
2902 |
+
var dayBodyFirstCellStretcher;
|
2903 |
+
var slotLayer;
|
2904 |
+
var daySegmentContainer;
|
2905 |
+
var allDayTable;
|
2906 |
+
var allDayRow;
|
2907 |
+
var slotScroller;
|
2908 |
+
var slotContent;
|
2909 |
+
var slotSegmentContainer;
|
2910 |
+
var slotTable;
|
2911 |
+
var slotTableFirstInner;
|
2912 |
+
var axisFirstCells;
|
2913 |
+
var gutterCells;
|
2914 |
+
var selectionHelper;
|
2915 |
+
|
2916 |
+
var viewWidth;
|
2917 |
+
var viewHeight;
|
2918 |
+
var axisWidth;
|
2919 |
+
var colWidth;
|
2920 |
+
var gutterWidth;
|
2921 |
+
var slotHeight; // TODO: what if slotHeight changes? (see issue 650)
|
2922 |
+
var savedScrollTop;
|
2923 |
+
|
2924 |
+
var colCnt;
|
2925 |
+
var slotCnt;
|
2926 |
+
var coordinateGrid;
|
2927 |
+
var hoverListener;
|
2928 |
+
var colContentPositions;
|
2929 |
+
var slotTopCache = {};
|
2930 |
+
|
2931 |
+
var tm;
|
2932 |
+
var firstDay;
|
2933 |
+
var nwe; // no weekends (int)
|
2934 |
+
var rtl, dis, dit; // day index sign / translate
|
2935 |
+
var minMinute, maxMinute;
|
2936 |
+
var colFormat;
|
2937 |
+
|
2938 |
+
|
2939 |
+
|
2940 |
+
/* Rendering
|
2941 |
+
-----------------------------------------------------------------------------*/
|
2942 |
+
|
2943 |
+
|
2944 |
+
disableTextSelection(element.addClass('fc-agenda'));
|
2945 |
+
|
2946 |
+
|
2947 |
+
function renderAgenda(c) {
|
2948 |
+
colCnt = c;
|
2949 |
+
updateOptions();
|
2950 |
+
if (!dayTable) {
|
2951 |
+
buildSkeleton();
|
2952 |
+
}else{
|
2953 |
+
clearEvents();
|
2954 |
+
}
|
2955 |
+
updateCells();
|
2956 |
+
}
|
2957 |
+
|
2958 |
+
|
2959 |
+
|
2960 |
+
function updateOptions() {
|
2961 |
+
tm = opt('theme') ? 'ui' : 'fc';
|
2962 |
+
nwe = opt('weekends') ? 0 : 1;
|
2963 |
+
firstDay = opt('firstDay');
|
2964 |
+
if (rtl = opt('isRTL')) {
|
2965 |
+
dis = -1;
|
2966 |
+
dit = colCnt - 1;
|
2967 |
+
}else{
|
2968 |
+
dis = 1;
|
2969 |
+
dit = 0;
|
2970 |
+
}
|
2971 |
+
minMinute = parseTime(opt('minTime'));
|
2972 |
+
maxMinute = parseTime(opt('maxTime'));
|
2973 |
+
colFormat = opt('columnFormat');
|
2974 |
+
}
|
2975 |
+
|
2976 |
+
|
2977 |
+
|
2978 |
+
function buildSkeleton() {
|
2979 |
+
var headerClass = tm + "-widget-header";
|
2980 |
+
var contentClass = tm + "-widget-content";
|
2981 |
+
var s;
|
2982 |
+
var i;
|
2983 |
+
var d;
|
2984 |
+
var maxd;
|
2985 |
+
var minutes;
|
2986 |
+
var slotNormal = opt('slotMinutes') % 15 == 0;
|
2987 |
+
|
2988 |
+
s =
|
2989 |
+
"<table style='width:100%' class='fc-agenda-days fc-border-separate' cellspacing='0'>" +
|
2990 |
+
"<thead>" +
|
2991 |
+
"<tr>" +
|
2992 |
+
"<th class='fc-agenda-axis " + headerClass + "'> </th>";
|
2993 |
+
for (i=0; i<colCnt; i++) {
|
2994 |
+
s +=
|
2995 |
+
"<th class='fc- fc-col" + i + ' ' + headerClass + "'/>"; // fc- needed for setDayID
|
2996 |
+
}
|
2997 |
+
s +=
|
2998 |
+
"<th class='fc-agenda-gutter " + headerClass + "'> </th>" +
|
2999 |
+
"</tr>" +
|
3000 |
+
"</thead>" +
|
3001 |
+
"<tbody>" +
|
3002 |
+
"<tr>" +
|
3003 |
+
"<th class='fc-agenda-axis " + headerClass + "'> </th>";
|
3004 |
+
for (i=0; i<colCnt; i++) {
|
3005 |
+
s +=
|
3006 |
+
"<td class='fc- fc-col" + i + ' ' + contentClass + "'>" + // fc- needed for setDayID
|
3007 |
+
"<div>" +
|
3008 |
+
"<div class='fc-day-content'>" +
|
3009 |
+
"<div style='position:relative'> </div>" +
|
3010 |
+
"</div>" +
|
3011 |
+
"</div>" +
|
3012 |
+
"</td>";
|
3013 |
+
}
|
3014 |
+
s +=
|
3015 |
+
"<td class='fc-agenda-gutter " + contentClass + "'> </td>" +
|
3016 |
+
"</tr>" +
|
3017 |
+
"</tbody>" +
|
3018 |
+
"</table>";
|
3019 |
+
dayTable = $(s).appendTo(element);
|
3020 |
+
dayHead = dayTable.find('thead');
|
3021 |
+
dayHeadCells = dayHead.find('th').slice(1, -1);
|
3022 |
+
dayBody = dayTable.find('tbody');
|
3023 |
+
dayBodyCells = dayBody.find('td').slice(0, -1);
|
3024 |
+
dayBodyCellInners = dayBodyCells.find('div.fc-day-content div');
|
3025 |
+
dayBodyFirstCell = dayBodyCells.eq(0);
|
3026 |
+
dayBodyFirstCellStretcher = dayBodyFirstCell.find('> div');
|
3027 |
+
|
3028 |
+
markFirstLast(dayHead.add(dayHead.find('tr')));
|
3029 |
+
markFirstLast(dayBody.add(dayBody.find('tr')));
|
3030 |
+
|
3031 |
+
axisFirstCells = dayHead.find('th:first');
|
3032 |
+
gutterCells = dayTable.find('.fc-agenda-gutter');
|
3033 |
+
|
3034 |
+
slotLayer =
|
3035 |
+
$("<div style='position:absolute;z-index:2;left:0;width:100%'/>")
|
3036 |
+
.appendTo(element);
|
3037 |
+
|
3038 |
+
if (opt('allDaySlot')) {
|
3039 |
+
|
3040 |
+
daySegmentContainer =
|
3041 |
+
$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
|
3042 |
+
.appendTo(slotLayer);
|
3043 |
+
|
3044 |
+
s =
|
3045 |
+
"<table style='width:100%' class='fc-agenda-allday' cellspacing='0'>" +
|
3046 |
+
"<tr>" +
|
3047 |
+
"<th class='" + headerClass + " fc-agenda-axis'>" + opt('allDayText') + "</th>" +
|
3048 |
+
"<td>" +
|
3049 |
+
"<div class='fc-day-content'><div style='position:relative'/></div>" +
|
3050 |
+
"</td>" +
|
3051 |
+
"<th class='" + headerClass + " fc-agenda-gutter'> </th>" +
|
3052 |
+
"</tr>" +
|
3053 |
+
"</table>";
|
3054 |
+
allDayTable = $(s).appendTo(slotLayer);
|
3055 |
+
allDayRow = allDayTable.find('tr');
|
3056 |
+
|
3057 |
+
dayBind(allDayRow.find('td'));
|
3058 |
+
|
3059 |
+
axisFirstCells = axisFirstCells.add(allDayTable.find('th:first'));
|
3060 |
+
gutterCells = gutterCells.add(allDayTable.find('th.fc-agenda-gutter'));
|
3061 |
+
|
3062 |
+
slotLayer.append(
|
3063 |
+
"<div class='fc-agenda-divider " + headerClass + "'>" +
|
3064 |
+
"<div class='fc-agenda-divider-inner'/>" +
|
3065 |
+
"</div>"
|
3066 |
+
);
|
3067 |
+
|
3068 |
+
}else{
|
3069 |
+
|
3070 |
+
daySegmentContainer = $([]); // in jQuery 1.4, we can just do $()
|
3071 |
+
|
3072 |
+
}
|
3073 |
+
|
3074 |
+
slotScroller =
|
3075 |
+
$("<div style='position:absolute;width:100%;overflow-x:hidden;overflow-y:auto'/>")
|
3076 |
+
.appendTo(slotLayer);
|
3077 |
+
|
3078 |
+
slotContent =
|
3079 |
+
$("<div style='position:relative;width:100%;overflow:hidden'/>")
|
3080 |
+
.appendTo(slotScroller);
|
3081 |
+
|
3082 |
+
slotSegmentContainer =
|
3083 |
+
$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
|
3084 |
+
.appendTo(slotContent);
|
3085 |
+
|
3086 |
+
s =
|
3087 |
+
"<table class='fc-agenda-slots' style='width:100%' cellspacing='0'>" +
|
3088 |
+
"<tbody>";
|
3089 |
+
d = zeroDate();
|
3090 |
+
maxd = addMinutes(cloneDate(d), maxMinute);
|
3091 |
+
addMinutes(d, minMinute);
|
3092 |
+
slotCnt = 0;
|
3093 |
+
for (i=0; d < maxd; i++) {
|
3094 |
+
minutes = d.getMinutes();
|
3095 |
+
s +=
|
3096 |
+
"<tr class='fc-slot" + i + ' ' + (!minutes ? '' : 'fc-minor') + "'>" +
|
3097 |
+
"<th class='fc-agenda-axis " + headerClass + "'>" +
|
3098 |
+
((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : ' ') +
|
3099 |
+
"</th>" +
|
3100 |
+
"<td class='" + contentClass + "'>" +
|
3101 |
+
"<div style='position:relative'> </div>" +
|
3102 |
+
"</td>" +
|
3103 |
+
"</tr>";
|
3104 |
+
addMinutes(d, opt('slotMinutes'));
|
3105 |
+
slotCnt++;
|
3106 |
+
}
|
3107 |
+
s +=
|
3108 |
+
"</tbody>" +
|
3109 |
+
"</table>";
|
3110 |
+
slotTable = $(s).appendTo(slotContent);
|
3111 |
+
slotTableFirstInner = slotTable.find('div:first');
|
3112 |
+
|
3113 |
+
slotBind(slotTable.find('td'));
|
3114 |
+
|
3115 |
+
axisFirstCells = axisFirstCells.add(slotTable.find('th:first'));
|
3116 |
+
}
|
3117 |
+
|
3118 |
+
|
3119 |
+
|
3120 |
+
function updateCells() {
|
3121 |
+
var i;
|
3122 |
+
var headCell;
|
3123 |
+
var bodyCell;
|
3124 |
+
var date;
|
3125 |
+
var today = clearTime(new Date());
|
3126 |
+
for (i=0; i<colCnt; i++) {
|
3127 |
+
date = colDate(i);
|
3128 |
+
headCell = dayHeadCells.eq(i);
|
3129 |
+
headCell.html(formatDate(date, colFormat));
|
3130 |
+
bodyCell = dayBodyCells.eq(i);
|
3131 |
+
if (+date == +today) {
|
3132 |
+
bodyCell.addClass(tm + '-state-highlight fc-today');
|
3133 |
+
}else{
|
3134 |
+
bodyCell.removeClass(tm + '-state-highlight fc-today');
|
3135 |
+
}
|
3136 |
+
setDayID(headCell.add(bodyCell), date);
|
3137 |
+
}
|
3138 |
+
}
|
3139 |
+
|
3140 |
+
|
3141 |
+
|
3142 |
+
function setHeight(height, dateChanged) {
|
3143 |
+
if (height === undefined) {
|
3144 |
+
height = viewHeight;
|
3145 |
+
}
|
3146 |
+
viewHeight = height;
|
3147 |
+
slotTopCache = {};
|
3148 |
+
|
3149 |
+
var headHeight = dayBody.position().top;
|
3150 |
+
var allDayHeight = slotScroller.position().top; // including divider
|
3151 |
+
var bodyHeight = Math.min( // total body height, including borders
|
3152 |
+
height - headHeight, // when scrollbars
|
3153 |
+
slotTable.height() + allDayHeight + 1 // when no scrollbars. +1 for bottom border
|
3154 |
+
);
|
3155 |
+
|
3156 |
+
dayBodyFirstCellStretcher
|
3157 |
+
.height(bodyHeight - vsides(dayBodyFirstCell));
|
3158 |
+
|
3159 |
+
slotLayer.css('top', headHeight);
|
3160 |
+
|
3161 |
+
slotScroller.height(bodyHeight - allDayHeight - 1);
|
3162 |
+
|
3163 |
+
slotHeight = slotTableFirstInner.height() + 1; // +1 for border
|
3164 |
+
|
3165 |
+
if (dateChanged) {
|
3166 |
+
resetScroll();
|
3167 |
+
}
|
3168 |
+
}
|
3169 |
+
|
3170 |
+
|
3171 |
+
|
3172 |
+
function setWidth(width) {
|
3173 |
+
viewWidth = width;
|
3174 |
+
colContentPositions.clear();
|
3175 |
+
|
3176 |
+
axisWidth = 0;
|
3177 |
+
setOuterWidth(
|
3178 |
+
axisFirstCells
|
3179 |
+
.width('')
|
3180 |
+
.each(function(i, _cell) {
|
3181 |
+
axisWidth = Math.max(axisWidth, $(_cell).outerWidth());
|
3182 |
+
}),
|
3183 |
+
axisWidth
|
3184 |
+
);
|
3185 |
+
|
3186 |
+
var slotTableWidth = slotScroller[0].clientWidth; // needs to be done after axisWidth (for IE7)
|
3187 |
+
//slotTable.width(slotTableWidth);
|
3188 |
+
|
3189 |
+
gutterWidth = slotScroller.width() - slotTableWidth;
|
3190 |
+
if (gutterWidth) {
|
3191 |
+
setOuterWidth(gutterCells, gutterWidth);
|
3192 |
+
gutterCells
|
3193 |
+
.show()
|
3194 |
+
.prev()
|
3195 |
+
.removeClass('fc-last');
|
3196 |
+
}else{
|
3197 |
+
gutterCells
|
3198 |
+
.hide()
|
3199 |
+
.prev()
|
3200 |
+
.addClass('fc-last');
|
3201 |
+
}
|
3202 |
+
|
3203 |
+
colWidth = Math.floor((slotTableWidth - axisWidth) / colCnt);
|
3204 |
+
setOuterWidth(dayHeadCells.slice(0, -1), colWidth);
|
3205 |
+
}
|
3206 |
+
|
3207 |
+
|
3208 |
+
|
3209 |
+
function resetScroll() {
|
3210 |
+
var d0 = zeroDate();
|
3211 |
+
var scrollDate = cloneDate(d0);
|
3212 |
+
scrollDate.setHours(opt('firstHour'));
|
3213 |
+
var top = timePosition(d0, scrollDate) + 1; // +1 for the border
|
3214 |
+
function scroll() {
|
3215 |
+
slotScroller.scrollTop(top);
|
3216 |
+
}
|
3217 |
+
scroll();
|
3218 |
+
setTimeout(scroll, 0); // overrides any previous scroll state made by the browser
|
3219 |
+
}
|
3220 |
+
|
3221 |
+
|
3222 |
+
function beforeHide() {
|
3223 |
+
savedScrollTop = slotScroller.scrollTop();
|
3224 |
+
}
|
3225 |
+
|
3226 |
+
|
3227 |
+
function afterShow() {
|
3228 |
+
slotScroller.scrollTop(savedScrollTop);
|
3229 |
+
}
|
3230 |
+
|
3231 |
+
|
3232 |
+
|
3233 |
+
/* Slot/Day clicking and binding
|
3234 |
+
-----------------------------------------------------------------------*/
|
3235 |
+
|
3236 |
+
|
3237 |
+
function dayBind(cells) {
|
3238 |
+
cells.click(slotClick)
|
3239 |
+
.mousedown(daySelectionMousedown);
|
3240 |
+
}
|
3241 |
+
|
3242 |
+
|
3243 |
+
function slotBind(cells) {
|
3244 |
+
cells.click(slotClick)
|
3245 |
+
.mousedown(slotSelectionMousedown);
|
3246 |
+
}
|
3247 |
+
|
3248 |
+
|
3249 |
+
function slotClick(ev) {
|
3250 |
+
if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick
|
3251 |
+
var col = Math.min(colCnt-1, Math.floor((ev.pageX - dayTable.offset().left - axisWidth) / colWidth));
|
3252 |
+
var date = colDate(col);
|
3253 |
+
var rowMatch = this.parentNode.className.match(/fc-slot(\d+)/); // TODO: maybe use data
|
3254 |
+
if (rowMatch) {
|
3255 |
+
var mins = parseInt(rowMatch[1]) * opt('slotMinutes');
|
3256 |
+
var hours = Math.floor(mins/60);
|
3257 |
+
date.setHours(hours);
|
3258 |
+
date.setMinutes(mins%60 + minMinute);
|
3259 |
+
trigger('dayClick', dayBodyCells[col], date, false, ev);
|
3260 |
+
}else{
|
3261 |
+
trigger('dayClick', dayBodyCells[col], date, true, ev);
|
3262 |
+
}
|
3263 |
+
}
|
3264 |
+
}
|
3265 |
+
|
3266 |
+
|
3267 |
+
|
3268 |
+
/* Semi-transparent Overlay Helpers
|
3269 |
+
-----------------------------------------------------*/
|
3270 |
+
|
3271 |
+
|
3272 |
+
function renderDayOverlay(startDate, endDate, refreshCoordinateGrid) { // endDate is exclusive
|
3273 |
+
if (refreshCoordinateGrid) {
|
3274 |
+
coordinateGrid.build();
|
3275 |
+
}
|
3276 |
+
var visStart = cloneDate(t.visStart);
|
3277 |
+
var startCol, endCol;
|
3278 |
+
if (rtl) {
|
3279 |
+
startCol = dayDiff(endDate, visStart)*dis+dit+1;
|
3280 |
+
endCol = dayDiff(startDate, visStart)*dis+dit+1;
|
3281 |
+
}else{
|
3282 |
+
startCol = dayDiff(startDate, visStart);
|
3283 |
+
endCol = dayDiff(endDate, visStart);
|
3284 |
+
}
|
3285 |
+
startCol = Math.max(0, startCol);
|
3286 |
+
endCol = Math.min(colCnt, endCol);
|
3287 |
+
if (startCol < endCol) {
|
3288 |
+
dayBind(
|
3289 |
+
renderCellOverlay(0, startCol, 0, endCol-1)
|
3290 |
+
);
|
3291 |
+
}
|
3292 |
+
}
|
3293 |
+
|
3294 |
+
|
3295 |
+
function renderCellOverlay(row0, col0, row1, col1) { // only for all-day?
|
3296 |
+
var rect = coordinateGrid.rect(row0, col0, row1, col1, slotLayer);
|
3297 |
+
return renderOverlay(rect, slotLayer);
|
3298 |
+
}
|
3299 |
+
|
3300 |
+
|
3301 |
+
function renderSlotOverlay(overlayStart, overlayEnd) {
|
3302 |
+
var dayStart = cloneDate(t.visStart);
|
3303 |
+
var dayEnd = addDays(cloneDate(dayStart), 1);
|
3304 |
+
for (var i=0; i<colCnt; i++) {
|
3305 |
+
var stretchStart = new Date(Math.max(dayStart, overlayStart));
|
3306 |
+
var stretchEnd = new Date(Math.min(dayEnd, overlayEnd));
|
3307 |
+
if (stretchStart < stretchEnd) {
|
3308 |
+
var col = i*dis+dit;
|
3309 |
+
var rect = coordinateGrid.rect(0, col, 0, col, slotContent); // only use it for horizontal coords
|
3310 |
+
var top = timePosition(dayStart, stretchStart);
|
3311 |
+
var bottom = timePosition(dayStart, stretchEnd);
|
3312 |
+
rect.top = top;
|
3313 |
+
rect.height = bottom - top;
|
3314 |
+
slotBind(
|
3315 |
+
renderOverlay(rect, slotContent)
|
3316 |
+
);
|
3317 |
+
}
|
3318 |
+
addDays(dayStart, 1);
|
3319 |
+
addDays(dayEnd, 1);
|
3320 |
+
}
|
3321 |
+
}
|
3322 |
+
|
3323 |
+
|
3324 |
+
|
3325 |
+
/* Coordinate Utilities
|
3326 |
+
-----------------------------------------------------------------------------*/
|
3327 |
+
|
3328 |
+
|
3329 |
+
coordinateGrid = new CoordinateGrid(function(rows, cols) {
|
3330 |
+
var e, n, p;
|
3331 |
+
dayHeadCells.each(function(i, _e) {
|
3332 |
+
e = $(_e);
|
3333 |
+
n = e.offset().left;
|
3334 |
+
if (i) {
|
3335 |
+
p[1] = n;
|
3336 |
+
}
|
3337 |
+
p = [n];
|
3338 |
+
cols[i] = p;
|
3339 |
+
});
|
3340 |
+
p[1] = n + e.outerWidth();
|
3341 |
+
if (opt('allDaySlot')) {
|
3342 |
+
e = allDayRow;
|
3343 |
+
n = e.offset().top;
|
3344 |
+
rows[0] = [n, n+e.outerHeight()];
|
3345 |
+
}
|
3346 |
+
var slotTableTop = slotContent.offset().top;
|
3347 |
+
var slotScrollerTop = slotScroller.offset().top;
|
3348 |
+
var slotScrollerBottom = slotScrollerTop + slotScroller.outerHeight();
|
3349 |
+
function constrain(n) {
|
3350 |
+
return Math.max(slotScrollerTop, Math.min(slotScrollerBottom, n));
|
3351 |
+
}
|
3352 |
+
for (var i=0; i<slotCnt; i++) {
|
3353 |
+
rows.push([
|
3354 |
+
constrain(slotTableTop + slotHeight*i),
|
3355 |
+
constrain(slotTableTop + slotHeight*(i+1))
|
3356 |
+
]);
|
3357 |
+
}
|
3358 |
+
});
|
3359 |
+
|
3360 |
+
|
3361 |
+
hoverListener = new HoverListener(coordinateGrid);
|
3362 |
+
|
3363 |
+
|
3364 |
+
colContentPositions = new HorizontalPositionCache(function(col) {
|
3365 |
+
return dayBodyCellInners.eq(col);
|
3366 |
+
});
|
3367 |
+
|
3368 |
+
|
3369 |
+
function colContentLeft(col) {
|
3370 |
+
return colContentPositions.left(col);
|
3371 |
+
}
|
3372 |
+
|
3373 |
+
|
3374 |
+
function colContentRight(col) {
|
3375 |
+
return colContentPositions.right(col);
|
3376 |
+
}
|
3377 |
+
|
3378 |
+
|
3379 |
+
|
3380 |
+
|
3381 |
+
function dateCell(date) { // "cell" terminology is now confusing
|
3382 |
+
return {
|
3383 |
+
row: Math.floor(dayDiff(date, t.visStart) / 7),
|
3384 |
+
col: dayOfWeekCol(date.getDay())
|
3385 |
+
};
|
3386 |
+
}
|
3387 |
+
|
3388 |
+
|
3389 |
+
function cellDate(cell) {
|
3390 |
+
var d = colDate(cell.col);
|
3391 |
+
var slotIndex = cell.row;
|
3392 |
+
if (opt('allDaySlot')) {
|
3393 |
+
slotIndex--;
|
3394 |
+
}
|
3395 |
+
if (slotIndex >= 0) {
|
3396 |
+
addMinutes(d, minMinute + slotIndex * opt('slotMinutes'));
|
3397 |
+
}
|
3398 |
+
return d;
|
3399 |
+
}
|
3400 |
+
|
3401 |
+
|
3402 |
+
function colDate(col) { // returns dates with 00:00:00
|
3403 |
+
return addDays(cloneDate(t.visStart), col*dis+dit);
|
3404 |
+
}
|
3405 |
+
|
3406 |
+
|
3407 |
+
function cellIsAllDay(cell) {
|
3408 |
+
return opt('allDaySlot') && !cell.row;
|
3409 |
+
}
|
3410 |
+
|
3411 |
+
|
3412 |
+
function dayOfWeekCol(dayOfWeek) {
|
3413 |
+
return ((dayOfWeek - Math.max(firstDay, nwe) + colCnt) % colCnt)*dis+dit;
|
3414 |
+
}
|
3415 |
+
|
3416 |
+
|
3417 |
+
|
3418 |
+
|
3419 |
+
// get the Y coordinate of the given time on the given day (both Date objects)
|
3420 |
+
function timePosition(day, time) { // both date objects. day holds 00:00 of current day
|
3421 |
+
day = cloneDate(day, true);
|
3422 |
+
if (time < addMinutes(cloneDate(day), minMinute)) {
|
3423 |
+
return 0;
|
3424 |
+
}
|
3425 |
+
if (time >= addMinutes(cloneDate(day), maxMinute)) {
|
3426 |
+
return slotTable.height();
|
3427 |
+
}
|
3428 |
+
var slotMinutes = opt('slotMinutes'),
|
3429 |
+
minutes = time.getHours()*60 + time.getMinutes() - minMinute,
|
3430 |
+
slotI = Math.floor(minutes / slotMinutes),
|
3431 |
+
slotTop = slotTopCache[slotI];
|
3432 |
+
if (slotTop === undefined) {
|
3433 |
+
slotTop = slotTopCache[slotI] = slotTable.find('tr:eq(' + slotI + ') td div')[0].offsetTop; //.position().top; // need this optimization???
|
3434 |
+
}
|
3435 |
+
return Math.max(0, Math.round(
|
3436 |
+
slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
|
3437 |
+
));
|
3438 |
+
}
|
3439 |
+
|
3440 |
+
|
3441 |
+
function allDayBounds() {
|
3442 |
+
return {
|
3443 |
+
left: axisWidth,
|
3444 |
+
right: viewWidth - gutterWidth
|
3445 |
+
}
|
3446 |
+
}
|
3447 |
+
|
3448 |
+
|
3449 |
+
function getAllDayRow(index) {
|
3450 |
+
return allDayRow;
|
3451 |
+
}
|
3452 |
+
|
3453 |
+
|
3454 |
+
function defaultEventEnd(event) {
|
3455 |
+
var start = cloneDate(event.start);
|
3456 |
+
if (event.allDay) {
|
3457 |
+
return start;
|
3458 |
+
}
|
3459 |
+
return addMinutes(start, opt('defaultEventMinutes'));
|
3460 |
+
}
|
3461 |
+
|
3462 |
+
|
3463 |
+
|
3464 |
+
/* Selection
|
3465 |
+
---------------------------------------------------------------------------------*/
|
3466 |
+
|
3467 |
+
|
3468 |
+
function defaultSelectionEnd(startDate, allDay) {
|
3469 |
+
if (allDay) {
|
3470 |
+
return cloneDate(startDate);
|
3471 |
+
}
|
3472 |
+
return addMinutes(cloneDate(startDate), opt('slotMinutes'));
|
3473 |
+
}
|
3474 |
+
|
3475 |
+
|
3476 |
+
function renderSelection(startDate, endDate, allDay) { // only for all-day
|
3477 |
+
if (allDay) {
|
3478 |
+
if (opt('allDaySlot')) {
|
3479 |
+
renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true);
|
3480 |
+
}
|
3481 |
+
}else{
|
3482 |
+
renderSlotSelection(startDate, endDate);
|
3483 |
+
}
|
3484 |
+
}
|
3485 |
+
|
3486 |
+
|
3487 |
+
function renderSlotSelection(startDate, endDate) {
|
3488 |
+
var helperOption = opt('selectHelper');
|
3489 |
+
coordinateGrid.build();
|
3490 |
+
if (helperOption) {
|
3491 |
+
var col = dayDiff(startDate, t.visStart) * dis + dit;
|
3492 |
+
if (col >= 0 && col < colCnt) { // only works when times are on same day
|
3493 |
+
var rect = coordinateGrid.rect(0, col, 0, col, slotContent); // only for horizontal coords
|
3494 |
+
var top = timePosition(startDate, startDate);
|
3495 |
+
var bottom = timePosition(startDate, endDate);
|
3496 |
+
if (bottom > top) { // protect against selections that are entirely before or after visible range
|
3497 |
+
rect.top = top;
|
3498 |
+
rect.height = bottom - top;
|
3499 |
+
rect.left += 2;
|
3500 |
+
rect.width -= 5;
|
3501 |
+
if ($.isFunction(helperOption)) {
|
3502 |
+
var helperRes = helperOption(startDate, endDate);
|
3503 |
+
if (helperRes) {
|
3504 |
+
rect.position = 'absolute';
|
3505 |
+
rect.zIndex = 8;
|
3506 |
+
selectionHelper = $(helperRes)
|
3507 |
+
.css(rect)
|
3508 |
+
.appendTo(slotContent);
|
3509 |
+
}
|
3510 |
+
}else{
|
3511 |
+
rect.isStart = true; // conside rect a "seg" now
|
3512 |
+
rect.isEnd = true; //
|
3513 |
+
selectionHelper = $(slotSegHtml(
|
3514 |
+
{
|
3515 |
+
title: '',
|
3516 |
+
start: startDate,
|
3517 |
+
end: endDate,
|
3518 |
+
className: ['fc-select-helper'],
|
3519 |
+
editable: false
|
3520 |
+
},
|
3521 |
+
rect
|
3522 |
+
));
|
3523 |
+
selectionHelper.css('opacity', opt('dragOpacity'));
|
3524 |
+
}
|
3525 |
+
if (selectionHelper) {
|
3526 |
+
slotBind(selectionHelper);
|
3527 |
+
slotContent.append(selectionHelper);
|
3528 |
+
setOuterWidth(selectionHelper, rect.width, true); // needs to be after appended
|
3529 |
+
setOuterHeight(selectionHelper, rect.height, true);
|
3530 |
+
}
|
3531 |
+
}
|
3532 |
+
}
|
3533 |
+
}else{
|
3534 |
+
renderSlotOverlay(startDate, endDate);
|
3535 |
+
}
|
3536 |
+
}
|
3537 |
+
|
3538 |
+
|
3539 |
+
function clearSelection() {
|
3540 |
+
clearOverlays();
|
3541 |
+
if (selectionHelper) {
|
3542 |
+
selectionHelper.remove();
|
3543 |
+
selectionHelper = null;
|
3544 |
+
}
|
3545 |
+
}
|
3546 |
+
|
3547 |
+
|
3548 |
+
function slotSelectionMousedown(ev) {
|
3549 |
+
if (ev.which == 1 && opt('selectable')) { // ev.which==1 means left mouse button
|
3550 |
+
unselect(ev);
|
3551 |
+
var dates;
|
3552 |
+
hoverListener.start(function(cell, origCell) {
|
3553 |
+
clearSelection();
|
3554 |
+
if (cell && cell.col == origCell.col && !cellIsAllDay(cell)) {
|
3555 |
+
var d1 = cellDate(origCell);
|
3556 |
+
var d2 = cellDate(cell);
|
3557 |
+
dates = [
|
3558 |
+
d1,
|
3559 |
+
addMinutes(cloneDate(d1), opt('slotMinutes')),
|
3560 |
+
d2,
|
3561 |
+
addMinutes(cloneDate(d2), opt('slotMinutes'))
|
3562 |
+
].sort(cmp);
|
3563 |
+
renderSlotSelection(dates[0], dates[3]);
|
3564 |
+
}else{
|
3565 |
+
dates = null;
|
3566 |
+
}
|
3567 |
+
}, ev);
|
3568 |
+
$(document).one('mouseup', function(ev) {
|
3569 |
+
hoverListener.stop();
|
3570 |
+
if (dates) {
|
3571 |
+
if (+dates[0] == +dates[1]) {
|
3572 |
+
reportDayClick(dates[0], false, ev);
|
3573 |
+
}
|
3574 |
+
reportSelection(dates[0], dates[3], false, ev);
|
3575 |
+
}
|
3576 |
+
});
|
3577 |
+
}
|
3578 |
+
}
|
3579 |
+
|
3580 |
+
|
3581 |
+
function reportDayClick(date, allDay, ev) {
|
3582 |
+
trigger('dayClick', dayBodyCells[dayOfWeekCol(date.getDay())], date, allDay, ev);
|
3583 |
+
}
|
3584 |
+
|
3585 |
+
|
3586 |
+
|
3587 |
+
/* External Dragging
|
3588 |
+
--------------------------------------------------------------------------------*/
|
3589 |
+
|
3590 |
+
|
3591 |
+
function dragStart(_dragElement, ev, ui) {
|
3592 |
+
hoverListener.start(function(cell) {
|
3593 |
+
clearOverlays();
|
3594 |
+
if (cell) {
|
3595 |
+
if (cellIsAllDay(cell)) {
|
3596 |
+
renderCellOverlay(cell.row, cell.col, cell.row, cell.col);
|
3597 |
+
}else{
|
3598 |
+
var d1 = cellDate(cell);
|
3599 |
+
var d2 = addMinutes(cloneDate(d1), opt('defaultEventMinutes'));
|
3600 |
+
renderSlotOverlay(d1, d2);
|
3601 |
+
}
|
3602 |
+
}
|
3603 |
+
}, ev);
|
3604 |
+
}
|
3605 |
+
|
3606 |
+
|
3607 |
+
function dragStop(_dragElement, ev, ui) {
|
3608 |
+
var cell = hoverListener.stop();
|
3609 |
+
clearOverlays();
|
3610 |
+
if (cell) {
|
3611 |
+
trigger('drop', _dragElement, cellDate(cell), cellIsAllDay(cell), ev, ui);
|
3612 |
+
}
|
3613 |
+
}
|
3614 |
+
|
3615 |
+
|
3616 |
+
}
|
3617 |
+
|
3618 |
+
function AgendaEventRenderer() {
|
3619 |
+
var t = this;
|
3620 |
+
|
3621 |
+
|
3622 |
+
// exports
|
3623 |
+
t.renderEvents = renderEvents;
|
3624 |
+
t.compileDaySegs = compileDaySegs; // for DayEventRenderer
|
3625 |
+
t.clearEvents = clearEvents;
|
3626 |
+
t.slotSegHtml = slotSegHtml;
|
3627 |
+
t.bindDaySeg = bindDaySeg;
|
3628 |
+
|
3629 |
+
|
3630 |
+
// imports
|
3631 |
+
DayEventRenderer.call(t);
|
3632 |
+
var opt = t.opt;
|
3633 |
+
var trigger = t.trigger;
|
3634 |
+
//var setOverflowHidden = t.setOverflowHidden;
|
3635 |
+
var isEventDraggable = t.isEventDraggable;
|
3636 |
+
var isEventResizable = t.isEventResizable;
|
3637 |
+
var eventEnd = t.eventEnd;
|
3638 |
+
var reportEvents = t.reportEvents;
|
3639 |
+
var reportEventClear = t.reportEventClear;
|
3640 |
+
var eventElementHandlers = t.eventElementHandlers;
|
3641 |
+
var setHeight = t.setHeight;
|
3642 |
+
var getDaySegmentContainer = t.getDaySegmentContainer;
|
3643 |
+
var getSlotSegmentContainer = t.getSlotSegmentContainer;
|
3644 |
+
var getHoverListener = t.getHoverListener;
|
3645 |
+
var getMaxMinute = t.getMaxMinute;
|
3646 |
+
var getMinMinute = t.getMinMinute;
|
3647 |
+
var timePosition = t.timePosition;
|
3648 |
+
var colContentLeft = t.colContentLeft;
|
3649 |
+
var colContentRight = t.colContentRight;
|
3650 |
+
var renderDaySegs = t.renderDaySegs;
|
3651 |
+
var resizableDayEvent = t.resizableDayEvent; // TODO: streamline binding architecture
|
3652 |
+
var getColCnt = t.getColCnt;
|
3653 |
+
var getColWidth = t.getColWidth;
|
3654 |
+
var getSlotHeight = t.getSlotHeight;
|
3655 |
+
var getBodyContent = t.getBodyContent;
|
3656 |
+
var reportEventElement = t.reportEventElement;
|
3657 |
+
var showEvents = t.showEvents;
|
3658 |
+
var hideEvents = t.hideEvents;
|
3659 |
+
var eventDrop = t.eventDrop;
|
3660 |
+
var eventResize = t.eventResize;
|
3661 |
+
var renderDayOverlay = t.renderDayOverlay;
|
3662 |
+
var clearOverlays = t.clearOverlays;
|
3663 |
+
var calendar = t.calendar;
|
3664 |
+
var formatDate = calendar.formatDate;
|
3665 |
+
var formatDates = calendar.formatDates;
|
3666 |
+
|
3667 |
+
|
3668 |
+
|
3669 |
+
/* Rendering
|
3670 |
+
----------------------------------------------------------------------------*/
|
3671 |
+
|
3672 |
+
|
3673 |
+
function renderEvents(events, modifiedEventId) {
|
3674 |
+
reportEvents(events);
|
3675 |
+
var i, len=events.length,
|
3676 |
+
dayEvents=[],
|
3677 |
+
slotEvents=[];
|
3678 |
+
for (i=0; i<len; i++) {
|
3679 |
+
if (events[i].allDay) {
|
3680 |
+
dayEvents.push(events[i]);
|
3681 |
+
}else{
|
3682 |
+
slotEvents.push(events[i]);
|
3683 |
+
}
|
3684 |
+
}
|
3685 |
+
if (opt('allDaySlot')) {
|
3686 |
+
renderDaySegs(compileDaySegs(dayEvents), modifiedEventId);
|
3687 |
+
setHeight(); // no params means set to viewHeight
|
3688 |
+
}
|
3689 |
+
renderSlotSegs(compileSlotSegs(slotEvents), modifiedEventId);
|
3690 |
+
}
|
3691 |
+
|
3692 |
+
|
3693 |
+
function clearEvents() {
|
3694 |
+
reportEventClear();
|
3695 |
+
getDaySegmentContainer().empty();
|
3696 |
+
getSlotSegmentContainer().empty();
|
3697 |
+
}
|
3698 |
+
|
3699 |
+
|
3700 |
+
function compileDaySegs(events) {
|
3701 |
+
var levels = stackSegs(sliceSegs(events, $.map(events, exclEndDay), t.visStart, t.visEnd)),
|
3702 |
+
i, levelCnt=levels.length, level,
|
3703 |
+
j, seg,
|
3704 |
+
segs=[];
|
3705 |
+
for (i=0; i<levelCnt; i++) {
|
3706 |
+
level = levels[i];
|
3707 |
+
for (j=0; j<level.length; j++) {
|
3708 |
+
seg = level[j];
|
3709 |
+
seg.row = 0;
|
3710 |
+
seg.level = i; // not needed anymore
|
3711 |
+
segs.push(seg);
|
3712 |
+
}
|
3713 |
+
}
|
3714 |
+
return segs;
|
3715 |
+
}
|
3716 |
+
|
3717 |
+
|
3718 |
+
function compileSlotSegs(events) {
|
3719 |
+
var colCnt = getColCnt(),
|
3720 |
+
minMinute = getMinMinute(),
|
3721 |
+
maxMinute = getMaxMinute(),
|
3722 |
+
d = addMinutes(cloneDate(t.visStart), minMinute),
|
3723 |
+
visEventEnds = $.map(events, slotEventEnd),
|
3724 |
+
i, col,
|
3725 |
+
j, level,
|
3726 |
+
k, seg,
|
3727 |
+
segs=[];
|
3728 |
+
for (i=0; i<colCnt; i++) {
|
3729 |
+
col = stackSegs(sliceSegs(events, visEventEnds, d, addMinutes(cloneDate(d), maxMinute-minMinute)));
|
3730 |
+
countForwardSegs(col);
|
3731 |
+
for (j=0; j<col.length; j++) {
|
3732 |
+
level = col[j];
|
3733 |
+
for (k=0; k<level.length; k++) {
|
3734 |
+
seg = level[k];
|
3735 |
+
seg.col = i;
|
3736 |
+
seg.level = j;
|
3737 |
+
segs.push(seg);
|
3738 |
+
}
|
3739 |
+
}
|
3740 |
+
addDays(d, 1, true);
|
3741 |
+
}
|
3742 |
+
return segs;
|
3743 |
+
}
|
3744 |
+
|
3745 |
+
|
3746 |
+
function slotEventEnd(event) {
|
3747 |
+
if (event.end) {
|
3748 |
+
return cloneDate(event.end);
|
3749 |
+
}else{
|
3750 |
+
return addMinutes(cloneDate(event.start), opt('defaultEventMinutes'));
|
3751 |
+
}
|
3752 |
+
}
|
3753 |
+
|
3754 |
+
|
3755 |
+
// renders events in the 'time slots' at the bottom
|
3756 |
+
|
3757 |
+
function renderSlotSegs(segs, modifiedEventId) {
|
3758 |
+
|
3759 |
+
var i, segCnt=segs.length, seg,
|
3760 |
+
event,
|
3761 |
+
classes,
|
3762 |
+
top, bottom,
|
3763 |
+
colI, levelI, forward,
|
3764 |
+
leftmost,
|
3765 |
+
availWidth,
|
3766 |
+
outerWidth,
|
3767 |
+
left,
|
3768 |
+
html='',
|
3769 |
+
eventElements,
|
3770 |
+
eventElement,
|
3771 |
+
triggerRes,
|
3772 |
+
vsideCache={},
|
3773 |
+
hsideCache={},
|
3774 |
+
key, val,
|
3775 |
+
contentElement,
|
3776 |
+
height,
|
3777 |
+
slotSegmentContainer = getSlotSegmentContainer(),
|
3778 |
+
rtl, dis, dit,
|
3779 |
+
colCnt = getColCnt();
|
3780 |
+
|
3781 |
+
if (rtl = opt('isRTL')) {
|
3782 |
+
dis = -1;
|
3783 |
+
dit = colCnt - 1;
|
3784 |
+
}else{
|
3785 |
+
dis = 1;
|
3786 |
+
dit = 0;
|
3787 |
+
}
|
3788 |
+
|
3789 |
+
// calculate position/dimensions, create html
|
3790 |
+
for (i=0; i<segCnt; i++) {
|
3791 |
+
seg = segs[i];
|
3792 |
+
event = seg.event;
|
3793 |
+
top = timePosition(seg.start, seg.start);
|
3794 |
+
bottom = timePosition(seg.start, seg.end);
|
3795 |
+
colI = seg.col;
|
3796 |
+
levelI = seg.level;
|
3797 |
+
forward = seg.forward || 0;
|
3798 |
+
leftmost = colContentLeft(colI*dis + dit);
|
3799 |
+
availWidth = colContentRight(colI*dis + dit) - leftmost;
|
3800 |
+
availWidth = Math.min(availWidth-6, availWidth*.95); // TODO: move this to CSS
|
3801 |
+
if (levelI) {
|
3802 |
+
// indented and thin
|
3803 |
+
outerWidth = availWidth / (levelI + forward + 1);
|
3804 |
+
}else{
|
3805 |
+
if (forward) {
|
3806 |
+
// moderately wide, aligned left still
|
3807 |
+
outerWidth = ((availWidth / (forward + 1)) - (12/2)) * 2; // 12 is the predicted width of resizer =
|
3808 |
+
}else{
|
3809 |
+
// can be entire width, aligned left
|
3810 |
+
outerWidth = availWidth;
|
3811 |
+
}
|
3812 |
+
}
|
3813 |
+
left = leftmost + // leftmost possible
|
3814 |
+
(availWidth / (levelI + forward + 1) * levelI) // indentation
|
3815 |
+
* dis + (rtl ? availWidth - outerWidth : 0); // rtl
|
3816 |
+
seg.top = top;
|
3817 |
+
seg.left = left;
|
3818 |
+
seg.outerWidth = outerWidth;
|
3819 |
+
seg.outerHeight = bottom - top;
|
3820 |
+
html += slotSegHtml(event, seg);
|
3821 |
+
}
|
3822 |
+
slotSegmentContainer[0].innerHTML = html; // faster than html()
|
3823 |
+
eventElements = slotSegmentContainer.children();
|
3824 |
+
|
3825 |
+
// retrieve elements, run through eventRender callback, bind event handlers
|
3826 |
+
for (i=0; i<segCnt; i++) {
|
3827 |
+
seg = segs[i];
|
3828 |
+
event = seg.event;
|
3829 |
+
eventElement = $(eventElements[i]); // faster than eq()
|
3830 |
+
triggerRes = trigger('eventRender', event, event, eventElement,t);
|
3831 |
+
if (triggerRes === false) {
|
3832 |
+
eventElement.remove();
|
3833 |
+
}else{
|
3834 |
+
if (triggerRes && triggerRes !== true) {
|
3835 |
+
eventElement.remove();
|
3836 |
+
eventElement = $(triggerRes)
|
3837 |
+
.css({
|
3838 |
+
position: 'absolute',
|
3839 |
+
top: seg.top,
|
3840 |
+
left: seg.left
|
3841 |
+
})
|
3842 |
+
.appendTo(slotSegmentContainer);
|
3843 |
+
}
|
3844 |
+
seg.element = eventElement;
|
3845 |
+
if (event._id === modifiedEventId) {
|
3846 |
+
bindSlotSeg(event, eventElement, seg);
|
3847 |
+
}else{
|
3848 |
+
eventElement[0]._fci = i; // for lazySegBind
|
3849 |
+
}
|
3850 |
+
reportEventElement(event, eventElement);
|
3851 |
+
}
|
3852 |
+
}
|
3853 |
+
|
3854 |
+
lazySegBind(slotSegmentContainer, segs, bindSlotSeg);
|
3855 |
+
|
3856 |
+
// record event sides and title positions
|
3857 |
+
for (i=0; i<segCnt; i++) {
|
3858 |
+
seg = segs[i];
|
3859 |
+
if (eventElement = seg.element) {
|
3860 |
+
val = vsideCache[key = seg.key = cssKey(eventElement[0])];
|
3861 |
+
seg.vsides = val === undefined ? (vsideCache[key] = vsides(eventElement, true)) : val;
|
3862 |
+
val = hsideCache[key];
|
3863 |
+
seg.hsides = val === undefined ? (hsideCache[key] = hsides(eventElement, true)) : val;
|
3864 |
+
contentElement = eventElement.find('div.fc-event-content');
|
3865 |
+
if (contentElement.length) {
|
3866 |
+
seg.contentTop = contentElement[0].offsetTop;
|
3867 |
+
}
|
3868 |
+
}
|
3869 |
+
}
|
3870 |
+
|
3871 |
+
// set all positions/dimensions at once
|
3872 |
+
for (i=0; i<segCnt; i++) {
|
3873 |
+
seg = segs[i];
|
3874 |
+
if (eventElement = seg.element) {
|
3875 |
+
eventElement[0].style.width = Math.max(0, seg.outerWidth - seg.hsides) + 'px';
|
3876 |
+
height = Math.max(0, seg.outerHeight - seg.vsides);
|
3877 |
+
eventElement[0].style.height = height + 'px';
|
3878 |
+
event = seg.event;
|
3879 |
+
if (seg.contentTop !== undefined && height - seg.contentTop < 10) {
|
3880 |
+
// not enough room for title, put it in the time header
|
3881 |
+
eventElement.find('div.fc-event-time')
|
3882 |
+
.text(formatDate(event.start, opt('timeFormat')) + ' - ' + event.title);
|
3883 |
+
eventElement.find('div.fc-event-title')
|
3884 |
+
.remove();
|
3885 |
+
}
|
3886 |
+
trigger('eventAfterRender', event, event, eventElement);
|
3887 |
+
}
|
3888 |
+
}
|
3889 |
+
|
3890 |
+
}
|
3891 |
+
|
3892 |
+
|
3893 |
+
function slotSegHtml(event, seg) {
|
3894 |
+
var html = "<";
|
3895 |
+
var url = event.url;
|
3896 |
+
var skinCss = getSkinCss(event, opt);
|
3897 |
+
var skinCssAttr = (skinCss ? " style='" + skinCss + "'" : '');
|
3898 |
+
var classes = ['fc-event', 'fc-event-skin', 'fc-event-vert'];
|
3899 |
+
if (isEventDraggable(event)) {
|
3900 |
+
classes.push('fc-event-draggable');
|
3901 |
+
}
|
3902 |
+
if (seg.isStart) {
|
3903 |
+
classes.push('fc-corner-top');
|
3904 |
+
}
|
3905 |
+
if (seg.isEnd) {
|
3906 |
+
classes.push('fc-corner-bottom');
|
3907 |
+
}
|
3908 |
+
classes = classes.concat(event.className);
|
3909 |
+
if (event.source) {
|
3910 |
+
classes = classes.concat(event.source.className || []);
|
3911 |
+
}
|
3912 |
+
if (url) {
|
3913 |
+
html += "a href='" + htmlEscape(event.url) + "'";
|
3914 |
+
}else{
|
3915 |
+
html += "div";
|
3916 |
+
}
|
3917 |
+
html +=
|
3918 |
+
" class='" + classes.join(' ') + "'" +
|
3919 |
+
" style='position:absolute;z-index:8;top:" + seg.top + "px;left:" + seg.left + "px;" + skinCss + "'" +
|
3920 |
+
">" +
|
3921 |
+
"<div class='fc-event-inner fc-event-skin'" + skinCssAttr + ">" +
|
3922 |
+
"<div class='fc-event-head fc-event-skin'" + skinCssAttr + ">" +
|
3923 |
+
"<div class='fc-event-time'>" +
|
3924 |
+
htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) +
|
3925 |
+
"</div>" +
|
3926 |
+
"</div>" +
|
3927 |
+
"<div class='fc-event-content'>" +
|
3928 |
+
"<div class='fc-event-title'>" +
|
3929 |
+
htmlEscape(event.title) +
|
3930 |
+
"</div>" +
|
3931 |
+
"</div>" +
|
3932 |
+
"<div class='fc-event-bg'></div>" +
|
3933 |
+
"</div>"; // close inner
|
3934 |
+
if (seg.isEnd && isEventResizable(event)) {
|
3935 |
+
html +=
|
3936 |
+
"<div class='ui-resizable-handle ui-resizable-s'>=</div>";
|
3937 |
+
}
|
3938 |
+
html +=
|
3939 |
+
"</" + (url ? "a" : "div") + ">";
|
3940 |
+
return html;
|
3941 |
+
}
|
3942 |
+
|
3943 |
+
|
3944 |
+
function bindDaySeg(event, eventElement, seg) {
|
3945 |
+
if (isEventDraggable(event)) {
|
3946 |
+
draggableDayEvent(event, eventElement, seg.isStart);
|
3947 |
+
}
|
3948 |
+
if (seg.isEnd && isEventResizable(event)) {
|
3949 |
+
resizableDayEvent(event, eventElement, seg);
|
3950 |
+
}
|
3951 |
+
eventElementHandlers(event, eventElement);
|
3952 |
+
// needs to be after, because resizableDayEvent might stopImmediatePropagation on click
|
3953 |
+
}
|
3954 |
+
|
3955 |
+
|
3956 |
+
function bindSlotSeg(event, eventElement, seg) {
|
3957 |
+
var timeElement = eventElement.find('div.fc-event-time');
|
3958 |
+
if (isEventDraggable(event)) {
|
3959 |
+
draggableSlotEvent(event, eventElement, timeElement);
|
3960 |
+
}
|
3961 |
+
if (seg.isEnd && isEventResizable(event)) {
|
3962 |
+
resizableSlotEvent(event, eventElement, timeElement);
|
3963 |
+
}
|
3964 |
+
eventElementHandlers(event, eventElement);
|
3965 |
+
}
|
3966 |
+
|
3967 |
+
|
3968 |
+
|
3969 |
+
/* Dragging
|
3970 |
+
-----------------------------------------------------------------------------------*/
|
3971 |
+
|
3972 |
+
|
3973 |
+
// when event starts out FULL-DAY
|
3974 |
+
|
3975 |
+
function draggableDayEvent(event, eventElement, isStart) {
|
3976 |
+
var origWidth;
|
3977 |
+
var revert;
|
3978 |
+
var allDay=true;
|
3979 |
+
var dayDelta;
|
3980 |
+
var dis = opt('isRTL') ? -1 : 1;
|
3981 |
+
var hoverListener = getHoverListener();
|
3982 |
+
var colWidth = getColWidth();
|
3983 |
+
var slotHeight = getSlotHeight();
|
3984 |
+
var minMinute = getMinMinute();
|
3985 |
+
eventElement.draggable({
|
3986 |
+
zIndex: 9,
|
3987 |
+
opacity: opt('dragOpacity', 'month'), // use whatever the month view was using
|
3988 |
+
revertDuration: opt('dragRevertDuration'),
|
3989 |
+
start: function(ev, ui) {
|
3990 |
+
trigger('eventDragStart', eventElement, event, ev, ui);
|
3991 |
+
hideEvents(event, eventElement);
|
3992 |
+
origWidth = eventElement.width();
|
3993 |
+
hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
3994 |
+
clearOverlays();
|
3995 |
+
if (cell) {
|
3996 |
+
//setOverflowHidden(true);
|
3997 |
+
revert = false;
|
3998 |
+
dayDelta = colDelta * dis;
|
3999 |
+
if (!cell.row) {
|
4000 |
+
// on full-days
|
4001 |
+
renderDayOverlay(
|
4002 |
+
addDays(cloneDate(event.start), dayDelta),
|
4003 |
+
addDays(exclEndDay(event), dayDelta)
|
4004 |
+
);
|
4005 |
+
resetElement();
|
4006 |
+
}else{
|
4007 |
+
// mouse is over bottom slots
|
4008 |
+
if (isStart) {
|
4009 |
+
if (allDay) {
|
4010 |
+
// convert event to temporary slot-event
|
4011 |
+
eventElement.width(colWidth - 10); // don't use entire width
|
4012 |
+
setOuterHeight(
|
4013 |
+
eventElement,
|
4014 |
+
slotHeight * Math.round(
|
4015 |
+
(event.end ? ((event.end - event.start) / MINUTE_MS) : opt('defaultEventMinutes'))
|
4016 |
+
/ opt('slotMinutes')
|
4017 |
+
)
|
4018 |
+
);
|
4019 |
+
eventElement.draggable('option', 'grid', [colWidth, 1]);
|
4020 |
+
allDay = false;
|
4021 |
+
}
|
4022 |
+
}else{
|
4023 |
+
revert = true;
|
4024 |
+
}
|
4025 |
+
}
|
4026 |
+
revert = revert || (allDay && !dayDelta);
|
4027 |
+
}else{
|
4028 |
+
resetElement();
|
4029 |
+
//setOverflowHidden(false);
|
4030 |
+
revert = true;
|
4031 |
+
}
|
4032 |
+
eventElement.draggable('option', 'revert', revert);
|
4033 |
+
}, ev, 'drag');
|
4034 |
+
},
|
4035 |
+
stop: function(ev, ui) {
|
4036 |
+
hoverListener.stop();
|
4037 |
+
clearOverlays();
|
4038 |
+
trigger('eventDragStop', eventElement, event, ev, ui);
|
4039 |
+
if (revert) {
|
4040 |
+
// hasn't moved or is out of bounds (draggable has already reverted)
|
4041 |
+
resetElement();
|
4042 |
+
eventElement.css('filter', ''); // clear IE opacity side-effects
|
4043 |
+
showEvents(event, eventElement);
|
4044 |
+
}else{
|
4045 |
+
// changed!
|
4046 |
+
var minuteDelta = 0;
|
4047 |
+
if (!allDay) {
|
4048 |
+
minuteDelta = Math.round((eventElement.offset().top - getBodyContent().offset().top) / slotHeight)
|
4049 |
+
* opt('slotMinutes')
|
4050 |
+
+ minMinute
|
4051 |
+
- (event.start.getHours() * 60 + event.start.getMinutes());
|
4052 |
+
}
|
4053 |
+
eventDrop(this, event, dayDelta, minuteDelta, allDay, ev, ui);
|
4054 |
+
}
|
4055 |
+
//setOverflowHidden(false);
|
4056 |
+
}
|
4057 |
+
});
|
4058 |
+
function resetElement() {
|
4059 |
+
if (!allDay) {
|
4060 |
+
eventElement
|
4061 |
+
.width(origWidth)
|
4062 |
+
.height('')
|
4063 |
+
.draggable('option', 'grid', null);
|
4064 |
+
allDay = true;
|
4065 |
+
}
|
4066 |
+
}
|
4067 |
+
}
|
4068 |
+
|
4069 |
+
|
4070 |
+
// when event starts out IN TIMESLOTS
|
4071 |
+
|
4072 |
+
function draggableSlotEvent(event, eventElement, timeElement) {
|
4073 |
+
var origPosition;
|
4074 |
+
var allDay=false;
|
4075 |
+
var dayDelta;
|
4076 |
+
var minuteDelta;
|
4077 |
+
var prevMinuteDelta;
|
4078 |
+
var dis = opt('isRTL') ? -1 : 1;
|
4079 |
+
var hoverListener = getHoverListener();
|
4080 |
+
var colCnt = getColCnt();
|
4081 |
+
var colWidth = getColWidth();
|
4082 |
+
var slotHeight = getSlotHeight();
|
4083 |
+
eventElement.draggable({
|
4084 |
+
zIndex: 9,
|
4085 |
+
scroll: false,
|
4086 |
+
grid: [colWidth, slotHeight],
|
4087 |
+
axis: colCnt==1 ? 'y' : false,
|
4088 |
+
opacity: opt('dragOpacity'),
|
4089 |
+
revertDuration: opt('dragRevertDuration'),
|
4090 |
+
start: function(ev, ui) {
|
4091 |
+
trigger('eventDragStart', eventElement, event, ev, ui);
|
4092 |
+
hideEvents(event, eventElement);
|
4093 |
+
origPosition = eventElement.position();
|
4094 |
+
minuteDelta = prevMinuteDelta = 0;
|
4095 |
+
hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
|
4096 |
+
eventElement.draggable('option', 'revert', !cell);
|
4097 |
+
clearOverlays();
|
4098 |
+
if (cell) {
|
4099 |
+
dayDelta = colDelta * dis;
|
4100 |
+
if (opt('allDaySlot') && !cell.row) {
|
4101 |
+
// over full days
|
4102 |
+
if (!allDay) {
|
4103 |
+
// convert to temporary all-day event
|
4104 |
+
allDay = true;
|
4105 |
+
timeElement.hide();
|
4106 |
+
eventElement.draggable('option', 'grid', null);
|
4107 |
+
}
|
4108 |
+
renderDayOverlay(
|
4109 |
+
addDays(cloneDate(event.start), dayDelta),
|
4110 |
+
addDays(exclEndDay(event), dayDelta)
|
4111 |
+
);
|
4112 |
+
}else{
|
4113 |
+
// on slots
|
4114 |
+
resetElement();
|
4115 |
+
}
|
4116 |
+
}
|
4117 |
+
}, ev, 'drag');
|
4118 |
+
},
|
4119 |
+
drag: function(ev, ui) {
|
4120 |
+
minuteDelta = Math.round((ui.position.top - origPosition.top) / slotHeight) * opt('slotMinutes');
|
4121 |
+
if (minuteDelta != prevMinuteDelta) {
|
4122 |
+
if (!allDay) {
|
4123 |
+
updateTimeText(minuteDelta);
|
4124 |
+
}
|
4125 |
+
prevMinuteDelta = minuteDelta;
|
4126 |
+
}
|
4127 |
+
},
|
4128 |
+
stop: function(ev, ui) {
|
4129 |
+
var cell = hoverListener.stop();
|
4130 |
+
clearOverlays();
|
4131 |
+
trigger('eventDragStop', eventElement, event, ev, ui);
|
4132 |
+
if (cell && (dayDelta || minuteDelta || allDay)) {
|
4133 |
+
// changed!
|
4134 |
+
eventDrop(this, event, dayDelta, allDay ? 0 : minuteDelta, allDay, ev, ui);
|
4135 |
+
}else{
|
4136 |
+
// either no change or out-of-bounds (draggable has already reverted)
|
4137 |
+
resetElement();
|
4138 |
+
eventElement.css('filter', ''); // clear IE opacity side-effects
|
4139 |
+
eventElement.css(origPosition); // sometimes fast drags make event revert to wrong position
|
4140 |
+
updateTimeText(0);
|
4141 |
+
showEvents(event, eventElement);
|
4142 |
+
}
|
4143 |
+
}
|
4144 |
+
});
|
4145 |
+
function updateTimeText(minuteDelta) {
|
4146 |
+
var newStart = addMinutes(cloneDate(event.start), minuteDelta);
|
4147 |
+
var newEnd;
|
4148 |
+
if (event.end) {
|
4149 |
+
newEnd = addMinutes(cloneDate(event.end), minuteDelta);
|
4150 |
+
}
|
4151 |
+
timeElement.text(formatDates(newStart, newEnd, opt('timeFormat')));
|
4152 |
+
}
|
4153 |
+
function resetElement() {
|
4154 |
+
// convert back to original slot-event
|
4155 |
+
if (allDay) {
|
4156 |
+
timeElement.css('display', ''); // show() was causing display=inline
|
4157 |
+
eventElement.draggable('option', 'grid', [colWidth, slotHeight]);
|
4158 |
+
allDay = false;
|
4159 |
+
}
|
4160 |
+
}
|
4161 |
+
}
|
4162 |
+
|
4163 |
+
|
4164 |
+
|
4165 |
+
/* Resizing
|
4166 |
+
--------------------------------------------------------------------------------------*/
|
4167 |
+
|
4168 |
+
|
4169 |
+
function resizableSlotEvent(event, eventElement, timeElement) {
|
4170 |
+
var slotDelta, prevSlotDelta;
|
4171 |
+
var slotHeight = getSlotHeight();
|
4172 |
+
eventElement.resizable({
|
4173 |
+
handles: {
|
4174 |
+
s: 'div.ui-resizable-s'
|
4175 |
+
},
|
4176 |
+
grid: slotHeight,
|
4177 |
+
start: function(ev, ui) {
|
4178 |
+
slotDelta = prevSlotDelta = 0;
|
4179 |
+
hideEvents(event, eventElement);
|
4180 |
+
eventElement.css('z-index', 9);
|
4181 |
+
trigger('eventResizeStart', this, event, ev, ui);
|
4182 |
+
},
|
4183 |
+
resize: function(ev, ui) {
|
4184 |
+
// don't rely on ui.size.height, doesn't take grid into account
|
4185 |
+
slotDelta = Math.round((Math.max(slotHeight, eventElement.height()) - ui.originalSize.height) / slotHeight);
|
4186 |
+
if (slotDelta != prevSlotDelta) {
|
4187 |
+
timeElement.text(
|
4188 |
+
formatDates(
|
4189 |
+
event.start,
|
4190 |
+
(!slotDelta && !event.end) ? null : // no change, so don't display time range
|
4191 |
+
addMinutes(eventEnd(event), opt('slotMinutes')*slotDelta),
|
4192 |
+
opt('timeFormat')
|
4193 |
+
)
|
4194 |
+
);
|
4195 |
+
prevSlotDelta = slotDelta;
|
4196 |
+
}
|
4197 |
+
},
|
4198 |
+
stop: function(ev, ui) {
|
4199 |
+
trigger('eventResizeStop', this, event, ev, ui);
|
4200 |
+
if (slotDelta) {
|
4201 |
+
eventResize(this, event, 0, opt('slotMinutes')*slotDelta, ev, ui);
|
4202 |
+
}else{
|
4203 |
+
eventElement.css('z-index', 8);
|
4204 |
+
showEvents(event, eventElement);
|
4205 |
+
// BUG: if event was really short, need to put title back in span
|
4206 |
+
}
|
4207 |
+
}
|
4208 |
+
});
|
4209 |
+
}
|
4210 |
+
|
4211 |
+
|
4212 |
+
}
|
4213 |
+
|
4214 |
+
|
4215 |
+
function countForwardSegs(levels) {
|
4216 |
+
var i, j, k, level, segForward, segBack;
|
4217 |
+
for (i=levels.length-1; i>0; i--) {
|
4218 |
+
level = levels[i];
|
4219 |
+
for (j=0; j<level.length; j++) {
|
4220 |
+
segForward = level[j];
|
4221 |
+
for (k=0; k<levels[i-1].length; k++) {
|
4222 |
+
segBack = levels[i-1][k];
|
4223 |
+
if (segsCollide(segForward, segBack)) {
|
4224 |
+
segBack.forward = Math.max(segBack.forward||0, (segForward.forward||0)+1);
|
4225 |
+
}
|
4226 |
+
}
|
4227 |
+
}
|
4228 |
+
}
|
4229 |
+
}
|
4230 |
+
|
4231 |
+
|
4232 |
+
|
4233 |
+
|
4234 |
+
function View(element, calendar, viewName) {
|
4235 |
+
var t = this;
|
4236 |
+
|
4237 |
+
|
4238 |
+
// exports
|
4239 |
+
t.element = element;
|
4240 |
+
t.calendar = calendar;
|
4241 |
+
t.name = viewName;
|
4242 |
+
t.opt = opt;
|
4243 |
+
t.trigger = trigger;
|
4244 |
+
//t.setOverflowHidden = setOverflowHidden;
|
4245 |
+
t.isEventDraggable = isEventDraggable;
|
4246 |
+
t.isEventResizable = isEventResizable;
|
4247 |
+
t.reportEvents = reportEvents;
|
4248 |
+
t.eventEnd = eventEnd;
|
4249 |
+
t.reportEventElement = reportEventElement;
|
4250 |
+
t.reportEventClear = reportEventClear;
|
4251 |
+
t.eventElementHandlers = eventElementHandlers;
|
4252 |
+
t.showEvents = showEvents;
|
4253 |
+
t.hideEvents = hideEvents;
|
4254 |
+
t.eventDrop = eventDrop;
|
4255 |
+
t.eventResize = eventResize;
|
4256 |
+
// t.title
|
4257 |
+
// t.start, t.end
|
4258 |
+
// t.visStart, t.visEnd
|
4259 |
+
|
4260 |
+
|
4261 |
+
// imports
|
4262 |
+
var defaultEventEnd = t.defaultEventEnd;
|
4263 |
+
var normalizeEvent = calendar.normalizeEvent; // in EventManager
|
4264 |
+
var reportEventChange = calendar.reportEventChange;
|
4265 |
+
|
4266 |
+
|
4267 |
+
// locals
|
4268 |
+
var eventsByID = {};
|
4269 |
+
var eventElements = [];
|
4270 |
+
var eventElementsByID = {};
|
4271 |
+
var options = calendar.options;
|
4272 |
+
|
4273 |
+
|
4274 |
+
|
4275 |
+
function opt(name, viewNameOverride) {
|
4276 |
+
var v = options[name];
|
4277 |
+
if (typeof v == 'object') {
|
4278 |
+
return smartProperty(v, viewNameOverride || viewName);
|
4279 |
+
}
|
4280 |
+
return v;
|
4281 |
+
}
|
4282 |
+
|
4283 |
+
|
4284 |
+
function trigger(name, thisObj) {
|
4285 |
+
return calendar.trigger.apply(
|
4286 |
+
calendar,
|
4287 |
+
[name, thisObj || t].concat(Array.prototype.slice.call(arguments, 2), [t])
|
4288 |
+
);
|
4289 |
+
}
|
4290 |
+
|
4291 |
+
|
4292 |
+
/*
|
4293 |
+
function setOverflowHidden(bool) {
|
4294 |
+
element.css('overflow', bool ? 'hidden' : '');
|
4295 |
+
}
|
4296 |
+
*/
|
4297 |
+
|
4298 |
+
|
4299 |
+
function isEventDraggable(event) {
|
4300 |
+
return isEventEditable(event) && !opt('disableDragging');
|
4301 |
+
}
|
4302 |
+
|
4303 |
+
|
4304 |
+
function isEventResizable(event) { // but also need to make sure the seg.isEnd == true
|
4305 |
+
return isEventEditable(event) && !opt('disableResizing');
|
4306 |
+
}
|
4307 |
+
|
4308 |
+
|
4309 |
+
function isEventEditable(event) {
|
4310 |
+
return firstDefined(event.editable, (event.source || {}).editable, opt('editable'));
|
4311 |
+
}
|
4312 |
+
|
4313 |
+
|
4314 |
+
|
4315 |
+
/* Event Data
|
4316 |
+
------------------------------------------------------------------------------*/
|
4317 |
+
|
4318 |
+
|
4319 |
+
// report when view receives new events
|
4320 |
+
function reportEvents(events) { // events are already normalized at this point
|
4321 |
+
eventsByID = {};
|
4322 |
+
var i, len=events.length, event;
|
4323 |
+
for (i=0; i<len; i++) {
|
4324 |
+
event = events[i];
|
4325 |
+
if (eventsByID[event._id]) {
|
4326 |
+
eventsByID[event._id].push(event);
|
4327 |
+
}else{
|
4328 |
+
eventsByID[event._id] = [event];
|
4329 |
+
}
|
4330 |
+
}
|
4331 |
+
}
|
4332 |
+
|
4333 |
+
|
4334 |
+
// returns a Date object for an event's end
|
4335 |
+
function eventEnd(event) {
|
4336 |
+
return event.end ? cloneDate(event.end) : defaultEventEnd(event);
|
4337 |
+
}
|
4338 |
+
|
4339 |
+
|
4340 |
+
|
4341 |
+
/* Event Elements
|
4342 |
+
------------------------------------------------------------------------------*/
|
4343 |
+
|
4344 |
+
|
4345 |
+
// report when view creates an element for an event
|
4346 |
+
function reportEventElement(event, element) {
|
4347 |
+
eventElements.push(element);
|
4348 |
+
if (eventElementsByID[event._id]) {
|
4349 |
+
eventElementsByID[event._id].push(element);
|
4350 |
+
}else{
|
4351 |
+
eventElementsByID[event._id] = [element];
|
4352 |
+
}
|
4353 |
+
}
|
4354 |
+
|
4355 |
+
|
4356 |
+
function reportEventClear() {
|
4357 |
+
eventElements = [];
|
4358 |
+
eventElementsByID = {};
|
4359 |
+
}
|
4360 |
+
|
4361 |
+
|
4362 |
+
// attaches eventClick, eventMouseover, eventMouseout
|
4363 |
+
function eventElementHandlers(event, eventElement) {
|
4364 |
+
eventElement
|
4365 |
+
.click(function(ev) {
|
4366 |
+
if (!eventElement.hasClass('ui-draggable-dragging') &&
|
4367 |
+
!eventElement.hasClass('ui-resizable-resizing')) {
|
4368 |
+
return trigger('eventClick', this, event, ev);
|
4369 |
+
}
|
4370 |
+
})
|
4371 |
+
.hover(
|
4372 |
+
function(ev) {
|
4373 |
+
trigger('eventMouseover', this, event, ev);
|
4374 |
+
},
|
4375 |
+
function(ev) {
|
4376 |
+
trigger('eventMouseout', this, event, ev);
|
4377 |
+
}
|
4378 |
+
);
|
4379 |
+
// TODO: don't fire eventMouseover/eventMouseout *while* dragging is occuring (on subject element)
|
4380 |
+
// TODO: same for resizing
|
4381 |
+
}
|
4382 |
+
|
4383 |
+
|
4384 |
+
function showEvents(event, exceptElement) {
|
4385 |
+
eachEventElement(event, exceptElement, 'show');
|
4386 |
+
}
|
4387 |
+
|
4388 |
+
|
4389 |
+
function hideEvents(event, exceptElement) {
|
4390 |
+
eachEventElement(event, exceptElement, 'hide');
|
4391 |
+
}
|
4392 |
+
|
4393 |
+
|
4394 |
+
function eachEventElement(event, exceptElement, funcName) {
|
4395 |
+
var elements = eventElementsByID[event._id],
|
4396 |
+
i, len = elements.length;
|
4397 |
+
for (i=0; i<len; i++) {
|
4398 |
+
if (!exceptElement || elements[i][0] != exceptElement[0]) {
|
4399 |
+
elements[i][funcName]();
|
4400 |
+
}
|
4401 |
+
}
|
4402 |
+
}
|
4403 |
+
|
4404 |
+
|
4405 |
+
|
4406 |
+
/* Event Modification Reporting
|
4407 |
+
---------------------------------------------------------------------------------*/
|
4408 |
+
|
4409 |
+
|
4410 |
+
function eventDrop(e, event, dayDelta, minuteDelta, allDay, ev, ui) {
|
4411 |
+
var oldAllDay = event.allDay;
|
4412 |
+
var eventId = event._id;
|
4413 |
+
moveEvents(eventsByID[eventId], dayDelta, minuteDelta, allDay);
|
4414 |
+
trigger(
|
4415 |
+
'eventDrop',
|
4416 |
+
e,
|
4417 |
+
event,
|
4418 |
+
dayDelta,
|
4419 |
+
minuteDelta,
|
4420 |
+
allDay,
|
4421 |
+
function() {
|
4422 |
+
// TODO: investigate cases where this inverse technique might not work
|
4423 |
+
moveEvents(eventsByID[eventId], -dayDelta, -minuteDelta, oldAllDay);
|
4424 |
+
reportEventChange(eventId);
|
4425 |
+
},
|
4426 |
+
ev,
|
4427 |
+
ui
|
4428 |
+
);
|
4429 |
+
reportEventChange(eventId);
|
4430 |
+
}
|
4431 |
+
|
4432 |
+
|
4433 |
+
function eventResize(e, event, dayDelta, minuteDelta, ev, ui) {
|
4434 |
+
var eventId = event._id;
|
4435 |
+
elongateEvents(eventsByID[eventId], dayDelta, minuteDelta);
|
4436 |
+
trigger(
|
4437 |
+
'eventResize',
|
4438 |
+
e,
|
4439 |
+
event,
|
4440 |
+
dayDelta,
|
4441 |
+
minuteDelta,
|
4442 |
+
function() {
|
4443 |
+
// TODO: investigate cases where this inverse technique might not work
|
4444 |
+
elongateEvents(eventsByID[eventId], -dayDelta, -minuteDelta);
|
4445 |
+
reportEventChange(eventId);
|
4446 |
+
},
|
4447 |
+
ev,
|
4448 |
+
ui
|
4449 |
+
);
|
4450 |
+
reportEventChange(eventId);
|
4451 |
+
}
|
4452 |
+
|
4453 |
+
|
4454 |
+
|
4455 |
+
/* Event Modification Math
|
4456 |
+
---------------------------------------------------------------------------------*/
|
4457 |
+
|
4458 |
+
|
4459 |
+
function moveEvents(events, dayDelta, minuteDelta, allDay) {
|
4460 |
+
minuteDelta = minuteDelta || 0;
|
4461 |
+
for (var e, len=events.length, i=0; i<len; i++) {
|
4462 |
+
e = events[i];
|
4463 |
+
if (allDay !== undefined) {
|
4464 |
+
e.allDay = allDay;
|
4465 |
+
}
|
4466 |
+
addMinutes(addDays(e.start, dayDelta, true), minuteDelta);
|
4467 |
+
if (e.end) {
|
4468 |
+
e.end = addMinutes(addDays(e.end, dayDelta, true), minuteDelta);
|
4469 |
+
}
|
4470 |
+
normalizeEvent(e, options);
|
4471 |
+
}
|
4472 |
+
}
|
4473 |
+
|
4474 |
+
|
4475 |
+
function elongateEvents(events, dayDelta, minuteDelta) {
|
4476 |
+
minuteDelta = minuteDelta || 0;
|
4477 |
+
for (var e, len=events.length, i=0; i<len; i++) {
|
4478 |
+
e = events[i];
|
4479 |
+
e.end = addMinutes(addDays(eventEnd(e), dayDelta, true), minuteDelta);
|
4480 |
+
normalizeEvent(e, options);
|
4481 |
+
}
|
4482 |
+
}
|
4483 |
+
|
4484 |
+
|
4485 |
+
}
|
4486 |
+
|
4487 |
+
function DayEventRenderer() {
|
4488 |
+
var t = this;
|
4489 |
+
|
4490 |
+
|
4491 |
+
// exports
|
4492 |
+
t.renderDaySegs = renderDaySegs;
|
4493 |
+
t.resizableDayEvent = resizableDayEvent;
|
4494 |
+
|
4495 |
+
|
4496 |
+
// imports
|
4497 |
+
var opt = t.opt;
|
4498 |
+
var trigger = t.trigger;
|
4499 |
+
var isEventDraggable = t.isEventDraggable;
|
4500 |
+
var isEventResizable = t.isEventResizable;
|
4501 |
+
var eventEnd = t.eventEnd;
|
4502 |
+
var reportEventElement = t.reportEventElement;
|
4503 |
+
var showEvents = t.showEvents;
|
4504 |
+
var hideEvents = t.hideEvents;
|
4505 |
+
var eventResize = t.eventResize;
|
4506 |
+
var getRowCnt = t.getRowCnt;
|
4507 |
+
var getColCnt = t.getColCnt;
|
4508 |
+
var getColWidth = t.getColWidth;
|
4509 |
+
var allDayRow = t.allDayRow;
|
4510 |
+
var allDayBounds = t.allDayBounds;
|
4511 |
+
var colContentLeft = t.colContentLeft;
|
4512 |
+
var colContentRight = t.colContentRight;
|
4513 |
+
var dayOfWeekCol = t.dayOfWeekCol;
|
4514 |
+
var dateCell = t.dateCell;
|
4515 |
+
var compileDaySegs = t.compileDaySegs;
|
4516 |
+
var getDaySegmentContainer = t.getDaySegmentContainer;
|
4517 |
+
var bindDaySeg = t.bindDaySeg; //TODO: streamline this
|
4518 |
+
var formatDates = t.calendar.formatDates;
|
4519 |
+
var renderDayOverlay = t.renderDayOverlay;
|
4520 |
+
var clearOverlays = t.clearOverlays;
|
4521 |
+
var clearSelection = t.clearSelection;
|
4522 |
+
|
4523 |
+
|
4524 |
+
|
4525 |
+
/* Rendering
|
4526 |
+
-----------------------------------------------------------------------------*/
|
4527 |
+
|
4528 |
+
|
4529 |
+
function renderDaySegs(segs, modifiedEventId) {
|
4530 |
+
var segmentContainer = getDaySegmentContainer();
|
4531 |
+
var rowDivs;
|
4532 |
+
var rowCnt = getRowCnt();
|
4533 |
+
var colCnt = getColCnt();
|
4534 |
+
var i = 0;
|
4535 |
+
var rowI;
|
4536 |
+
var levelI;
|
4537 |
+
var colHeights;
|
4538 |
+
var j;
|
4539 |
+
var segCnt = segs.length;
|
4540 |
+
var seg;
|
4541 |
+
var top;
|
4542 |
+
var k;
|
4543 |
+
segmentContainer[0].innerHTML = daySegHTML(segs); // faster than .html()
|
4544 |
+
daySegElementResolve(segs, segmentContainer.children());
|
4545 |
+
daySegElementReport(segs);
|
4546 |
+
daySegHandlers(segs, segmentContainer, modifiedEventId);
|
4547 |
+
daySegCalcHSides(segs);
|
4548 |
+
daySegSetWidths(segs);
|
4549 |
+
daySegCalcHeights(segs);
|
4550 |
+
rowDivs = getRowDivs();
|
4551 |
+
// set row heights, calculate event tops (in relation to row top)
|
4552 |
+
for (rowI=0; rowI<rowCnt; rowI++) {
|
4553 |
+
levelI = 0;
|
4554 |
+
colHeights = [];
|
4555 |
+
for (j=0; j<colCnt; j++) {
|
4556 |
+
colHeights[j] = 0;
|
4557 |
+
}
|
4558 |
+
while (i<segCnt && (seg = segs[i]).row == rowI) {
|
4559 |
+
// loop through segs in a row
|
4560 |
+
top = arrayMax(colHeights.slice(seg.startCol, seg.endCol));
|
4561 |
+
seg.top = top;
|
4562 |
+
top += seg.outerHeight;
|
4563 |
+
for (k=seg.startCol; k<seg.endCol; k++) {
|
4564 |
+
colHeights[k] = top;
|
4565 |
+
}
|
4566 |
+
i++;
|
4567 |
+
}
|
4568 |
+
rowDivs[rowI].height(arrayMax(colHeights));
|
4569 |
+
}
|
4570 |
+
daySegSetTops(segs, getRowTops(rowDivs));
|
4571 |
+
}
|
4572 |
+
|
4573 |
+
|
4574 |
+
function renderTempDaySegs(segs, adjustRow, adjustTop) {
|
4575 |
+
var tempContainer = $("<div/>");
|
4576 |
+
var elements;
|
4577 |
+
var segmentContainer = getDaySegmentContainer();
|
4578 |
+
var i;
|
4579 |
+
var segCnt = segs.length;
|
4580 |
+
var element;
|
4581 |
+
tempContainer[0].innerHTML = daySegHTML(segs); // faster than .html()
|
4582 |
+
elements = tempContainer.children();
|
4583 |
+
segmentContainer.append(elements);
|
4584 |
+
daySegElementResolve(segs, elements);
|
4585 |
+
daySegCalcHSides(segs);
|
4586 |
+
daySegSetWidths(segs);
|
4587 |
+
daySegCalcHeights(segs);
|
4588 |
+
daySegSetTops(segs, getRowTops(getRowDivs()));
|
4589 |
+
elements = [];
|
4590 |
+
for (i=0; i<segCnt; i++) {
|
4591 |
+
element = segs[i].element;
|
4592 |
+
if (element) {
|
4593 |
+
if (segs[i].row === adjustRow) {
|
4594 |
+
element.css('top', adjustTop);
|
4595 |
+
}
|
4596 |
+
elements.push(element[0]);
|
4597 |
+
}
|
4598 |
+
}
|
4599 |
+
return $(elements);
|
4600 |
+
}
|
4601 |
+
|
4602 |
+
|
4603 |
+
function daySegHTML(segs) { // also sets seg.left and seg.outerWidth
|
4604 |
+
var rtl = opt('isRTL');
|
4605 |
+
var i;
|
4606 |
+
var segCnt=segs.length;
|
4607 |
+
var seg;
|
4608 |
+
var event;
|
4609 |
+
var url;
|
4610 |
+
var classes;
|
4611 |
+
var bounds = allDayBounds();
|
4612 |
+
var minLeft = bounds.left;
|
4613 |
+
var maxLeft = bounds.right;
|
4614 |
+
var leftCol;
|
4615 |
+
var rightCol;
|
4616 |
+
var left;
|
4617 |
+
var right;
|
4618 |
+
var skinCss;
|
4619 |
+
var html = '';
|
4620 |
+
// calculate desired position/dimensions, create html
|
4621 |
+
for (i=0; i<segCnt; i++) {
|
4622 |
+
seg = segs[i];
|
4623 |
+
event = seg.event;
|
4624 |
+
classes = ['fc-event', 'fc-event-skin', 'fc-event-hori'];
|
4625 |
+
if (isEventDraggable(event)) {
|
4626 |
+
classes.push('fc-event-draggable');
|
4627 |
+
}
|
4628 |
+
if (rtl) {
|
4629 |
+
if (seg.isStart) {
|
4630 |
+
classes.push('fc-corner-right');
|
4631 |
+
}
|
4632 |
+
if (seg.isEnd) {
|
4633 |
+
classes.push('fc-corner-left');
|
4634 |
+
}
|
4635 |
+
leftCol = dayOfWeekCol(seg.end.getDay()-1);
|
4636 |
+
rightCol = dayOfWeekCol(seg.start.getDay());
|
4637 |
+
left = seg.isEnd ? colContentLeft(leftCol) : minLeft;
|
4638 |
+
right = seg.isStart ? colContentRight(rightCol) : maxLeft;
|
4639 |
+
}else{
|
4640 |
+
if (seg.isStart) {
|
4641 |
+
classes.push('fc-corner-left');
|
4642 |
+
}
|
4643 |
+
if (seg.isEnd) {
|
4644 |
+
classes.push('fc-corner-right');
|
4645 |
+
}
|
4646 |
+
leftCol = dayOfWeekCol(seg.start.getDay());
|
4647 |
+
rightCol = dayOfWeekCol(seg.end.getDay()-1);
|
4648 |
+
left = seg.isStart ? colContentLeft(leftCol) : minLeft;
|
4649 |
+
right = seg.isEnd ? colContentRight(rightCol) : maxLeft;
|
4650 |
+
}
|
4651 |
+
classes = classes.concat(event.className);
|
4652 |
+
if (event.source) {
|
4653 |
+
classes = classes.concat(event.source.className || []);
|
4654 |
+
}
|
4655 |
+
url = event.url;
|
4656 |
+
skinCss = getSkinCss(event, opt);
|
4657 |
+
if (url) {
|
4658 |
+
html += "<a href='" + htmlEscape(url) + "'";
|
4659 |
+
}else{
|
4660 |
+
html += "<div";
|
4661 |
+
}
|
4662 |
+
html +=
|
4663 |
+
" class='" + classes.join(' ') + "'" +
|
4664 |
+
" style='position:absolute;z-index:8;left:"+left+"px;" + skinCss + "'" +
|
4665 |
+
">" +
|
4666 |
+
"<div" +
|
4667 |
+
" class='fc-event-inner fc-event-skin'" +
|
4668 |
+
(skinCss ? " style='" + skinCss + "'" : '') +
|
4669 |
+
">";
|
4670 |
+
if (!event.allDay && seg.isStart) {
|
4671 |
+
html +=
|
4672 |
+
"<span class='fc-event-time'>" +
|
4673 |
+
htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) +
|
4674 |
+
"</span>";
|
4675 |
+
}
|
4676 |
+
html +=
|
4677 |
+
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
4678 |
+
"</div>";
|
4679 |
+
if (seg.isEnd && isEventResizable(event)) {
|
4680 |
+
html +=
|
4681 |
+
"<div class='ui-resizable-handle ui-resizable-" + (rtl ? 'w' : 'e') + "'>" +
|
4682 |
+
" " + // makes hit area a lot better for IE6/7
|
4683 |
+
"</div>";
|
4684 |
+
}
|
4685 |
+
html +=
|
4686 |
+
"</" + (url ? "a" : "div" ) + ">";
|
4687 |
+
seg.left = left;
|
4688 |
+
seg.outerWidth = right - left;
|
4689 |
+
seg.startCol = leftCol;
|
4690 |
+
seg.endCol = rightCol + 1; // needs to be exclusive
|
4691 |
+
}
|
4692 |
+
return html;
|
4693 |
+
}
|
4694 |
+
|
4695 |
+
|
4696 |
+
function daySegElementResolve(segs, elements) { // sets seg.element
|
4697 |
+
var i;
|
4698 |
+
var segCnt = segs.length;
|
4699 |
+
var seg;
|
4700 |
+
var event;
|
4701 |
+
var element;
|
4702 |
+
var triggerRes;
|
4703 |
+
for (i=0; i<segCnt; i++) {
|
4704 |
+
seg = segs[i];
|
4705 |
+
event = seg.event;
|
4706 |
+
element = $(elements[i]); // faster than .eq()
|
4707 |
+
triggerRes = trigger('eventRender', event, event, element, t);
|
4708 |
+
if (triggerRes === false) {
|
4709 |
+
element.remove();
|
4710 |
+
}else{
|
4711 |
+
if (triggerRes && triggerRes !== true) {
|
4712 |
+
triggerRes = $(triggerRes)
|
4713 |
+
.css({
|
4714 |
+
position: 'absolute',
|
4715 |
+
left: seg.left
|
4716 |
+
});
|
4717 |
+
element.replaceWith(triggerRes);
|
4718 |
+
element = triggerRes;
|
4719 |
+
}
|
4720 |
+
seg.element = element;
|
4721 |
+
}
|
4722 |
+
}
|
4723 |
+
}
|
4724 |
+
|
4725 |
+
|
4726 |
+
function daySegElementReport(segs) {
|
4727 |
+
var i;
|
4728 |
+
var segCnt = segs.length;
|
4729 |
+
var seg;
|
4730 |
+
var element;
|
4731 |
+
for (i=0; i<segCnt; i++) {
|
4732 |
+
seg = segs[i];
|
4733 |
+
element = seg.element;
|
4734 |
+
if (element) {
|
4735 |
+
reportEventElement(seg.event, element);
|
4736 |
+
}
|
4737 |
+
}
|
4738 |
+
}
|
4739 |
+
|
4740 |
+
|
4741 |
+
function daySegHandlers(segs, segmentContainer, modifiedEventId) {
|
4742 |
+
var i;
|
4743 |
+
var segCnt = segs.length;
|
4744 |
+
var seg;
|
4745 |
+
var element;
|
4746 |
+
var event;
|
4747 |
+
// retrieve elements, run through eventRender callback, bind handlers
|
4748 |
+
for (i=0; i<segCnt; i++) {
|
4749 |
+
seg = segs[i];
|
4750 |
+
element = seg.element;
|
4751 |
+
if (element) {
|
4752 |
+
event = seg.event;
|
4753 |
+
if (event._id === modifiedEventId) {
|
4754 |
+
bindDaySeg(event, element, seg);
|
4755 |
+
}else{
|
4756 |
+
element[0]._fci = i; // for lazySegBind
|
4757 |
+
}
|
4758 |
+
}
|
4759 |
+
}
|
4760 |
+
lazySegBind(segmentContainer, segs, bindDaySeg);
|
4761 |
+
}
|
4762 |
+
|
4763 |
+
|
4764 |
+
function daySegCalcHSides(segs) { // also sets seg.key
|
4765 |
+
var i;
|
4766 |
+
var segCnt = segs.length;
|
4767 |
+
var seg;
|
4768 |
+
var element;
|
4769 |
+
var key, val;
|
4770 |
+
var hsideCache = {};
|
4771 |
+
// record event horizontal sides
|
4772 |
+
for (i=0; i<segCnt; i++) {
|
4773 |
+
seg = segs[i];
|
4774 |
+
element = seg.element;
|
4775 |
+
if (element) {
|
4776 |
+
key = seg.key = cssKey(element[0]);
|
4777 |
+
val = hsideCache[key];
|
4778 |
+
if (val === undefined) {
|
4779 |
+
val = hsideCache[key] = hsides(element, true);
|
4780 |
+
}
|
4781 |
+
seg.hsides = val;
|
4782 |
+
}
|
4783 |
+
}
|
4784 |
+
}
|
4785 |
+
|
4786 |
+
|
4787 |
+
function daySegSetWidths(segs) {
|
4788 |
+
var i;
|
4789 |
+
var segCnt = segs.length;
|
4790 |
+
var seg;
|
4791 |
+
var element;
|
4792 |
+
for (i=0; i<segCnt; i++) {
|
4793 |
+
seg = segs[i];
|
4794 |
+
element = seg.element;
|
4795 |
+
if (element) {
|
4796 |
+
element[0].style.width = Math.max(0, seg.outerWidth - seg.hsides) + 'px';
|
4797 |
+
}
|
4798 |
+
}
|
4799 |
+
}
|
4800 |
+
|
4801 |
+
|
4802 |
+
function daySegCalcHeights(segs) {
|
4803 |
+
var i;
|
4804 |
+
var segCnt = segs.length;
|
4805 |
+
var seg;
|
4806 |
+
var element;
|
4807 |
+
var key, val;
|
4808 |
+
var vmarginCache = {};
|
4809 |
+
// record event heights
|
4810 |
+
for (i=0; i<segCnt; i++) {
|
4811 |
+
seg = segs[i];
|
4812 |
+
element = seg.element;
|
4813 |
+
if (element) {
|
4814 |
+
key = seg.key; // created in daySegCalcHSides
|
4815 |
+
val = vmarginCache[key];
|
4816 |
+
if (val === undefined) {
|
4817 |
+
val = vmarginCache[key] = vmargins(element);
|
4818 |
+
}
|
4819 |
+
seg.outerHeight = element[0].offsetHeight + val;
|
4820 |
+
}
|
4821 |
+
}
|
4822 |
+
}
|
4823 |
+
|
4824 |
+
|
4825 |
+
function getRowDivs() {
|
4826 |
+
var i;
|
4827 |
+
var rowCnt = getRowCnt();
|
4828 |
+
var rowDivs = [];
|
4829 |
+
for (i=0; i<rowCnt; i++) {
|
4830 |
+
rowDivs[i] = allDayRow(i)
|
4831 |
+
.find('td:first div.fc-day-content > div'); // optimal selector?
|
4832 |
+
}
|
4833 |
+
return rowDivs;
|
4834 |
+
}
|
4835 |
+
|
4836 |
+
|
4837 |
+
function getRowTops(rowDivs) {
|
4838 |
+
var i;
|
4839 |
+
var rowCnt = rowDivs.length;
|
4840 |
+
var tops = [];
|
4841 |
+
for (i=0; i<rowCnt; i++) {
|
4842 |
+
tops[i] = rowDivs[i][0].offsetTop; // !!?? but this means the element needs position:relative if in a table cell!!!!
|
4843 |
+
}
|
4844 |
+
return tops;
|
4845 |
+
}
|
4846 |
+
|
4847 |
+
|
4848 |
+
function daySegSetTops(segs, rowTops) { // also triggers eventAfterRender
|
4849 |
+
var i;
|
4850 |
+
var segCnt = segs.length;
|
4851 |
+
var seg;
|
4852 |
+
var element;
|
4853 |
+
var event;
|
4854 |
+
for (i=0; i<segCnt; i++) {
|
4855 |
+
seg = segs[i];
|
4856 |
+
element = seg.element;
|
4857 |
+
if (element) {
|
4858 |
+
element[0].style.top = rowTops[seg.row] + (seg.top||0) + 'px';
|
4859 |
+
event = seg.event;
|
4860 |
+
trigger('eventAfterRender', event, event, element);
|
4861 |
+
}
|
4862 |
+
}
|
4863 |
+
}
|
4864 |
+
|
4865 |
+
|
4866 |
+
|
4867 |
+
/* Resizing
|
4868 |
+
-----------------------------------------------------------------------------------*/
|
4869 |
+
|
4870 |
+
|
4871 |
+
function resizableDayEvent(event, element, seg) {
|
4872 |
+
var rtl = opt('isRTL');
|
4873 |
+
var direction = rtl ? 'w' : 'e';
|
4874 |
+
var handle = element.find('div.ui-resizable-' + direction);
|
4875 |
+
var isResizing = false;
|
4876 |
+
|
4877 |
+
// TODO: look into using jquery-ui mouse widget for this stuff
|
4878 |
+
disableTextSelection(element); // prevent native <a> selection for IE
|
4879 |
+
element
|
4880 |
+
.mousedown(function(ev) { // prevent native <a> selection for others
|
4881 |
+
ev.preventDefault();
|
4882 |
+
})
|
4883 |
+
.click(function(ev) {
|
4884 |
+
if (isResizing) {
|
4885 |
+
ev.preventDefault(); // prevent link from being visited (only method that worked in IE6)
|
4886 |
+
ev.stopImmediatePropagation(); // prevent fullcalendar eventClick handler from being called
|
4887 |
+
// (eventElementHandlers needs to be bound after resizableDayEvent)
|
4888 |
+
}
|
4889 |
+
});
|
4890 |
+
|
4891 |
+
handle.mousedown(function(ev) {
|
4892 |
+
if (ev.which != 1) {
|
4893 |
+
return; // needs to be left mouse button
|
4894 |
+
}
|
4895 |
+
isResizing = true;
|
4896 |
+
var hoverListener = t.getHoverListener();
|
4897 |
+
var rowCnt = getRowCnt();
|
4898 |
+
var colCnt = getColCnt();
|
4899 |
+
var dis = rtl ? -1 : 1;
|
4900 |
+
var dit = rtl ? colCnt-1 : 0;
|
4901 |
+
var elementTop = element.css('top');
|
4902 |
+
var dayDelta;
|
4903 |
+
var helpers;
|
4904 |
+
var eventCopy = $.extend({}, event);
|
4905 |
+
var minCell = dateCell(event.start);
|
4906 |
+
clearSelection();
|
4907 |
+
$('body')
|
4908 |
+
.css('cursor', direction + '-resize')
|
4909 |
+
.one('mouseup', mouseup);
|
4910 |
+
trigger('eventResizeStart', this, event, ev);
|
4911 |
+
hoverListener.start(function(cell, origCell) {
|
4912 |
+
if (cell) {
|
4913 |
+
var r = Math.max(minCell.row, cell.row);
|
4914 |
+
var c = cell.col;
|
4915 |
+
if (rowCnt == 1) {
|
4916 |
+
r = 0; // hack for all-day area in agenda views
|
4917 |
+
}
|
4918 |
+
if (r == minCell.row) {
|
4919 |
+
if (rtl) {
|
4920 |
+
c = Math.min(minCell.col, c);
|
4921 |
+
}else{
|
4922 |
+
c = Math.max(minCell.col, c);
|
4923 |
+
}
|
4924 |
+
}
|
4925 |
+
dayDelta = (r*7 + c*dis+dit) - (origCell.row*7 + origCell.col*dis+dit);
|
4926 |
+
var newEnd = addDays(eventEnd(event), dayDelta, true);
|
4927 |
+
if (dayDelta) {
|
4928 |
+
eventCopy.end = newEnd;
|
4929 |
+
var oldHelpers = helpers;
|
4930 |
+
helpers = renderTempDaySegs(compileDaySegs([eventCopy]), seg.row, elementTop);
|
4931 |
+
helpers.find('*').css('cursor', direction + '-resize');
|
4932 |
+
if (oldHelpers) {
|
4933 |
+
oldHelpers.remove();
|
4934 |
+
}
|
4935 |
+
hideEvents(event);
|
4936 |
+
}else{
|
4937 |
+
if (helpers) {
|
4938 |
+
showEvents(event);
|
4939 |
+
helpers.remove();
|
4940 |
+
helpers = null;
|
4941 |
+
}
|
4942 |
+
}
|
4943 |
+
clearOverlays();
|
4944 |
+
renderDayOverlay(event.start, addDays(cloneDate(newEnd), 1)); // coordinate grid already rebuild at hoverListener.start
|
4945 |
+
}
|
4946 |
+
}, ev);
|
4947 |
+
|
4948 |
+
function mouseup(ev) {
|
4949 |
+
trigger('eventResizeStop', this, event, ev);
|
4950 |
+
$('body').css('cursor', '');
|
4951 |
+
hoverListener.stop();
|
4952 |
+
clearOverlays();
|
4953 |
+
if (dayDelta) {
|
4954 |
+
eventResize(this, event, dayDelta, 0, ev);
|
4955 |
+
// event redraw will clear helpers
|
4956 |
+
}
|
4957 |
+
// otherwise, the drag handler already restored the old events
|
4958 |
+
|
4959 |
+
setTimeout(function() { // make this happen after the element's click event
|
4960 |
+
isResizing = false;
|
4961 |
+
},0);
|
4962 |
+
}
|
4963 |
+
|
4964 |
+
});
|
4965 |
+
}
|
4966 |
+
|
4967 |
+
|
4968 |
+
}
|
4969 |
+
|
4970 |
+
//BUG: unselect needs to be triggered when events are dragged+dropped
|
4971 |
+
|
4972 |
+
function SelectionManager() {
|
4973 |
+
var t = this;
|
4974 |
+
|
4975 |
+
|
4976 |
+
// exports
|
4977 |
+
t.select = select;
|
4978 |
+
t.unselect = unselect;
|
4979 |
+
t.reportSelection = reportSelection;
|
4980 |
+
t.daySelectionMousedown = daySelectionMousedown;
|
4981 |
+
|
4982 |
+
|
4983 |
+
// imports
|
4984 |
+
var opt = t.opt;
|
4985 |
+
var trigger = t.trigger;
|
4986 |
+
var defaultSelectionEnd = t.defaultSelectionEnd;
|
4987 |
+
var renderSelection = t.renderSelection;
|
4988 |
+
var clearSelection = t.clearSelection;
|
4989 |
+
|
4990 |
+
|
4991 |
+
// locals
|
4992 |
+
var selected = false;
|
4993 |
+
|
4994 |
+
|
4995 |
+
|
4996 |
+
// unselectAuto
|
4997 |
+
if (opt('selectable') && opt('unselectAuto')) {
|
4998 |
+
$(document).mousedown(function(ev) {
|
4999 |
+
var ignore = opt('unselectCancel');
|
5000 |
+
if (ignore) {
|
5001 |
+
if ($(ev.target).parents(ignore).length) { // could be optimized to stop after first match
|
5002 |
+
return;
|
5003 |
+
}
|
5004 |
+
}
|
5005 |
+
unselect(ev);
|
5006 |
+
});
|
5007 |
+
}
|
5008 |
+
|
5009 |
+
|
5010 |
+
function select(startDate, endDate, allDay) {
|
5011 |
+
unselect();
|
5012 |
+
if (!endDate) {
|
5013 |
+
endDate = defaultSelectionEnd(startDate, allDay);
|
5014 |
+
}
|
5015 |
+
renderSelection(startDate, endDate, allDay);
|
5016 |
+
reportSelection(startDate, endDate, allDay);
|
5017 |
+
}
|
5018 |
+
|
5019 |
+
|
5020 |
+
function unselect(ev) {
|
5021 |
+
if (selected) {
|
5022 |
+
selected = false;
|
5023 |
+
clearSelection();
|
5024 |
+
trigger('unselect', null, ev);
|
5025 |
+
}
|
5026 |
+
}
|
5027 |
+
|
5028 |
+
|
5029 |
+
function reportSelection(startDate, endDate, allDay, ev) {
|
5030 |
+
selected = true;
|
5031 |
+
trigger('select', null, startDate, endDate, allDay, ev);
|
5032 |
+
}
|
5033 |
+
|
5034 |
+
|
5035 |
+
function daySelectionMousedown(ev) { // not really a generic manager method, oh well
|
5036 |
+
var cellDate = t.cellDate;
|
5037 |
+
var cellIsAllDay = t.cellIsAllDay;
|
5038 |
+
var hoverListener = t.getHoverListener();
|
5039 |
+
var reportDayClick = t.reportDayClick; // this is hacky and sort of weird
|
5040 |
+
if (ev.which == 1 && opt('selectable')) { // which==1 means left mouse button
|
5041 |
+
unselect(ev);
|
5042 |
+
var _mousedownElement = this;
|
5043 |
+
var dates;
|
5044 |
+
hoverListener.start(function(cell, origCell) { // TODO: maybe put cellDate/cellIsAllDay info in cell
|
5045 |
+
clearSelection();
|
5046 |
+
if (cell && cellIsAllDay(cell)) {
|
5047 |
+
dates = [ cellDate(origCell), cellDate(cell) ].sort(cmp);
|
5048 |
+
renderSelection(dates[0], dates[1], true);
|
5049 |
+
}else{
|
5050 |
+
dates = null;
|
5051 |
+
}
|
5052 |
+
}, ev);
|
5053 |
+
$(document).one('mouseup', function(ev) {
|
5054 |
+
hoverListener.stop();
|
5055 |
+
if (dates) {
|
5056 |
+
if (+dates[0] == +dates[1]) {
|
5057 |
+
reportDayClick(dates[0], true, ev);
|
5058 |
+
}
|
5059 |
+
reportSelection(dates[0], dates[1], true, ev);
|
5060 |
+
}
|
5061 |
+
});
|
5062 |
+
}
|
5063 |
+
}
|
5064 |
+
|
5065 |
+
|
5066 |
+
}
|
5067 |
+
|
5068 |
+
function OverlayManager() {
|
5069 |
+
var t = this;
|
5070 |
+
|
5071 |
+
|
5072 |
+
// exports
|
5073 |
+
t.renderOverlay = renderOverlay;
|
5074 |
+
t.clearOverlays = clearOverlays;
|
5075 |
+
|
5076 |
+
|
5077 |
+
// locals
|
5078 |
+
var usedOverlays = [];
|
5079 |
+
var unusedOverlays = [];
|
5080 |
+
|
5081 |
+
|
5082 |
+
function renderOverlay(rect, parent) {
|
5083 |
+
var e = unusedOverlays.shift();
|
5084 |
+
if (!e) {
|
5085 |
+
e = $("<div class='fc-cell-overlay' style='position:absolute;z-index:3'/>");
|
5086 |
+
}
|
5087 |
+
if (e[0].parentNode != parent[0]) {
|
5088 |
+
e.appendTo(parent);
|
5089 |
+
}
|
5090 |
+
usedOverlays.push(e.css(rect).show());
|
5091 |
+
return e;
|
5092 |
+
}
|
5093 |
+
|
5094 |
+
|
5095 |
+
function clearOverlays() {
|
5096 |
+
var e;
|
5097 |
+
while (e = usedOverlays.shift()) {
|
5098 |
+
unusedOverlays.push(e.hide().unbind());
|
5099 |
+
}
|
5100 |
+
}
|
5101 |
+
|
5102 |
+
|
5103 |
+
}
|
5104 |
+
|
5105 |
+
function CoordinateGrid(buildFunc) {
|
5106 |
+
|
5107 |
+
var t = this;
|
5108 |
+
var rows;
|
5109 |
+
var cols;
|
5110 |
+
|
5111 |
+
|
5112 |
+
t.build = function() {
|
5113 |
+
rows = [];
|
5114 |
+
cols = [];
|
5115 |
+
buildFunc(rows, cols);
|
5116 |
+
};
|
5117 |
+
|
5118 |
+
|
5119 |
+
t.cell = function(x, y) {
|
5120 |
+
var rowCnt = rows.length;
|
5121 |
+
var colCnt = cols.length;
|
5122 |
+
var i, r=-1, c=-1;
|
5123 |
+
for (i=0; i<rowCnt; i++) {
|
5124 |
+
if (y >= rows[i][0] && y < rows[i][1]) {
|
5125 |
+
r = i;
|
5126 |
+
break;
|
5127 |
+
}
|
5128 |
+
}
|
5129 |
+
for (i=0; i<colCnt; i++) {
|
5130 |
+
if (x >= cols[i][0] && x < cols[i][1]) {
|
5131 |
+
c = i;
|
5132 |
+
break;
|
5133 |
+
}
|
5134 |
+
}
|
5135 |
+
return (r>=0 && c>=0) ? { row:r, col:c } : null;
|
5136 |
+
};
|
5137 |
+
|
5138 |
+
|
5139 |
+
t.rect = function(row0, col0, row1, col1, originElement) { // row1,col1 is inclusive
|
5140 |
+
var origin = originElement.offset();
|
5141 |
+
return {
|
5142 |
+
top: rows[row0][0] - origin.top,
|
5143 |
+
left: cols[col0][0] - origin.left,
|
5144 |
+
width: cols[col1][1] - cols[col0][0],
|
5145 |
+
height: rows[row1][1] - rows[row0][0]
|
5146 |
+
};
|
5147 |
+
};
|
5148 |
+
|
5149 |
+
}
|
5150 |
+
|
5151 |
+
function HoverListener(coordinateGrid) {
|
5152 |
+
|
5153 |
+
|
5154 |
+
var t = this;
|
5155 |
+
var bindType;
|
5156 |
+
var change;
|
5157 |
+
var firstCell;
|
5158 |
+
var cell;
|
5159 |
+
|
5160 |
+
|
5161 |
+
t.start = function(_change, ev, _bindType) {
|
5162 |
+
change = _change;
|
5163 |
+
firstCell = cell = null;
|
5164 |
+
coordinateGrid.build();
|
5165 |
+
mouse(ev);
|
5166 |
+
bindType = _bindType || 'mousemove';
|
5167 |
+
$(document).bind(bindType, mouse);
|
5168 |
+
};
|
5169 |
+
|
5170 |
+
|
5171 |
+
function mouse(ev) {
|
5172 |
+
_fixUIEvent(ev); // see below
|
5173 |
+
var newCell = coordinateGrid.cell(ev.pageX, ev.pageY);
|
5174 |
+
if (!newCell != !cell || newCell && (newCell.row != cell.row || newCell.col != cell.col)) {
|
5175 |
+
if (newCell) {
|
5176 |
+
if (!firstCell) {
|
5177 |
+
firstCell = newCell;
|
5178 |
+
}
|
5179 |
+
change(newCell, firstCell, newCell.row-firstCell.row, newCell.col-firstCell.col);
|
5180 |
+
}else{
|
5181 |
+
change(newCell, firstCell);
|
5182 |
+
}
|
5183 |
+
cell = newCell;
|
5184 |
+
}
|
5185 |
+
}
|
5186 |
+
|
5187 |
+
|
5188 |
+
t.stop = function() {
|
5189 |
+
$(document).unbind(bindType, mouse);
|
5190 |
+
return cell;
|
5191 |
+
};
|
5192 |
+
|
5193 |
+
|
5194 |
+
}
|
5195 |
+
|
5196 |
+
|
5197 |
+
|
5198 |
+
// this fix was only necessary for jQuery UI 1.8.16 (and jQuery 1.7 or 1.7.1)
|
5199 |
+
// upgrading to jQuery UI 1.8.17 (and using either jQuery 1.7 or 1.7.1) fixed the problem
|
5200 |
+
// but keep this in here for 1.8.16 users
|
5201 |
+
// and maybe remove it down the line
|
5202 |
+
|
5203 |
+
function _fixUIEvent(event) { // for issue 1168
|
5204 |
+
if (event.pageX === undefined) {
|
5205 |
+
event.pageX = event.originalEvent.pageX;
|
5206 |
+
event.pageY = event.originalEvent.pageY;
|
5207 |
+
}
|
5208 |
+
}
|
5209 |
+
function HorizontalPositionCache(getElement) {
|
5210 |
+
|
5211 |
+
var t = this,
|
5212 |
+
elements = {},
|
5213 |
+
lefts = {},
|
5214 |
+
rights = {};
|
5215 |
+
|
5216 |
+
function e(i) {
|
5217 |
+
return elements[i] = elements[i] || getElement(i);
|
5218 |
+
}
|
5219 |
+
|
5220 |
+
t.left = function(i) {
|
5221 |
+
return lefts[i] = lefts[i] === undefined ? e(i).position().left : lefts[i];
|
5222 |
+
};
|
5223 |
+
|
5224 |
+
t.right = function(i) {
|
5225 |
+
return rights[i] = rights[i] === undefined ? t.left(i) + e(i).width() : rights[i];
|
5226 |
+
};
|
5227 |
+
|
5228 |
+
t.clear = function() {
|
5229 |
+
elements = {};
|
5230 |
+
lefts = {};
|
5231 |
+
rights = {};
|
5232 |
+
};
|
5233 |
+
|
5234 |
+
}
|
5235 |
+
|
5236 |
+
})(jQuery);
|
js/fullcalendar.min.js
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
- * NOTE: This is an edited version of the FullCalendar v1.5.4 (eventorganiser branch)
|
3 |
+
-*/
|
4 |
+
/*
|
5 |
+
|
6 |
+
FullCalendar v1.5.4
|
7 |
+
http://arshaw.com/fullcalendar/
|
8 |
+
|
9 |
+
Use fullcalendar.css for basic styling.
|
10 |
+
For event drag & drop, requires jQuery UI draggable.
|
11 |
+
For event resizing, requires jQuery UI resizable.
|
12 |
+
|
13 |
+
Copyright (c) 2011 Adam Shaw
|
14 |
+
Dual licensed under the MIT and GPL licenses, located in
|
15 |
+
MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
16 |
+
|
17 |
+
Date: Sat Nov 3 20:29:34 2012 +0000
|
18 |
+
|
19 |
+
*/
|
20 |
+
(function(l,na){function wb(a){l.extend(true,Ya,a)}function Yb(a,b,e){function d(k){if(E){u();o();la();T(k)}else f()}function f(){B=b.theme?"ui":"fc";a.addClass("fc");b.isRTL&&a.addClass("fc-rtl");b.theme&&a.addClass("ui-widget");E=l("<div class='fc-content' style='position:relative'/>").prependTo(a);C=new Zb(U,b);(Q=C.render())&&a.prepend(Q);y(b.defaultView);l(window).resize(oa);t()||g()}function g(){setTimeout(function(){!n.start&&t()&&T()},0)}function m(){l(window).unbind("resize",oa);C.destroy();
|
21 |
+
E.remove();a.removeClass("fc fc-rtl ui-widget")}function j(){return i.offsetWidth!==0}function t(){return l("body")[0].offsetWidth!==0}function y(k){if(!n||k!=n.name){F++;ra();var D=n,Z;if(D){(D.beforeHide||xb)();Za(E,E.height());D.element.hide()}else Za(E,1);E.css("overflow","hidden");if(n=Y[k])n.element.show();else n=Y[k]=new Ja[k](Z=s=l("<div class='fc-view fc-view-"+k+"' style='position:absolute'/>").appendTo(E),U);D&&C.deactivateButton(D.name);C.activateButton(k);T();E.css("overflow","");D&&
|
22 |
+
Za(E,1);Z||(n.afterShow||xb)();F--}}function T(k){if(j()){F++;ra();p===na&&u();var D=false;if(!n.start||k||r<n.start||r>=n.end){n.render(r,k||0);ea(true);D=true}else if(n.sizeDirty){n.clearEvents();ea();D=true}else if(n.eventsDirty){n.clearEvents();D=true}n.sizeDirty=false;n.eventsDirty=false;ga(D);X=a.outerWidth();C.updateTitle(n.title);k=new Date;k>=n.start&&k<n.end?C.disableButton("today"):C.enableButton("today");F--;n.trigger("viewDisplay",i)}}function R(){o();if(j()){u();ea();ra();n.clearEvents();
|
23 |
+
n.renderEvents(I);n.sizeDirty=false}}function o(){l.each(Y,function(k,D){D.sizeDirty=true})}function u(){p=b.contentHeight?b.contentHeight:b.height?b.height-(Q?Q.height():0)-Sa(E):Math.round(E.width()/Math.max(b.aspectRatio,0.5))}function ea(k){F++;n.setHeight(p,k);if(s){s.css("position","relative");s=null}n.setWidth(E.width(),k);F--}function oa(){if(!F)if(n.start){var k=++v;setTimeout(function(){if(k==v&&!F&&j())if(X!=(X=a.outerWidth())){F++;R();n.trigger("windowResize",i);F--}},200)}else g()}function ga(k){if(!b.lazyFetching||
|
24 |
+
ya(n.visStart,n.visEnd))pa();else k&&ca()}function pa(){J(n.visStart,n.visEnd,b)}function qa(k){I=k;ca()}function ha(k){ca(k)}function ca(k){la();if(j()){n.clearEvents();n.renderEvents(I,k);n.eventsDirty=false}}function la(){l.each(Y,function(k,D){D.eventsDirty=true})}function ua(k,D,Z){n.select(k,D,Z===na?true:Z)}function ra(){n&&n.unselect()}function V(){T(-1)}function da(){T(1)}function ka(){gb(r,-1);T()}function sa(){gb(r,1);T()}function G(){r=new Date;T()}function q(k,D,Z){if(k instanceof Date)r=
|
25 |
+
M(k);else yb(r,k,D,Z);T()}function K(k,D,Z){k!==na&&gb(r,k);D!==na&&hb(r,D);Z!==na&&ba(r,Z);T()}function c(){return M(r)}function z(){return n}function O(k,D){if(D===na)return b[k];if(k=="height"||k=="contentHeight"||k=="aspectRatio"){b[k]=D;R()}else{b[k]=D;ca()}}function N(k,D){if(b[k])return b[k].apply(D||i,Array.prototype.slice.call(arguments,2))}var U=this;U.options=b;U.render=d;U.destroy=m;U.refetchEvents=pa;U.reportEvents=qa;U.reportEventChange=ha;U.rerenderEvents=ca;U.changeView=y;U.select=
|
26 |
+
ua;U.unselect=ra;U.prev=V;U.next=da;U.prevYear=ka;U.nextYear=sa;U.today=G;U.gotoDate=q;U.incrementDate=K;U.formatDate=function(k,D){return Oa(k,D,b)};U.formatDates=function(k,D,Z){return ib(k,D,Z,b)};U.getDate=c;U.getView=z;U.option=O;U.trigger=N;$b.call(U,b,e);var ya=U.isFetchNeeded,J=U.fetchEvents,i=a[0],C,Q,E,B,n,Y={},X,p,s,v=0,F=0,r=new Date,I=[],L;yb(r,b.year,b.month,b.date);b.droppable&&l(document).bind("dragstart",function(k,D){var Z=k.target,ja=l(Z);if(!ja.parents(".fc").length){var ia=b.dropAccept;
|
27 |
+
if(l.isFunction(ia)?ia.call(Z,ja):ja.is(ia)){L=Z;n.dragStart(L,k,D)}}}).bind("dragstop",function(k,D){if(L){n.dragStop(L,k,D);L=null}})}function Zb(a,b){function e(){o=b.theme?"ui":"fc";if(b.header)return R=l("<table class='fc-header' style='width:100%'/>").append(l("<tr/>").append(f("left")).append(f("center")).append(f("right")))}function d(){R.remove()}function f(u){var ea=l("<td class='fc-header-"+u+"'/>");(u=b.header[u])&&l.each(u.split(" "),function(oa){oa>0&&ea.append("<span class='fc-header-space'/>");
|
28 |
+
var ga;l.each(this.split(","),function(pa,qa){if(qa=="title"){ea.append("<span class='fc-header-title'><h2> </h2></span>");ga&&ga.addClass(o+"-corner-right");ga=null}else if(l.isFunction(b.customButtons[qa])){pa=b.customButtons[qa](b);ea.append(pa)}else{var ha;if(a[qa])ha=a[qa];else if(Ja[qa])ha=function(){la.removeClass(o+"-state-hover");a.changeView(qa)};if(ha){pa=b.theme?jb(b.buttonIcons,qa):null;var ca=jb(b.buttonText,qa);if(b.buttonui){var la=l("<span class='fc-button fc-button-"+qa+" "+
|
29 |
+
o+"-state-default'>"+ca+"</span>");la.button()}else la=l("<span class='fc-button fc-button-"+qa+" "+o+"-state-default'><span class='fc-button-inner'><span class='fc-button-content'>"+(pa?"<span class='fc-icon-wrap'><span class='ui-icon ui-icon-"+pa+"'/></span>":ca)+"</span><span class='fc-button-effect'><span></span></span></span></span>");if(la){la.click(function(){la.hasClass(o+"-state-disabled")||ha()}).mousedown(function(){la.not("."+o+"-state-active").not("."+o+"-state-disabled").addClass(o+
|
30 |
+
"-state-down")}).mouseup(function(){la.removeClass(o+"-state-down")}).hover(function(){la.not("."+o+"-state-active").not("."+o+"-state-disabled").addClass(o+"-state-hover")},function(){la.removeClass(o+"-state-hover").removeClass(o+"-state-down")}).appendTo(ea);ga||la.addClass(o+"-corner-left");ga=la}}}});ga&&ga.addClass(o+"-corner-right")});return ea}function g(u){R.find("h2").html(u)}function m(u){R.find("span.fc-button-"+u).addClass(o+"-state-active")}function j(u){R.find("span.fc-button-"+u).removeClass(o+
|
31 |
+
"-state-active")}function t(u){R.find("span.fc-button-"+u).addClass(o+"-state-disabled")}function y(u){R.find("span.fc-button-"+u).removeClass(o+"-state-disabled")}var T=this;T.render=e;T.destroy=d;T.updateTitle=g;T.activateButton=m;T.deactivateButton=j;T.disableButton=t;T.enableButton=y;var R=l([]),o}function $b(a,b){function e(c,z){return!da||c<da||z>ka}function d(c,z,O){da=c;ka=z;K=[];c=++sa;G=z=V.length;for(var N=0;N<z;N++)f(V[N],c,O)}function f(c,z,O){g(c,function(N){if(z==sa){if(N){for(var U=
|
32 |
+
0;U<N.length;U++){N[U].source=c;oa(N[U])}K=K.concat(N)}G--;G||ua(K)}},O)}function g(c,z){var O,N=Aa.sourceFetchers,U;for(O=0;O<N.length;O++){U=N[O](c,da,ka,z);if(U===true)return;else if(typeof U=="object"){g(U,z,a);return}}if(O=c.events)if(l.isFunction(O)){u();O(M(da),M(ka),function(C){z(C);ea()},a)}else l.isArray(O)?z(O):z();else if(c.url){var ya=c.success,J=c.error,i=c.complete;O=l.extend({},c.data||{});N=Ta(c.startParam,a.startParam);U=Ta(c.endParam,a.endParam);if(N)O[N]=Math.round(+da/1E3);if(U)O[U]=
|
33 |
+
Math.round(+ka/1E3);u();l.ajax(l.extend({},ac,c,{data:O,success:function(C){C=C||[];var Q=$a(ya,this,arguments);if(l.isArray(Q))C=Q;z(C)},error:function(){$a(J,this,arguments);z()},complete:function(){$a(i,this,arguments);ea()}}))}else z()}function m(c){if(c=j(c)){G++;f(c,sa)}}function j(c){if(l.isFunction(c)||l.isArray(c))c={events:c};else if(typeof c=="string")c={url:c};if(typeof c=="object"){ga(c);V.push(c);return c}}function t(c){V=l.grep(V,function(z){return!pa(z,c)});K=l.grep(K,function(z){return!pa(z.source,
|
34 |
+
c)});ua(K)}function y(c){var z,O=K.length,N,U=la().defaultEventEnd,ya=c.start-c._start,J=c.end?c.end-(c._end||U(c)):0;for(z=0;z<O;z++){N=K[z];if(N._id==c._id&&N!=c){N.start=new Date(+N.start+ya);N.end=c.end?N.end?new Date(+N.end+J):new Date(+U(N)+J):null;N.title=c.title;N.url=c.url;N.allDay=c.allDay;N.className=c.className;N.editable=c.editable;N.color=c.color;N.backgroudColor=c.backgroudColor;N.borderColor=c.borderColor;N.textColor=c.textColor;oa(N)}}oa(c);ua(K)}function T(c,z){oa(c);if(!c.source){if(z){ra.events.push(c);
|
35 |
+
c.source=ra}K.push(c)}ua(K)}function R(c){if(c){if(!l.isFunction(c)){var z=c+"";c=function(N){return N._id==z}}K=l.grep(K,c,true);for(O=0;O<V.length;O++)if(l.isArray(V[O].events))V[O].events=l.grep(V[O].events,c,true)}else{K=[];for(var O=0;O<V.length;O++)if(l.isArray(V[O].events))V[O].events=[]}ua(K)}function o(c){if(l.isFunction(c))return l.grep(K,c);else if(c){c+="";return l.grep(K,function(z){return z._id==c})}return K}function u(){q++||ca("loading",null,true)}function ea(){--q||ca("loading",null,
|
36 |
+
false)}function oa(c){var z=c.source||{},O=Ta(z.ignoreTimezone,a.ignoreTimezone);c._id=c._id||(c.id===na?"_fc"+bc++:c.id+"");if(c.date){if(!c.start)c.start=c.date;delete c.date}c._start=M(c.start=kb(c.start,O));c.end=kb(c.end,O);if(c.end&&c.end<=c.start)c.end=null;c._end=c.end?M(c.end):null;if(c.allDay===na)c.allDay=Ta(z.allDayDefault,a.allDayDefault);if(c.className){if(typeof c.className=="string")c.className=c.className.split(/\s+/)}else c.className=[]}function ga(c){if(c.className){if(typeof c.className==
|
37 |
+
"string")c.className=c.className.split(/\s+/)}else c.className=[];for(var z=Aa.sourceNormalizers,O=0;O<z.length;O++)z[O](c)}function pa(c,z){return c&&z&&qa(c)==qa(z)}function qa(c){return(typeof c=="object"?c.events||c.url:"")||c}var ha=this;ha.isFetchNeeded=e;ha.fetchEvents=d;ha.addEventSource=m;ha.removeEventSource=t;ha.updateEvent=y;ha.renderEvent=T;ha.removeEvents=R;ha.clientEvents=o;ha.normalizeEvent=oa;var ca=ha.trigger,la=ha.getView,ua=ha.reportEvents,ra={events:[]},V=[ra],da,ka,sa=0,G=0,
|
38 |
+
q=0,K=[];for(ha=0;ha<b.length;ha++)j(b[ha])}function gb(a,b,e){a.setFullYear(a.getFullYear()+b);e||Ka(a);return a}function hb(a,b,e){if(+a){b=a.getMonth()+b;var d=M(a);d.setDate(1);d.setMonth(b);a.setMonth(b);for(e||Ka(a);a.getMonth()!=d.getMonth();)a.setDate(a.getDate()+(a<d?1:-1))}return a}function ba(a,b,e){if(+a){b=a.getDate()+b;var d=M(a);d.setHours(9);d.setDate(b);a.setDate(b);e||Ka(a);lb(a,d)}return a}function lb(a,b){if(+a)for(;a.getDate()!=b.getDate();)a.setTime(+a+(a<b?1:-1)*cc)}function xa(a,
|
39 |
+
b){a.setMinutes(a.getMinutes()+b);return a}function Ka(a){a.setHours(0);a.setMinutes(0);a.setSeconds(0);a.setMilliseconds(0);return a}function M(a,b){if(b)return Ka(new Date(+a));return new Date(+a)}function zb(){var a=0,b;do b=new Date(1970,a++,1);while(b.getHours());return b}function Fa(a,b,e){for(b=b||1;!a.getDay()||e&&a.getDay()==1||!e&&a.getDay()==6;)ba(a,b);return a}function Ca(a,b){return Math.round((M(a,true)-M(b,true))/Ab)}function yb(a,b,e,d){if(b!==na&&b!=a.getFullYear()){a.setDate(1);
|
40 |
+
a.setMonth(0);a.setFullYear(b)}if(e!==na&&e!=a.getMonth()){a.setDate(1);a.setMonth(e)}d!==na&&a.setDate(d)}function kb(a,b){if(typeof a=="object")return a;if(typeof a=="number")return new Date(a*1E3);if(typeof a=="string"){if(a.match(/^\d+(\.\d+)?$/))return new Date(parseFloat(a)*1E3);if(b===na)b=true;return Bb(a,b)||(a?new Date(a):null)}return null}function Bb(a,b){a=a.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/);
|
41 |
+
if(!a)return null;var e=new Date(a[1],0,1);if(b||!a[13]){b=new Date(a[1],0,1,9,0);if(a[3]){e.setMonth(a[3]-1);b.setMonth(a[3]-1)}if(a[5]){e.setDate(a[5]);b.setDate(a[5])}lb(e,b);a[7]&&e.setHours(a[7]);a[8]&&e.setMinutes(a[8]);a[10]&&e.setSeconds(a[10]);a[12]&&e.setMilliseconds(Number("0."+a[12])*1E3);lb(e,b)}else{e.setUTCFullYear(a[1],a[3]?a[3]-1:0,a[5]||1);e.setUTCHours(a[7]||0,a[8]||0,a[10]||0,a[12]?Number("0."+a[12])*1E3:0);if(a[14]){b=Number(a[16])*60+(a[18]?Number(a[18]):0);b*=a[15]=="-"?1:-1;
|
42 |
+
e=new Date(+e+b*60*1E3)}}return e}function mb(a){if(typeof a=="number")return a*60;if(typeof a=="object")return a.getHours()*60+a.getMinutes();if(a=a.match(/(\d+)(?::(\d+))?\s*(\w+)?/)){var b=parseInt(a[1],10);if(a[3]){b%=12;if(a[3].toLowerCase().charAt(0)=="p")b+=12}return b*60+(a[2]?parseInt(a[2],10):0)}}function Oa(a,b,e){return ib(a,null,b,e)}function ib(a,b,e,d){d=d||Ya;var f=a,g=b,m,j=e.length,t,y,T,R="";for(m=0;m<j;m++){t=e.charAt(m);if(t=="'")for(y=m+1;y<j;y++){if(e.charAt(y)=="'"){if(f){R+=
|
43 |
+
y==m+1?"'":e.substring(m+1,y);m=y}break}}else if(t=="(")for(y=m+1;y<j;y++){if(e.charAt(y)==")"){m=Oa(f,e.substring(m+1,y),d);if(parseInt(m.replace(/\D/,""),10))R+=m;m=y;break}}else if(t=="[")for(y=m+1;y<j;y++){if(e.charAt(y)=="]"){t=e.substring(m+1,y);m=Oa(f,t,d);if(m!=Oa(g,t,d))R+=m;m=y;break}}else if(t=="{"){f=b;g=a}else if(t=="}"){f=a;g=b}else{for(y=j;y>m;y--)if(T=dc[e.substring(m,y)]){if(f)R+=T(f,d);m=y-1;break}if(y==m)if(f)R+=t}}return R}function Ua(a){return a.end?ec(a.end,a.allDay):ba(M(a.start),
|
44 |
+
1)}function ec(a,b){a=M(a);return b||a.getHours()||a.getMinutes()?ba(a,1):Ka(a)}function fc(a,b){return(b.msLength-a.msLength)*100+(a.event.start-b.event.start)}function Cb(a,b){return a.end>b.start&&a.start<b.end}function nb(a,b,e,d){var f=[],g,m=a.length,j,t,y,T,R;for(g=0;g<m;g++){j=a[g];t=j.start;y=b[g];if(y>e&&t<d){if(t<e){t=M(e);T=false}else{t=t;T=true}if(y>d){y=M(d);R=false}else{y=y;R=true}f.push({event:j,start:t,end:y,isStart:T,isEnd:R,msLength:y-t})}}return f.sort(fc)}function ob(a){var b=
|
45 |
+
[],e,d=a.length,f,g,m,j;for(e=0;e<d;e++){f=a[e];for(g=0;;){m=false;if(b[g])for(j=0;j<b[g].length;j++)if(Cb(b[g][j],f)){m=true;break}if(m)g++;else break}if(b[g])b[g].push(f);else b[g]=[f]}return b}function Db(a,b,e){a.unbind("mouseover").mouseover(function(d){for(var f=d.target,g;f!=this;){g=f;f=f.parentNode}if((f=g._fci)!==na){g._fci=na;g=b[f];e(g.event,g.element,g);l(d.target).trigger(d)}d.stopPropagation()})}function Va(a,b,e){for(var d=0,f;d<a.length;d++){f=l(a[d]);f.width(Math.max(0,b-pb(f,e)))}}
|
46 |
+
function Eb(a,b,e){for(var d=0,f;d<a.length;d++){f=l(a[d]);f.height(Math.max(0,b-Sa(f,e)))}}function pb(a,b){return gc(a)+hc(a)+(b?ic(a):0)}function gc(a){return(parseFloat(l.css(a[0],"paddingLeft",true))||0)+(parseFloat(l.css(a[0],"paddingRight",true))||0)}function ic(a){return(parseFloat(l.css(a[0],"marginLeft",true))||0)+(parseFloat(l.css(a[0],"marginRight",true))||0)}function hc(a){return(parseFloat(l.css(a[0],"borderLeftWidth",true))||0)+(parseFloat(l.css(a[0],"borderRightWidth",true))||0)}function Sa(a,
|
47 |
+
b){return jc(a)+kc(a)+(b?Fb(a):0)}function jc(a){return(parseFloat(l.css(a[0],"paddingTop",true))||0)+(parseFloat(l.css(a[0],"paddingBottom",true))||0)}function Fb(a){return(parseFloat(l.css(a[0],"marginTop",true))||0)+(parseFloat(l.css(a[0],"marginBottom",true))||0)}function kc(a){return(parseFloat(l.css(a[0],"borderTopWidth",true))||0)+(parseFloat(l.css(a[0],"borderBottomWidth",true))||0)}function Za(a,b){b=typeof b=="number"?b+"px":b;a.each(function(e,d){d.style.cssText+=";min-height:"+b+";_height:"+
|
48 |
+
b})}function xb(){}function Gb(a,b){return a-b}function Hb(a){return Math.max.apply(Math,a)}function Pa(a){return(a<10?"0":"")+a}function jb(a,b){if(a[b]!==na)return a[b];b=b.split(/(?=[A-Z])/);for(var e=b.length-1,d;e>=0;e--){d=a[b[e].toLowerCase()];if(d!==na)return d}return a[""]}function Qa(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"<br />")}function Ib(a){return a.id+"/"+a.className+"/"+a.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig,
|
49 |
+
"")}function qb(a){a.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})}function ab(a){a.children().removeClass("fc-first fc-last").filter(":first-child").addClass("fc-first").end().filter(":last-child").addClass("fc-last")}function rb(a,b){a.each(function(e,d){d.className=d.className.replace(/^fc-\w*/,"fc-"+lc[b.getDay()])})}function Jb(a,b){var e=a.source||{},d=a.color,f=e.color,g=b("eventColor"),m=a.backgroundColor||d||e.backgroundColor||f||b("eventBackgroundColor")||
|
50 |
+
g;d=a.borderColor||d||e.borderColor||f||b("eventBorderColor")||g;a=a.textColor||e.textColor||b("eventTextColor");b=[];m&&b.push("background-color:"+m);d&&b.push("border-color:"+d);a&&b.push("color:"+a);return b.join(";")}function $a(a,b,e){if(l.isFunction(a))a=[a];if(a){var d,f;for(d=0;d<a.length;d++)f=a[d].apply(b,e)||f;return f}}function Ta(){for(var a=0;a<arguments.length;a++)if(arguments[a]!==na)return arguments[a]}function mc(a,b){function e(j,t){if(t){hb(j,t);j.setDate(1)}j=M(j,true);j.setDate(1);
|
51 |
+
t=hb(M(j),1);var y=M(j),T=M(t),R=f("firstDay"),o=f("weekends")?0:1;if(o){Fa(y);Fa(T,-1,true)}ba(y,-((y.getDay()-Math.max(R,o)+7)%7));ba(T,(7-T.getDay()+Math.max(R,o))%7);R=Math.round((T-y)/(Ab*7));if(f("weekMode")=="fixed"){ba(T,(6-R)*7);R=6}d.title=m(j,f("titleFormat"));d.start=j;d.end=t;d.visStart=y;d.visEnd=T;g(6,R,o?5:7,true)}var d=this;d.render=e;sb.call(d,a,b,"month");var f=d.opt,g=d.renderBasic,m=b.formatDate}function nc(a,b){function e(j,t){t&&ba(j,t*7);j=ba(M(j),-((j.getDay()-f("firstDay")+
|
52 |
+
7)%7));t=ba(M(j),7);var y=M(j),T=M(t),R=f("weekends");if(!R){Fa(y);Fa(T,-1,true)}d.title=m(y,ba(M(T),-1),f("titleFormat"));d.start=j;d.end=t;d.visStart=y;d.visEnd=T;g(1,1,R?7:5,false)}var d=this;d.render=e;sb.call(d,a,b,"basicWeek");var f=d.opt,g=d.renderBasic,m=b.formatDates}function oc(a,b){function e(j,t){if(t){ba(j,t);f("weekends")||Fa(j,t<0?-1:1)}d.title=m(j,f("titleFormat"));d.start=d.visStart=M(j,true);d.end=d.visEnd=ba(M(d.start),1);g(1,1,1,false)}var d=this;d.render=e;sb.call(d,a,b,"basicDay");
|
53 |
+
var f=d.opt,g=d.renderBasic,m=b.formatDate}function sb(a,b,e){function d(w,H,S,W){v=H;F=S;f();(H=!C)?g(w,W):z();m(H)}function f(){if(k=K("isRTL")){D=-1;Z=F-1}else{D=1;Z=0}ja=K("firstDay");ia=K("weekends")?0:1;ma=K("theme")?"ui":"fc";$=K("columnFormat")}function g(w,H){var S,W=ma+"-widget-header",fa=ma+"-widget-content",aa;S="<table class='fc-border-separate' style='width:100%' cellspacing='0'><thead><tr>";for(aa=0;aa<F;aa++)S+="<th class='fc- "+W+"'/>";S+="</tr></thead><tbody>";for(aa=0;aa<w;aa++){S+=
|
54 |
+
"<tr class='fc-week"+aa+"'>";for(W=0;W<F;W++)S+="<td class='fc- "+fa+" fc-day"+(aa*F+W)+"'><div>"+(H?"<div class='fc-day-number'/>":"")+"<div class='fc-day-content'><div style='position:relative'> </div></div></div></td>";S+="</tr>"}S+="</tbody></table>";w=l(S).appendTo(a);J=w.find("thead");i=J.find("th");C=w.find("tbody");Q=C.find("tr");E=C.find("td");B=E.filter(":first-child");n=Q.eq(0).find("div.fc-day-content div");ab(J.add(J.find("tr")));ab(Q);Q.eq(0).addClass("fc-first");y(E);Y=l("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(a)}
|
55 |
+
function m(w){var H=w||v==1,S=q.start.getMonth(),W=Ka(new Date),fa,aa,va;H&&i.each(function(wa,Ga){fa=l(Ga);aa=da(wa);fa.html(ya(aa,$));rb(fa,aa)});E.each(function(wa,Ga){fa=l(Ga);aa=da(wa);aa.getMonth()==S?fa.removeClass("fc-other-month"):fa.addClass("fc-other-month");+aa==+W?fa.addClass(ma+"-state-highlight fc-today"):fa.removeClass(ma+"-state-highlight fc-today");fa.find("div.fc-day-number").text(aa.getDate());H&&rb(fa,aa)});Q.each(function(wa,Ga){va=l(Ga);if(wa<v){va.show();wa==v-1?va.addClass("fc-last"):
|
56 |
+
va.removeClass("fc-last")}else va.hide()})}function j(w){p=w;w=p-J.height();var H,S,W;if(K("weekMode")=="variable")H=S=Math.floor(w/(v==1?2:6));else{H=Math.floor(w/v);S=w-H*(v-1)}B.each(function(fa,aa){if(fa<v){W=l(aa);Za(W.find("> div"),(fa==v-1?S:H)-Sa(W))}})}function t(w){X=w;L.clear();s=Math.floor(X/F);Va(i.slice(0,-1),s)}function y(w){w.click(T).mousedown(U)}function T(w){if(!K("selectable")){var H=parseInt(this.className.match(/fc\-day(\d+)/)[1]);H=da(H);c("dayClick",this,H,true,w)}}function R(w,
|
57 |
+
H,S){S&&r.build();S=M(q.visStart);for(var W=ba(M(S),F),fa=0;fa<v;fa++){var aa=new Date(Math.max(S,w)),va=new Date(Math.min(W,H));if(aa<va){var wa;if(k){wa=Ca(va,S)*D+Z+1;aa=Ca(aa,S)*D+Z+1}else{wa=Ca(aa,S);aa=Ca(va,S)}y(o(fa,wa,fa,aa-1))}ba(S,7);ba(W,7)}}function o(w,H,S,W){w=r.rect(w,H,S,W,a);return O(w,a)}function u(w){return M(w)}function ea(w,H){R(w,ba(M(H),1),true)}function oa(){N()}function ga(w,H,S){var W=ua(w);c("dayClick",E[W.row*F+W.col],w,H,S)}function pa(w,H){I.start(function(S){N();S&&
|
58 |
+
o(S.row,S.col,S.row,S.col)},H)}function qa(w,H,S){var W=I.stop();N();if(W){W=ra(W);c("drop",w,W,true,H,S)}}function ha(w){return M(w.start)}function ca(w){return L.left(w)}function la(w){return L.right(w)}function ua(w){return{row:Math.floor(Ca(w,q.visStart)/7),col:ka(w.getDay())}}function ra(w){return V(w.row,w.col)}function V(w,H){return ba(M(q.visStart),w*7+H*D+Z)}function da(w){return V(Math.floor(w/F),w%F)}function ka(w){return(w-Math.max(ja,ia)+F)%F*D+Z}function sa(w){return Q.eq(w)}function G(){return{left:0,
|
59 |
+
right:X}}var q=this;q.renderBasic=d;q.setHeight=j;q.setWidth=t;q.renderDayOverlay=R;q.defaultSelectionEnd=u;q.renderSelection=ea;q.clearSelection=oa;q.reportDayClick=ga;q.dragStart=pa;q.dragStop=qa;q.defaultEventEnd=ha;q.getHoverListener=function(){return I};q.colContentLeft=ca;q.colContentRight=la;q.dayOfWeekCol=ka;q.dateCell=ua;q.cellDate=ra;q.cellIsAllDay=function(){return true};q.allDayRow=sa;q.allDayBounds=G;q.getRowCnt=function(){return v};q.getColCnt=function(){return F};q.getColWidth=function(){return s};
|
60 |
+
q.getDaySegmentContainer=function(){return Y};Kb.call(q,a,b,e);Lb.call(q);Mb.call(q);pc.call(q);var K=q.opt,c=q.trigger,z=q.clearEvents,O=q.renderOverlay,N=q.clearOverlays,U=q.daySelectionMousedown,ya=b.formatDate,J,i,C,Q,E,B,n,Y,X,p,s,v,F,r,I,L,k,D,Z,ja,ia,ma,$;qb(a.addClass("fc-grid"));r=new Nb(function(w,H){var S,W,fa;i.each(function(aa,va){S=l(va);W=S.offset().left;if(aa)fa[1]=W;fa=[W];H[aa]=fa});fa[1]=W+S.outerWidth();Q.each(function(aa,va){if(aa<v){S=l(va);W=S.offset().top;if(aa)fa[1]=W;fa=
|
61 |
+
[W];w[aa]=fa}});fa[1]=W+S.outerHeight()});I=new Ob(r);L=new Pb(function(w){return n.eq(w)})}function pc(){function a(V,da){T(V);ua(e(V),da)}function b(){R();ga().empty()}function e(V){var da=ca(),ka=la(),sa=M(g.visStart);ka=ba(M(sa),ka);var G=l.map(V,Ua),q,K,c,z,O,N,U=[];for(q=0;q<da;q++){K=ob(nb(V,G,sa,ka));for(c=0;c<K.length;c++){z=K[c];for(O=0;O<z.length;O++){N=z[O];N.row=q;N.level=c;U.push(N)}}ba(sa,7);ba(ka,7)}return U}function d(V,da,ka){t(V)&&f(V,da);ka.isEnd&&y(V)&&ra(V,da,ka);o(V,da)}function f(V,
|
62 |
+
da){var ka=pa(),sa;da.draggable({zIndex:9,delay:50,opacity:m("dragOpacity"),revertDuration:m("dragRevertDuration"),start:function(G,q){j("eventDragStart",da,V,G,q);ea(V,da);ka.start(function(K,c,z,O){da.draggable("option","revert",!K||!z&&!O);ha();if(K){sa=z*7+O*(m("isRTL")?-1:1);qa(ba(M(V.start),sa),ba(Ua(V),sa))}else sa=0},G,"drag")},stop:function(G,q){ka.stop();ha();j("eventDragStop",da,V,G,q);if(sa)oa(this,V,sa,0,V.allDay,G,q);else{da.css("filter","");u(V,da)}}})}var g=this;g.renderEvents=a;g.compileDaySegs=
|
63 |
+
e;g.clearEvents=b;g.bindDaySeg=d;Qb.call(g);var m=g.opt,j=g.trigger,t=g.isEventDraggable,y=g.isEventResizable,T=g.reportEvents,R=g.reportEventClear,o=g.eventElementHandlers,u=g.showEvents,ea=g.hideEvents,oa=g.eventDrop,ga=g.getDaySegmentContainer,pa=g.getHoverListener,qa=g.renderDayOverlay,ha=g.clearOverlays,ca=g.getRowCnt,la=g.getColCnt,ua=g.renderDaySegs,ra=g.resizableDayEvent}function qc(a,b){function e(j,t){t&&ba(j,t*7);j=ba(M(j),-((j.getDay()-f("firstDay")+7)%7));t=ba(M(j),7);var y=M(j),T=M(t),
|
64 |
+
R=f("weekends");if(!R){Fa(y);Fa(T,-1,true)}d.title=m(y,ba(M(T),-1),f("titleFormat"));d.start=j;d.end=t;d.visStart=y;d.visEnd=T;g(R?7:5)}var d=this;d.render=e;Rb.call(d,a,b,"agendaWeek");var f=d.opt,g=d.renderAgenda,m=b.formatDates}function rc(a,b){function e(j,t){if(t){ba(j,t);f("weekends")||Fa(j,t<0?-1:1)}t=M(j,true);var y=ba(M(t),1);d.title=m(j,f("titleFormat"));d.start=d.visStart=t;d.end=d.visEnd=y;g(1)}var d=this;d.render=e;Rb.call(d,a,b,"agendaDay");var f=d.opt,g=d.renderAgenda,m=b.formatDate}
|
65 |
+
function Rb(a,b,e){function d(h){Ba=h;f();v?Q():g();m()}function f(){Wa=i("theme")?"ui":"fc";Sb=i("weekends")?0:1;Tb=i("firstDay");if(Ub=i("isRTL")){Ha=-1;Ia=Ba-1}else{Ha=1;Ia=0}La=mb(i("minTime"));bb=mb(i("maxTime"));Vb=i("columnFormat")}function g(){var h=Wa+"-widget-header",P=Wa+"-widget-content",x,A,ta,za,Da,Ea=i("slotMinutes")%15==0;x="<table style='width:100%' class='fc-agenda-days fc-border-separate' cellspacing='0'><thead><tr><th class='fc-agenda-axis "+h+"'> </th>";for(A=0;A<Ba;A++)x+=
|
66 |
+
"<th class='fc- fc-col"+A+" "+h+"'/>";x+="<th class='fc-agenda-gutter "+h+"'> </th></tr></thead><tbody><tr><th class='fc-agenda-axis "+h+"'> </th>";for(A=0;A<Ba;A++)x+="<td class='fc- fc-col"+A+" "+P+"'><div><div class='fc-day-content'><div style='position:relative'> </div></div></div></td>";x+="<td class='fc-agenda-gutter "+P+"'> </td></tr></tbody></table>";v=l(x).appendTo(a);F=v.find("thead");r=F.find("th").slice(1,-1);I=v.find("tbody");L=I.find("td").slice(0,-1);k=L.find("div.fc-day-content div");
|
67 |
+
D=L.eq(0);Z=D.find("> div");ab(F.add(F.find("tr")));ab(I.add(I.find("tr")));aa=F.find("th:first");va=v.find(".fc-agenda-gutter");ja=l("<div style='position:absolute;z-index:2;left:0;width:100%'/>").appendTo(a);if(i("allDaySlot")){ia=l("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(ja);x="<table style='width:100%' class='fc-agenda-allday' cellspacing='0'><tr><th class='"+h+" fc-agenda-axis'>"+i("allDayText")+"</th><td><div class='fc-day-content'><div style='position:relative'/></div></td><th class='"+
|
68 |
+
h+" fc-agenda-gutter'> </th></tr></table>";ma=l(x).appendTo(ja);$=ma.find("tr");o($.find("td"));aa=aa.add(ma.find("th:first"));va=va.add(ma.find("th.fc-agenda-gutter"));ja.append("<div class='fc-agenda-divider "+h+"'><div class='fc-agenda-divider-inner'/></div>")}else ia=l([]);w=l("<div style='position:absolute;width:100%;overflow-x:hidden;overflow-y:auto'/>").appendTo(ja);H=l("<div style='position:relative;width:100%;overflow:hidden'/>").appendTo(w);S=l("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(H);
|
69 |
+
x="<table class='fc-agenda-slots' style='width:100%' cellspacing='0'><tbody>";ta=zb();za=xa(M(ta),bb);xa(ta,La);for(A=tb=0;ta<za;A++){Da=ta.getMinutes();x+="<tr class='fc-slot"+A+" "+(!Da?"":"fc-minor")+"'><th class='fc-agenda-axis "+h+"'>"+(!Ea||!Da?s(ta,i("axisFormat")):" ")+"</th><td class='"+P+"'><div style='position:relative'> </div></td></tr>";xa(ta,i("slotMinutes"));tb++}x+="</tbody></table>";W=l(x).appendTo(H);fa=W.find("div:first");u(W.find("td"));aa=aa.add(W.find("th:first"))}
|
70 |
+
function m(){var h,P,x,A,ta=Ka(new Date);for(h=0;h<Ba;h++){A=ua(h);P=r.eq(h);P.html(s(A,Vb));x=L.eq(h);+A==+ta?x.addClass(Wa+"-state-highlight fc-today"):x.removeClass(Wa+"-state-highlight fc-today");rb(P.add(x),A)}}function j(h,P){if(h===na)h=Wb;Wb=h;ub={};var x=I.position().top,A=w.position().top;h=Math.min(h-x,W.height()+A+1);Z.height(h-Sa(D));ja.css("top",x);w.height(h-A-1);Xa=fa.height()+1;P&&y()}function t(h){Ga=h;cb.clear();Ma=0;Va(aa.width("").each(function(P,x){Ma=Math.max(Ma,l(x).outerWidth())}),
|
71 |
+
Ma);h=w[0].clientWidth;if(vb=w.width()-h){Va(va,vb);va.show().prev().removeClass("fc-last")}else va.hide().prev().addClass("fc-last");db=Math.floor((h-Ma)/Ba);Va(r.slice(0,-1),db)}function y(){function h(){w.scrollTop(A)}var P=zb(),x=M(P);x.setHours(i("firstHour"));var A=da(P,x)+1;h();setTimeout(h,0)}function T(){Xb=w.scrollTop()}function R(){w.scrollTop(Xb)}function o(h){h.click(ea).mousedown(X)}function u(h){h.click(ea).mousedown(O)}function ea(h){if(!i("selectable")){var P=Math.min(Ba-1,Math.floor((h.pageX-
|
72 |
+
v.offset().left-Ma)/db)),x=ua(P),A=this.parentNode.className.match(/fc-slot(\d+)/);if(A){A=parseInt(A[1])*i("slotMinutes");var ta=Math.floor(A/60);x.setHours(ta);x.setMinutes(A%60+La);C("dayClick",L[P],x,false,h)}else C("dayClick",L[P],x,true,h)}}function oa(h,P,x){x&&Na.build();var A=M(J.visStart);if(Ub){x=Ca(P,A)*Ha+Ia+1;h=Ca(h,A)*Ha+Ia+1}else{x=Ca(h,A);h=Ca(P,A)}x=Math.max(0,x);h=Math.min(Ba,h);x<h&&o(ga(0,x,0,h-1))}function ga(h,P,x,A){h=Na.rect(h,P,x,A,ja);return E(h,ja)}function pa(h,P){for(var x=
|
73 |
+
M(J.visStart),A=ba(M(x),1),ta=0;ta<Ba;ta++){var za=new Date(Math.max(x,h)),Da=new Date(Math.min(A,P));if(za<Da){var Ea=ta*Ha+Ia;Ea=Na.rect(0,Ea,0,Ea,H);za=da(x,za);Da=da(x,Da);Ea.top=za;Ea.height=Da-za;u(E(Ea,H))}ba(x,1);ba(A,1)}}function qa(h){return cb.left(h)}function ha(h){return cb.right(h)}function ca(h){return{row:Math.floor(Ca(h,J.visStart)/7),col:V(h.getDay())}}function la(h){var P=ua(h.col);h=h.row;i("allDaySlot")&&h--;h>=0&&xa(P,La+h*i("slotMinutes"));return P}function ua(h){return ba(M(J.visStart),
|
74 |
+
h*Ha+Ia)}function ra(h){return i("allDaySlot")&&!h.row}function V(h){return(h-Math.max(Tb,Sb)+Ba)%Ba*Ha+Ia}function da(h,P){h=M(h,true);if(P<xa(M(h),La))return 0;if(P>=xa(M(h),bb))return W.height();h=i("slotMinutes");P=P.getHours()*60+P.getMinutes()-La;var x=Math.floor(P/h),A=ub[x];if(A===na)A=ub[x]=W.find("tr:eq("+x+") td div")[0].offsetTop;return Math.max(0,Math.round(A-1+Xa*(P%h/h)))}function ka(){return{left:Ma,right:Ga-vb}}function sa(){return $}function G(h){var P=M(h.start);if(h.allDay)return P;
|
75 |
+
return xa(P,i("defaultEventMinutes"))}function q(h,P){if(P)return M(h);return xa(M(h),i("slotMinutes"))}function K(h,P,x){if(x)i("allDaySlot")&&oa(h,ba(M(P),1),true);else c(h,P)}function c(h,P){var x=i("selectHelper");Na.build();if(x){var A=Ca(h,J.visStart)*Ha+Ia;if(A>=0&&A<Ba){A=Na.rect(0,A,0,A,H);var ta=da(h,h),za=da(h,P);if(za>ta){A.top=ta;A.height=za-ta;A.left+=2;A.width-=5;if(l.isFunction(x)){if(h=x(h,P)){A.position="absolute";A.zIndex=8;wa=l(h).css(A).appendTo(H)}}else{A.isStart=true;A.isEnd=
|
76 |
+
true;wa=l(p({title:"",start:h,end:P,className:["fc-select-helper"],editable:false},A));wa.css("opacity",i("dragOpacity"))}if(wa){u(wa);H.append(wa);Va(wa,A.width,true);Eb(wa,A.height,true)}}}}else pa(h,P)}function z(){B();if(wa){wa.remove();wa=null}}function O(h){if(h.which==1&&i("selectable")){Y(h);var P;Ra.start(function(x,A){z();if(x&&x.col==A.col&&!ra(x)){A=la(A);x=la(x);P=[A,xa(M(A),i("slotMinutes")),x,xa(M(x),i("slotMinutes"))].sort(Gb);c(P[0],P[3])}else P=null},h);l(document).one("mouseup",
|
77 |
+
function(x){Ra.stop();if(P){+P[0]==+P[1]&&N(P[0],false,x);n(P[0],P[3],false,x)}})}}function N(h,P,x){C("dayClick",L[V(h.getDay())],h,P,x)}function U(h,P){Ra.start(function(x){B();if(x)if(ra(x))ga(x.row,x.col,x.row,x.col);else{x=la(x);var A=xa(M(x),i("defaultEventMinutes"));pa(x,A)}},P)}function ya(h,P,x){var A=Ra.stop();B();A&&C("drop",h,la(A),ra(A),P,x)}var J=this;J.renderAgenda=d;J.setWidth=t;J.setHeight=j;J.beforeHide=T;J.afterShow=R;J.defaultEventEnd=G;J.timePosition=da;J.dayOfWeekCol=V;J.dateCell=
|
78 |
+
ca;J.cellDate=la;J.cellIsAllDay=ra;J.allDayRow=sa;J.allDayBounds=ka;J.getHoverListener=function(){return Ra};J.colContentLeft=qa;J.colContentRight=ha;J.getDaySegmentContainer=function(){return ia};J.getSlotSegmentContainer=function(){return S};J.getMinMinute=function(){return La};J.getMaxMinute=function(){return bb};J.getBodyContent=function(){return H};J.getRowCnt=function(){return 1};J.getColCnt=function(){return Ba};J.getColWidth=function(){return db};J.getSlotHeight=function(){return Xa};J.defaultSelectionEnd=
|
79 |
+
q;J.renderDayOverlay=oa;J.renderSelection=K;J.clearSelection=z;J.reportDayClick=N;J.dragStart=U;J.dragStop=ya;Kb.call(J,a,b,e);Lb.call(J);Mb.call(J);sc.call(J);var i=J.opt,C=J.trigger,Q=J.clearEvents,E=J.renderOverlay,B=J.clearOverlays,n=J.reportSelection,Y=J.unselect,X=J.daySelectionMousedown,p=J.slotSegHtml,s=b.formatDate,v,F,r,I,L,k,D,Z,ja,ia,ma,$,w,H,S,W,fa,aa,va,wa,Ga,Wb,Ma,db,vb,Xa,Xb,Ba,tb,Na,Ra,cb,ub={},Wa,Tb,Sb,Ub,Ha,Ia,La,bb,Vb;qb(a.addClass("fc-agenda"));Na=new Nb(function(h,P){function x(eb){return Math.max(Ea,
|
80 |
+
Math.min(tc,eb))}var A,ta,za;r.each(function(eb,uc){A=l(uc);ta=A.offset().left;if(eb)za[1]=ta;za=[ta];P[eb]=za});za[1]=ta+A.outerWidth();if(i("allDaySlot")){A=$;ta=A.offset().top;h[0]=[ta,ta+A.outerHeight()]}for(var Da=H.offset().top,Ea=w.offset().top,tc=Ea+w.outerHeight(),fb=0;fb<tb;fb++)h.push([x(Da+Xa*fb),x(Da+Xa*(fb+1))])});Ra=new Ob(Na);cb=new Pb(function(h){return k.eq(h)})}function sc(){function a(p,s){qa(p);var v,F=p.length,r=[],I=[];for(v=0;v<F;v++)p[v].allDay?r.push(p[v]):I.push(p[v]);if(u("allDaySlot")){K(e(r),
|
81 |
+
s);la()}g(d(I),s)}function b(){ha();ua().empty();ra().empty()}function e(p){p=ob(nb(p,l.map(p,Ua),o.visStart,o.visEnd));var s,v=p.length,F,r,I,L=[];for(s=0;s<v;s++){F=p[s];for(r=0;r<F.length;r++){I=F[r];I.row=0;I.level=s;L.push(I)}}return L}function d(p){var s=z(),v=ka(),F=da(),r=xa(M(o.visStart),v),I=l.map(p,f),L,k,D,Z,ja,ia,ma=[];for(L=0;L<s;L++){k=ob(nb(p,I,r,xa(M(r),F-v)));vc(k);for(D=0;D<k.length;D++){Z=k[D];for(ja=0;ja<Z.length;ja++){ia=Z[ja];ia.col=L;ia.level=D;ma.push(ia)}}ba(r,1,true)}return ma}
|
82 |
+
function f(p){return p.end?M(p.end):xa(M(p.start),u("defaultEventMinutes"))}function g(p,s){var v,F=p.length,r,I,L,k,D,Z,ja,ia,ma,$="",w,H,S={},W={},fa=ra(),aa;v=z();if(w=u("isRTL")){H=-1;aa=v-1}else{H=1;aa=0}for(v=0;v<F;v++){r=p[v];I=r.event;L=sa(r.start,r.start);k=sa(r.start,r.end);D=r.col;Z=r.level;ja=r.forward||0;ia=G(D*H+aa);ma=q(D*H+aa)-ia;ma=Math.min(ma-6,ma*0.95);D=Z?ma/(Z+ja+1):ja?(ma/(ja+1)-6)*2:ma;Z=ia+ma/(Z+ja+1)*Z*H+(w?ma-D:0);r.top=L;r.left=Z;r.outerWidth=D;r.outerHeight=k-L;$+=m(I,
|
83 |
+
r)}fa[0].innerHTML=$;w=fa.children();for(v=0;v<F;v++){r=p[v];I=r.event;$=l(w[v]);H=ea("eventRender",I,I,$,o);if(H===false)$.remove();else{if(H&&H!==true){$.remove();$=l(H).css({position:"absolute",top:r.top,left:r.left}).appendTo(fa)}r.element=$;if(I._id===s)t(I,$,r);else $[0]._fci=v;ya(I,$)}}Db(fa,p,t);for(v=0;v<F;v++){r=p[v];if($=r.element){I=S[s=r.key=Ib($[0])];r.vsides=I===na?(S[s]=Sa($,true)):I;I=W[s];r.hsides=I===na?(W[s]=pb($,true)):I;s=$.find("div.fc-event-content");if(s.length)r.contentTop=
|
84 |
+
s[0].offsetTop}}for(v=0;v<F;v++){r=p[v];if($=r.element){$[0].style.width=Math.max(0,r.outerWidth-r.hsides)+"px";S=Math.max(0,r.outerHeight-r.vsides);$[0].style.height=S+"px";I=r.event;if(r.contentTop!==na&&S-r.contentTop<10){$.find("div.fc-event-time").text(Y(I.start,u("timeFormat"))+" - "+I.title);$.find("div.fc-event-title").remove()}ea("eventAfterRender",I,I,$)}}}function m(p,s){var v="<",F=p.url,r=Jb(p,u),I=r?" style='"+r+"'":"",L=["fc-event","fc-event-skin","fc-event-vert"];oa(p)&&L.push("fc-event-draggable");
|
85 |
+
s.isStart&&L.push("fc-corner-top");s.isEnd&&L.push("fc-corner-bottom");L=L.concat(p.className);if(p.source)L=L.concat(p.source.className||[]);v+=F?"a href='"+Qa(p.url)+"'":"div";v+=" class='"+L.join(" ")+"' style='position:absolute;z-index:8;top:"+s.top+"px;left:"+s.left+"px;"+r+"'><div class='fc-event-inner fc-event-skin'"+I+"><div class='fc-event-head fc-event-skin'"+I+"><div class='fc-event-time'>"+Qa(X(p.start,p.end,u("timeFormat")))+"</div></div><div class='fc-event-content'><div class='fc-event-title'>"+
|
86 |
+
Qa(p.title)+"</div></div><div class='fc-event-bg'></div></div>";if(s.isEnd&&ga(p))v+="<div class='ui-resizable-handle ui-resizable-s'>=</div>";v+="</"+(F?"a":"div")+">";return v}function j(p,s,v){oa(p)&&y(p,s,v.isStart);v.isEnd&&ga(p)&&c(p,s,v);ca(p,s)}function t(p,s,v){var F=s.find("div.fc-event-time");oa(p)&&T(p,s,F);v.isEnd&&ga(p)&&R(p,s,F);ca(p,s)}function y(p,s,v){function F(){if(!L){s.width(r).height("").draggable("option","grid",null);L=true}}var r,I,L=true,k,D=u("isRTL")?-1:1,Z=V(),ja=O(),
|
87 |
+
ia=N(),ma=ka();s.draggable({zIndex:9,opacity:u("dragOpacity","month"),revertDuration:u("dragRevertDuration"),start:function($,w){ea("eventDragStart",s,p,$,w);i(p,s);r=s.width();Z.start(function(H,S,W,fa){B();if(H){I=false;k=fa*D;if(H.row)if(v){if(L){s.width(ja-10);Eb(s,ia*Math.round((p.end?(p.end-p.start)/wc:u("defaultEventMinutes"))/u("slotMinutes")));s.draggable("option","grid",[ja,1]);L=false}}else I=true;else{E(ba(M(p.start),k),ba(Ua(p),k));F()}I=I||L&&!k}else{F();I=true}s.draggable("option",
|
88 |
+
"revert",I)},$,"drag")},stop:function($,w){Z.stop();B();ea("eventDragStop",s,p,$,w);if(I){F();s.css("filter","");J(p,s)}else{var H=0;L||(H=Math.round((s.offset().top-U().offset().top)/ia)*u("slotMinutes")+ma-(p.start.getHours()*60+p.start.getMinutes()));C(this,p,k,H,L,$,w)}}})}function T(p,s,v){function F(H){var S=xa(M(p.start),H),W;if(p.end)W=xa(M(p.end),H);v.text(X(S,W,u("timeFormat")))}function r(){if(L){v.css("display","");s.draggable("option","grid",[$,w]);L=false}}var I,L=false,k,D,Z,ja=u("isRTL")?
|
89 |
+
-1:1,ia=V(),ma=z(),$=O(),w=N();s.draggable({zIndex:9,scroll:false,grid:[$,w],axis:ma==1?"y":false,opacity:u("dragOpacity"),revertDuration:u("dragRevertDuration"),start:function(H,S){ea("eventDragStart",s,p,H,S);i(p,s);I=s.position();D=Z=0;ia.start(function(W,fa,aa,va){s.draggable("option","revert",!W);B();if(W){k=va*ja;if(u("allDaySlot")&&!W.row){if(!L){L=true;v.hide();s.draggable("option","grid",null)}E(ba(M(p.start),k),ba(Ua(p),k))}else r()}},H,"drag")},drag:function(H,S){D=Math.round((S.position.top-
|
90 |
+
I.top)/w)*u("slotMinutes");if(D!=Z){L||F(D);Z=D}},stop:function(H,S){var W=ia.stop();B();ea("eventDragStop",s,p,H,S);if(W&&(k||D||L))C(this,p,k,L?0:D,L,H,S);else{r();s.css("filter","");s.css(I);F(0);J(p,s)}}})}function R(p,s,v){var F,r,I=N();s.resizable({handles:{s:"div.ui-resizable-s"},grid:I,start:function(L,k){F=r=0;i(p,s);s.css("z-index",9);ea("eventResizeStart",this,p,L,k)},resize:function(L,k){F=Math.round((Math.max(I,s.height())-k.originalSize.height)/I);if(F!=r){v.text(X(p.start,!F&&!p.end?
|
91 |
+
null:xa(pa(p),u("slotMinutes")*F),u("timeFormat")));r=F}},stop:function(L,k){ea("eventResizeStop",this,p,L,k);if(F)Q(this,p,0,u("slotMinutes")*F,L,k);else{s.css("z-index",8);J(p,s)}}})}var o=this;o.renderEvents=a;o.compileDaySegs=e;o.clearEvents=b;o.slotSegHtml=m;o.bindDaySeg=j;Qb.call(o);var u=o.opt,ea=o.trigger,oa=o.isEventDraggable,ga=o.isEventResizable,pa=o.eventEnd,qa=o.reportEvents,ha=o.reportEventClear,ca=o.eventElementHandlers,la=o.setHeight,ua=o.getDaySegmentContainer,ra=o.getSlotSegmentContainer,
|
92 |
+
V=o.getHoverListener,da=o.getMaxMinute,ka=o.getMinMinute,sa=o.timePosition,G=o.colContentLeft,q=o.colContentRight,K=o.renderDaySegs,c=o.resizableDayEvent,z=o.getColCnt,O=o.getColWidth,N=o.getSlotHeight,U=o.getBodyContent,ya=o.reportEventElement,J=o.showEvents,i=o.hideEvents,C=o.eventDrop,Q=o.eventResize,E=o.renderDayOverlay,B=o.clearOverlays,n=o.calendar,Y=n.formatDate,X=n.formatDates}function vc(a){var b,e,d,f,g,m;for(b=a.length-1;b>0;b--){f=a[b];for(e=0;e<f.length;e++){g=f[e];for(d=0;d<a[b-1].length;d++){m=
|
93 |
+
a[b-1][d];if(Cb(g,m))m.forward=Math.max(m.forward||0,(g.forward||0)+1)}}}}function Kb(a,b,e){function d(G,q){G=sa[G];if(typeof G=="object")return jb(G,q||e);return G}function f(G,q){return b.trigger.apply(b,[G,q||ca].concat(Array.prototype.slice.call(arguments,2),[ca]))}function g(G){return j(G)&&!d("disableDragging")}function m(G){return j(G)&&!d("disableResizing")}function j(G){return Ta(G.editable,(G.source||{}).editable,d("editable"))}function t(G){V={};var q,K=G.length,c;for(q=0;q<K;q++){c=G[q];
|
94 |
+
if(V[c._id])V[c._id].push(c);else V[c._id]=[c]}}function y(G){return G.end?M(G.end):la(G)}function T(G,q){da.push(q);if(ka[G._id])ka[G._id].push(q);else ka[G._id]=[q]}function R(){da=[];ka={}}function o(G,q){q.click(function(K){if(!q.hasClass("ui-draggable-dragging")&&!q.hasClass("ui-resizable-resizing"))return f("eventClick",this,G,K)}).hover(function(K){f("eventMouseover",this,G,K)},function(K){f("eventMouseout",this,G,K)})}function u(G,q){oa(G,q,"show")}function ea(G,q){oa(G,q,"hide")}function oa(G,
|
95 |
+
q,K){G=ka[G._id];var c,z=G.length;for(c=0;c<z;c++)if(!q||G[c][0]!=q[0])G[c][K]()}function ga(G,q,K,c,z,O,N){var U=q.allDay,ya=q._id;qa(V[ya],K,c,z);f("eventDrop",G,q,K,c,z,function(){qa(V[ya],-K,-c,U);ra(ya)},O,N);ra(ya)}function pa(G,q,K,c,z,O){var N=q._id;ha(V[N],K,c);f("eventResize",G,q,K,c,function(){ha(V[N],-K,-c);ra(N)},z,O);ra(N)}function qa(G,q,K,c){K=K||0;for(var z,O=G.length,N=0;N<O;N++){z=G[N];if(c!==na)z.allDay=c;xa(ba(z.start,q,true),K);if(z.end)z.end=xa(ba(z.end,q,true),K);ua(z,sa)}}
|
96 |
+
function ha(G,q,K){K=K||0;for(var c,z=G.length,O=0;O<z;O++){c=G[O];c.end=xa(ba(y(c),q,true),K);ua(c,sa)}}var ca=this;ca.element=a;ca.calendar=b;ca.name=e;ca.opt=d;ca.trigger=f;ca.isEventDraggable=g;ca.isEventResizable=m;ca.reportEvents=t;ca.eventEnd=y;ca.reportEventElement=T;ca.reportEventClear=R;ca.eventElementHandlers=o;ca.showEvents=u;ca.hideEvents=ea;ca.eventDrop=ga;ca.eventResize=pa;var la=ca.defaultEventEnd,ua=b.normalizeEvent,ra=b.reportEventChange,V={},da=[],ka={},sa=b.options}function Qb(){function a(i,
|
97 |
+
C){var Q=z(),E=ra(),B=V(),n=0,Y,X,p=i.length,s,v;Q[0].innerHTML=e(i);d(i,Q.children());f(i);g(i,Q,C);m(i);j(i);t(i);C=y();for(Q=0;Q<E;Q++){Y=[];for(X=0;X<B;X++)Y[X]=0;for(;n<p&&(s=i[n]).row==Q;){X=Hb(Y.slice(s.startCol,s.endCol));s.top=X;X+=s.outerHeight;for(v=s.startCol;v<s.endCol;v++)Y[v]=X;n++}C[Q].height(Hb(Y))}R(i,T(C))}function b(i,C,Q){var E=l("<div/>"),B=z(),n=i.length,Y;E[0].innerHTML=e(i);E=E.children();B.append(E);d(i,E);m(i);j(i);t(i);R(i,T(y()));E=[];for(B=0;B<n;B++)if(Y=i[B].element){i[B].row===
|
98 |
+
C&&Y.css("top",Q);E.push(Y[0])}return l(E)}function e(i){var C=ea("isRTL"),Q,E=i.length,B,n,Y,X;Q=ka();var p=Q.left,s=Q.right,v,F,r,I,L,k="";for(Q=0;Q<E;Q++){B=i[Q];n=B.event;X=["fc-event","fc-event-skin","fc-event-hori"];ga(n)&&X.push("fc-event-draggable");if(C){B.isStart&&X.push("fc-corner-right");B.isEnd&&X.push("fc-corner-left");v=q(B.end.getDay()-1);F=q(B.start.getDay());r=B.isEnd?sa(v):p;I=B.isStart?G(F):s}else{B.isStart&&X.push("fc-corner-left");B.isEnd&&X.push("fc-corner-right");v=q(B.start.getDay());
|
99 |
+
F=q(B.end.getDay()-1);r=B.isStart?sa(v):p;I=B.isEnd?G(F):s}X=X.concat(n.className);if(n.source)X=X.concat(n.source.className||[]);Y=n.url;L=Jb(n,ea);k+=Y?"<a href='"+Qa(Y)+"'":"<div";k+=" class='"+X.join(" ")+"' style='position:absolute;z-index:8;left:"+r+"px;"+L+"'><div class='fc-event-inner fc-event-skin'"+(L?" style='"+L+"'":"")+">";if(!n.allDay&&B.isStart)k+="<span class='fc-event-time'>"+Qa(N(n.start,n.end,ea("timeFormat")))+"</span>";k+="<span class='fc-event-title'>"+Qa(n.title)+"</span></div>";
|
100 |
+
if(B.isEnd&&pa(n))k+="<div class='ui-resizable-handle ui-resizable-"+(C?"w":"e")+"'> </div>";k+="</"+(Y?"a":"div")+">";B.left=r;B.outerWidth=I-r;B.startCol=v;B.endCol=F+1}return k}function d(i,C){var Q,E=i.length,B,n,Y;for(Q=0;Q<E;Q++){B=i[Q];n=B.event;Y=l(C[Q]);n=oa("eventRender",n,n,Y,u);if(n===false)Y.remove();else{if(n&&n!==true){n=l(n).css({position:"absolute",left:B.left});Y.replaceWith(n);Y=n}B.element=Y}}}function f(i){var C,Q=i.length,E,B;for(C=0;C<Q;C++){E=i[C];(B=E.element)&&
|
101 |
+
ha(E.event,B)}}function g(i,C,Q){var E,B=i.length,n,Y,X;for(E=0;E<B;E++){n=i[E];if(Y=n.element){X=n.event;if(X._id===Q)O(X,Y,n);else Y[0]._fci=E}}Db(C,i,O)}function m(i){var C,Q=i.length,E,B,n,Y,X={};for(C=0;C<Q;C++){E=i[C];if(B=E.element){n=E.key=Ib(B[0]);Y=X[n];if(Y===na)Y=X[n]=pb(B,true);E.hsides=Y}}}function j(i){var C,Q=i.length,E,B;for(C=0;C<Q;C++){E=i[C];if(B=E.element)B[0].style.width=Math.max(0,E.outerWidth-E.hsides)+"px"}}function t(i){var C,Q=i.length,E,B,n,Y,X={};for(C=0;C<Q;C++){E=i[C];
|
102 |
+
if(B=E.element){n=E.key;Y=X[n];if(Y===na)Y=X[n]=Fb(B);E.outerHeight=B[0].offsetHeight+Y}}}function y(){var i,C=ra(),Q=[];for(i=0;i<C;i++)Q[i]=da(i).find("td:first div.fc-day-content > div");return Q}function T(i){var C,Q=i.length,E=[];for(C=0;C<Q;C++)E[C]=i[C][0].offsetTop;return E}function R(i,C){var Q,E=i.length,B,n;for(Q=0;Q<E;Q++){B=i[Q];if(n=B.element){n[0].style.top=C[B.row]+(B.top||0)+"px";B=B.event;oa("eventAfterRender",B,B,n)}}}function o(i,C,Q){var E=ea("isRTL"),B=E?"w":"e",n=C.find("div.ui-resizable-"+
|
103 |
+
B),Y=false;qb(C);C.mousedown(function(X){X.preventDefault()}).click(function(X){if(Y){X.preventDefault();X.stopImmediatePropagation()}});n.mousedown(function(X){function p(ia){oa("eventResizeStop",this,i,ia);l("body").css("cursor","");s.stop();ya();k&&ua(this,i,k,0,ia);setTimeout(function(){Y=false},0)}if(X.which==1){Y=true;var s=u.getHoverListener(),v=ra(),F=V(),r=E?-1:1,I=E?F-1:0,L=C.css("top"),k,D,Z=l.extend({},i),ja=K(i.start);J();l("body").css("cursor",B+"-resize").one("mouseup",p);oa("eventResizeStart",
|
104 |
+
this,i,X);s.start(function(ia,ma){if(ia){var $=Math.max(ja.row,ia.row);ia=ia.col;if(v==1)$=0;if($==ja.row)ia=E?Math.min(ja.col,ia):Math.max(ja.col,ia);k=$*7+ia*r+I-(ma.row*7+ma.col*r+I);ma=ba(qa(i),k,true);if(k){Z.end=ma;$=D;D=b(c([Z]),Q.row,L);D.find("*").css("cursor",B+"-resize");$&&$.remove();la(i)}else if(D){ca(i);D.remove();D=null}ya();U(i.start,ba(M(ma),1))}},X)}})}var u=this;u.renderDaySegs=a;u.resizableDayEvent=o;var ea=u.opt,oa=u.trigger,ga=u.isEventDraggable,pa=u.isEventResizable,qa=u.eventEnd,
|
105 |
+
ha=u.reportEventElement,ca=u.showEvents,la=u.hideEvents,ua=u.eventResize,ra=u.getRowCnt,V=u.getColCnt,da=u.allDayRow,ka=u.allDayBounds,sa=u.colContentLeft,G=u.colContentRight,q=u.dayOfWeekCol,K=u.dateCell,c=u.compileDaySegs,z=u.getDaySegmentContainer,O=u.bindDaySeg,N=u.calendar.formatDates,U=u.renderDayOverlay,ya=u.clearOverlays,J=u.clearSelection}function Mb(){function a(R,o,u){b();o||(o=j(R,u));t(R,o,u);e(R,o,u)}function b(R){if(T){T=false;y();m("unselect",null,R)}}function e(R,o,u,ea){T=true;m("select",
|
106 |
+
null,R,o,u,ea)}function d(R){var o=f.cellDate,u=f.cellIsAllDay,ea=f.getHoverListener(),oa=f.reportDayClick;if(R.which==1&&g("selectable")){b(R);var ga;ea.start(function(pa,qa){y();if(pa&&u(pa)){ga=[o(qa),o(pa)].sort(Gb);t(ga[0],ga[1],true)}else ga=null},R);l(document).one("mouseup",function(pa){ea.stop();if(ga){+ga[0]==+ga[1]&&oa(ga[0],true,pa);e(ga[0],ga[1],true,pa)}})}}var f=this;f.select=a;f.unselect=b;f.reportSelection=e;f.daySelectionMousedown=d;var g=f.opt,m=f.trigger,j=f.defaultSelectionEnd,
|
107 |
+
t=f.renderSelection,y=f.clearSelection,T=false;g("selectable")&&g("unselectAuto")&&l(document).mousedown(function(R){var o=g("unselectCancel");if(o)if(l(R.target).parents(o).length)return;b(R)})}function Lb(){function a(g,m){var j=f.shift();j||(j=l("<div class='fc-cell-overlay' style='position:absolute;z-index:3'/>"));j[0].parentNode!=m[0]&&j.appendTo(m);d.push(j.css(g).show());return j}function b(){for(var g;g=d.shift();)f.push(g.hide().unbind())}var e=this;e.renderOverlay=a;e.clearOverlays=b;var d=
|
108 |
+
[],f=[]}function Nb(a){var b=this,e,d;b.build=function(){e=[];d=[];a(e,d)};b.cell=function(f,g){var m=e.length,j=d.length,t,y=-1,T=-1;for(t=0;t<m;t++)if(g>=e[t][0]&&g<e[t][1]){y=t;break}for(t=0;t<j;t++)if(f>=d[t][0]&&f<d[t][1]){T=t;break}return y>=0&&T>=0?{row:y,col:T}:null};b.rect=function(f,g,m,j,t){t=t.offset();return{top:e[f][0]-t.top,left:d[g][0]-t.left,width:d[j][1]-d[g][0],height:e[m][1]-e[f][0]}}}function Ob(a){function b(j){xc(j);j=a.cell(j.pageX,j.pageY);if(!j!=!m||j&&(j.row!=m.row||j.col!=
|
109 |
+
m.col)){if(j){g||(g=j);f(j,g,j.row-g.row,j.col-g.col)}else f(j,g);m=j}}var e=this,d,f,g,m;e.start=function(j,t,y){f=j;g=m=null;a.build();b(t);d=y||"mousemove";l(document).bind(d,b)};e.stop=function(){l(document).unbind(d,b);return m}}function xc(a){if(a.pageX===na){a.pageX=a.originalEvent.pageX;a.pageY=a.originalEvent.pageY}}function Pb(a){function b(m){return d[m]=d[m]||a(m)}var e=this,d={},f={},g={};e.left=function(m){return f[m]=f[m]===na?b(m).position().left:f[m]};e.right=function(m){return g[m]=
|
110 |
+
g[m]===na?e.left(m)+b(m).width():g[m]};e.clear=function(){d={};f={};g={}}}var Ya={defaultView:"month",aspectRatio:1.35,header:{left:"title",center:"",right:"today prev,next"},weekends:true,allDayDefault:true,ignoreTimezone:true,lazyFetching:true,startParam:"start",endParam:"end",titleFormat:{month:"MMMM yyyy",week:"MMM d[ yyyy]{ '—'[ MMM] d yyyy}",day:"dddd, MMM d, yyyy"},columnFormat:{month:"ddd",week:"ddd M/d",day:"dddd M/d"},timeFormat:{"":"h(:mm)t"},isRTL:false,firstDay:0,monthNames:["January",
|
111 |
+
"February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],buttonText:{prev:" ◄ ",next:" ► ",prevYear:" << ",nextYear:" >> ",today:"today",month:"month",week:"week",
|
112 |
+
day:"day"},theme:false,buttonIcons:{prev:"circle-triangle-w",next:"circle-triangle-e"},unselectAuto:true,dropAccept:"*"},yc={header:{left:"next,prev today",center:"",right:"title"},buttonText:{prev:" ► ",next:" ◄ ",prevYear:" >> ",nextYear:" << "},buttonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w"}},Aa=l.fullCalendar={version:"1.5.4"},Ja=Aa.views={};l.fn.fullCalendar=function(a){if(typeof a=="string"){var b=Array.prototype.slice.call(arguments,
|
113 |
+
1),e;this.each(function(){var f=l.data(this,"fullCalendar");if(f&&l.isFunction(f[a])){f=f[a].apply(f,b);if(e===na)e=f;a=="destroy"&&l.removeData(this,"fullCalendar")}});if(e!==na)return e;return this}var d=a.eventSources||[];delete a.eventSources;if(a.events){d.push(a.events);delete a.events}a=l.extend(true,{},Ya,a.isRTL||a.isRTL===na&&Ya.isRTL?yc:{},a);this.each(function(f,g){f=l(g);g=new Yb(f,a,d);f.data("fullCalendar",g);g.render()});return this};Aa.sourceNormalizers=[];Aa.sourceFetchers=[];var ac=
|
114 |
+
{dataType:"json",cache:false},bc=1;Aa.addDays=ba;Aa.cloneDate=M;Aa.parseDate=kb;Aa.parseISO8601=Bb;Aa.parseTime=mb;Aa.formatDate=Oa;Aa.formatDates=ib;var lc=["sun","mon","tue","wed","thu","fri","sat"],Ab=864E5,cc=36E5,wc=6E4,dc={s:function(a){return a.getSeconds()},ss:function(a){return Pa(a.getSeconds())},m:function(a){return a.getMinutes()},mm:function(a){return Pa(a.getMinutes())},h:function(a){return a.getHours()%12||12},hh:function(a){return Pa(a.getHours()%12||12)},H:function(a){return a.getHours()},
|
115 |
+
HH:function(a){return Pa(a.getHours())},d:function(a){return a.getDate()},dd:function(a){return Pa(a.getDate())},ddd:function(a,b){return b.dayNamesShort[a.getDay()]},dddd:function(a,b){return b.dayNames[a.getDay()]},M:function(a){return a.getMonth()+1},MM:function(a){return Pa(a.getMonth()+1)},MMM:function(a,b){return b.monthNamesShort[a.getMonth()]},MMMM:function(a,b){return b.monthNames[a.getMonth()]},yy:function(a){return(a.getFullYear()+"").substring(2)},yyyy:function(a){return a.getFullYear()},
|
116 |
+
t:function(a){return a.getHours()<12?"a":"p"},tt:function(a){return a.getHours()<12?"am":"pm"},T:function(a){return a.getHours()<12?"A":"P"},TT:function(a){return a.getHours()<12?"AM":"PM"},u:function(a){return Oa(a,"yyyy-MM-dd'T'HH:mm:ss'Z'")},S:function(a){a=a.getDate();if(a>10&&a<20)return"th";return["st","nd","rd"][a%10-1]||"th"}};Aa.applyAll=$a;Ja.month=mc;Ja.basicWeek=nc;Ja.basicDay=oc;wb({weekMode:"fixed"});Ja.agendaWeek=qc;Ja.agendaDay=rc;wb({allDaySlot:true,allDayText:"all-day",firstHour:6,
|
117 |
+
slotMinutes:30,defaultEventMinutes:120,axisFormat:"h(:mm)tt",timeFormat:{agenda:"h:mm{ - h:mm}"},dragOpacity:{agenda:0.5},minTime:0,maxTime:24})})(jQuery);
|
js/inline-help.js
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
//TODO Needs compressing
|
2 |
+
jQuery(document).ready(function($) {
|
3 |
+
$('.eo-inline-help').each(function() {
|
4 |
+
var id = $(this).attr('id').substr(15);
|
5 |
+
$(this).click(function(e){e.preventDefault();});
|
6 |
+
$(this).qtip({
|
7 |
+
content: {
|
8 |
+
text: eoHelp[id].content,
|
9 |
+
title: {
|
10 |
+
text: eoHelp[id].title
|
11 |
+
}
|
12 |
+
},
|
13 |
+
show: {
|
14 |
+
solo: true
|
15 |
+
},
|
16 |
+
hide: 'unfocus',
|
17 |
+
style: {
|
18 |
+
classes: 'qtip-wiki qtip-light qtip-shadow'
|
19 |
+
},
|
20 |
+
position : {
|
21 |
+
viewport: $(window)
|
22 |
+
}
|
23 |
+
});
|
24 |
+
});
|
25 |
+
});
|
js/qtip2.js
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
/*! qTip2 v2.0.0 | http://craigsworks.com/projects/qtip2/ | Licensed MIT, GPL */
|
2 |
+
(function(a){"use strict",typeof define=="function"&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.qtip&&a(jQuery)})(function(a){function G(){G.history=G.history||[],G.history.push(arguments);if("object"==typeof console){var a=console[console.warn?"warn":"log"],b=Array.prototype.slice.call(arguments),c;typeof arguments[0]=="string"&&(b[0]="qTip2: "+b[0]),c=a.apply?a.apply(console,b):a(b)}}function H(b){var e=function(a){return a===d||"object"!=typeof a},f=function(b){return!a.isFunction(b)&&(!b&&!b.attr||b.length<1||"object"==typeof b&&!b.jquery)};if(!b||"object"!=typeof b)return c;e(b.metadata)&&(b.metadata={type:b.metadata});if("content"in b){if(e(b.content)||b.content.jquery)b.content={text:b.content};f(b.content.text||c)&&(b.content.text=c),"title"in b.content&&(e(b.content.title)&&(b.content.title={text:b.content.title}),f(b.content.title.text||c)&&(b.content.title.text=c))}return"position"in b&&e(b.position)&&(b.position={my:b.position,at:b.position}),"show"in b&&e(b.show)&&(b.show=b.show.jquery?{target:b.show}:{event:b.show}),"hide"in b&&e(b.hide)&&(b.hide=b.hide.jquery?{target:b.hide}:{event:b.hide}),"style"in b&&e(b.style)&&(b.style={classes:b.style}),a.each(r,function(){this.sanitize&&this.sanitize(b)}),b}function I(e,f,n,o){function N(a){var b=0,c,d=f,e=a.split(".");while(d=d[e[b++]])b<e.length&&(c=d);return[c||f,e.pop()]}function O(){var a=f.style.widget;J.toggleClass(v,a).toggleClass(y,f.style.def&&!a),L.content.toggleClass(v+"-content",a),L.titlebar&&L.titlebar.toggleClass(v+"-header",a),L.button&&L.button.toggleClass(u+"-icon",!a)}function P(a){L.title&&(L.titlebar.remove(),L.titlebar=L.title=L.button=d,a!==c&&p.reposition())}function Q(){var b=f.content.title.button,d=typeof b=="string",e=d?b:"Close tooltip";L.button&&L.button.remove(),b.jquery?L.button=b:L.button=a("<a />",{"class":"ui-state-default ui-tooltip-close "+(f.style.widget?"":u+"-icon"),title:e,"aria-label":e}).prepend(a("<span />",{"class":"ui-icon ui-icon-close",html:"×"})),L.button.appendTo(L.titlebar).attr("role","button").click(function(a){return J.hasClass(w)||p.hide(a),c}),p.redraw()}function R(){var c=D+"-title";L.titlebar&&P(),L.titlebar=a("<div />",{"class":u+"-titlebar "+(f.style.widget?"ui-widget-header":"")}).append(L.title=a("<div />",{id:c,"class":u+"-title","aria-atomic":b})).insertBefore(L.content).delegate(".ui-tooltip-close","mousedown keydown mouseup keyup mouseout",function(b){a(this).toggleClass("ui-state-active ui-state-focus",b.type.substr(-4)==="down")}).delegate(".ui-tooltip-close","mouseover mouseout",function(b){a(this).toggleClass("ui-state-hover",b.type==="mouseover")}),f.content.title.button?Q():p.rendered&&p.redraw()}function S(a){var b=L.button,d=L.title;if(!p.rendered)return c;a?(d||R(),Q()):b.remove()}function T(b,d){var f=L.title;if(!p.rendered||!b)return c;a.isFunction(b)&&(b=b.call(e,M.event,p));if(b===c||!b&&b!=="")return P(c);b.jquery&&b.length>0?f.empty().append(b.css({display:"block"})):f.html(b),p.redraw(),d!==c&&p.rendered&&J[0].offsetWidth>0&&p.reposition(M.event)}function U(b,d){function g(b){function h(e){e&&(delete g[e.src],clearTimeout(p.timers.img[e.src]),a(e).unbind(K)),a.isEmptyObject(g)&&(p.redraw(),d!==c&&p.reposition(M.event),b())}var e,g={};if((e=f.find("img[src]:not([height]):not([width])")).length===0)return h();e.each(function(b,c){if(g[c.src]!==undefined)return;var d=0,e=3;(function f(){if(c.height||c.width||d>e)return h(c);d+=1,p.timers.img[c.src]=setTimeout(f,700)})(),a(c).bind("error"+K+" load"+K,function(){h(this)}),g[c.src]=c})}var f=L.content;return!p.rendered||!b?c:(a.isFunction(b)&&(b=b.call(e,M.event,p)||""),b.jquery&&b.length>0?f.empty().append(b.css({display:"block"})):f.html(b),p.rendered<0?J.queue("fx",g):(I=0,g(a.noop)),p)}function V(){function j(a){if(J.hasClass(w))return c;clearTimeout(p.timers.show),clearTimeout(p.timers.hide);var d=function(){p.toggle(b,a)};f.show.delay>0?p.timers.show=setTimeout(d,f.show.delay):d()}function k(b){if(J.hasClass(w)||G||I)return c;var e=a(b.relatedTarget||b.target),h=e.closest(x)[0]===J[0],i=e[0]===g.show[0];clearTimeout(p.timers.show),clearTimeout(p.timers.hide);if(d.target==="mouse"&&h||f.hide.fixed&&/mouse(out|leave|move)/.test(b.type)&&(h||i)){try{b.preventDefault(),b.stopImmediatePropagation()}catch(j){}return}f.hide.delay>0?p.timers.hide=setTimeout(function(){p.hide(b)},f.hide.delay):p.hide(b)}function l(a){if(J.hasClass(w))return c;clearTimeout(p.timers.inactive),p.timers.inactive=setTimeout(function(){p.hide(a)},f.hide.inactive)}function m(a){p.rendered&&J[0].offsetWidth>0&&p.reposition(a)}var d=f.position,g={show:f.show.target,hide:f.hide.target,viewport:a(d.viewport),document:a(document),body:a(document.body),window:a(window)},h={show:a.trim(""+f.show.event).split(" "),hide:a.trim(""+f.hide.event).split(" ")},i=a.browser.msie&&parseInt(a.browser.version,10)===6;J.bind("mouseenter"+K+" mouseleave"+K,function(a){var b=a.type==="mouseenter";b&&p.focus(a),J.toggleClass(A,b)}),/mouse(out|leave)/i.test(f.hide.event)&&f.hide.leave==="window"&&g.window.bind("mouseout"+K+" blur"+K,function(a){!/select|option/.test(a.target.nodeName)&&!a.relatedTarget&&p.hide(a)}),f.hide.fixed?(g.hide=g.hide.add(J),J.bind("mouseover"+K,function(){J.hasClass(w)||clearTimeout(p.timers.hide)})):/mouse(over|enter)/i.test(f.show.event)&&g.hide.bind("mouseleave"+K,function(a){clearTimeout(p.timers.show)}),(""+f.hide.event).indexOf("unfocus")>-1&&d.container.closest("html").bind("mousedown"+K,function(b){var c=a(b.target),d=p.rendered&&!J.hasClass(w)&&J[0].offsetWidth>0,f=c.parents(x).filter(J[0]).length>0;c[0]!==e[0]&&c[0]!==J[0]&&!f&&!e.has(c[0]).length&&!c.attr("disabled")&&p.hide(b)}),"number"==typeof f.hide.inactive&&(g.show.bind("qtip-"+n+"-inactive",l),a.each(q.inactiveEvents,function(a,b){g.hide.add(L.tooltip).bind(b+K+"-inactive",l)})),a.each(h.hide,function(b,c){var d=a.inArray(c,h.show),e=a(g.hide);d>-1&&e.add(g.show).length===e.length||c==="unfocus"?(g.show.bind(c+K,function(a){J[0].offsetWidth>0?k(a):j(a)}),delete h.show[d]):g.hide.bind(c+K,k)}),a.each(h.show,function(a,b){g.show.bind(b+K,j)}),"number"==typeof f.hide.distance&&g.show.add(J).bind("mousemove"+K,function(a){var b=M.origin||{},c=f.hide.distance,d=Math.abs;(d(a.pageX-b.pageX)>=c||d(a.pageY-b.pageY)>=c)&&p.hide(a)}),d.target==="mouse"&&(g.show.bind("mousemove"+K,function(a){s={pageX:a.pageX,pageY:a.pageY,type:"mousemove"}}),d.adjust.mouse&&(f.hide.event&&(J.bind("mouseleave"+K,function(a){(a.relatedTarget||a.target)!==g.show[0]&&p.hide(a)}),L.target.bind("mouseenter"+K+" mouseleave"+K,function(a){M.onTarget=a.type==="mouseenter"})),g.document.bind("mousemove"+K,function(a){p.rendered&&M.onTarget&&!J.hasClass(w)&&J[0].offsetWidth>0&&p.reposition(a||s)}))),(d.adjust.resize||g.viewport.length)&&(a.event.special.resize?g.viewport:g.window).bind("resize"+K,m),(g.viewport.length||i&&J.css("position")==="fixed")&&g.viewport.bind("scroll"+K,m)}function W(){var b=[f.show.target[0],f.hide.target[0],p.rendered&&L.tooltip[0],f.position.container[0],f.position.viewport[0],f.position.container.closest("html")[0],window,document];p.rendered?a([]).pushStack(a.grep(b,function(a){return typeof a=="object"})).unbind(K):f.show.target.unbind(K+"-create")}var p=this,C=document.body,D=u+"-"+n,G=0,I=0,J=a(),K=".qtip-"+n,L,M;p.id=n,p.rendered=c,p.destroyed=c,p.elements=L={target:e},p.timers={img:{}},p.options=f,p.checks={},p.plugins={},p.cache=M={event:{},target:a(),disabled:c,attr:o,onTarget:c,lastClass:""},p.checks.builtin={"^id$":function(d,e,f){var g=f===b?q.nextid:f,h=u+"-"+g;g!==c&&g.length>0&&!a("#"+h).length&&(J[0].id=h,L.content[0].id=h+"-content",L.title[0].id=h+"-title")},"^content.text$":function(a,b,c){U(c)},"^content.title.text$":function(a,b,c){if(!c)return P();!L.title&&c&&R(),T(c)},"^content.title.button$":function(a,b,c){S(c)},"^position.(my|at)$":function(a,b,c){"string"==typeof c&&(a[b]=new r.Corner(c))},"^position.container$":function(a,b,c){p.rendered&&J.appendTo(c)},"^show.ready$":function(){p.rendered?p.toggle(b):p.render(1)},"^style.classes$":function(a,b,c){J.attr("class",u+" qtip ui-helper-reset "+c)},"^style.widget|content.title":O,"^events.(render|show|move|hide|focus|blur)$":function(b,c,d){J[(a.isFunction(d)?"":"un")+"bind"]("tooltip"+c,d)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){var a=f.position;J.attr("tracking",a.target==="mouse"&&a.adjust.mouse),W(),V()}},a.extend(p,{render:function(d){if(p.rendered)return p;var g=f.content.text,h=f.content.title.text,i=f.position,j=a.Event("tooltiprender");return a.attr(e[0],"aria-describedby",D),J=L.tooltip=a("<div/>",{id:D,"class":u+" qtip ui-helper-reset "+y+" "+f.style.classes+" "+u+"-pos-"+f.position.my.abbrev(),width:f.style.width||"",height:f.style.height||"",tracking:i.target==="mouse"&&i.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":c,"aria-describedby":D+"-content","aria-hidden":b}).toggleClass(w,M.disabled).data("qtip",p).appendTo(f.position.container).append(L.content=a("<div />",{"class":u+"-content",id:D+"-content","aria-atomic":b})),p.rendered=-1,I=1,G=1,h&&(R(),a.isFunction(h)||T(h,c)),a.isFunction(g)||U(g,c),p.rendered=b,O(),a.each(f.events,function(b,c){a.isFunction(c)&&J.bind(b==="toggle"?"tooltipshow tooltiphide":"tooltip"+b,c)}),a.each(r,function(){this.initialize==="render"&&this(p)}),V(),J.queue("fx",function(a){j.originalEvent=M.event,J.trigger(j,[p]),I=0,G=0,p.redraw(),(f.show.ready||d)&&p.toggle(b,M.event,c),a()}),p},get:function(a){var b,c;switch(a.toLowerCase()){case"dimensions":b={height:J.outerHeight(),width:J.outerWidth()};break;case"offset":b=r.offset(J,f.position.container);break;default:c=N(a.toLowerCase()),b=c[0][c[1]],b=b.precedance?b.string():b}return b},set:function(e,g){function n(a,b){var c,d,e;for(c in l)for(d in l[c])if(e=(new RegExp(d,"i")).exec(a))b.push(e),l[c][d].apply(p,b)}var h=/^position\.(my|at|adjust|target|container)|style|content|show\.ready/i,i=/^content\.(title|attr)|style/i,j=c,k=c,l=p.checks,m;return"string"==typeof e?(m=e,e={},e[m]=g):e=a.extend(b,{},e),a.each(e,function(b,c){var d=N(b.toLowerCase()),f;f=d[0][d[1]],d[0][d[1]]="object"==typeof c&&c.nodeType?a(c):c,e[b]=[d[0],d[1],c,f],j=h.test(b)||j,k=i.test(b)||k}),H(f),G=I=1,a.each(e,n),G=I=0,p.rendered&&J[0].offsetWidth>0&&(j&&p.reposition(f.position.target==="mouse"?d:M.event),k&&p.redraw()),p},toggle:function(e,g){function u(){e?(a.browser.msie&&J[0].style.removeAttribute("filter"),J.css("overflow",""),"string"==typeof i.autofocus&&a(i.autofocus,J).focus(),i.target.trigger("qtip-"+n+"-inactive")):J.css({display:"",visibility:"",opacity:"",left:"",top:""}),t=a.Event("tooltip"+(e?"visible":"hidden")),t.originalEvent=g?M.event:d,J.trigger(t,[p])}if(!p.rendered)return e?p.render(1):p;var h=e?"show":"hide",i=f[h],j=f[e?"hide":"show"],k=f.position,l=f.content,m=J[0].offsetWidth>0,o=e||i.target.length===1,q=!g||i.target.length<2||M.target[0]===g.target,r,t;(typeof e).search("boolean|number")&&(e=!m);if(!J.is(":animated")&&m===e&&q)return p;if(g){if(/over|enter/.test(g.type)&&/out|leave/.test(M.event.type)&&f.show.target.add(g.target).length===f.show.target.length&&J.has(g.relatedTarget).length)return p;M.event=a.extend({},g)}return t=a.Event("tooltip"+h),t.originalEvent=g?M.event:d,J.trigger(t,[p,90]),t.isDefaultPrevented()?p:(a.attr(J[0],"aria-hidden",!e),e?(M.origin=a.extend({},s),p.focus(g),a.isFunction(l.text)&&U(l.text,c),a.isFunction(l.title.text)&&T(l.title.text,c),!F&&k.target==="mouse"&&k.adjust.mouse&&(a(document).bind("mousemove.qtip",function(a){s={pageX:a.pageX,pageY:a.pageY,type:"mousemove"}}),F=b),p.reposition(g,arguments[2]),(t.solo=!!i.solo)&&a(x,i.solo).not(J).qtip("hide",t)):(clearTimeout(p.timers.show),delete M.origin,F&&!a(x+'[tracking="true"]:visible',i.solo).not(J).length&&(a(document).unbind("mousemove.qtip"),F=c),p.blur(g)),i.effect===c||o===c?(J[h](),u.call(J)):a.isFunction(i.effect)?(J.stop(1,1),i.effect.call(J,p),J.queue("fx",function(a){u(),a()})):J.fadeTo(90,e?1:0,u),e&&i.target.trigger("qtip-"+n+"-inactive"),p)},show:function(a){return p.toggle(b,a)},hide:function(a){return p.toggle(c,a)},focus:function(b){if(!p.rendered)return p;var c=a(x),d=parseInt(J[0].style.zIndex,10),e=q.zindex+c.length,f=a.extend({},b),g,h;return J.hasClass(z)||(h=a.Event("tooltipfocus"),h.originalEvent=f,J.trigger(h,[p,e]),h.isDefaultPrevented()||(d!==e&&(c.each(function(){this.style.zIndex>d&&(this.style.zIndex=this.style.zIndex-1)}),c.filter("."+z).qtip("blur",f)),J.addClass(z)[0].style.zIndex=e)),p},blur:function(b){var c=a.extend({},b),d;return J.removeClass(z),d=a.Event("tooltipblur"),d.originalEvent=c,J.trigger(d,[p]),p},reposition:function(b,d){if(!p.rendered||G)return p;G=1;var e=f.position.target,g=f.position,h=g.my,n=g.at,o=g.adjust,q=o.method.split(" "),t=J.outerWidth(),u=J.outerHeight(),v=0,w=0,x=a.Event("tooltipmove"),y=J.css("position")==="fixed",z=g.viewport,A={left:0,top:0},B=g.container,C=J[0].offsetWidth>0,D,E,F;if(a.isArray(e)&&e.length===2)n={x:j,y:i},A={left:e[0],top:e[1]};else if(e==="mouse"&&(b&&b.pageX||M.event.pageX))n={x:j,y:i},b=(b&&(b.type==="resize"||b.type==="scroll")?M.event:b&&b.pageX&&b.type==="mousemove"?b:s&&s.pageX&&(o.mouse||!b||!b.pageX)?{pageX:s.pageX,pageY:s.pageY}:!o.mouse&&M.origin&&M.origin.pageX&&f.show.distance?M.origin:b)||b||M.event||s||{},A={top:b.pageY,left:b.pageX};else{e==="event"&&b&&b.target&&b.type!=="scroll"&&b.type!=="resize"?M.target=a(b.target):e!=="event"&&(M.target=a(e.jquery?e:L.target)),e=M.target,e=a(e).eq(0);if(e.length===0)return p;e[0]===document||e[0]===window?(v=r.iOS?window.innerWidth:e.width(),w=r.iOS?window.innerHeight:e.height(),e[0]===window&&(A={top:(z||e).scrollTop(),left:(z||e).scrollLeft()})):r.imagemap&&e.is("area")?D=r.imagemap(p,e,n,r.viewport?q:c):r.svg&&typeof e[0].xmlbase=="string"?D=r.svg(p,e,n,r.viewport?q:c):(v=e.outerWidth(),w=e.outerHeight(),A=r.offset(e,B)),D&&(v=D.width,w=D.height,E=D.offset,A=D.position);if(r.iOS>3.1&&r.iOS<4.1||r.iOS>=4.3&&r.iOS<4.33||!r.iOS&&y)F=a(window),A.left-=F.scrollLeft(),A.top-=F.scrollTop();A.left+=n.x===l?v:n.x===m?v/2:0,A.top+=n.y===k?w:n.y===m?w/2:0}return A.left+=o.x+(h.x===l?-t:h.x===m?-t/2:0),A.top+=o.y+(h.y===k?-u:h.y===m?-u/2:0),r.viewport?(A.adjusted=r.viewport(p,A,g,v,w,t,u),E&&A.adjusted.left&&(A.left+=E.left),E&&A.adjusted.top&&(A.top+=E.top)):A.adjusted={left:0,top:0},x.originalEvent=a.extend({},b),J.trigger(x,[p,A,z.elem||z]),x.isDefaultPrevented()?p:(delete A.adjusted,d===c||!C||isNaN(A.left)||isNaN(A.top)||e==="mouse"||!a.isFunction(g.effect)?J.css(A):a.isFunction(g.effect)&&(g.effect.call(J,p,a.extend({},A)),J.queue(function(b){a(this).css({opacity:"",height:""}),a.browser.msie&&this.style.removeAttribute("filter"),b()})),G=0,p)},redraw:function(){if(p.rendered<1||I)return p;var a=f.position.container,b,c,d,e;return I=1,f.style.height&&J.css(h,f.style.height),f.style.width?J.css(g,f.style.width):(J.css(g,"").addClass(B),c=J.width()+1,d=J.css("max-width")||"",e=J.css("min-width")||"",b=(d+e).indexOf("%")>-1?a.width()/100:0,d=(d.indexOf("%")>-1?b:1)*parseInt(d,10)||c,e=(e.indexOf("%")>-1?b:1)*parseInt(e,10)||0,c=d+e?Math.min(Math.max(c,e),d):c,J.css(g,Math.round(c)).removeClass(B)),I=0,p},disable:function(b){return"boolean"!=typeof b&&(b=!J.hasClass(w)&&!M.disabled),p.rendered?(J.toggleClass(w,b),a.attr(J[0],"aria-disabled",b)):M.disabled=!!b,p},enable:function(){return p.disable(c)},destroy:function(){var c=e[0],d=a.attr(c,E),g=e.data("qtip");p.destroyed=b,p.rendered&&(J.stop(1,0).remove(),a.each(p.plugins,function(){this.destroy&&this.destroy()})),clearTimeout(p.timers.show),clearTimeout(p.timers.hide),W();if(!g||p===g)a.removeData(c,"qtip"),f.suppress&&d&&(a.attr(c,"title",d),e.removeAttr(E)),e.removeAttr("aria-describedby");return e.unbind(".qtip-"+n),delete t[p.id],e}})}function J(e,f){var g,h,i,j,k,l=a(this),m=a(document.body),n=this===document?m:l,o=l.metadata?l.metadata(f.metadata):d,p=f.metadata.type==="html5"&&o?o[f.metadata.name]:d,s=l.data(f.metadata.name||"qtipopts");try{s=typeof s=="string"?a.parseJSON(s):s}catch(t){G("Unable to parse HTML5 attribute data: "+s)}j=a.extend(b,{},q.defaults,f,typeof s=="object"?H(s):d,H(p||o)),h=j.position,j.id=e;if("boolean"==typeof j.content.text){i=l.attr(j.content.attr);if(j.content.attr!==c&&i)j.content.text=i;else return G("Unable to locate content for tooltip! Aborting render of tooltip on element: ",l),c}h.container.length||(h.container=m),h.target===c&&(h.target=n),j.show.target===c&&(j.show.target=n),j.show.solo===b&&(j.show.solo=h.container.closest("body")),j.hide.target===c&&(j.hide.target=n),j.position.viewport===b&&(j.position.viewport=h.container),h.container=h.container.eq(0),h.at=new r.Corner(h.at),h.my=new r.Corner(h.my);if(a.data(this,"qtip"))if(j.overwrite)l.qtip("destroy");else if(j.overwrite===c)return c;return j.suppress&&(k=a.attr(this,"title"))&&a(this).removeAttr("title").attr(E,k).attr("title",""),g=new I(l,j,e,!!i),a.data(this,"qtip",g),l.bind("remove.qtip-"+e+" removeqtip.qtip-"+e,function(){g.destroy()}),g}function K(d){var e=this,f=d.elements.tooltip,g=d.options.content.ajax,h=q.defaults.content.ajax,i=".qtip-ajax",j=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,k=b,l=c,m;d.checks.ajax={"^content.ajax":function(a,b,c){b==="ajax"&&(g=c),b==="once"?e.init():g&&g.url?e.load():f.unbind(i)}},a.extend(e,{init:function(){return g&&g.url&&f.unbind(i)[g.once?"one":"bind"]("tooltipshow"+i,e.load),e},load:function(f){function r(){var e;if(d.destroyed)return;k=c,p&&(l=b,d.show(f.originalEvent)),(e=h.complete||g.complete)&&a.isFunction(e)&&e.apply(g.context||d,arguments)}function s(b,c,e){var f;if(d.destroyed)return;o&&(b=a("<div/>").append(b.replace(j,"")).find(o)),(f=h.success||g.success)&&a.isFunction(f)?f.call(g.context||d,b,c,e):d.set("content.text",b)}function t(a,b,c){if(d.destroyed||a.status===0)return;d.set("content.text",b+": "+c)}if(l){l=c;return}var i=g.url.indexOf(" "),n=g.url,o,p=!g.loading&&k;if(p)try{f.preventDefault()}catch(q){}else if(f&&f.isDefaultPrevented())return e;m&&m.abort&&m.abort(),i>-1&&(o=n.substr(i),n=n.substr(0,i)),m=a.ajax(a.extend({error:h.error||t,context:d},g,{url:n,success:s,complete:r}))},destroy:function(){m&&m.abort&&m.abort(),d.destroyed=b}}),e.init()}function L(a,b,c){var d=Math.ceil(b/2),e=Math.ceil(c/2),f={bottomright:[[0,0],[b,c],[b,0]],bottomleft:[[0,0],[b,0],[0,c]],topright:[[0,c],[b,0],[b,c]],topleft:[[0,0],[0,c],[b,c]],topcenter:[[0,c],[d,0],[b,c]],bottomcenter:[[0,0],[b,0],[d,c]],rightcenter:[[0,0],[b,e],[0,c]],leftcenter:[[b,0],[b,c],[0,e]]};return f.lefttop=f.bottomright,f.righttop=f.bottomleft,f.leftbottom=f.topright,f.rightbottom=f.topleft,f[a.string()]}function M(n,o){function C(){w.width=s.height,w.height=s.width}function D(){w.width=s.width,w.height=s.height}function E(a,d,g,h){if(!t.tip)return;var o=q.corner.clone(),r=g.adjusted,u=n.options.position.adjust.method.split(" "),w=u[0],x=u[1]||u[0],y={left:c,top:c,x:0,y:0},z,A={},B;q.corner.fixed!==b&&(w===p&&o.precedance===e&&r.left&&o.y!==m?o.precedance=o.precedance===e?f:e:w!==p&&r.left&&(o.x=o.x===m?r.left>0?j:l:o.x===j?l:j),x===p&&o.precedance===f&&r.top&&o.x!==m?o.precedance=o.precedance===f?e:f:x!==p&&r.top&&(o.y=o.y===m?r.top>0?i:k:o.y===i?k:i),o.string()!==v.corner.string()&&(v.top!==r.top||v.left!==r.left)&&q.update(o,c)),z=q.position(o,r),z[o.x]+=F(o,o.x,b),z[o.y]+=F(o,o.y,b),z.right!==undefined&&(z.left=-z.right),z.bottom!==undefined&&(z.top=-z.bottom),z.user=Math.max(0,s.offset);if(y.left=w===p&&!!r.left)o.x===m?A["margin-left"]=y.x=z["margin-left"]-r.left:(B=z.right!==undefined?[r.left,-z.left]:[-r.left,z.left],(y.x=Math.max(B[0],B[1]))>B[0]&&(g.left-=r.left,y.left=c),A[z.right!==undefined?l:j]=y.x);if(y.top=x===p&&!!r.top)o.y===m?A["margin-top"]=y.y=z["margin-top"]-r.top:(B=z.bottom!==undefined?[r.top,-z.top]:[-r.top,z.top],(y.y=Math.max(B[0],B[1]))>B[0]&&(g.top-=r.top,y.top=c),A[z.bottom!==undefined?k:i]=y.y);t.tip.css(A).toggle(!(y.x&&y.y||o.x===m&&y.y||o.y===m&&y.x)),g.left-=z.left.charAt?z.user:w!==p||y.top||!y.left&&!y.top?z.left:0,g.top-=z.top.charAt?z.user:x!==p||y.left||!y.left&&!y.top?z.top:0,v.left=r.left,v.top=r.top,v.corner=o.clone()}function F(a,b,c){b=b?b:a[a.precedance];var d=u.hasClass(B),e=t.titlebar&&a.y===i,f=e?t.titlebar:t.tooltip,g="border-"+b+"-width",h;return u.addClass(B),h=parseInt(f.css(g),10),h=(c?h||parseInt(u.css(g),10):h)||0,u.toggleClass(B,d),h}function G(b){function j(a){return parseInt(d.css(a),10)||parseInt(u.css(a),10)}var c=t.titlebar&&b.y===i,d=c?t.titlebar:t.content,e=a.browser.mozilla,f=e?"-moz-":a.browser.webkit?"-webkit-":"",g="border-radius-"+b.y+b.x,h="border-"+b.y+"-"+b.x+"-radius";return j(h)||j(f+h)||j(f+g)||j(g)||0}function H(a){var b=a.precedance===f,c=w[b?g:h],d=w[b?h:g],e=a.string().indexOf(m)>-1,i=c*(e?.5:1),j=Math.pow,k=Math.round,l,n,o,p=Math.sqrt(j(i,2)+j(d,2)),q=[y/i*p,y/d*p];return q[2]=Math.sqrt(j(q[0],2)-j(y,2)),q[3]=Math.sqrt(j(q[1],2)-j(y,2)),l=p+q[2]+q[3]+(e?0:q[0]),n=l/p,o=[k(n*d),k(n*c)],{height:o[b?0:1],width:o[b?1:0]}}var q=this,s=n.options.style.tip,t=n.elements,u=t.tooltip,v={top:0,left:0},w={width:s.width,height:s.height},x={},y=s.border||0,z=".qtip-tip",A=!!(a("<canvas />")[0]||{}).getContext;q.corner=d,q.mimic=d,q.border=y,q.offset=s.offset,q.size=w,n.checks.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){q.init()||q.destroy(),n.reposition()},"^style.tip.(height|width)$":function(){w={width:s.width,height:s.height},q.create(),q.update(),n.reposition()},"^content.title.text|style.(classes|widget)$":function(){t.tip&&t.tip.length&&q.update()}},a.extend(q,{init:function(){var b=q.detectCorner()&&(A||a.browser.msie);return b&&(q.create(),q.update(),u.unbind(z).bind("tooltipmove"+z,E)),b},detectCorner:function(){var a=s.corner,d=n.options.position,e=d.at,f=d.my.string?d.my.string():d.my;return a===c||f===c&&e===c?c:(a===b?q.corner=new r.Corner(f):a.string||(q.corner=new r.Corner(a),q.corner.fixed=b),v.corner=new r.Corner(q.corner.string()),q.corner.string()!=="centercenter")},detectColours:function(b){var c,d,e,f=t.tip.css("cssText",""),g=b||q.corner,h=g[g.precedance],j="border-"+h+"-color",k="border"+h.charAt(0)+h.substr(1)+"Color",l=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,n="background-color",o="transparent",p=" !important",r=t.titlebar&&(g.y===i||g.y===m&&f.position().top+w.height/2+s.offset<t.titlebar.outerHeight(1)),v=r?t.titlebar:t.tooltip;u.addClass(B),x.fill=d=f.css(n),x.border=e=f[0].style[k]||f.css(j)||u.css(j);if(!d||l.test(d))x.fill=v.css(n)||o,l.test(x.fill)&&(x.fill=u.css(n)||d);if(!e||l.test(e)||e===a(document.body).css("color")){x.border=v.css(j)||o;if(l.test(x.border)||x.border===v.css("color"))x.border=u.css(j)||u.css(k)||e}a("*",f).add(f).css("cssText",n+":"+o+p+";border:0"+p+";"),u.removeClass(B)},create:function(){var b=w.width,c=w.height,d;t.tip&&t.tip.remove(),t.tip=a("<div />",{"class":"ui-tooltip-tip"}).css({width:b,height:c}).prependTo(u),A?a("<canvas />").appendTo(t.tip)[0].getContext("2d").save():(d='<vml:shape coordorigin="0,0" style="display:inline-block; position:absolute; behavior:url(#default#VML);"></vml:shape>',t.tip.html(d+d),a("*",t.tip).bind("click mousedown",function(a){a.stopPropagation()}))},update:function(g,h){var n=t.tip,o=n.children(),p=w.width,z=w.height,B="px solid ",E="px dashed transparent",G=s.mimic,I=Math.round,J,K,M,N,O;g||(g=v.corner||q.corner),G===c?G=g:(G=new r.Corner(G),G.precedance=g.precedance,G.x==="inherit"?G.x=g.x:G.y==="inherit"?G.y=g.y:G.x===G.y&&(G[g.precedance]=g[g.precedance])),J=G.precedance,g.precedance===e?C():D(),t.tip.css({width:p=w.width,height:z=w.height}),q.detectColours(g),x.border!=="transparent"?(y=F(g,d,b),s.border===0&&y>0&&(x.fill=x.border),q.border=y=s.border!==b?s.border:y):q.border=y=0,M=L(G,p,z),q.size=O=H(g),n.css(O),g.precedance===f?N=[I(G.x===j?y:G.x===l?O.width-p-y:(O.width-p)/2),I(G.y===i?O.height-z:0)]:N=[I(G.x===j?O.width-p:0),I(G.y===i?y:G.y===k?O.height-z-y:(O.height-z)/2)],A?(o.attr(O),K=o[0].getContext("2d"),K.restore(),K.save(),K.clearRect(0,0,3e3,3e3),K.fillStyle=x.fill,K.strokeStyle=x.border,K.lineWidth=y*2,K.lineJoin="miter",K.miterLimit=100,K.translate(N[0],N[1]),K.beginPath(),K.moveTo(M[0][0],M[0][1]),K.lineTo(M[1][0],M[1][1]),K.lineTo(M[2][0],M[2][1]),K.closePath(),y&&(u.css("background-clip")==="border-box"&&(K.strokeStyle=x.fill,K.stroke()),K.strokeStyle=x.border,K.stroke()),K.fill()):(M="m"+M[0][0]+","+M[0][1]+" l"+M[1][0]+","+M[1][1]+" "+M[2][0]+","+M[2][1]+" xe",N[2]=y&&/^(r|b)/i.test(g.string())?parseFloat(a.browser.version,10)===8?2:1:0,o.css({antialias:""+(G.string().indexOf(m)>-1),left:N[0]-N[2]*Number(J===e),top:N[1]-N[2]*Number(J===f),width:p+y,height:z+y}).each(function(b){var c=a(this);c[c.prop?"prop":"attr"]({coordsize:p+y+" "+(z+y),path:M,fillcolor:x.fill,filled:!!b,stroked:!b}).css({display:y||b?"block":"none"}),!b&&c.html()===""&&c.html('<vml:stroke weight="'+y*2+'px" color="'+x.border+'" miterlimit="1000" joinstyle="miter" '+' style="behavior:url(#default#VML); display:inline-block;" />')})),h!==c&&q.position(g)},position:function(b){var d=t.tip,k={},l=Math.max(0,s.offset),n,o,p;return s.corner===c||!d?c:(b=b||q.corner,n=b.precedance,o=H(b),p=[b.x,b.y],n===e&&p.reverse(),a.each(p,function(a,c){var d,e;c===m?(d=n===f?j:i,k[d]="50%",k["margin-"+d]=-Math.round(o[n===f?g:h]/2)+l):(d=F(b,c),e=G(b),k[c]=a?0:l+(e>d?e:-d))}),k[b[n]]-=o[n===e?g:h],d.css({top:"",bottom:"",left:"",right:"",margin:""}).css(k),k)},destroy:function(){t.tip&&t.tip.remove(),t.tip=!1,u.unbind(z)}}),q.init()}function N(d){function q(){o=a(n,h).not("[disabled]").map(function(){return typeof this.focus=="function"?this:null})}function s(a){o.length<1&&a.length?a.not("body").blur():o.first().focus()}function t(b){var d=a(b.target),e=d.closest(".qtip"),f;f=e.length<1?c:parseInt(e[0].style.zIndex,10)>parseInt(h[0].style.zIndex,10),!f&&a(b.target).closest(x)[0]!==h[0]&&s(d)}var e=this,f=d.options.show.modal,g=d.elements,h=g.tooltip,i="#qtip-overlay",j=".qtipmodal",k=j+d.id,l="is-modal-qtip",m=a(document.body),n=r.modal.focusable.join(","),o={},p;d.checks.modal={"^show.modal.(on|blur)$":function(){e.init(),g.overlay.toggle(h.is(":visible"))},"^content.text$":function(){q()}},a.extend(e,{init:function(){return f.on?(p=e.create(),h.attr(l,b).css("z-index",r.modal.zindex+a(x+"["+l+"]").length).unbind(j).unbind(k).bind("tooltipshow"+j+" tooltiphide"+j,function(b,c,d){var f=b.originalEvent;if(b.target===h[0])if(f&&b.type==="tooltiphide"&&/mouse(leave|enter)/.test(f.type)&&a(f.relatedTarget).closest(p[0]).length)try{b.preventDefault()}catch(g){}else(!f||f&&!f.solo)&&e[b.type.replace("tooltip","")](b,d)}).bind("tooltipfocus"+j,function(b){if(b.isDefaultPrevented()||b.target!==h[0])return;var c=a(x).filter("["+l+"]"),d=r.modal.zindex+c.length,e=parseInt(h[0].style.zIndex,10);p[0].style.zIndex=d-2,c.each(function(){this.style.zIndex>e&&(this.style.zIndex-=1)}),c.end().filter("."+z).qtip("blur",b.originalEvent),h.addClass(z)[0].style.zIndex=d;try{b.preventDefault()}catch(f){}}).bind("tooltiphide"+j,function(b){b.target===h[0]&&a("["+l+"]").filter(":visible").not(h).last().qtip("focus",b)}),f.escape&&a(document).unbind(k).bind("keydown"+k,function(a){a.keyCode===27&&h.hasClass(z)&&d.hide(a)}),f.blur&&g.overlay.unbind(k).bind("click"+k,function(a){h.hasClass(z)&&d.hide(a)}),q(),e):e},create:function(){function d(){p.css({height:a(window).height(),width:a(window).width()})}var b=a(i);return b.length?g.overlay=b.insertAfter(a(x).last()):(p=g.overlay=a("<div />",{id:i.substr(1),html:"<div></div>",mousedown:function(){return c}}).hide().insertAfter(a(x).last()),a(window).unbind(j).bind("resize"+j,d),d(),p)},toggle:function(d,g,i){if(d&&d.isDefaultPrevented())return e;var j=f.effect,n=g?"show":"hide",o=p.is(":visible"),q=a("["+l+"]").filter(":visible").not(h),r;return p||(p=e.create()),p.is(":animated")&&o===g||!g&&q.length?e:(g?(p.css({left:0,top:0}),p.toggleClass("blurs",f.blur),f.stealfocus!==c&&(m.bind("focusin"+k,t),s(a("body *")))):m.unbind("focusin"+k),p.stop(b,c),a.isFunction(j)?j.call(p,g):j===c?p[n]():p.fadeTo(parseInt(i,10)||90,g?1:0,function(){g||a(this).hide()}),g||p.queue(function(a){p.css({left:"",top:""}),a()}),e)},show:function(a,c){return e.toggle(a,b,c)},hide:function(a,b){return e.toggle(a,c,b)},destroy:function(){var b=p;return b&&(b=a("["+l+"]").not(h).length<1,b?(g.overlay.remove(),a(document).unbind(j)):g.overlay.unbind(j+d.id),m.undelegate("*","focusin"+k)),h.removeAttr(l).unbind(j)}}),e.init()}function O(b){var c=this,d=b.elements,e=d.tooltip,f=".bgiframe-"+b.id;a.extend(c,{init:function(){d.bgiframe=a('<iframe class="ui-tooltip-bgiframe" frameborder="0" tabindex="-1" src="javascript:\'\';" style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=0); -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";"></iframe>'),d.bgiframe.appendTo(e),e.bind("tooltipmove"+f,c.adjust)},adjust:function(){var a=b.get("dimensions"),c=b.plugins.tip,f=d.tip,g,h;h=parseInt(e.css("border-left-width"),10)||0,h={left:-h,top:-h},c&&f&&(g=c.corner.precedance==="x"?["width","left"]:["height","top"],h[g[1]]-=f[g[0]]()),d.bgiframe.css(h).css(a)},destroy:function(){d.bgiframe.remove(),e.unbind(f)}}),c.init()}"use strict";var b=!0,c=!1,d=null,e="x",f="y",g="width",h="height",i="top",j="left",k="bottom",l="right",m="center",n="flip",o="flipinvert",p="shift",q,r,s,t={},u="ui-tooltip",v="ui-widget",w="ui-state-disabled",x="div.qtip."+u,y=u+"-default",z=u+"-focus",A=u+"-hover",B=u+"-fluid",C="-31000px",D="_replacedByqTip",E="oldtitle",F;q=a.fn.qtip=function(e,f,g){var h=(""+e).toLowerCase(),i=d,j=a.makeArray(arguments).slice(1),k=j[j.length-1],l=this[0]?a.data(this[0],"qtip"):d;if(!arguments.length&&l||h==="api")return l;if("string"==typeof e)return this.each(function(){var d=a.data(this,"qtip");if(!d)return b;k&&k.timeStamp&&(d.cache.event=k);if(h!=="option"&&h!=="options"||!f)d[h]&&d[h].apply(d[h],j);else if(a.isPlainObject(f)||g!==undefined)d.set(f,g);else return i=d.get(f),c}),i!==d?i:this;if("object"==typeof e||!arguments.length)return l=H(a.extend(b,{},e)),q.bind.call(this,l,k)},q.bind=function(d,e){return this.each(function(f){function m(b){function d(){k.render(typeof b=="object"||g.show.ready),h.show.add(h.hide).unbind(j)}if(k.cache.disabled)return c;k.cache.event=a.extend({},b),k.cache.target=b?a(b.target):[undefined],g.show.delay>0?(clearTimeout(k.timers.show),k.timers.show=setTimeout(d,g.show.delay),i.show!==i.hide&&h.hide.bind(i.hide,function(){clearTimeout(k.timers.show)})):d()}var g,h,i,j,k,l;l=a.isArray(d.id)?d.id[f]:d.id,l=!l||l===c||l.length<1||t[l]?q.nextid++:t[l]=l,j=".qtip-"+l+"-create",k=J.call(this,l,d);if(k===c)return b;g=k.options,a.each(r,function(){this.initialize==="initialize"&&this(k)}),h={show:g.show.target,hide:g.hide.target},i={show:a.trim(""+g.show.event).replace(/ /g,j+" ")+j,hide:a.trim(""+g.hide.event).replace(/ /g,j+" ")+j},/mouse(over|enter)/i.test(i.show)&&!/mouse(out|leave)/i.test(i.hide)&&(i.hide+=" mouseleave"+j),h.show.bind("mousemove"+j,function(a){s={pageX:a.pageX,pageY:a.pageY,type:"mousemove"},k.cache.onTarget=b}),h.show.bind(i.show,m),(g.show.ready||g.prerender)&&m(e)})},r=q.plugins={Corner:function(a){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,m).toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase();var b=a.charAt(0);this.precedance=b==="t"||b==="b"?f:e,this.string=function(){return this.precedance===f?this.y+this.x:this.x+this.y},this.abbrev=function(){var a=this.x.substr(0,1),b=this.y.substr(0,1);return a===b?a:this.precedance===f?b+a:a+b},this.invertx=function(a){this.x=this.x===j?l:this.x===l?j:a||this.x},this.inverty=function(a){this.y=this.y===i?k:this.y===k?i:a||this.y},this.clone=function(){return{x:this.x,y:this.y,precedance:this.precedance,string:this.string,abbrev:this.abbrev,clone:this.clone,invertx:this.invertx,inverty:this.inverty}}},offset:function(b,c){function j(a,b){d.left+=b*a.scrollLeft(),d.top+=b*a.scrollTop()}var d=b.offset(),e=b.closest("body")[0],f=c,g,h,i;if(f){do f.css("position")!=="static"&&(h=f.position(),d.left-=h.left+(parseInt(f.css("borderLeftWidth"),10)||0)+(parseInt(f.css("marginLeft"),10)||0),d.top-=h.top+(parseInt(f.css("borderTopWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0),!g&&(i=f.css("overflow"))!=="hidden"&&i!=="visible"&&(g=f));while((f=a(f[0].offsetParent)).length);g&&g[0]!==e&&j(g,1)}return d},iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||c,fn:{attr:function(b,c){if(this.length){var d=this[0],e="title",f=a.data(d,"qtip");if(b===e&&f&&"object"==typeof f&&f.options.suppress)return arguments.length<2?a.attr(d,E):(f&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",c),this.attr(E,c))}return a.fn["attr"+D].apply(this,arguments)},clone:function(b){var c=a([]),d="title",e=a.fn["clone"+D].apply(this,arguments);return b||e.filter("["+E+"]").attr("title",function(){return a.attr(this,E)}).removeAttr(E),e}}},a.each(r.fn,function(c,d){if(!d||a.fn[c+D])return b;var e=a.fn[c+D]=a.fn[c];a.fn[c]=function(){return d.apply(this,arguments)||e.apply(this,arguments)}}),a.ui||(a["cleanData"+D]=a.cleanData,a.cleanData=function(b){for(var c=0,d;(d=b[c])!==undefined;c++)try{a(d).triggerHandler("removeqtip")}catch(e){}a["cleanData"+D](b)}),q.version="@VERSION",q.nextid=0,q.inactiveEvents="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),q.zindex=15e3,q.defaults={prerender:c,id:c,overwrite:b,suppress:b,content:{text:b,attr:"title",title:{text:c,button:c}},position:{my:"top left",at:"bottom right",target:c,container:c,viewport:c,adjust:{x:0,y:0,mouse:b,resize:b,method:"flip flip"},effect:function(b,d,e){a(this).animate(d,{duration:200,queue:c})}},show:{target:c,event:"mouseenter",effect:b,delay:90,solo:c,ready:c,autofocus:c},hide:{target:c,event:"mouseleave",effect:b,delay:0,fixed:c,inactive:c,leave:"window",distance:c},style:{classes:"",widget:c,width:c,height:c,def:b},events:{render:d,move:d,show:d,hide:d,toggle:d,visible:d,hidden:d,focus:d,blur:d}},r.svg=function(b,c,d,e){var f=a(document),g=c[0],h={width:0,height:0,position:{top:1e10,left:1e10}},i,j,k,l,m;while(!g.getBBox)g=g.parentNode;if(g.getBBox&&g.parentNode){i=g.getBBox(),j=g.getScreenCTM(),k=g.farthestViewportElement||g;if(!k.createSVGPoint)return h;l=k.createSVGPoint(),l.x=i.x,l.y=i.y,m=l.matrixTransform(j),h.position.left=m.x,h.position.top=m.y,l.x+=i.width,l.y+=i.height,m=l.matrixTransform(j),h.width=m.x-h.position.left,h.height=m.y-h.position.top,h.position.left+=f.scrollLeft(),h.position.top+=f.scrollTop()}return h},r.ajax=function(a){var b=a.plugins.ajax;return"object"==typeof b?b:a.plugins.ajax=new K(a)},r.ajax.initialize="render",r.ajax.sanitize=function(a){var b=a.content,c;b&&"ajax"in b&&(c=b.ajax,typeof c!="object"&&(c=a.content.ajax={url:c}),"boolean"!=typeof c.once&&c.once&&(c.once=!!c.once))},a.extend(b,q.defaults,{content:{ajax:{loading:b,once:b}}}),r.tip=function(a){var b=a.plugins.tip;return"object"==typeof b?b:a.plugins.tip=new M(a)},r.tip.initialize="render",r.tip.sanitize=function(a){var c=a.style,d;c&&"tip"in c&&(d=a.style.tip,typeof d!="object"&&(a.style.tip={corner:d}),/string|boolean/i.test(typeof d.corner)||(d.corner=b),typeof d.width!="number"&&delete d.width,typeof d.height!="number"&&delete d.height,typeof d.border!="number"&&d.border!==b&&delete d.border,typeof d.offset!="number"&&delete d.offset)},a.extend(b,q.defaults,{style:{tip:{corner:b,mimic:c,width:6,height:6,border:b,offset:0}}}),r.modal=function(a){var b=a.plugins.modal;return"object"==typeof b?b:a.plugins.modal=new N(a)},r.modal.initialize="render",r.modal.sanitize=function(a){a.show&&(typeof a.show.modal!="object"?a.show.modal={on:!!a.show.modal}:typeof a.show.modal.on=="undefined"&&(a.show.modal.on=b))},r.modal.zindex=q.zindex-200,r.modal.focusable=["a[href]","area[href]","input","select","textarea","button","iframe","object","embed","[tabindex]","[contenteditable]"],a.extend(b,q.defaults,{show:{modal:{on:c,effect:b,blur:b,stealfocus:b,escape:b}}}),r.viewport=function(a,b,c,d,n,q,r){function J(a,c,d,e,f,g,h,i,j){var k=b[f],l=v[a],n=w[a],q=d===p,r=-C.offset[f]+B.offset[f]+B["scroll"+f],s=l===f?j:l===g?-j:-j/2,t=n===f?i:n===g?-i:-i/2,u=E&&E.size?E.size[h]||0:0,x=E&&E.corner&&E.corner.precedance===a&&!q?u:0,y=r-k+x,z=k+j-B[h]-r+x,A=s-(v.precedance===a||l===v[c]?t:0)-(n===m?i/2:0);return q?(x=E&&E.corner&&E.corner.precedance===c?u:0,A=(l===f?1:-1)*s-x,b[f]+=y>0?y:z>0?-z:0,b[f]=Math.max(-C.offset[f]+B.offset[f]+(x&&E.corner[a]===m?E.offset:0),k-A,Math.min(Math.max(-C.offset[f]+B.offset[f]+B[h],k+A),b[f]))):(e*=d===o?2:0,y>0&&(l!==f||z>0)?(b[f]-=A+e,H["invert"+a](f)):z>0&&(l!==g||y>0)&&(b[f]-=(l===m?-A:A)+e,H["invert"+a](g)),b[f]<r&&-b[f]>z&&(b[f]=k,H=undefined)),b[f]-k}var s=c.target,t=a.elements.tooltip,v=c.my,w=c.at,x=c.adjust,y=x.method.split(" "),z=y[0],A=y[1]||y[0],B=c.viewport,C=c.container,D=a.cache,E=a.plugins.tip,F={left:0,top:0},G,H,I;if(!B.jquery||s[0]===window||s[0]===document.body||x.method==="none")return F;G=t.css("position")==="fixed",B={elem:B,height:B[(B[0]===window?"h":"outerH")+"eight"](),width:B[(B[0]===window?"w":"outerW")+"idth"](),scrollleft:G?0:B.scrollLeft(),scrolltop:G?0:B.scrollTop(),offset:B.offset()||{left:0,top:0}},C={elem:C,scrollLeft:C.scrollLeft(),scrollTop:C.scrollTop(),offset:C.offset()||{left:0,top:0}};if(z!=="shift"||A!=="shift")H=v.clone();return F={left:z!=="none"?J(e,f,z,x.x,j,l,g,d,q):0,top:A!=="none"?J(f,e,A,x.y,i,k,h,n,r):0},H&&D.lastClass!==(I=u+"-pos-"+H.abbrev())&&t.removeClass(a.cache.lastClass).addClass(a.cache.lastClass=I),F},r.imagemap=function(b,c,d,e){function v(a,b,c){var d=0,e=1,f=1,g=0,h=0,n=a.width,o=a.height;while(n>0&&o>0&&e>0&&f>0){n=Math.floor(n/2),o=Math.floor(o/2),c.x===j?e=n:c.x===l?e=a.width-n:e+=Math.floor(n/2),c.y===i?f=o:c.y===k?f=a.height-o:f+=Math.floor(o/2),d=b.length;while(d--){if(b.length<2)break;g=b[d][0]-a.position.left,h=b[d][1]-a.position.top,(c.x===j&&g>=e||c.x===l&&g<=e||c.x===m&&(g<e||g>a.width-e)||c.y===i&&h>=f||c.y===k&&h<=f||c.y===m&&(h<f||h>a.height-f))&&b.splice(d,1)}}return{left:b[0][0],top:b[0][1]}}c.jquery||(c=a(c));var f=b.cache.areas={},g=(c[0].shape||c.attr("shape")).toLowerCase(),h=c[0].coords||c.attr("coords"),n=h.split(","),o=[],p=a('img[usemap="#'+c.parent("map").attr("name")+'"]'),q=p.offset(),r={width:0,height:0,position:{top:1e10,right:0,bottom:0,left:1e10}},s=0,t=0,u;q.left+=Math.ceil((p.outerWidth()-p.width())/2),q.top+=Math.ceil((p.outerHeight()-p.height())/2);if(g==="poly"){s=n.length;while(s--)t=[parseInt(n[--s],10),parseInt(n[s+1],10)],t[0]>r.position.right&&(r.position.right=t[0]),t[0]<r.position.left&&(r.position.left=t[0]),t[1]>r.position.bottom&&(r.position.bottom=t[1]),t[1]<r.position.top&&(r.position.top=t[1]),o.push(t)}else{s=-1;while(s++<n.length)o.push(parseInt(n[s],10))}switch(g){case"rect":r={width:Math.abs(o[2]-o[0]),height:Math.abs(o[3]-o[1]),position:{left:Math.min(o[0],o[2]),top:Math.min(o[1],o[3])}};break;case"circle":r={width:o[2]+2,height:o[2]+2,position:{left:o[0],top:o[1]}};break;case"poly":r.width=Math.abs(r.position.right-r.position.left),r.height=Math.abs(r.position.bottom-r.position.top),d.abbrev()==="c"?r.position={left:r.position.left+r.width/2,top:r.position.top+r.height/2}:(f[d+h]||(r.position=v(r,o.slice(),d),e&&(e[0]==="flip"||e[1]==="flip")&&(r.offset=v(r,o.slice(),{x:d.x===j?l:d.x===l?j:m,y:d.y===i?k:d.y===k?i:m}),r.offset.left-=r.position.left,r.offset.top-=r.position.top),f[d+h]=r),r=f[d+h]),r.width=r.height=0}return r.position.left+=q.left,r.position.top+=q.top,r},r.bgiframe=function(b){var d=a.browser,e=b.plugins.bgiframe;return a("select, object").length<1||!d.msie||(""+d.version).charAt(0)!=="6"?c:"object"==typeof e?e:b.plugins.bgiframe=new O(b)},r.bgiframe.initialize="render"});
|
js/venues.js
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var map;
|
2 |
+
var marker;
|
3 |
+
jQuery(document).ready(function () {
|
4 |
+
if (typeof EO_Venue != 'undefined') {
|
5 |
+
postboxes.add_postbox_toggles(pagenow);
|
6 |
+
}
|
7 |
+
|
8 |
+
if (typeof google !== "undefined") {
|
9 |
+
var eo_venue_Lat = jQuery("#eo_venue_Lat").val();
|
10 |
+
var eo_venue_Lng = jQuery("#eo_venue_Lng").val();
|
11 |
+
if (typeof eo_venue_Lat !== "undefined" && typeof eo_venue_Lng !== "undefined") {
|
12 |
+
eo_initialize_map(eo_venue_Lat, eo_venue_Lng);
|
13 |
+
|
14 |
+
if( eo_venue_Lat == 0 && eo_venue_Lng == 0 ){
|
15 |
+
if( typeof EO_Venue != 'undefined'){
|
16 |
+
var address = EO_Venue.location.split("/");
|
17 |
+
address = address[address.length-1];
|
18 |
+
}
|
19 |
+
if( typeof address != 'undefined' && address ){
|
20 |
+
eventorganiser_code_address(address);
|
21 |
+
}else{
|
22 |
+
map.setZoom(1);
|
23 |
+
}
|
24 |
+
}
|
25 |
+
jQuery(".eo_addressInput").change(function () {
|
26 |
+
var address = [];
|
27 |
+
jQuery(".eo_addressInput").each(function () {
|
28 |
+
address.push(jQuery(this).val());
|
29 |
+
});
|
30 |
+
eventorganiser_code_address(address.join(', '))
|
31 |
+
})
|
32 |
+
}
|
33 |
+
}
|
34 |
+
});
|
35 |
+
|
36 |
+
function eo_initialize_map(Lat, Lng) {
|
37 |
+
|
38 |
+
if (typeof google !== "undefined") {
|
39 |
+
var latlng = new google.maps.LatLng(Lat, Lng);
|
40 |
+
|
41 |
+
var myOptions = {
|
42 |
+
zoom: 15,
|
43 |
+
center: latlng,
|
44 |
+
mapTypeId: google.maps.MapTypeId.ROADMAP
|
45 |
+
};
|
46 |
+
|
47 |
+
map = new google.maps.Map(document.getElementById("venuemap"), myOptions);
|
48 |
+
|
49 |
+
if (typeof EO_Venue != 'undefined') {
|
50 |
+
var draggable = true
|
51 |
+
} else {
|
52 |
+
var draggable = false
|
53 |
+
}
|
54 |
+
|
55 |
+
marker = new google.maps.Marker({
|
56 |
+
position: latlng,
|
57 |
+
map: map,
|
58 |
+
draggable: draggable
|
59 |
+
});
|
60 |
+
|
61 |
+
if (typeof EO_Venue != 'undefined') {
|
62 |
+
google.maps.event.addListener(marker, 'dragend', function (evt) {
|
63 |
+
jQuery("#eo_venue_Lat").val(evt.latLng.lat().toFixed(6));
|
64 |
+
jQuery("#eo_venue_Lng").val(evt.latLng.lng().toFixed(6));
|
65 |
+
map.setCenter(marker.position)
|
66 |
+
})
|
67 |
+
}
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
function eventorganiser_code_address(addrStr) {
|
72 |
+
var geocoder = new google.maps.Geocoder();
|
73 |
+
geocoder.geocode({'address': addrStr}, function (results, status) {
|
74 |
+
if ( status == google.maps.GeocoderStatus.OK){
|
75 |
+
|
76 |
+
marker.setMap(null);
|
77 |
+
map.setCenter(results[0].geometry.location);
|
78 |
+
if (typeof EO_Venue != 'undefined') {
|
79 |
+
var draggable = true
|
80 |
+
} else {
|
81 |
+
var draggable = false
|
82 |
+
}
|
83 |
+
marker = new google.maps.Marker({
|
84 |
+
map: map,
|
85 |
+
position: results[0].geometry.location,
|
86 |
+
draggable: draggable
|
87 |
+
});
|
88 |
+
map.setZoom(15);
|
89 |
+
if (typeof EO_Venue != 'undefined') {
|
90 |
+
google.maps.event.addListener(marker, 'dragend', function (evt) {
|
91 |
+
jQuery("#eo_venue_Lat").val(evt.latLng.lat().toFixed(6));
|
92 |
+
jQuery("#eo_venue_Lng").val(evt.latLng.lng().toFixed(6));
|
93 |
+
map.setCenter(marker.position)
|
94 |
+
})
|
95 |
+
}
|
96 |
+
jQuery("#eo_venue_Lat").val(results[0].geometry.location.lat());
|
97 |
+
jQuery("#eo_venue_Lng").val(results[0].geometry.location.lng());
|
98 |
+
}
|
99 |
+
})
|
100 |
+
}
|
js/venues.min.js
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var map,marker;
|
2 |
+
jQuery(document).ready(function(){typeof EO_Venue!="undefined"&&postboxes.add_postbox_toggles(pagenow);if(typeof google!=="undefined"){var c=jQuery("#eo_venue_Lat").val(),a=jQuery("#eo_venue_Lng").val();if(typeof c!=="undefined"&&typeof a!=="undefined"){eo_initialize_map(c,a);if(c==0&&a==0){if(typeof EO_Venue!="undefined"){var b=EO_Venue.location.split("/");b=b[b.length-1]}typeof b!="undefined"&&b?eventorganiser_code_address(b):map.setZoom(1)}jQuery(".eo_addressInput").change(function(){var d=[];
|
3 |
+
jQuery(".eo_addressInput").each(function(){d.push(jQuery(this).val())});eventorganiser_code_address(d.join(", "))})}}});
|
4 |
+
function eo_initialize_map(c,a){if(typeof google!=="undefined"){c=new google.maps.LatLng(c,a);a={zoom:15,center:c,mapTypeId:google.maps.MapTypeId.ROADMAP};map=new google.maps.Map(document.getElementById("venuemap"),a);marker=new google.maps.Marker({position:c,map:map,draggable:typeof EO_Venue!="undefined"?true:false});typeof EO_Venue!="undefined"&&google.maps.event.addListener(marker,"dragend",function(b){jQuery("#eo_venue_Lat").val(b.latLng.lat().toFixed(6));jQuery("#eo_venue_Lng").val(b.latLng.lng().toFixed(6));
|
5 |
+
map.setCenter(marker.position)})}}
|
6 |
+
function eventorganiser_code_address(c){(new google.maps.Geocoder).geocode({address:c},function(a,b){if(b==google.maps.GeocoderStatus.OK){marker.setMap(null);map.setCenter(a[0].geometry.location);marker=new google.maps.Marker({map:map,position:a[0].geometry.location,draggable:typeof EO_Venue!="undefined"?true:false});map.setZoom(15);typeof EO_Venue!="undefined"&&google.maps.event.addListener(marker,"dragend",function(d){jQuery("#eo_venue_Lat").val(d.latLng.lat().toFixed(6));jQuery("#eo_venue_Lng").val(d.latLng.lng().toFixed(6));
|
7 |
+
map.setCenter(marker.position)});jQuery("#eo_venue_Lat").val(a[0].geometry.location.lat());jQuery("#eo_venue_Lng").val(a[0].geometry.location.lng())}})};
|
languages/eventorganiser-da_DK.mo
ADDED
Binary file
|
languages/eventorganiser-da_DK.po
ADDED
@@ -0,0 +1,1538 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
msgid ""
|
2 |
+
msgstr ""
|
3 |
+
"Project-Id-Version: Event Organiser\n"
|
4 |
+
"Report-Msgid-Bugs-To: \n"
|
5 |
+
"POT-Creation-Date: 2012-04-04 01:40+0100\n"
|
6 |
+
"PO-Revision-Date: 2012-09-02 00:57+0100\n"
|
7 |
+
"Last-Translator: Intox Studio <jv@intox.dk>\n"
|
8 |
+
"Language-Team: Intox Studio <jv@intox.dk>\n"
|
9 |
+
"Language: da_DK\n"
|
10 |
+
"MIME-Version: 1.0\n"
|
11 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
12 |
+
"Content-Transfer-Encoding: 8bit\n"
|
13 |
+
"X-Poedit-KeywordsList: __;_e;ngettext;_n\n"
|
14 |
+
"X-Poedit-Basepath: .\n"
|
15 |
+
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
16 |
+
"X-Poedit-SearchPath-0: ..\n"
|
17 |
+
|
18 |
+
#: ../event-organiser-manage.php:18 ../includes/event-organiser-cpt.php:130
|
19 |
+
msgid "Event"
|
20 |
+
msgstr "Begivenhed"
|
21 |
+
|
22 |
+
#: ../event-organiser-manage.php:22 ../event-organiser-settings.php:180
|
23 |
+
#: ../event-organiser-edit.php:27 ../includes/event-organiser-ajax.php:180
|
24 |
+
msgid "Organiser"
|
25 |
+
msgstr "Arrangør"
|
26 |
+
|
27 |
+
#: ../event-organiser-manage.php:24 ../event-organiser-venues.php:24
|
28 |
+
#: ../event-organiser-edit.php:145
|
29 |
+
#: ../classes/class-eo-event-list-widget.php:43
|
30 |
+
msgid "Venue"
|
31 |
+
msgstr "Sted"
|
32 |
+
|
33 |
+
#: ../event-organiser-manage.php:25 ../includes/event-organiser-cpt.php:67
|
34 |
+
msgid "Categories"
|
35 |
+
msgstr "Kategorier"
|
36 |
+
|
37 |
+
#: ../event-organiser-manage.php:26 ../event-organiser-edit.php:69
|
38 |
+
msgid "Start Date/Time"
|
39 |
+
msgstr "Startdato/-tid"
|
40 |
+
|
41 |
+
#: ../event-organiser-manage.php:27 ../event-organiser-edit.php:76
|
42 |
+
msgid "End Date/Time"
|
43 |
+
msgstr "Slutdato/-tid"
|
44 |
+
|
45 |
+
#: ../event-organiser-manage.php:28
|
46 |
+
msgid "Reoccurrence"
|
47 |
+
msgstr "Gentagelse"
|
48 |
+
|
49 |
+
#: ../event-organiser-manage.php:109 ../event-organiser-calendar.php:48
|
50 |
+
#: ../includes/event-organiser-register.php:26
|
51 |
+
msgid "View all categories"
|
52 |
+
msgstr "Vis alle kategorier"
|
53 |
+
|
54 |
+
#: ../event-organiser-manage.php:123 ../event-organiser-calendar.php:49
|
55 |
+
#: ../includes/event-organiser-register.php:27
|
56 |
+
msgid "View all venues"
|
57 |
+
msgstr "Vis alle steder"
|
58 |
+
|
59 |
+
#: ../event-organiser-manage.php:136
|
60 |
+
msgid "View all events"
|
61 |
+
msgstr "Vis alle begivenheder"
|
62 |
+
|
63 |
+
#: ../event-organiser-manage.php:137
|
64 |
+
msgid "Future events"
|
65 |
+
msgstr "Fremtidige begivenheder"
|
66 |
+
|
67 |
+
#: ../event-organiser-manage.php:138
|
68 |
+
msgid "Expired events"
|
69 |
+
msgstr "Udløbne begivenheder"
|
70 |
+
|
71 |
+
#: ../event-organiser-manage.php:139
|
72 |
+
msgid "Events within 24 hours"
|
73 |
+
msgstr "Begivenheder inden for 24 timer"
|
74 |
+
|
75 |
+
#: ../event-organiser-manage.php:140
|
76 |
+
msgid "Events within 1 week"
|
77 |
+
msgstr "Begivenheder inden for 1 uge"
|
78 |
+
|
79 |
+
#: ../event-organiser-manage.php:141
|
80 |
+
#, php-format
|
81 |
+
msgid "Events within %d weeks"
|
82 |
+
msgstr "Begivenheder inden for %d uger"
|
83 |
+
|
84 |
+
#: ../event-organiser-manage.php:142
|
85 |
+
msgid "Events within 1 month"
|
86 |
+
msgstr "Begivenheder inden for 1 måned"
|
87 |
+
|
88 |
+
#: ../event-organiser-manage.php:143
|
89 |
+
#, php-format
|
90 |
+
msgid "Events within %d months"
|
91 |
+
msgstr "Begivenheder inden for %d måneder"
|
92 |
+
|
93 |
+
#: ../event-organiser-manage.php:144
|
94 |
+
msgid "Events within 1 year"
|
95 |
+
msgstr "Begivenheder inden for 1 år"
|
96 |
+
|
97 |
+
#: ../event-organiser-manage.php:189
|
98 |
+
msgid "— No Change —"
|
99 |
+
msgstr "— Ingen ændringer —"
|
100 |
+
|
101 |
+
#: ../event-organiser.php:51 ../event-organiser-settings.php:182
|
102 |
+
msgid "Edit Events"
|
103 |
+
msgstr "Rediger begivenheder"
|
104 |
+
|
105 |
+
#: ../event-organiser.php:52 ../event-organiser-settings.php:183
|
106 |
+
msgid "Publish Events"
|
107 |
+
msgstr "Udgiv begivenheder"
|
108 |
+
|
109 |
+
#: ../event-organiser.php:53 ../event-organiser-settings.php:184
|
110 |
+
msgid "Delete Events"
|
111 |
+
msgstr "Slet begivenheder"
|
112 |
+
|
113 |
+
#: ../event-organiser.php:54 ../event-organiser-settings.php:185
|
114 |
+
msgid "Edit Others' Events"
|
115 |
+
msgstr "Rediger andres begivenheder"
|
116 |
+
|
117 |
+
#: ../event-organiser.php:55 ../event-organiser-settings.php:186
|
118 |
+
msgid "Delete Other's Events"
|
119 |
+
msgstr "Slet andres begivenheder"
|
120 |
+
|
121 |
+
#: ../event-organiser.php:56 ../event-organiser-settings.php:187
|
122 |
+
msgid "Read Private Events"
|
123 |
+
msgstr "Læs private begivenheder"
|
124 |
+
|
125 |
+
#: ../event-organiser.php:57 ../event-organiser-settings.php:188
|
126 |
+
msgid "Manage Venues"
|
127 |
+
msgstr "Håndter steder"
|
128 |
+
|
129 |
+
#: ../event-organiser.php:58 ../event-organiser-settings.php:189
|
130 |
+
msgid "Manage Event Categories & Tags"
|
131 |
+
msgstr "Håndter begivenhedskategorier og -tags"
|
132 |
+
|
133 |
+
#: ../event-organiser-venues.php:10 ../event-organiser-venues.php:11
|
134 |
+
#: ../event-organiser-venues.php:80 ../event-organiser-venues.php:136
|
135 |
+
#: ../event-organiser-settings.php:426
|
136 |
+
msgid "Venues"
|
137 |
+
msgstr "Steder"
|
138 |
+
|
139 |
+
#: ../event-organiser-venues.php:25 ../event-organiser-venues.php:204
|
140 |
+
msgid "Address"
|
141 |
+
msgstr "Adresse"
|
142 |
+
|
143 |
+
#: ../event-organiser-venues.php:26 ../event-organiser-venues.php:208
|
144 |
+
msgid "Post Code"
|
145 |
+
msgstr "Postnummer"
|
146 |
+
|
147 |
+
#: ../event-organiser-venues.php:27 ../event-organiser-venues.php:212
|
148 |
+
msgid "Country"
|
149 |
+
msgstr "Land"
|
150 |
+
|
151 |
+
#: ../event-organiser-venues.php:28
|
152 |
+
msgid "Slug"
|
153 |
+
msgstr "Kort titel"
|
154 |
+
|
155 |
+
#: ../event-organiser-venues.php:29 ../event-organiser-settings.php:102
|
156 |
+
#: ../event-organiser-settings.php:313 ../event-organiser-settings.php:419
|
157 |
+
#: ../includes/event-organiser-install.php:63
|
158 |
+
#: ../includes/event-organiser-install.php:146
|
159 |
+
#: ../includes/event-organiser-cpt.php:129
|
160 |
+
#: ../includes/event-organiser-cpt.php:141
|
161 |
+
#: ../classes/class-eo-event-list-widget.php:23
|
162 |
+
msgid "Events"
|
163 |
+
msgstr "Begivenheder"
|
164 |
+
|
165 |
+
#: ../event-organiser-venues.php:49
|
166 |
+
msgid "You do not have permission to manage venues"
|
167 |
+
msgstr "Du har ikke rettigheder til at håndtere steder"
|
168 |
+
|
169 |
+
#: ../event-organiser-venues.php:54 ../event-organiser-venues.php:61
|
170 |
+
msgid "You do not have permission to edit this venue."
|
171 |
+
msgstr "Du har ikke rettigheder til at redigere dette sted."
|
172 |
+
|
173 |
+
#: ../event-organiser-venues.php:73
|
174 |
+
msgid "You do not have permission to delete this venue"
|
175 |
+
msgstr "Du har ikke rettigheder til at slette dette sted"
|
176 |
+
|
177 |
+
#: ../event-organiser-venues.php:110 ../includes/event-organiser-cpt.php:30
|
178 |
+
msgid "Edit Venue"
|
179 |
+
msgstr "Rediger sted"
|
180 |
+
|
181 |
+
#: ../event-organiser-venues.php:114 ../includes/event-organiser-cpt.php:32
|
182 |
+
msgid "Add New Venue"
|
183 |
+
msgstr "Tilføj nyt sted"
|
184 |
+
|
185 |
+
#: ../event-organiser-venues.php:139
|
186 |
+
#, php-format
|
187 |
+
msgid "Search results for “%s”"
|
188 |
+
msgstr "Søgeresultater for “%s”"
|
189 |
+
|
190 |
+
#: ../event-organiser-venues.php:149 ../includes/event-organiser-cpt.php:28
|
191 |
+
msgid "Search Venues"
|
192 |
+
msgstr "Søg steder"
|
193 |
+
|
194 |
+
#: ../event-organiser-venues.php:180
|
195 |
+
msgid "Venue name"
|
196 |
+
msgstr "Stednavn"
|
197 |
+
|
198 |
+
#: ../event-organiser-venues.php:185
|
199 |
+
msgid "Permalink:"
|
200 |
+
msgstr "Permanent link:"
|
201 |
+
|
202 |
+
#: ../event-organiser-venues.php:192
|
203 |
+
msgid "Get Link"
|
204 |
+
msgstr "Vis link"
|
205 |
+
|
206 |
+
#: ../event-organiser-venues.php:193
|
207 |
+
msgid "View Venue"
|
208 |
+
msgstr "Vis sted"
|
209 |
+
|
210 |
+
#: ../event-organiser-venues.php:200
|
211 |
+
msgid "Venue Location"
|
212 |
+
msgstr "Stedlokation"
|
213 |
+
|
214 |
+
#: ../event-organiser-venues.php:229 ../includes/event-organiser-cpt.php:31
|
215 |
+
msgid "Update Venue"
|
216 |
+
msgstr "Opdater sted"
|
217 |
+
|
218 |
+
#: ../event-organiser-venues.php:229
|
219 |
+
msgid "Add Venue"
|
220 |
+
msgstr "Tilføj sted"
|
221 |
+
|
222 |
+
#: ../event-organiser-settings.php:16
|
223 |
+
msgid "Event Organiser Settings"
|
224 |
+
msgstr "Indstillinger for begivenhedsarrangør"
|
225 |
+
|
226 |
+
#: ../event-organiser-settings.php:28 ../event-organiser-settings.php:326
|
227 |
+
msgid "dd-mm-yyyy"
|
228 |
+
msgstr "dd-mm-yyyy"
|
229 |
+
|
230 |
+
#: ../event-organiser-settings.php:29 ../event-organiser-settings.php:327
|
231 |
+
msgid "mm-dd-yyyy"
|
232 |
+
msgstr "mm-dd-yyyy"
|
233 |
+
|
234 |
+
#: ../event-organiser-settings.php:41 ../event-organiser-settings.php:353
|
235 |
+
msgid "Yes"
|
236 |
+
msgstr "Ja"
|
237 |
+
|
238 |
+
#: ../event-organiser-settings.php:42 ../event-organiser-settings.php:355
|
239 |
+
msgid "No"
|
240 |
+
msgstr "Nej"
|
241 |
+
|
242 |
+
#: ../event-organiser-settings.php:180
|
243 |
+
msgid "Author"
|
244 |
+
msgstr "Forfatter"
|
245 |
+
|
246 |
+
#: ../event-organiser-settings.php:180
|
247 |
+
msgid "Thumbnail"
|
248 |
+
msgstr "Thumbnail"
|
249 |
+
|
250 |
+
#: ../event-organiser-settings.php:180
|
251 |
+
msgid "Excerpt"
|
252 |
+
msgstr "Uddrag"
|
253 |
+
|
254 |
+
#: ../event-organiser-settings.php:180
|
255 |
+
msgid "Custom Fields"
|
256 |
+
msgstr "Egne felter"
|
257 |
+
|
258 |
+
#: ../event-organiser-settings.php:180
|
259 |
+
msgid "Comments"
|
260 |
+
msgstr "Kommentarer"
|
261 |
+
|
262 |
+
#: ../event-organiser-settings.php:180
|
263 |
+
msgid "Revisions"
|
264 |
+
msgstr "Ændringer"
|
265 |
+
|
266 |
+
#: ../event-organiser-settings.php:200
|
267 |
+
msgid "Event Settings"
|
268 |
+
msgstr "Begivenhedsindstillinger"
|
269 |
+
|
270 |
+
#: ../event-organiser-settings.php:201
|
271 |
+
msgid "General"
|
272 |
+
msgstr "Generelt"
|
273 |
+
|
274 |
+
#: ../event-organiser-settings.php:202
|
275 |
+
msgid "Permissions"
|
276 |
+
msgstr "Rettigheder"
|
277 |
+
|
278 |
+
#: ../event-organiser-settings.php:203
|
279 |
+
msgid "Permalinks"
|
280 |
+
msgstr "Permanente links"
|
281 |
+
|
282 |
+
#: ../event-organiser-settings.php:204
|
283 |
+
msgid "Import"
|
284 |
+
msgstr "Importer"
|
285 |
+
|
286 |
+
#: ../event-organiser-settings.php:204
|
287 |
+
msgid "Export"
|
288 |
+
msgstr "Eksporter"
|
289 |
+
|
290 |
+
#: ../event-organiser-settings.php:234
|
291 |
+
msgid "Save Changes"
|
292 |
+
msgstr "Gem ændringer"
|
293 |
+
|
294 |
+
#: ../event-organiser-settings.php:242
|
295 |
+
msgid "Set permissions for events and venue management"
|
296 |
+
msgstr "Opsæt rettigheder for håndtering af begivenheder og steder"
|
297 |
+
|
298 |
+
#: ../event-organiser-settings.php:247
|
299 |
+
msgid "Role"
|
300 |
+
msgstr "Rolle"
|
301 |
+
|
302 |
+
#: ../event-organiser-settings.php:258
|
303 |
+
msgid "None"
|
304 |
+
msgstr "Ingen"
|
305 |
+
|
306 |
+
#: ../event-organiser-settings.php:279
|
307 |
+
msgid "Select which features events should support"
|
308 |
+
msgstr "Vælg hvilke egenskaber begivenheder skal understøtte"
|
309 |
+
|
310 |
+
#: ../event-organiser-settings.php:295 ../event-organiser-settings.php:440
|
311 |
+
#: ../includes/event-organiser-cpt.php:88
|
312 |
+
msgid "Event Tags"
|
313 |
+
msgstr "Begivenhedstags"
|
314 |
+
|
315 |
+
#: ../event-organiser-settings.php:301
|
316 |
+
msgid "Add an 'events' link to the navigation menu:"
|
317 |
+
msgstr "Tilføj et link for 'begivenheder' til menuen:"
|
318 |
+
|
319 |
+
#: ../event-organiser-settings.php:306
|
320 |
+
msgid "Do not add to menu"
|
321 |
+
msgstr "Tilføj ikke til menu"
|
322 |
+
|
323 |
+
#: ../event-organiser-settings.php:310
|
324 |
+
msgid "Page list (fallback)"
|
325 |
+
msgstr "Sideliste (tilbagefald)"
|
326 |
+
|
327 |
+
#: ../event-organiser-settings.php:318
|
328 |
+
msgid "(This may not work with some themes):"
|
329 |
+
msgstr "(Dette virker muligvis ikke med nogle temaer):"
|
330 |
+
|
331 |
+
#: ../event-organiser-settings.php:322
|
332 |
+
msgid "Date Format:"
|
333 |
+
msgstr "Dato-format:"
|
334 |
+
|
335 |
+
#: ../event-organiser-settings.php:329
|
336 |
+
msgid "This alters the default format for inputting dates."
|
337 |
+
msgstr "Dette ændrer standardformatet for at indtaste datoer."
|
338 |
+
|
339 |
+
#: ../event-organiser-settings.php:334
|
340 |
+
msgid "Show past events:"
|
341 |
+
msgstr "Vis tidligere begivenheder:"
|
342 |
+
|
343 |
+
#: ../event-organiser-settings.php:337
|
344 |
+
msgid ""
|
345 |
+
"Display past events on calendars, event lists and archives (this can be over-"
|
346 |
+
"ridden by shortcode attributes and widget options)."
|
347 |
+
msgstr ""
|
348 |
+
"Vis overståede begivenheder i kalendere, lister og arkiver (dette kan "
|
349 |
+
"tilsidesættes af shortcode-attributter og widget-indstillinger)."
|
350 |
+
|
351 |
+
#: ../event-organiser-settings.php:341
|
352 |
+
#: ../classes/class-eo-event-list-widget.php:69
|
353 |
+
msgid "Group occurrences"
|
354 |
+
msgstr "Gruppér gentagelser"
|
355 |
+
|
356 |
+
#: ../event-organiser-settings.php:345
|
357 |
+
msgid ""
|
358 |
+
"If selected only one occurrence of an event will be displayed on event lists "
|
359 |
+
"and archives (this can be over-ridden by shortcode attributes and widget "
|
360 |
+
"options)."
|
361 |
+
msgstr ""
|
362 |
+
"Hvis valgt vil kun én forekomst af en begivenhed blive vist på "
|
363 |
+
"begivenhedslister og -arkiver (dette kan tilsidesættes af shortcode-"
|
364 |
+
"attributter og widget-indstillinger)."
|
365 |
+
|
366 |
+
#: ../event-organiser-settings.php:349
|
367 |
+
msgid "Are current events past?"
|
368 |
+
msgstr "Er igangværende begivenheder overståede?"
|
369 |
+
|
370 |
+
#: ../event-organiser-settings.php:356
|
371 |
+
msgid ""
|
372 |
+
"If 'no' is selected, an occurrence of an event is only past when it has "
|
373 |
+
"finished. Otherwise, an occurrence is considered 'past' as soon as it starts."
|
374 |
+
msgstr ""
|
375 |
+
"Hvis 'nej' er valgt, er en forekomst af en begivenhed først overstået, når "
|
376 |
+
"den er slut. Ellers vil en begivenhed betragtes som 'overstået', så snart "
|
377 |
+
"den starter."
|
378 |
+
|
379 |
+
#: ../event-organiser-settings.php:360
|
380 |
+
msgid "Delete expired events:"
|
381 |
+
msgstr "Slet udløbne begivenheder:"
|
382 |
+
|
383 |
+
#: ../event-organiser-settings.php:363
|
384 |
+
msgid ""
|
385 |
+
"If selected the event will be automatically trashed 24 hours after the last "
|
386 |
+
"occurrence finishes."
|
387 |
+
msgstr ""
|
388 |
+
"Hvis valgt, vil begivenheden automatisk blive lagt i papirkurven 24 timer "
|
389 |
+
"efter den sidste gentagelse slutter."
|
390 |
+
|
391 |
+
#: ../event-organiser-settings.php:367
|
392 |
+
msgid "Enable events ICAL feed:"
|
393 |
+
msgstr "Aktiver ICAL-feed for begivenheder:"
|
394 |
+
|
395 |
+
#: ../event-organiser-settings.php:370
|
396 |
+
#, php-format
|
397 |
+
msgid "If selected, visitors can subscribe to your events with the url: %s"
|
398 |
+
msgstr "Hvis valgt, kan besøgende abonnere på dine begivenheder med url'en: %s"
|
399 |
+
|
400 |
+
#: ../event-organiser-settings.php:375
|
401 |
+
msgid "Exclude events from searches:"
|
402 |
+
msgstr "Ekskluder begivenheder fra søgninger:"
|
403 |
+
|
404 |
+
#: ../event-organiser-settings.php:381
|
405 |
+
msgid "Enable templates:"
|
406 |
+
msgstr "Aktiver skabeloner:"
|
407 |
+
|
408 |
+
#: ../event-organiser-settings.php:383
|
409 |
+
msgid ""
|
410 |
+
"For each of the pages, the corresponding template is used. To use your own "
|
411 |
+
"template simply give it the same name and store in your theme folder. By "
|
412 |
+
"default, if Event Organiser cannot find a template in your theme directory, "
|
413 |
+
"it will use its own default template. To prevent this, uncheck this option. "
|
414 |
+
"WordPress will then decide which template from your theme's folder to use."
|
415 |
+
msgstr ""
|
416 |
+
"For hver side benyttes den tilsvarende skabelon. For at benytte din egen "
|
417 |
+
"skabelon, skal du navngive den det samme navn og gemme den i din tema-mappe. "
|
418 |
+
"Som standard, hvis Event Organiser ikke kan finde en skabelon i dit tema, "
|
419 |
+
"vil en standardskabelon benyttes i stedet. For at undgå dette skal fluebenet "
|
420 |
+
"fjernes fra denne indstilling. WordPress vil herefter afgøre hvilken "
|
421 |
+
"skabelon der skal benyttes fra din tema-mappe."
|
422 |
+
|
423 |
+
#: ../event-organiser-settings.php:385
|
424 |
+
msgid "Events archives:"
|
425 |
+
msgstr "Side til begivenhedsarkiver:"
|
426 |
+
|
427 |
+
#: ../event-organiser-settings.php:388
|
428 |
+
msgid "Event page:"
|
429 |
+
msgstr "Side til begivenhed:"
|
430 |
+
|
431 |
+
#: ../event-organiser-settings.php:391
|
432 |
+
msgid "Venue page:"
|
433 |
+
msgstr "Side til sted:"
|
434 |
+
|
435 |
+
#: ../event-organiser-settings.php:394
|
436 |
+
msgid "Events Category page:"
|
437 |
+
msgstr "Side til begivenhedskategori:"
|
438 |
+
|
439 |
+
#: ../event-organiser-settings.php:407
|
440 |
+
msgid ""
|
441 |
+
"Choose a custom permalink structure for events, venues, event categories and "
|
442 |
+
"event tags."
|
443 |
+
msgstr ""
|
444 |
+
"Vælg en brugerdefineret struktur til permalinks for begivenheder, steder, "
|
445 |
+
"begivenhedskategorier og -tags."
|
446 |
+
|
447 |
+
#: ../event-organiser-settings.php:409
|
448 |
+
msgid ""
|
449 |
+
"Please note to enable these structures you must first have pretty permalinks "
|
450 |
+
"enabled on WordPress in Settings > Permalinks."
|
451 |
+
msgstr ""
|
452 |
+
"Bemærk at dette kræver, at du har aktiveret pæne permalinks for WordPress "
|
453 |
+
"under Indstillinger > Permanente links."
|
454 |
+
|
455 |
+
#: ../event-organiser-settings.php:414
|
456 |
+
msgid "Enable event pretty permalinks:"
|
457 |
+
msgstr "Aktiver pæne permalinks til begivenheder"
|
458 |
+
|
459 |
+
#: ../event-organiser-settings.php:416
|
460 |
+
msgid ""
|
461 |
+
"If you have pretty permalinks enabled, select to have pretty premalinks for "
|
462 |
+
"events."
|
463 |
+
msgstr ""
|
464 |
+
"Hvis du har aktiveret pæne permalinks, vælg dette for også at aktivere det "
|
465 |
+
"til begivenheder."
|
466 |
+
|
467 |
+
#: ../event-organiser-settings.php:433 ../includes/event-organiser-cpt.php:56
|
468 |
+
msgid "Event Categories"
|
469 |
+
msgstr "Begivenhedskategorier"
|
470 |
+
|
471 |
+
#: ../event-organiser-settings.php:447
|
472 |
+
msgid ""
|
473 |
+
"Please note that you will need go to WordPress Settings > Permalinks and "
|
474 |
+
"click 'Save Changes' before any changes will take effect."
|
475 |
+
msgstr ""
|
476 |
+
"Bemærk at du skal gå til Indstillinger > Permanente links og klikke 'Gem "
|
477 |
+
"ændringer' før eventuelle ændringer vil træde i kraft."
|
478 |
+
|
479 |
+
#: ../event-organiser-edit.php:16
|
480 |
+
msgid "Event Details"
|
481 |
+
msgstr "Begivenhedsdetaljer"
|
482 |
+
|
483 |
+
#: ../event-organiser-edit.php:59
|
484 |
+
msgid "This is a reoccurring event"
|
485 |
+
msgstr "Dette er en gentagende begivenhed"
|
486 |
+
|
487 |
+
#: ../event-organiser-edit.php:61
|
488 |
+
msgid "Check to edit this event and its reoccurrences"
|
489 |
+
msgstr "Marker for at redigere denne begivenhed og dens gentagelser"
|
490 |
+
|
491 |
+
#: ../event-organiser-edit.php:66
|
492 |
+
#, php-format
|
493 |
+
msgid ""
|
494 |
+
"Ensure dates are entered in %1$s format and times in %2$s (24 hour) format"
|
495 |
+
msgstr ""
|
496 |
+
"Dobbelttjek at datoer er indtastet i formatet %1$s og tider i formatet %2$s "
|
497 |
+
"(24 timer)"
|
498 |
+
|
499 |
+
#: ../event-organiser-edit.php:82
|
500 |
+
msgid "All day"
|
501 |
+
msgstr "Hele dagen"
|
502 |
+
|
503 |
+
#: ../event-organiser-edit.php:88
|
504 |
+
msgid "Reoccurence:"
|
505 |
+
msgstr "Gentagelse:"
|
506 |
+
|
507 |
+
#: ../event-organiser-edit.php:92
|
508 |
+
msgid "once"
|
509 |
+
msgstr "ingen"
|
510 |
+
|
511 |
+
#: ../event-organiser-edit.php:93
|
512 |
+
msgid "daily"
|
513 |
+
msgstr "dagligt"
|
514 |
+
|
515 |
+
#: ../event-organiser-edit.php:94
|
516 |
+
msgid "weekly"
|
517 |
+
msgstr "ugentligt"
|
518 |
+
|
519 |
+
#: ../event-organiser-edit.php:95
|
520 |
+
msgid "monthly"
|
521 |
+
msgstr "månedligt"
|
522 |
+
|
523 |
+
#: ../event-organiser-edit.php:96
|
524 |
+
msgid "yearly"
|
525 |
+
msgstr "årligt"
|
526 |
+
|
527 |
+
#: ../event-organiser-edit.php:109
|
528 |
+
msgid "Repeat every "
|
529 |
+
msgstr "Gentag hver"
|
530 |
+
|
531 |
+
#: ../event-organiser-edit.php:115
|
532 |
+
#: ../classes/class-eo-event-list-widget.php:116
|
533 |
+
msgid "on"
|
534 |
+
msgstr "på"
|
535 |
+
|
536 |
+
#: ../event-organiser-edit.php:129
|
537 |
+
msgid "day of month"
|
538 |
+
msgstr "dag i måneden"
|
539 |
+
|
540 |
+
#: ../event-organiser-edit.php:131
|
541 |
+
msgid "day of week"
|
542 |
+
msgstr "dag i ugen"
|
543 |
+
|
544 |
+
#: ../event-organiser-edit.php:135
|
545 |
+
#: ../includes/event-organiser-register.php:132
|
546 |
+
#: ../includes/event-organiser-event-functions.php:536
|
547 |
+
msgid "until"
|
548 |
+
msgstr "indtil"
|
549 |
+
|
550 |
+
#: ../event-organiser-edit.php:158
|
551 |
+
#: ../includes/event-organiser-venue-functions.php:436
|
552 |
+
msgid "Select a venue"
|
553 |
+
msgstr "Vælg et sted"
|
554 |
+
|
555 |
+
#: ../event-organiser-edit.php:163
|
556 |
+
msgid "Search for a venue. To add a venues go to the venue page."
|
557 |
+
msgstr "Søg efter et sted. For at tilføje steder, gå til Steder-vinduet."
|
558 |
+
|
559 |
+
#: ../event-organiser-edit.php:317
|
560 |
+
msgid "You are not allowed to delete events."
|
561 |
+
msgstr "Du må ikke slette begivenheder."
|
562 |
+
|
563 |
+
#: ../event-organiser-calendar.php:10 ../event-organiser-calendar.php:11
|
564 |
+
msgid "Calendar View"
|
565 |
+
msgstr "Kalendervisning"
|
566 |
+
|
567 |
+
#: ../event-organiser-calendar.php:43
|
568 |
+
#: ../includes/event-organiser-register.php:21
|
569 |
+
msgid "today"
|
570 |
+
msgstr "i dag"
|
571 |
+
|
572 |
+
#: ../event-organiser-calendar.php:44
|
573 |
+
#: ../includes/event-organiser-register.php:22
|
574 |
+
#: ../includes/event-organiser-register.php:115
|
575 |
+
msgid "day"
|
576 |
+
msgstr "dag"
|
577 |
+
|
578 |
+
#: ../event-organiser-calendar.php:45
|
579 |
+
#: ../includes/event-organiser-register.php:23
|
580 |
+
#: ../includes/event-organiser-register.php:117
|
581 |
+
msgid "week"
|
582 |
+
msgstr "uge"
|
583 |
+
|
584 |
+
#: ../event-organiser-calendar.php:46
|
585 |
+
#: ../includes/event-organiser-register.php:24
|
586 |
+
#: ../includes/event-organiser-register.php:119
|
587 |
+
msgid "month"
|
588 |
+
msgstr "måned"
|
589 |
+
|
590 |
+
#: ../event-organiser-calendar.php:47
|
591 |
+
#: ../includes/event-organiser-register.php:25
|
592 |
+
msgid "go to date"
|
593 |
+
msgstr "gå til dato"
|
594 |
+
|
595 |
+
#: ../event-organiser-calendar.php:82
|
596 |
+
msgid "You do not have sufficient permissions to create events"
|
597 |
+
msgstr "Du har ikke rettigheder til at oprette begivenheder"
|
598 |
+
|
599 |
+
#: ../event-organiser-calendar.php:139
|
600 |
+
msgid "You do not have sufficient permissions to edit this event"
|
601 |
+
msgstr "Du har ikke rettigheder til at redigere denne begivenhed"
|
602 |
+
|
603 |
+
#: ../event-organiser-calendar.php:221
|
604 |
+
msgid "You do not have sufficient permissions to delete this event"
|
605 |
+
msgstr "Du har ikke rettigheder til at slette denne begivenhed"
|
606 |
+
|
607 |
+
#: ../event-organiser-calendar.php:227
|
608 |
+
msgid "Occurrence deleted."
|
609 |
+
msgstr "Gentagelse slettet."
|
610 |
+
|
611 |
+
#: ../event-organiser-calendar.php:241
|
612 |
+
msgid "Events Calendar"
|
613 |
+
msgstr "Begivenhedskalender"
|
614 |
+
|
615 |
+
#: ../event-organiser-calendar.php:244
|
616 |
+
msgid "Loading…"
|
617 |
+
msgstr "Indlæser…"
|
618 |
+
|
619 |
+
#: ../event-organiser-calendar.php:245
|
620 |
+
msgid "Day"
|
621 |
+
msgstr "Dag"
|
622 |
+
|
623 |
+
#: ../event-organiser-calendar.php:246
|
624 |
+
msgid "Week"
|
625 |
+
msgstr "Uge"
|
626 |
+
|
627 |
+
#: ../event-organiser-calendar.php:247
|
628 |
+
msgid "Month"
|
629 |
+
msgstr "Måned"
|
630 |
+
|
631 |
+
#: ../event-organiser-calendar.php:250
|
632 |
+
msgid "Current date/time"
|
633 |
+
msgstr "Nuværende tidspunkt"
|
634 |
+
|
635 |
+
#: ../event-organiser-calendar.php:258
|
636 |
+
msgid "When"
|
637 |
+
msgstr "Hvornår"
|
638 |
+
|
639 |
+
#: ../event-organiser-calendar.php:262
|
640 |
+
msgid "Event Title"
|
641 |
+
msgstr "Begivenhedstitel"
|
642 |
+
|
643 |
+
#: ../event-organiser-calendar.php:266
|
644 |
+
#: ../includes/event-organiser-ajax.php:193
|
645 |
+
msgid "Where"
|
646 |
+
msgstr "Hvor"
|
647 |
+
|
648 |
+
#: ../event-organiser-calendar.php:291
|
649 |
+
msgid "Save Draft"
|
650 |
+
msgstr "Gem kladde"
|
651 |
+
|
652 |
+
#: ../event-organiser-calendar.php:293
|
653 |
+
msgid "Publish Event"
|
654 |
+
msgstr "Udgiv begivenhed"
|
655 |
+
|
656 |
+
#: ../event-organiser-calendar.php:299
|
657 |
+
msgid "Cancel"
|
658 |
+
msgstr "Annuller"
|
659 |
+
|
660 |
+
#: ../event-organiser-calendar.php:300
|
661 |
+
msgid "Submit for Review"
|
662 |
+
msgstr "Indsend til gennemgang"
|
663 |
+
|
664 |
+
#: ../includes/event-organiser-register.php:113
|
665 |
+
msgid "Hour"
|
666 |
+
msgstr "Time"
|
667 |
+
|
668 |
+
#: ../includes/event-organiser-register.php:114
|
669 |
+
msgid "Minute"
|
670 |
+
msgstr "Minut"
|
671 |
+
|
672 |
+
#: ../includes/event-organiser-register.php:116
|
673 |
+
msgid "days"
|
674 |
+
msgstr "dage"
|
675 |
+
|
676 |
+
#: ../includes/event-organiser-register.php:118
|
677 |
+
msgid "weeks"
|
678 |
+
msgstr "uger"
|
679 |
+
|
680 |
+
#: ../includes/event-organiser-register.php:120
|
681 |
+
msgid "months"
|
682 |
+
msgstr "måneder"
|
683 |
+
|
684 |
+
#: ../includes/event-organiser-register.php:121
|
685 |
+
msgid "year"
|
686 |
+
msgstr "år"
|
687 |
+
|
688 |
+
#: ../includes/event-organiser-register.php:122
|
689 |
+
msgid "years"
|
690 |
+
msgstr "år"
|
691 |
+
|
692 |
+
#: ../includes/event-organiser-register.php:123
|
693 |
+
#: ../includes/event-organiser-event-functions.php:475
|
694 |
+
msgid "every day"
|
695 |
+
msgstr "hver dag"
|
696 |
+
|
697 |
+
#: ../includes/event-organiser-register.php:124
|
698 |
+
#: ../includes/event-organiser-event-functions.php:477
|
699 |
+
#, php-format
|
700 |
+
msgid "every %d days"
|
701 |
+
msgstr "hver %d. dag"
|
702 |
+
|
703 |
+
#: ../includes/event-organiser-register.php:125
|
704 |
+
#: ../includes/event-organiser-event-functions.php:483
|
705 |
+
msgid "every week on"
|
706 |
+
msgstr "hver uge på en"
|
707 |
+
|
708 |
+
#: ../includes/event-organiser-register.php:126
|
709 |
+
#: ../includes/event-organiser-event-functions.php:485
|
710 |
+
#, php-format
|
711 |
+
msgid "every %d weeks on"
|
712 |
+
msgstr "hver %d. uge på en"
|
713 |
+
|
714 |
+
#: ../includes/event-organiser-register.php:127
|
715 |
+
#: ../includes/event-organiser-event-functions.php:497
|
716 |
+
msgid "every month on the"
|
717 |
+
msgstr "hver måned på den"
|
718 |
+
|
719 |
+
#: ../includes/event-organiser-register.php:128
|
720 |
+
#: ../includes/event-organiser-event-functions.php:499
|
721 |
+
#, php-format
|
722 |
+
msgid "every %d months on the"
|
723 |
+
msgstr "hver %d. måned på den"
|
724 |
+
|
725 |
+
#: ../includes/event-organiser-register.php:129
|
726 |
+
msgid "every year on the"
|
727 |
+
msgstr "hvert år på den"
|
728 |
+
|
729 |
+
#: ../includes/event-organiser-register.php:130
|
730 |
+
#, php-format
|
731 |
+
msgid "every %d years on the"
|
732 |
+
msgstr "hvert %d. år på den"
|
733 |
+
|
734 |
+
#: ../includes/event-organiser-register.php:131
|
735 |
+
msgid "This event will repeat"
|
736 |
+
msgstr "Denne begivenhed vil gentages"
|
737 |
+
|
738 |
+
#: ../includes/event-organiser-register.php:133
|
739 |
+
#: ../includes/event-organiser-event-functions.php:458
|
740 |
+
msgid "first"
|
741 |
+
msgstr "første"
|
742 |
+
|
743 |
+
#: ../includes/event-organiser-register.php:133
|
744 |
+
#: ../includes/event-organiser-event-functions.php:458
|
745 |
+
msgid "second"
|
746 |
+
msgstr "anden"
|
747 |
+
|
748 |
+
#: ../includes/event-organiser-register.php:133
|
749 |
+
#: ../includes/event-organiser-event-functions.php:458
|
750 |
+
msgid "third"
|
751 |
+
msgstr "tredje"
|
752 |
+
|
753 |
+
#: ../includes/event-organiser-register.php:133
|
754 |
+
#: ../includes/event-organiser-event-functions.php:458
|
755 |
+
msgid "fourth"
|
756 |
+
msgstr "fjerde"
|
757 |
+
|
758 |
+
#: ../includes/event-organiser-register.php:133
|
759 |
+
#: ../includes/event-organiser-event-functions.php:458
|
760 |
+
msgid "last"
|
761 |
+
msgstr "sidste"
|
762 |
+
|
763 |
+
#: ../includes/event-organiser-event-functions.php:468
|
764 |
+
msgid "one time only"
|
765 |
+
msgstr "ingen"
|
766 |
+
|
767 |
+
#: ../includes/event-organiser-event-functions.php:528
|
768 |
+
msgid "every year"
|
769 |
+
msgstr "hvert år"
|
770 |
+
|
771 |
+
#: ../includes/event-organiser-event-functions.php:530
|
772 |
+
#, php-format
|
773 |
+
msgid "every %d years"
|
774 |
+
msgstr "hvert %d. år"
|
775 |
+
|
776 |
+
#: ../includes/class-event-organiser-im-export.php:60
|
777 |
+
#, php-format
|
778 |
+
msgid "File Error encountered: %d"
|
779 |
+
msgstr "Fejl i filupload: %d"
|
780 |
+
|
781 |
+
#: ../includes/class-event-organiser-im-export.php:66
|
782 |
+
msgid "No file detected."
|
783 |
+
msgstr "Ingen fil registreret."
|
784 |
+
|
785 |
+
#: ../includes/class-event-organiser-im-export.php:69
|
786 |
+
msgid ""
|
787 |
+
"Invalid file uploaded. The file must be a ics calendar file, no larger than "
|
788 |
+
"2MB."
|
789 |
+
msgstr ""
|
790 |
+
"Ugyldig fil uploadet. Filen skal være en kalenderfil af typen ics og ikke "
|
791 |
+
"større end 2MB."
|
792 |
+
|
793 |
+
#: ../includes/class-event-organiser-im-export.php:86
|
794 |
+
msgid "Export Events"
|
795 |
+
msgstr "Eksporter begivenheder"
|
796 |
+
|
797 |
+
#: ../includes/class-event-organiser-im-export.php:87
|
798 |
+
msgid ""
|
799 |
+
"The export button below generates an ICS file of your events that can be "
|
800 |
+
"imported in to other calendar applications such as Google Calendar."
|
801 |
+
msgstr ""
|
802 |
+
"Eksport-knappen nedenfor genererer en ICS-fil af dine begivenheder, som kan "
|
803 |
+
"importeres af andre kalender-applikationer såsom Google Calendar."
|
804 |
+
|
805 |
+
#: ../includes/class-event-organiser-im-export.php:92
|
806 |
+
msgid "Download Export File"
|
807 |
+
msgstr "Download eksportfil"
|
808 |
+
|
809 |
+
#: ../includes/class-event-organiser-im-export.php:97
|
810 |
+
msgid "Import Events"
|
811 |
+
msgstr "Importer begivenheder"
|
812 |
+
|
813 |
+
#: ../includes/class-event-organiser-im-export.php:99
|
814 |
+
msgid "Import an ICS file."
|
815 |
+
msgstr "Importer en ICS-fil."
|
816 |
+
|
817 |
+
#: ../includes/class-event-organiser-im-export.php:102
|
818 |
+
msgid "Import venues"
|
819 |
+
msgstr "Importer steder"
|
820 |
+
|
821 |
+
#: ../includes/class-event-organiser-im-export.php:103
|
822 |
+
msgid "Import categories"
|
823 |
+
msgstr "Importer kategorier"
|
824 |
+
|
825 |
+
#: ../includes/class-event-organiser-im-export.php:106
|
826 |
+
msgid "Upload ICS file"
|
827 |
+
msgstr "Upload ICS-fil"
|
828 |
+
|
829 |
+
#: ../includes/class-event-organiser-im-export.php:299
|
830 |
+
msgid "You do not have sufficient permissions to import events."
|
831 |
+
msgstr "Du har ikke rettigheder til at importere begivenheder."
|
832 |
+
|
833 |
+
#: ../includes/class-event-organiser-im-export.php:438
|
834 |
+
msgid "No events were imported."
|
835 |
+
msgstr "Ingen begivenheder blev importeret."
|
836 |
+
|
837 |
+
#: ../includes/class-event-organiser-im-export.php:444
|
838 |
+
msgid "1 event was successfully imported"
|
839 |
+
msgstr "1 begivenhed blev importeret"
|
840 |
+
|
841 |
+
#: ../includes/class-event-organiser-im-export.php:446
|
842 |
+
#, php-format
|
843 |
+
msgid "%d events were successfully imported"
|
844 |
+
msgstr "%d begivenheder blev importeret"
|
845 |
+
|
846 |
+
#: ../includes/class-event-organiser-im-export.php:449
|
847 |
+
msgid "1 venue was created"
|
848 |
+
msgstr "1 sted blev oprettet"
|
849 |
+
|
850 |
+
#: ../includes/class-event-organiser-im-export.php:451
|
851 |
+
#, php-format
|
852 |
+
msgid "%d venues were created"
|
853 |
+
msgstr "%d steder blev oprettet"
|
854 |
+
|
855 |
+
#: ../includes/class-event-organiser-im-export.php:455
|
856 |
+
msgid "1 category was created"
|
857 |
+
msgstr "1 kategori blev oprettet"
|
858 |
+
|
859 |
+
#: ../includes/class-event-organiser-im-export.php:457
|
860 |
+
#, php-format
|
861 |
+
msgid "%d categories were created"
|
862 |
+
msgstr "%d kategorier blev oprettet"
|
863 |
+
|
864 |
+
#: ../includes/event-organiser-cpt.php:26
|
865 |
+
msgid "Event Venues"
|
866 |
+
msgstr "Begivenhedssted
|