Simple Calendar – Google Calendar Plugin - Version 0.2

Version Description

  • Added customization options for how information is displayed.
  • Can now display: start time, end time and date, location, description and event link.
  • Tooltips now using qTip jQuery plugin.
Download this release

Release Info

Developer rosshanney
Plugin Icon 128x128 Simple Calendar – Google Calendar Plugin
Version 0.2
Comparing to
See all releases

Code changes from version 0.1.4 to 0.2

admin/add.php CHANGED
@@ -87,6 +87,15 @@ function gce_add_time_format_field(){
87
  <?php
88
  }
89
 
 
 
 
 
 
 
 
 
 
90
  //Cache duration
91
  function gce_add_cache_duration_field(){
92
  ?>
@@ -95,4 +104,73 @@ function gce_add_cache_duration_field(){
95
  <input type="text" name="gce_options[cache_duration]" value="43200" />
96
  <?php
97
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  ?>
87
  <?php
88
  }
89
 
90
+ //Timezone offset
91
+ /*function gce_add_offset_field(){
92
+ ?>
93
+ <span class="description"><?php _e('If you are having issues with dates not being displayed in your timezone, enter an offset, in seconds (3600 = 1 hour), here. This can be positive or negative.', GCE_TEXT_DOMAIN); ?></span>
94
+ <br />
95
+ <input type="text" name="gce_options[offset]" value="0" />
96
+ <?php
97
+ }*/
98
+
99
  //Cache duration
100
  function gce_add_cache_duration_field(){
101
  ?>
104
  <input type="text" name="gce_options[cache_duration]" value="43200" />
105
  <?php
106
  }
107
+
108
+
109
+ //Display options
110
+ function gce_add_display_main_text(){
111
+ ?>
112
+ <p><?php _e('These settings control what information will be displayed in the tooltip (for grids), or in a list.', GCE_TEXT_DOMAIN); ?></p>
113
+ <p><?php _e('You can use some HTML in the text fields, but ensure it is valid or things might go wonky. Text fields can be empty too.', GCE_TEXT_DOMAIN); ?></p>
114
+ <?php
115
+ }
116
+
117
+ function gce_add_display_title_field(){
118
+ ?>
119
+ <input type="checkbox" name="gce_options[display_title]" value="on" checked="checked" />
120
+ <span class="description"><?php _e('Show a title ("Events on 7th March:" for example)?', GCE_TEXT_DOMAIN); ?></span>
121
+ <br /><br />
122
+ <input type="text" name="gce_options[display_title_text]" value="" />
123
+ <span class="description"><?php _e('Text to display before the date in the title.', GCE_TEXT_DOMAIN); ?></span>
124
+ <?php
125
+ }
126
+
127
+ function gce_add_display_start_field(){
128
+ ?>
129
+ <input type="checkbox" name="gce_options[display_start]" value="on" checked="checked" />
130
+ <span class="description"><?php _e('Show the start time of events?', GCE_TEXT_DOMAIN); ?></span>
131
+ <br /><br />
132
+ <input type="text" name="gce_options[display_start_text]" value="Starts:" />
133
+ <span class="description"><?php _e('Text to display before the start time.', GCE_TEXT_DOMAIN); ?></span>
134
+ <?php
135
+ }
136
+
137
+ function gce_add_display_end_field(){
138
+ ?>
139
+ <input type="checkbox" name="gce_options[display_end]" value="on" />
140
+ <span class="description"><?php _e('Show the end time and date of events? (Date will be shown as well as time as events can span several days).', GCE_TEXT_DOMAIN); ?></span>
141
+ <br /><br />
142
+ <input type="text" name="gce_options[display_end_text]" value="Ends:" />
143
+ <span class="description"><?php _e('Text to display before the end time / date.', GCE_TEXT_DOMAIN); ?></span>
144
+ <?php
145
+ }
146
+
147
+ function gce_add_display_location_field(){
148
+ ?>
149
+ <input type="checkbox" name="gce_options[display_location]" value="on" />
150
+ <span class="description"><?php _e('Show the location of events?', GCE_TEXT_DOMAIN); ?></span>
151
+ <br /><br />
152
+ <input type="text" name="gce_options[display_location_text]" value="Location:" />
153
+ <span class="description"><?php _e('Text to display before the location.', GCE_TEXT_DOMAIN); ?></span>
154
+ <?php
155
+ }
156
+
157
+ function gce_add_display_desc_field(){
158
+ ?>
159
+ <input type="checkbox" name="gce_options[display_desc]" value="on" />
160
+ <span class="description"><?php _e('Show the description of events? (URLs in the description will be made into links).', GCE_TEXT_DOMAIN); ?></span>
161
+ <br /><br />
162
+ <input type="text" name="gce_options[display_desc_text]" value="Description:" />
163
+ <span class="description"><?php _e('Text to display before the description.', GCE_TEXT_DOMAIN); ?></span>
164
+ <?php
165
+ }
166
+
167
+ function gce_add_display_link_field(){
168
+ ?>
169
+ <input type="checkbox" name="gce_options[display_link]" value="on" checked="checked" />
170
+ <span class="description"><?php _e('Show a link to the Google Calendar page for an event?', GCE_TEXT_DOMAIN); ?></span>
171
+ <br /><br />
172
+ <input type="text" name="gce_options[display_link_text]" value="More details" />
173
+ <span class="description"><?php _e('The link text to be displayed.', GCE_TEXT_DOMAIN); ?></span>
174
+ <?php
175
+ }
176
  ?>
admin/edit.php CHANGED
@@ -92,6 +92,17 @@ function gce_edit_time_format_field(){
92
  <?php
93
  }
94
 
 
 
 
 
 
 
 
 
 
 
 
95
  //Cache duration
96
  function gce_edit_cache_duration_field(){
97
  $options = get_option(GCE_OPTIONS_NAME);
@@ -102,4 +113,85 @@ function gce_edit_cache_duration_field(){
102
  <input type="text" name="gce_options[cache_duration]" value="<?php echo $options['cache_duration']; ?>" />
103
  <?php
104
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  ?>
92
  <?php
93
  }
94
 
95
+ //Timezone offset
96
+ /*function gce_edit_offset_field(){
97
+ $options = get_option(GCE_OPTIONS_NAME);
98
+ $options = $options[$_GET['id']];
99
+ ?>
100
+ <span class="description"><?php _e('If you are having issues with dates not being displayed in your timezone, enter an offset, in seconds (3600 = 1 hour), here. This can be positive or negative.', GCE_TEXT_DOMAIN); ?></span>
101
+ <br />
102
+ <input type="text" name="gce_options[offset]" value="<?php echo $options['offset']; ?>" />
103
+ <?php
104
+ }*/
105
+
106
  //Cache duration
107
  function gce_edit_cache_duration_field(){
108
  $options = get_option(GCE_OPTIONS_NAME);
113
  <input type="text" name="gce_options[cache_duration]" value="<?php echo $options['cache_duration']; ?>" />
114
  <?php
115
  }
116
+
117
+ //display options
118
+
119
+ function gce_edit_display_main_text(){
120
+ ?>
121
+ <p><?php _e('These settings control what information will be displayed in the tooltip (for grids), or in a list.', GCE_TEXT_DOMAIN); ?></p>
122
+ <p><?php _e('You can use some HTML in the text fields, but ensure it is valid or things might go wonky. Text fields can be empty too.', GCE_TEXT_DOMAIN); ?></p>
123
+ <?php
124
+ }
125
+
126
+ function gce_edit_display_title_field(){
127
+ $options = get_option(GCE_OPTIONS_NAME);
128
+ $options = $options[$_GET['id']];
129
+ ?>
130
+ <input type="checkbox" name="gce_options[display_title]"<?php checked($options['display_title'], 'on'); ?> value="on" />
131
+ <span class="description"><?php _e('Show a title ("Events on 7th March:" for example)?', GCE_TEXT_DOMAIN); ?></span>
132
+ <br /><br />
133
+ <input type="text" name="gce_options[display_title_text]" value="<?php echo stripslashes(esc_html($options['display_title_text'])); ?>" />
134
+ <span class="description"><?php _e('Text to display before the date in title.', GCE_TEXT_DOMAIN); ?></span>
135
+ <?php
136
+ }
137
+
138
+ function gce_edit_display_start_field(){
139
+ $options = get_option(GCE_OPTIONS_NAME);
140
+ $options = $options[$_GET['id']];
141
+ ?>
142
+ <input type="checkbox" name="gce_options[display_start]"<?php checked($options['display_start'], 'on'); ?> value="on" />
143
+ <span class="description"><?php _e('Show the start time of events?', GCE_TEXT_DOMAIN); ?></span>
144
+ <br /><br />
145
+ <input type="text" name="gce_options[display_start_text]" value="<?php echo stripslashes(esc_html($options['display_start_text'])); ?>" />
146
+ <span class="description"><?php _e('Text to display before the start time.', GCE_TEXT_DOMAIN); ?></span>
147
+ <?php
148
+ }
149
+
150
+ function gce_edit_display_end_field(){
151
+ $options = get_option(GCE_OPTIONS_NAME);
152
+ $options = $options[$_GET['id']];
153
+ ?>
154
+ <input type="checkbox" name="gce_options[display_end]"<?php checked($options['display_end'], 'on'); ?> value="on" />
155
+ <span class="description"><?php _e('Show the end time and date of events? (Date will be shown as well as time as events can span several days).', GCE_TEXT_DOMAIN); ?></span>
156
+ <br /><br />
157
+ <input type="text" name="gce_options[display_end_text]" value="<?php echo stripslashes(esc_html($options['display_end_text'])); ?>" />
158
+ <span class="description"><?php _e('Text to display before the end time / date.', GCE_TEXT_DOMAIN); ?></span>
159
+ <?php
160
+ }
161
+
162
+ function gce_edit_display_location_field(){
163
+ $options = get_option(GCE_OPTIONS_NAME);
164
+ $options = $options[$_GET['id']];
165
+ ?>
166
+ <input type="checkbox" name="gce_options[display_location]"<?php checked($options['display_location'], 'on'); ?> value="on" />
167
+ <span class="description"><?php _e('Show the location of events?', GCE_TEXT_DOMAIN); ?></span>
168
+ <br /><br />
169
+ <input type="text" name="gce_options[display_location_text]" value="<?php echo stripslashes(esc_html($options['display_location_text'])); ?>" />
170
+ <span class="description"><?php _e('Text to display before the location.', GCE_TEXT_DOMAIN); ?></span>
171
+ <?php
172
+ }
173
+
174
+ function gce_edit_display_desc_field(){
175
+ $options = get_option(GCE_OPTIONS_NAME);
176
+ $options = $options[$_GET['id']];
177
+ ?>
178
+ <input type="checkbox" name="gce_options[display_desc]"<?php checked($options['display_desc'], 'on'); ?> value="on" />
179
+ <span class="description"><?php _e('Show the description of events? (URLs in the description will be made into links).', GCE_TEXT_DOMAIN); ?></span>
180
+ <br /><br />
181
+ <input type="text" name="gce_options[display_desc_text]" value="<?php echo stripslashes(esc_html($options['display_desc_text'])); ?>" />
182
+ <span class="description"><?php _e('Text to display before the description.', GCE_TEXT_DOMAIN); ?></span>
183
+ <?php
184
+ }
185
+
186
+ function gce_edit_display_link_field(){
187
+ $options = get_option(GCE_OPTIONS_NAME);
188
+ $options = $options[$_GET['id']];
189
+ ?>
190
+ <input type="checkbox" name="gce_options[display_link]"<?php checked($options['display_link'], 'on'); ?> value="on" />
191
+ <span class="description"><?php _e('Show a link to the Google Calendar page for an event?', GCE_TEXT_DOMAIN); ?></span>
192
+ <br /><br />
193
+ <input type="text" name="gce_options[display_link_text]" value="<?php echo stripslashes(esc_html($options['display_link_text'])); ?>" />
194
+ <span class="description"><?php _e('The link text to be displayed.', GCE_TEXT_DOMAIN); ?></span>
195
+ <?php
196
+ }
197
  ?>
css/gce-style.css CHANGED
@@ -56,11 +56,34 @@
56
 
57
  /* PAGE LIST */
58
 
59
- .gce-page-list .gce-list .gce-date-time{
 
 
 
 
 
 
 
 
 
60
  margin:0 !important;
 
 
 
 
 
 
 
 
 
 
 
61
  font-weight:bold;
62
  }
63
 
 
 
 
64
  /* WIDGET GRID */
65
 
66
  .gce-widget-grid .gce-calendar .gce-caption{
@@ -112,40 +135,76 @@
112
 
113
  /* WIDGET LIST */
114
 
115
- .gce-widget-list .gce-list{
116
  margin:10px 0 0 0;
117
  }
118
 
119
- .gce-widget-list .gce-list .gce-date-time{
120
- margin:0;
121
- font-weight:bold;
122
  }
123
 
124
- .gce-widget-list .gce-list .gce-event-text{
125
  margin:0;
126
  }
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  /* TOOLTIP */
129
 
130
- #gce-tooltip{ /* Tooltip container */
131
- position:absolute;
132
- display:none;
133
  background-color:#FFFFFF;
134
  border:1px solid #333333;
135
  text-align:left;
136
- max-width:200px;
137
  }
138
 
139
- #gce-tooltip p{ /* 'Events on...' text */
140
  margin:5px !important;
 
 
141
  }
142
 
143
- #gce-tooltip ul{ /* Events list */
144
  padding:0 !important;
145
  margin:5px !important;
146
- list-style-type:none;
147
  }
148
 
149
- #gce-tooltip ul li{ /* Event list item */
150
- margin:5px 0 0 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  }
56
 
57
  /* PAGE LIST */
58
 
59
+ .gce-page-list .gce-list{ /* The list itself */
60
+ margin-top:10px;
61
+ }
62
+
63
+ .gce-page-list .gce-list li{ /* Each event in the list */
64
+ margin-top:5px;
65
+ content:none;
66
+ }
67
+
68
+ .gce-page-list .gce-list p{ /* Each piece of information in the list */
69
  margin:0 !important;
70
+ }
71
+
72
+ .gce-page-list .gce-list p span{ /* The text displayed before each piece of info, 'Starts:' for example */
73
+ color:#999999;
74
+ }
75
+
76
+ .gce-page-list .gce-list .gce-list-event{ /* The event title */
77
+ background-color:#DDDDDD;
78
+ }
79
+
80
+ .gce-page-list .gce-list .gce-list-title{ /* The title (not the same as event title) */
81
  font-weight:bold;
82
  }
83
 
84
+ /* Also available: .gce-list-start, .gce-list-end, .gce-list-loc, .gce-list-desc, .gce-list-link */
85
+
86
+
87
  /* WIDGET GRID */
88
 
89
  .gce-widget-grid .gce-calendar .gce-caption{
135
 
136
  /* WIDGET LIST */
137
 
138
+ .gce-widget-list .gce-list{ /* The list itself */
139
  margin:10px 0 0 0;
140
  }
141
 
142
+ .gce-widget-list .gce-list li{ /* Each event in the list */
143
+ margin:5px 0 0 0;
 
144
  }
145
 
146
+ .gce-widget-list .gce-list p{ /* Each piece of information in the list */
147
  margin:0;
148
  }
149
 
150
+ .gce-widget-list .gce-list p span{ /* The text displayed before each piece of info, 'Starts:' for example */
151
+ color:#999999;
152
+ }
153
+
154
+ .gce-widget-list .gce-list .gce-list-event{ /* The event title */
155
+ background-color:#DDDDDD;
156
+ }
157
+
158
+ .gce-widget-list .gce-list .gce-list-title{ /* The title (not the same as event title) */
159
+ font-weight:bold;
160
+ }
161
+
162
+ /* Also available: .gce-list-start, .gce-list-end, .gce-list-loc, .gce-list-desc, .gce-list-link */
163
+
164
+
165
  /* TOOLTIP */
166
 
167
+ .gce-event-info{ /* Tooltip container */
 
 
168
  background-color:#FFFFFF;
169
  border:1px solid #333333;
170
  text-align:left;
171
+ max-width:300px;
172
  }
173
 
174
+ .gce-event-info .gce-tooltip-title{ /* 'Events on...' text */
175
  margin:5px !important;
176
+ font-weight:bold;
177
+ font-size:1.2em;
178
  }
179
 
180
+ .gce-event-info ul{ /* Events list */
181
  padding:0 !important;
182
  margin:5px !important;
183
+ list-style-type:none !important;
184
  }
185
 
186
+ .gce-event-info ul li{ /* Event list item */
187
+ margin:10px 0 0 0;
188
+ }
189
+
190
+ .gce-event-info ul li p{ /* Each piece of information */
191
+ margin:0;
192
+ }
193
+
194
+ .gce-event-info ul li p span{ /* The text displayed before each piece of info, 'Starts:' for example */
195
+ color:#999999;
196
+ }
197
+
198
+ .gce-event-info .gce-tooltip-event{ /* The event title */
199
+ background-color:#DDDDDD;
200
+ font-weight:bold;
201
+ }
202
+
203
+ /* Also available: .gce-tooltip-start, .gce-tooltip-end, .gce-tooltip-loc, .gce-tooltip-desc, .gce-tooltip-link */
204
+
205
+
206
+
207
+ /* Sort of fixes weird list stuff in old default theme */
208
+ .entry .gce-page-list li:before, #sidebar .gce-widget-list ul li:before {
209
+ content:none;
210
  }
google-calendar-events.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Google Calendar Events
4
  Plugin URI: http://www.rhanney.co.uk/plugins/google-calendar-events
5
  Description: Parses Google Calendar feeds and displays the events as a calendar grid or list on a page, post or widget.
6
- Version: 0.1.4
7
  Author: Ross Hanney
8
  Author URI: http://www.rhanney.co.uk
9
  License: GPL2
@@ -55,14 +55,53 @@ if(!class_exists('Google_Calendar_Events')){
55
  add_action('wp_print_scripts', array($this, 'add_scripts'));
56
  }
57
 
 
58
  function init_plugin(){
59
  add_option(GCE_OPTIONS_NAME);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  }
61
 
62
  //Setup admin settings page
63
  function setup_admin(){
64
  if(function_exists('add_options_page')) add_options_page('Google Calendar Events', 'Google Calendar Events', 'manage_options', basename(__FILE__), array($this, 'admin_page'));
65
-
66
  }
67
 
68
  //Prints admin settings page
@@ -95,12 +134,14 @@ if(!class_exists('Google_Calendar_Events')){
95
  //Add feed section
96
  case 'add':
97
  do_settings_sections('add_feed');
 
98
  ?><p class="submit"><input type="submit" class="button-primary submit" value="<?php esc_attr_e('Add Feed', GCE_TEXT_DOMAIN); ?>" /></p>
99
  <p><a href="<?php echo admin_url() . 'options-general.php?page=' . GCE_PLUGIN_NAME . '.php'; ?>" class="button-secondary">Cancel</a></p><?php
100
  break;
101
  //Edit feed section
102
  case 'edit':
103
  do_settings_sections('edit_feed');
 
104
  ?><p class="submit"><input type="submit" class="button-primary" value="<?php esc_attr_e('Save Changes', GCE_TEXT_DOMAIN); ?>" /></p>
105
  <p><a href="<?php echo admin_url() . 'options-general.php?page=' . GCE_PLUGIN_NAME . '.php'; ?>" class="button-secondary">Cancel</a></p><?php
106
  break;
@@ -138,8 +179,17 @@ if(!class_exists('Google_Calendar_Events')){
138
  add_settings_field('gce_add_max_events_field', __('Maximum number of events to retrieve', GCE_TEXT_DOMAIN), 'gce_add_max_events_field', 'add_feed', 'gce_add');
139
  add_settings_field('gce_add_date_format_field', __('Date format', GCE_TEXT_DOMAIN), 'gce_add_date_format_field', 'add_feed', 'gce_add');
140
  add_settings_field('gce_add_time_format_field', __('Time format', GCE_TEXT_DOMAIN), 'gce_add_time_format_field', 'add_feed', 'gce_add');
 
141
  add_settings_field('gce_add_cache_duration_field', __('Cache duration', GCE_TEXT_DOMAIN), 'gce_add_cache_duration_field', 'add_feed', 'gce_add');
142
 
 
 
 
 
 
 
 
 
143
  //Setup edit feed admin section and all fields
144
  require_once 'admin/edit.php';
145
  add_settings_section('gce_edit', __('Edit Feed', GCE_TEXT_DOMAIN), 'gce_edit_main_text', 'edit_feed');
@@ -151,8 +201,17 @@ if(!class_exists('Google_Calendar_Events')){
151
  add_settings_field('gce_edit_max_events_field', __('Maximum number of events to retrieve', GCE_TEXT_DOMAIN), 'gce_edit_max_events_field', 'edit_feed', 'gce_edit');
152
  add_settings_field('gce_edit_date_format_field', __('Date format', GCE_TEXT_DOMAIN), 'gce_edit_date_format_field', 'edit_feed', 'gce_edit');
153
  add_settings_field('gce_edit_time_format_field', __('Time format', GCE_TEXT_DOMAIN), 'gce_edit_time_format_field', 'edit_feed', 'gce_edit');
 
154
  add_settings_field('gce_edit_cache_duration_field', __('Cache duration', GCE_TEXT_DOMAIN), 'gce_edit_cache_duration_field', 'edit_feed', 'gce_edit');
155
 
 
 
 
 
 
 
 
 
156
  //Setup delete feed admin section and all fields
157
  require_once 'admin/delete.php';
158
  add_settings_section('gce_delete', __('Delete Feed', GCE_TEXT_DOMAIN), 'gce_delete_main_text', 'delete_feed');
@@ -183,8 +242,11 @@ if(!class_exists('Google_Calendar_Events')){
183
  //Check max events is a positive integer. If absint returns 0, reset to default (25)
184
  $max_events = (absint($input['max_events']) == 0 ? 25 : absint($input['max_events']));
185
 
186
- $date_format = $input['date_format'];
187
- $time_format = $input['time_format'];
 
 
 
188
 
189
  //Make sure cache duration is a positive integer or 0. If user has typed 0, leave as 0 but if 0 is returned from absint, set to default (43200)
190
  $cache_duration = $input['cache_duration'];
@@ -192,6 +254,22 @@ if(!class_exists('Google_Calendar_Events')){
192
  $cache_duration = (absint($cache_duration) == 0 ? 43200 : absint($cache_duration));
193
  }
194
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  //Fill options array with validated values
196
  $options[$id] = array(
197
  'id' => $id,
@@ -201,7 +279,20 @@ if(!class_exists('Google_Calendar_Events')){
201
  'max_events' => $max_events,
202
  'date_format' => $date_format,
203
  'time_format' => $time_format,
204
- 'cache_duration' => $cache_duration
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  );
206
  }
207
 
@@ -253,7 +344,9 @@ if(!class_exists('Google_Calendar_Events')){
253
  //Don't add scripts if on admin screens
254
  if(!is_admin()){
255
  wp_enqueue_script('jquery');
256
- wp_enqueue_script('gce_scripts', WP_PLUGIN_URL . '/' . GCE_PLUGIN_NAME . '/js/gce-tooltip-script.js');
 
 
257
  }
258
  }
259
  }
@@ -269,6 +362,16 @@ function gce_print_list($feed_id){
269
  if($df == '') $df = get_option('date_format');
270
  if($tf == '') $tf = get_option('time_format');
271
 
 
 
 
 
 
 
 
 
 
 
272
  //Creates a new GCE_Parser object for $feed_id
273
  $feed_data = new GCE_Parser(
274
  $options[$feed_id]['url'],
@@ -277,7 +380,9 @@ function gce_print_list($feed_id){
277
  $options[$feed_id]['cache_duration'],
278
  $df,
279
  $tf,
280
- get_option('start_of_week')
 
 
281
  );
282
 
283
  //If the feed parsed ok
@@ -300,6 +405,16 @@ function gce_print_grid($feed_id, $ajaxified = false, $month = null, $year = nul
300
  if($df == '') $df = get_option('date_format');
301
  if($tf == '') $tf = get_option('time_format');
302
 
 
 
 
 
 
 
 
 
 
 
303
  //Creates a new GCE_Parser object for $feed_id
304
  $feed_data = new GCE_Parser(
305
  $options[$feed_id]['url'],
@@ -308,7 +423,9 @@ function gce_print_grid($feed_id, $ajaxified = false, $month = null, $year = nul
308
  $options[$feed_id]['cache_duration'],
309
  $df,
310
  $tf,
311
- get_option('start_of_week')
 
 
312
  );
313
 
314
  //If the feed parsed ok
3
  Plugin Name: Google Calendar Events
4
  Plugin URI: http://www.rhanney.co.uk/plugins/google-calendar-events
5
  Description: Parses Google Calendar feeds and displays the events as a calendar grid or list on a page, post or widget.
6
+ Version: 0.2
7
  Author: Ross Hanney
8
  Author URI: http://www.rhanney.co.uk
9
  License: GPL2
55
  add_action('wp_print_scripts', array($this, 'add_scripts'));
56
  }
57
 
58
+ //If any new options have been added between versions, this will update any saved feeds with defaults for new options (shouldn't overwrite anything saved)
59
  function init_plugin(){
60
  add_option(GCE_OPTIONS_NAME);
61
+
62
+ $options = get_option(GCE_OPTIONS_NAME);
63
+
64
+ if(!empty($options)){
65
+ foreach($options as $key => $saved_feed_options){
66
+ $defaults = array(
67
+ 'id' => 1,
68
+ 'title' => '',
69
+ 'url' => '',
70
+ 'show_past_events' => 'false',
71
+ 'max_events' => 25,
72
+ 'date_format' => '',
73
+ 'time_format' => '',
74
+ //'offset' => 0,
75
+ 'cache_duration' => 43200,
76
+ 'display_title' => 'on',
77
+ 'display_start' => 'on',
78
+ 'display_end' => '',
79
+ 'display_location' => '',
80
+ 'display_desc' => '',
81
+ 'display_link' => 'on',
82
+ 'display_title_text' => '',
83
+ 'display_start_text' => 'Starts:',
84
+ 'display_end_text' => 'Ends:',
85
+ 'display_location_text' => 'Location:',
86
+ 'display_desc_text' => 'Description:',
87
+ 'display_link_text' => 'More details'
88
+ );
89
+
90
+ //Merge saved options with defaults
91
+ foreach($saved_feed_options as $option_name => $option){
92
+ $defaults[$option_name] = $saved_feed_options[$option_name];
93
+ }
94
+
95
+ $options[$key] = $defaults;
96
+ }
97
+ }
98
+
99
+ update_option(GCE_OPTIONS_NAME, $options);
100
  }
101
 
102
  //Setup admin settings page
103
  function setup_admin(){
104
  if(function_exists('add_options_page')) add_options_page('Google Calendar Events', 'Google Calendar Events', 'manage_options', basename(__FILE__), array($this, 'admin_page'));
 
105
  }
106
 
107
  //Prints admin settings page
134
  //Add feed section
135
  case 'add':
136
  do_settings_sections('add_feed');
137
+ do_settings_sections('add_display');
138
  ?><p class="submit"><input type="submit" class="button-primary submit" value="<?php esc_attr_e('Add Feed', GCE_TEXT_DOMAIN); ?>" /></p>
139
  <p><a href="<?php echo admin_url() . 'options-general.php?page=' . GCE_PLUGIN_NAME . '.php'; ?>" class="button-secondary">Cancel</a></p><?php
140
  break;
141
  //Edit feed section
142
  case 'edit':
143
  do_settings_sections('edit_feed');
144
+ do_settings_sections('edit_display');
145
  ?><p class="submit"><input type="submit" class="button-primary" value="<?php esc_attr_e('Save Changes', GCE_TEXT_DOMAIN); ?>" /></p>
146
  <p><a href="<?php echo admin_url() . 'options-general.php?page=' . GCE_PLUGIN_NAME . '.php'; ?>" class="button-secondary">Cancel</a></p><?php
147
  break;
179
  add_settings_field('gce_add_max_events_field', __('Maximum number of events to retrieve', GCE_TEXT_DOMAIN), 'gce_add_max_events_field', 'add_feed', 'gce_add');
180
  add_settings_field('gce_add_date_format_field', __('Date format', GCE_TEXT_DOMAIN), 'gce_add_date_format_field', 'add_feed', 'gce_add');
181
  add_settings_field('gce_add_time_format_field', __('Time format', GCE_TEXT_DOMAIN), 'gce_add_time_format_field', 'add_feed', 'gce_add');
182
+ //add_settings_field('gce_add_offset_field', __('Timezone offset', GCE_TEXT_DOMAIN), 'gce_add_offset_field', 'add_feed', 'gce_add');
183
  add_settings_field('gce_add_cache_duration_field', __('Cache duration', GCE_TEXT_DOMAIN), 'gce_add_cache_duration_field', 'add_feed', 'gce_add');
184
 
185
+ add_settings_section('gce_add_display', __('Display Options', GCE_TEXT_DOMAIN), 'gce_add_display_main_text', 'add_display');
186
+ add_settings_field('gce_add_display_title_field', __('Display title?', GCE_TEXT_DOMAIN), 'gce_add_display_title_field', 'add_display', 'gce_add_display');
187
+ add_settings_field('gce_add_display_start_field', __('Display start time?', GCE_TEXT_DOMAIN), 'gce_add_display_start_field', 'add_display', 'gce_add_display');
188
+ add_settings_field('gce_add_display_end_field', __('Display end time and date?', GCE_TEXT_DOMAIN), 'gce_add_display_end_field', 'add_display', 'gce_add_display');
189
+ add_settings_field('gce_add_display_location_field', __('Display location?', GCE_TEXT_DOMAIN), 'gce_add_display_location_field', 'add_display', 'gce_add_display');
190
+ add_settings_field('gce_add_display_desc_field', __('Display description?', GCE_TEXT_DOMAIN), 'gce_add_display_desc_field', 'add_display', 'gce_add_display');
191
+ add_settings_field('gce_add_display_link_field', __('Display link to event?', GCE_TEXT_DOMAIN), 'gce_add_display_link_field', 'add_display', 'gce_add_display');
192
+
193
  //Setup edit feed admin section and all fields
194
  require_once 'admin/edit.php';
195
  add_settings_section('gce_edit', __('Edit Feed', GCE_TEXT_DOMAIN), 'gce_edit_main_text', 'edit_feed');
201
  add_settings_field('gce_edit_max_events_field', __('Maximum number of events to retrieve', GCE_TEXT_DOMAIN), 'gce_edit_max_events_field', 'edit_feed', 'gce_edit');
202
  add_settings_field('gce_edit_date_format_field', __('Date format', GCE_TEXT_DOMAIN), 'gce_edit_date_format_field', 'edit_feed', 'gce_edit');
203
  add_settings_field('gce_edit_time_format_field', __('Time format', GCE_TEXT_DOMAIN), 'gce_edit_time_format_field', 'edit_feed', 'gce_edit');
204
+ //add_settings_field('gce_edit_offset_field', __('Timezone offset', GCE_TEXT_DOMAIN), 'gce_edit_offset_field', 'edit_feed', 'gce_edit');
205
  add_settings_field('gce_edit_cache_duration_field', __('Cache duration', GCE_TEXT_DOMAIN), 'gce_edit_cache_duration_field', 'edit_feed', 'gce_edit');
206
 
207
+ add_settings_section('gce_edit_display', __('Display Options', GCE_TEXT_DOMAIN), 'gce_edit_display_main_text', 'edit_display');
208
+ add_settings_field('gce_edit_display_title_field', __('Display title?', GCE_TEXT_DOMAIN), 'gce_edit_display_title_field', 'edit_display', 'gce_edit_display');
209
+ add_settings_field('gce_edit_display_start_field', __('Display start time?', GCE_TEXT_DOMAIN), 'gce_edit_display_start_field', 'edit_display', 'gce_edit_display');
210
+ add_settings_field('gce_edit_display_end_field', __('Display end time and date?', GCE_TEXT_DOMAIN), 'gce_edit_display_end_field', 'edit_display', 'gce_edit_display');
211
+ add_settings_field('gce_edit_display_location_field', __('Display location?', GCE_TEXT_DOMAIN), 'gce_edit_display_location_field', 'edit_display', 'gce_edit_display');
212
+ add_settings_field('gce_edit_display_desc_field', __('Display description?', GCE_TEXT_DOMAIN), 'gce_edit_display_desc_field', 'edit_display', 'gce_edit_display');
213
+ add_settings_field('gce_edit_display_link_field', __('Display link to event?', GCE_TEXT_DOMAIN), 'gce_edit_display_link_field', 'edit_display', 'gce_edit_display');
214
+
215
  //Setup delete feed admin section and all fields
216
  require_once 'admin/delete.php';
217
  add_settings_section('gce_delete', __('Delete Feed', GCE_TEXT_DOMAIN), 'gce_delete_main_text', 'delete_feed');
242
  //Check max events is a positive integer. If absint returns 0, reset to default (25)
243
  $max_events = (absint($input['max_events']) == 0 ? 25 : absint($input['max_events']));
244
 
245
+ $date_format = wp_filter_kses($input['date_format']);
246
+ $time_format = wp_filter_kses($input['time_format']);
247
+
248
+ //Check timezone offset is an integer
249
+ //$offset = (int)$input['offset'];
250
 
251
  //Make sure cache duration is a positive integer or 0. If user has typed 0, leave as 0 but if 0 is returned from absint, set to default (43200)
252
  $cache_duration = $input['cache_duration'];
254
  $cache_duration = (absint($cache_duration) == 0 ? 43200 : absint($cache_duration));
255
  }
256
 
257
+ //Dooltip options must be 'on' or null
258
+ $display_title = ($input['display_title'] == 'on' ? 'on' : null);
259
+ $display_start = ($input['display_start'] == 'on' ? 'on' : null);
260
+ $display_end = ($input['display_end'] == 'on' ? 'on' : null);
261
+ $display_location = ($input['display_location'] == 'on' ? 'on' : null);
262
+ $display_desc = ($input['display_desc'] == 'on' ? 'on' : null);
263
+ $display_link = ($input['display_link'] == 'on' ? 'on' : null);
264
+
265
+ //Escape display text
266
+ $display_title_text = wp_filter_kses($input['display_title_text']);
267
+ $display_start_text = wp_filter_kses($input['display_start_text']);
268
+ $display_end_text = wp_filter_kses($input['display_end_text']);
269
+ $display_location_text = wp_filter_kses($input['display_location_text']);
270
+ $display_desc_text = wp_filter_kses($input['display_desc_text']);
271
+ $display_link_text = wp_filter_kses($input['display_link_text']);
272
+
273
  //Fill options array with validated values
274
  $options[$id] = array(
275
  'id' => $id,
279
  'max_events' => $max_events,
280
  'date_format' => $date_format,
281
  'time_format' => $time_format,
282
+ //'offset' => $offset,
283
+ 'cache_duration' => $cache_duration,
284
+ 'display_title' => $display_title,
285
+ 'display_start' => $display_start,
286
+ 'display_end' => $display_end,
287
+ 'display_location' => $display_location,
288
+ 'display_desc' => $display_desc,
289
+ 'display_link' => $display_link,
290
+ 'display_title_text' => $display_title_text,
291
+ 'display_start_text' => $display_start_text,
292
+ 'display_end_text' => $display_end_text,
293
+ 'display_location_text' => $display_location_text,
294
+ 'display_desc_text' => $display_desc_text,
295
+ 'display_link_text' => $display_link_text
296
  );
297
  }
298
 
344
  //Don't add scripts if on admin screens
345
  if(!is_admin()){
346
  wp_enqueue_script('jquery');
347
+ wp_enqueue_script('gce_jquery_qtip', WP_PLUGIN_URL . '/' . GCE_PLUGIN_NAME . '/js/jquery-qtip.js');
348
+ wp_enqueue_script('gce_scripts', WP_PLUGIN_URL . '/' . GCE_PLUGIN_NAME . '/js/gce-script.js');
349
+
350
  }
351
  }
352
  }
362
  if($df == '') $df = get_option('date_format');
363
  if($tf == '') $tf = get_option('time_format');
364
 
365
+ $display_options = array();
366
+
367
+ //Add display options text to array if they have been turned on (if turned off, don't add them)
368
+ if($options[$feed_id]['display_title'] == 'on') $display_options['title'] = $options[$feed_id]['display_title_text'];
369
+ if($options[$feed_id]['display_start'] == 'on') $display_options['start'] = $options[$feed_id]['display_start_text'];
370
+ if($options[$feed_id]['display_end'] == 'on') $display_options['end'] = $options[$feed_id]['display_end_text'];
371
+ if($options[$feed_id]['display_location'] == 'on') $display_options['location'] = $options[$feed_id]['display_location_text'];
372
+ if($options[$feed_id]['display_desc'] == 'on') $display_options['desc'] = $options[$feed_id]['display_desc_text'];
373
+ if($options[$feed_id]['display_link'] == 'on') $display_options['link'] = $options[$feed_id]['display_link_text'];
374
+
375
  //Creates a new GCE_Parser object for $feed_id
376
  $feed_data = new GCE_Parser(
377
  $options[$feed_id]['url'],
380
  $options[$feed_id]['cache_duration'],
381
  $df,
382
  $tf,
383
+ //$options[$feed_id]['offset'],
384
+ null,
385
+ $display_options
386
  );
387
 
388
  //If the feed parsed ok
405
  if($df == '') $df = get_option('date_format');
406
  if($tf == '') $tf = get_option('time_format');
407
 
408
+ $display_options = array();
409
+
410
+ //Add display options text to array if they have been turned on (if turned off, don't add them)
411
+ if($options[$feed_id]['display_title'] == 'on') $display_options['title'] = $options[$feed_id]['display_title_text'];
412
+ if($options[$feed_id]['display_start'] == 'on') $display_options['start'] = $options[$feed_id]['display_start_text'];
413
+ if($options[$feed_id]['display_end'] == 'on') $display_options['end'] = $options[$feed_id]['display_end_text'];
414
+ if($options[$feed_id]['display_location'] == 'on') $display_options['location'] = $options[$feed_id]['display_location_text'];
415
+ if($options[$feed_id]['display_desc'] == 'on') $display_options['desc'] = $options[$feed_id]['display_desc_text'];
416
+ if($options[$feed_id]['display_link'] == 'on') $display_options['link'] = $options[$feed_id]['display_link_text'];
417
+
418
  //Creates a new GCE_Parser object for $feed_id
419
  $feed_data = new GCE_Parser(
420
  $options[$feed_id]['url'],
423
  $options[$feed_id]['cache_duration'],
424
  $df,
425
  $tf,
426
+ //$options[$feed_id]['offset'],
427
+ get_option('start_of_week'),
428
+ $display_options
429
  );
430
 
431
  //If the feed parsed ok
inc/gce-parser.php CHANGED
@@ -7,14 +7,16 @@ class GCE_Parser{
7
  var $d_format;
8
  var $t_format;
9
  var $week_start_day;
 
 
10
 
11
  //PHP 4 constructor
12
- function GCE_Parser($feed_url = null, $past_events = false, $max_events = 25, $cache_duration = 43200, $date_format = 'F j, Y', $time_format = 'g:i a', $week_start = 0){
13
- $this->__construct($feed_url, $past_events, $max_events, $cache_duration, $date_format, $week_start);
14
  }
15
 
16
  //PHP 5 constructor
17
- function __construct($feed_url = null, $past_events = false, $max_events = 25, $cache_duration = 43200, $date_format = 'F j, Y', $time_format = 'g:i a', $week_start = 0){
18
  $new_feed = new SimplePie_GCalendar(null, null, $cache_duration);
19
  $new_feed->set_cache_class('WP_Feed_Cache');
20
  $new_feed->set_file_class('WP_SimplePie_File');
@@ -35,6 +37,8 @@ class GCE_Parser{
35
  $this->d_format = $date_format;
36
  $this->t_format = $time_format;
37
  $this->week_start_day = $week_start;
 
 
38
  }
39
 
40
  //Check for SimplePie errors. Return false if an error occurred, otherwise return true
@@ -75,14 +79,25 @@ class GCE_Parser{
75
 
76
  foreach($event_days as $key => $event_day){
77
  foreach($event_day as $event){
78
- $markup .=
79
- '<li>' .
80
- '<p class="gce-date-time">' .
81
- '<span class="gce-date">' . date($this->d_format, $key) . '</span> ' .
82
- '<span class="gce-time">' . date($this->t_format, $event->get_start_date()) . '</span>' .
83
- '</p>' .
84
- '<p class="gce-event-text">' . $event->get_title() . '</p>' .
85
- '</li>';
 
 
 
 
 
 
 
 
 
 
 
86
  }
87
  }
88
 
@@ -115,11 +130,35 @@ class GCE_Parser{
115
  //If this event day is the last in $event_days, there are no more events so set $no_more_events to true
116
  if($event_day === end($event_days)) $no_more_events = true;
117
 
118
- //Create markup for tooltip
119
- $events_markup = '<div class="gce-event-info"><p>Events on ' . date($this->d_format, $key) . ':</p><ul>';
 
 
 
 
 
 
120
  foreach($event_day as $event){
121
- $events_markup .= '<li><strong>' . date($this->t_format, $event->get_start_date()) . '</strong><br />' . $event->get_title() . '</p></li>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  }
 
123
  $events_markup .= '</ul></div>';
124
 
125
  //If this event day is 'today', add gce-today class to $css_classes
7
  var $d_format;
8
  var $t_format;
9
  var $week_start_day;
10
+ var $display_options;
11
+ //var $tz_offset;
12
 
13
  //PHP 4 constructor
14
+ function GCE_Parser($feed_url = null, $past_events = false, $max_events = 25, $cache_duration = 43200, $date_format = 'F j, Y', $time_format = 'g:i a',/*$offset = 0,*/ $week_start = 0, $display_opts = array()){
15
+ $this->__construct($feed_url, $past_events, $max_events, $cache_duration, $date_format,/*$offset*/ $week_start, $display_opts);
16
  }
17
 
18
  //PHP 5 constructor
19
+ function __construct($feed_url = null, $past_events = false, $max_events = 25, $cache_duration = 43200, $date_format = 'F j, Y', $time_format = 'g:i a',/*$offset = 0,*/ $week_start = 0, $display_opts = array()){
20
  $new_feed = new SimplePie_GCalendar(null, null, $cache_duration);
21
  $new_feed->set_cache_class('WP_Feed_Cache');
22
  $new_feed->set_file_class('WP_SimplePie_File');
37
  $this->d_format = $date_format;
38
  $this->t_format = $time_format;
39
  $this->week_start_day = $week_start;
40
+ $this->display_options = $display_opts;
41
+ //$this->tz_offset = $offset;
42
  }
43
 
44
  //Check for SimplePie errors. Return false if an error occurred, otherwise return true
79
 
80
  foreach($event_days as $key => $event_day){
81
  foreach($event_day as $event){
82
+ //Get the various information from the event
83
+ $event_start_time = date_i18n($this->t_format, $event->get_start_date());
84
+ $event_end_time = date_i18n($this->t_format . ' ' . $this->d_format, $event->get_end_date());
85
+ $event_location = $event->get_location();
86
+ $event_desc = make_clickable($event->get_description());
87
+ $event_link = $event->get_link();
88
+
89
+ $markup .= '<li>';
90
+
91
+ //Check whether to add each piece of info. If yes, add info (location and desc are also checked if empty, as they may not have been entered when event was created)
92
+ if(isset($this->display_options['title'])) $markup .= '<p class="gce-list-title">' . $this->display_options['title'] . ' ' . date($this->d_format, $key) . '</p>';
93
+ $markup .= '<p class="gce-list-event">' . $event->get_title() . '</p>';
94
+ if(isset($this->display_options['start'])) $markup .= '<p class="gce-list-start"><span>' . $this->display_options['start'] . '</span> ' . $event_start_time . '</p>';
95
+ if(isset($this->display_options['end'])) $markup .= '<p class="gce-list-end"><span>' . $this->display_options['end'] . '</span> ' . $event_end_time . '</p>';
96
+ if(isset($this->display_options['location']) && $location != '') $markup .= '<p class="gce-list-loc"><span>' . $this->display_options['location'] . '</span> ' . $event_location . '</p>';
97
+ if(isset($this->display_options['desc']) && $event_desc != '') $markup .= '<p class="gce-list-desc"><span>' . $this->display_options['desc'] . '</span> ' . $event_desc . '</p>';
98
+ if(isset($this->display_options['link'])) $markup .= '<p class="gce-list-link"><a href="' . $event_link . '">' . $this->display_options['link'] . '</a></p>';
99
+
100
+ $markup .= '</li>';
101
  }
102
  }
103
 
130
  //If this event day is the last in $event_days, there are no more events so set $no_more_events to true
131
  if($event_day === end($event_days)) $no_more_events = true;
132
 
133
+ //Create markup for display
134
+ $events_markup = '<div class="gce-event-info">';
135
+
136
+ //If title option has been set for display, add it
137
+ if(isset($this->display_options['title'])) $events_markup .= '<p class="gce-tooltip-title">' . $this->display_options['title'] . ' ' . date($this->d_format, $key) . '</p>';
138
+
139
+ $events_markup .= '<ul>';
140
+
141
  foreach($event_day as $event){
142
+ //Get the various information from the event
143
+ $event_start_time = date_i18n($this->t_format, $event->get_start_date());
144
+ $event_end_time = date_i18n($this->t_format . ' ' . $this->d_format, $event->get_end_date());
145
+ $event_location = $event->get_location();
146
+ $event_desc = make_clickable($event->get_description());
147
+ $event_link = $event->get_link();
148
+
149
+ //Add event title
150
+ $events_markup .= '<li><p class="gce-tooltip-event">' . $event->get_title() . '</p>';
151
+
152
+ //Check whether to add each piece of info. If yes, add info (location and desc are also checked if empty, as they may not have been entered when event was created)
153
+ if(isset($this->display_options['start'])) $events_markup .= '<p class="gce-tooltip-start"><span>' . $this->display_options['start'] . '</span> ' . $event_start_time . '</p>';
154
+ if(isset($this->display_options['end'])) $events_markup .= '<p class="gce-tooltip-end"><span>' . $this->display_options['end'] . '</span> ' . $event_end_time . '</p>';
155
+ if(isset($this->display_options['location']) && $event_location != '') $events_markup .= '<p class="gce-tooltip-loc"><span>' . $this->display_options['location'] . '</span> ' . $event_location . '</p>';
156
+ if(isset($this->display_options['desc']) && $event_desc != '') $events_markup .= '<p class="gce-tooltip-desc"><span>' . $this->display_options['desc'] . '</span> ' . $event_desc . '</p>';
157
+ if(isset($this->display_options['link'])) $events_markup .= '<p class="gce-tooltip-link"><a href="' . $event_link . '">' . $this->display_options['link'] . '</a></p>';
158
+
159
+ $events_markup .= '</li>';
160
  }
161
+
162
  $events_markup .= '</ul></div>';
163
 
164
  //If this event day is 'today', add gce-today class to $css_classes
js/gce-script.js ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function gce_ajaxify(target, feed_id, type){
2
+ //Add click event to change month links
3
+ jQuery('#' + target + ' .gce-change-month').click(function(){
4
+ //Extract month and year
5
+ var month_year = jQuery(this).attr('name').split('-', 2);
6
+ //Add loading text to table caption
7
+ jQuery('#' + target + ' caption').html('Loading...');
8
+ //Send AJAX request
9
+ jQuery.get('index.php', {gce_type:type, gce_feed_id:feed_id, gce_widget_id:target, gce_month:month_year[0], gce_year:month_year[1]}, function(data){
10
+ //Replace existing data with returned AJAX data
11
+ if(type == 'widget'){
12
+ jQuery('#' + target).html(data);
13
+ }else{
14
+ jQuery('#' + target).replaceWith(data);
15
+ }
16
+ gce_tooltips('#' + target + ' .gce-has-events');
17
+ });
18
+ });
19
+ }
20
+
21
+ function gce_tooltips(target_items){
22
+ jQuery(target_items).each(function(){
23
+ //Add qtip to all target items
24
+ jQuery(this).qtip({
25
+ content: jQuery(this).children('.gce-event-info'),
26
+ position: { corner: { target: 'center', tooltip: 'bottomLeft' }, adjust: { screen: true } },
27
+ hide: { fixed: true, delay: 100, effect: { length: 0 } },
28
+ show: { solo: true, delay: 0, effect: { length: 0 } },
29
+ style: { padding: "0", classes: { tooltip: 'gce-qtip', tip: 'gce-qtip-tip', title: 'gce-qtip-title', content: 'gce-qtip-content', active: 'gce-qtip-active' }, border: { width: 0 } }
30
+ });
31
+ });
32
+ }
33
+
34
+ jQuery(document).ready(function(){
35
+ gce_tooltips('.gce-has-events');
36
+ });
js/gce-tooltip-script.js DELETED
@@ -1,71 +0,0 @@
1
- function gce_simple_tooltip(target_items){
2
- if(jQuery('#gce-tooltip').html() == null){
3
- //Appends a div, which will be used as the tooltip
4
- jQuery('body').append('<div id="gce-tooltip"></div>');
5
- };
6
-
7
- jQuery(target_items).each(function(){
8
- //Reference to div appended above
9
- var my_tooltip = jQuery('#gce-tooltip');
10
-
11
- //On mouse over
12
- jQuery(this).mouseover(function(){
13
- //Sets the tooltip to the correct information for the day (hidden in <td>)
14
- my_tooltip.html(jQuery(this).children('div').html());
15
- //Shows the tooltip
16
- my_tooltip.show();
17
- //On mouse move
18
- }).mousemove(function(kmouse){
19
- //All this stuff prevents tooltip going out of viewport
20
- var border_top = jQuery(window).scrollTop();
21
- var border_right = jQuery(window).width();
22
- var left_pos;
23
- var top_pos;
24
- var offset = 5; //Offset from mouse pointer
25
-
26
- if(border_right - (offset * 2) >= my_tooltip.width() + kmouse.pageX){
27
- left_pos = kmouse.pageX + offset;
28
- }else{
29
- left_pos = border_right - my_tooltip.width() - offset;
30
- }
31
-
32
- if(border_top + (offset * 2) >= kmouse.pageY - my_tooltip.height()){
33
- top_pos = border_top + offset;
34
- }else{
35
- top_pos = kmouse.pageY - my_tooltip.height() - offset;
36
- }
37
-
38
- my_tooltip.css({left:left_pos, top:top_pos});
39
- //On mouse out
40
- }).mouseout(function(){
41
- //Hide the tooltip
42
- my_tooltip.hide();
43
- });
44
- });
45
- }
46
-
47
- function gce_ajaxify(target, feed_id, type){
48
- //Add click event to change month links
49
- jQuery('#' + target + ' .gce-change-month').click(function(){
50
- //Extract month and year
51
- var month_year = jQuery(this).attr('name').split('-', 2);
52
- //Add loading text to table caption
53
- jQuery('#' + target + ' caption').html('Loading...');
54
- //Send AJAX request
55
- jQuery.get('index.php', {gce_type:type, gce_feed_id:feed_id, gce_widget_id:target, gce_month:month_year[0], gce_year:month_year[1]}, function(data){
56
- //Replace existing data with returned AJAX data
57
- if(type == 'widget'){
58
- jQuery('#' + target).html(data);
59
- gce_simple_tooltip('.gce-widget-grid .gce-has-events');
60
- }else{
61
- jQuery('#' + target).replaceWith(data);
62
- gce_simple_tooltip('.gce-page-grid .gce-has-events');
63
- }
64
- });
65
- });
66
- }
67
-
68
- jQuery(document).ready(function(){
69
- gce_simple_tooltip('.gce-widget-grid .gce-has-events');
70
- gce_simple_tooltip('.gce-page-grid .gce-has-events');
71
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/jquery-qtip.js ADDED
@@ -0,0 +1,2149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jquery.qtip. The jQuery tooltip plugin
3
+ *
4
+ * Copyright (c) 2009 Craig Thompson
5
+ * http://craigsworks.com
6
+ *
7
+ * Licensed under MIT
8
+ * http://www.opensource.org/licenses/mit-license.php
9
+ *
10
+ * Launch : February 2009
11
+ * Version : 1.0.0-rc3
12
+ * Released: Tuesday 12th May, 2009 - 00:00
13
+ * Debug: jquery.qtip.debug.js
14
+ */
15
+ (function($)
16
+ {
17
+ // Implementation
18
+ $.fn.qtip = function(options, blanket)
19
+ {
20
+ var i, id, interfaces, opts, obj, command, config, api;
21
+
22
+ // Return API / Interfaces if requested
23
+ if(typeof options == 'string')
24
+ {
25
+ // Make sure API data exists if requested
26
+ if(typeof $(this).data('qtip') !== 'object')
27
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.NO_TOOLTIP_PRESENT, false);
28
+
29
+ // Return requested object
30
+ if(options == 'api')
31
+ return $(this).data('qtip').interfaces[ $(this).data('qtip').current ];
32
+ else if(options == 'interfaces')
33
+ return $(this).data('qtip').interfaces;
34
+ }
35
+
36
+ // Validate provided options
37
+ else
38
+ {
39
+ // Set null options object if no options are provided
40
+ if(!options) options = {};
41
+
42
+ // Sanitize option data
43
+ if(typeof options.content !== 'object' || (options.content.jquery && options.content.length > 0)) options.content = { text: options.content };
44
+ if(typeof options.content.title !== 'object') options.content.title = { text: options.content.title };
45
+ if(typeof options.position !== 'object') options.position = { corner: options.position };
46
+ if(typeof options.position.corner !== 'object') options.position.corner = { target: options.position.corner, tooltip: options.position.corner };
47
+ if(typeof options.show !== 'object') options.show = { when: options.show };
48
+ if(typeof options.show.when !== 'object') options.show.when = { event: options.show.when };
49
+ if(typeof options.show.effect !== 'object') options.show.effect = { type: options.show.effect };
50
+ if(typeof options.hide !== 'object') options.hide = { when: options.hide };
51
+ if(typeof options.hide.when !== 'object') options.hide.when = { event: options.hide.when };
52
+ if(typeof options.hide.effect !== 'object') options.hide.effect = { type: options.hide.effect };
53
+ if(typeof options.style !== 'object') options.style = { name: options.style };
54
+ options.style = sanitizeStyle(options.style);
55
+
56
+ // Build main options object
57
+ opts = $.extend(true, {}, $.fn.qtip.defaults, options);
58
+
59
+ // Inherit all style properties into one syle object and include original options
60
+ opts.style = buildStyle.call({ options: opts }, opts.style);
61
+ opts.user = $.extend(true, {}, options);
62
+ };
63
+
64
+ // Iterate each matched element
65
+ return $(this).each(function() // Return original elements as per jQuery guidelines
66
+ {
67
+ // Check for API commands
68
+ if(typeof options == 'string')
69
+ {
70
+ command = options.toLowerCase();
71
+ interfaces = $(this).qtip('interfaces');
72
+
73
+ // Make sure API data exists$('.qtip').qtip('destroy')
74
+ if(typeof interfaces == 'object')
75
+ {
76
+ // Check if API call is a BLANKET DESTROY command
77
+ if(blanket === true && command == 'destroy')
78
+ while(interfaces.length > 0) interfaces[interfaces.length-1].destroy();
79
+
80
+ // API call is not a BLANKET DESTROY command
81
+ else
82
+ {
83
+ // Check if supplied command effects this tooltip only (NOT BLANKET)
84
+ if(blanket !== true) interfaces = [ $(this).qtip('api') ];
85
+
86
+ // Execute command on chosen qTips
87
+ for(i = 0; i < interfaces.length; i++)
88
+ {
89
+ // Destroy command doesn't require tooltip to be rendered
90
+ if(command == 'destroy') interfaces[i].destroy();
91
+
92
+ // Only call API if tooltip is rendered and it wasn't a destroy call
93
+ else if(interfaces[i].status.rendered === true)
94
+ {
95
+ if(command == 'show') interfaces[i].show();
96
+ else if(command == 'hide') interfaces[i].hide();
97
+ else if(command == 'focus') interfaces[i].focus();
98
+ else if(command == 'disable') interfaces[i].disable(true);
99
+ else if(command == 'enable') interfaces[i].disable(false);
100
+ };
101
+ };
102
+ };
103
+ };
104
+ }
105
+
106
+ // No API commands, continue with qTip creation
107
+ else
108
+ {
109
+ // Create unique configuration object
110
+ config = $.extend(true, {}, opts);
111
+ config.hide.effect.length = opts.hide.effect.length;
112
+ config.show.effect.length = opts.show.effect.length;
113
+
114
+ // Sanitize target options
115
+ if(config.position.container === false) config.position.container = $(document.body);
116
+ if(config.position.target === false) config.position.target = $(this);
117
+ if(config.show.when.target === false) config.show.when.target = $(this);
118
+ if(config.hide.when.target === false) config.hide.when.target = $(this);
119
+
120
+ // Determine tooltip ID (Reuse array slots if possible)
121
+ id = $.fn.qtip.interfaces.length;
122
+ for(i = 0; i < id; i++)
123
+ {
124
+ if(typeof $.fn.qtip.interfaces[i] == 'undefined'){ id = i; break; };
125
+ };
126
+
127
+ // Instantiate the tooltip
128
+ obj = new qTip($(this), config, id);
129
+
130
+ // Add API references
131
+ $.fn.qtip.interfaces[id] = obj;
132
+
133
+ // Check if element already has qTip data assigned
134
+ if(typeof $(this).data('qtip') == 'object' && $(this).data('qtip'))
135
+ {
136
+ // Set new current interface id
137
+ if(typeof $(this).attr('qtip') === 'undefined')
138
+ $(this).data('qtip').current = $(this).data('qtip').interfaces.length;
139
+
140
+ // Push new API interface onto interfaces array
141
+ $(this).data('qtip').interfaces.push(obj);
142
+ }
143
+
144
+ // No qTip data is present, create now
145
+ else $(this).data('qtip', { current: 0, interfaces: [obj] });
146
+
147
+ // If prerendering is disabled, create tooltip on showEvent
148
+ if(config.content.prerender === false && config.show.when.event !== false && config.show.ready !== true)
149
+ {
150
+ config.show.when.target.bind(config.show.when.event+'.qtip-'+id+'-create', { qtip: id }, function(event)
151
+ {
152
+ // Retrieve API interface via passed qTip Id
153
+ api = $.fn.qtip.interfaces[ event.data.qtip ];
154
+
155
+ // Unbind show event and cache mouse coords
156
+ api.options.show.when.target.unbind(api.options.show.when.event+'.qtip-'+event.data.qtip+'-create');
157
+ api.cache.mouse = { x: event.pageX, y: event.pageY };
158
+
159
+ // Render tooltip and start the event sequence
160
+ construct.call( api );
161
+ api.options.show.when.target.trigger(api.options.show.when.event);
162
+ });
163
+ }
164
+
165
+ // Prerendering is enabled, create tooltip now
166
+ else
167
+ {
168
+ // Set mouse position cache to top left of the element
169
+ obj.cache.mouse = {
170
+ x: config.show.when.target.offset().left,
171
+ y: config.show.when.target.offset().top
172
+ };
173
+
174
+ // Construct the tooltip
175
+ construct.call(obj);
176
+ }
177
+ };
178
+ });
179
+ };
180
+
181
+ // Instantiator
182
+ function qTip(target, options, id)
183
+ {
184
+ // Declare this reference
185
+ var self = this;
186
+
187
+ // Setup class attributes
188
+ self.id = id;
189
+ self.options = options;
190
+ self.status = {
191
+ animated: false,
192
+ rendered: false,
193
+ disabled: false,
194
+ focused: false
195
+ };
196
+ self.elements = {
197
+ target: target.addClass(self.options.style.classes.target),
198
+ tooltip: null,
199
+ wrapper: null,
200
+ content: null,
201
+ contentWrapper: null,
202
+ title: null,
203
+ button: null,
204
+ tip: null,
205
+ bgiframe: null
206
+ };
207
+ self.cache = {
208
+ mouse: {},
209
+ position: {},
210
+ toggle: 0
211
+ };
212
+ self.timers = {};
213
+
214
+ // Define exposed API methods
215
+ $.extend(self, self.options.api,
216
+ {
217
+ show: function(event)
218
+ {
219
+ var returned, solo;
220
+
221
+ // Make sure tooltip is rendered and if not, return
222
+ if(!self.status.rendered)
223
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'show');
224
+
225
+ // Only continue if element is visible
226
+ if(self.elements.tooltip.css('display') !== 'none') return self;
227
+
228
+ // Clear animation queue
229
+ self.elements.tooltip.stop(true, false);
230
+
231
+ // Call API method and if return value is false, halt
232
+ returned = self.beforeShow.call(self, event);
233
+ if(returned === false) return self;
234
+
235
+ // Define afterShow callback method
236
+ function afterShow()
237
+ {
238
+ // Call API method and focus if it isn't static
239
+ if(self.options.position.type !== 'static') self.focus();
240
+ self.onShow.call(self, event);
241
+
242
+ // Prevent antialias from disappearing in IE7 by removing filter attribute
243
+ if($.browser.msie) self.elements.tooltip.get(0).style.removeAttribute('filter');
244
+ };
245
+
246
+ // Maintain toggle functionality if enabled
247
+ self.cache.toggle = 1;
248
+
249
+ // Update tooltip position if it isn't static
250
+ if(self.options.position.type !== 'static')
251
+ self.updatePosition(event, (self.options.show.effect.length > 0));
252
+
253
+ // Hide other tooltips if tooltip is solo
254
+ if(typeof self.options.show.solo == 'object') solo = $(self.options.show.solo);
255
+ else if(self.options.show.solo === true) solo = $('div.qtip').not(self.elements.tooltip);
256
+ if(solo) solo.each(function(){ if($(this).qtip('api').status.rendered === true) $(this).qtip('api').hide(); });
257
+
258
+ // Show tooltip
259
+ if(typeof self.options.show.effect.type == 'function')
260
+ {
261
+ self.options.show.effect.type.call(self.elements.tooltip, self.options.show.effect.length);
262
+ self.elements.tooltip.queue(function(){ afterShow(); $(this).dequeue(); });
263
+ }
264
+ else
265
+ {
266
+ switch(self.options.show.effect.type.toLowerCase())
267
+ {
268
+ case 'fade':
269
+ self.elements.tooltip.fadeIn(self.options.show.effect.length, afterShow);
270
+ break;
271
+ case 'slide':
272
+ self.elements.tooltip.slideDown(self.options.show.effect.length, function()
273
+ {
274
+ afterShow();
275
+ if(self.options.position.type !== 'static') self.updatePosition(event, true);
276
+ });
277
+ break;
278
+ case 'grow':
279
+ self.elements.tooltip.show(self.options.show.effect.length, afterShow);
280
+ break;
281
+ default:
282
+ self.elements.tooltip.show(null, afterShow);
283
+ break;
284
+ };
285
+
286
+ // Add active class to tooltip
287
+ self.elements.tooltip.addClass(self.options.style.classes.active);
288
+ };
289
+
290
+ // Log event and return
291
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_SHOWN, 'show');
292
+ },
293
+
294
+ hide: function(event)
295
+ {
296
+ var returned;
297
+
298
+ // Make sure tooltip is rendered and if not, return
299
+ if(!self.status.rendered)
300
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'hide');
301
+
302
+ // Only continue if element is visible
303
+ else if(self.elements.tooltip.css('display') === 'none') return self;
304
+
305
+ // Stop show timer and animation queue
306
+ clearTimeout(self.timers.show);
307
+ self.elements.tooltip.stop(true, false);
308
+
309
+ // Call API method and if return value is false, halt
310
+ returned = self.beforeHide.call(self, event);
311
+ if(returned === false) return self;
312
+
313
+ // Define afterHide callback method
314
+ function afterHide(){ self.onHide.call(self, event); };
315
+
316
+ // Maintain toggle functionality if enabled
317
+ self.cache.toggle = 0;
318
+
319
+ // Hide tooltip
320
+ if(typeof self.options.hide.effect.type == 'function')
321
+ {
322
+ self.options.hide.effect.type.call(self.elements.tooltip, self.options.hide.effect.length);
323
+ self.elements.tooltip.queue(function(){ afterHide(); $(this).dequeue(); });
324
+ }
325
+ else
326
+ {
327
+ switch(self.options.hide.effect.type.toLowerCase())
328
+ {
329
+ case 'fade':
330
+ self.elements.tooltip.fadeOut(self.options.hide.effect.length, afterHide);
331
+ break;
332
+ case 'slide':
333
+ self.elements.tooltip.slideUp(self.options.hide.effect.length, afterHide);
334
+ break;
335
+ case 'grow':
336
+ self.elements.tooltip.hide(self.options.hide.effect.length, afterHide);
337
+ break;
338
+ default:
339
+ self.elements.tooltip.hide(null, afterHide);
340
+ break;
341
+ };
342
+
343
+ // Remove active class to tooltip
344
+ self.elements.tooltip.removeClass(self.options.style.classes.active);
345
+ };
346
+
347
+ // Log event and return
348
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_HIDDEN, 'hide');
349
+ },
350
+
351
+ updatePosition: function(event, animate)
352
+ {
353
+ var i, target, tooltip, coords, mapName, imagePos, newPosition, ieAdjust, ie6Adjust, borderAdjust, mouseAdjust, offset, curPosition, returned
354
+
355
+ // Make sure tooltip is rendered and if not, return
356
+ if(!self.status.rendered)
357
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updatePosition');
358
+
359
+ // If tooltip is static, return
360
+ else if(self.options.position.type == 'static')
361
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.CANNOT_POSITION_STATIC, 'updatePosition');
362
+
363
+ // Define property objects
364
+ target = {
365
+ position: { left: 0, top: 0 },
366
+ dimensions: { height: 0, width: 0 },
367
+ corner: self.options.position.corner.target
368
+ };
369
+ tooltip = {
370
+ position: self.getPosition(),
371
+ dimensions: self.getDimensions(),
372
+ corner: self.options.position.corner.tooltip
373
+ };
374
+
375
+ // Target is an HTML element
376
+ if(self.options.position.target !== 'mouse')
377
+ {
378
+ // If the HTML element is AREA, calculate position manually
379
+ if(self.options.position.target.get(0).nodeName.toLowerCase() == 'area')
380
+ {
381
+ // Retrieve coordinates from coords attribute and parse into integers
382
+ coords = self.options.position.target.attr('coords').split(',');
383
+ for(i = 0; i < coords.length; i++) coords[i] = parseInt(coords[i]);
384
+
385
+ // Setup target position object
386
+ mapName = self.options.position.target.parent('map').attr('name');
387
+ imagePos = $('img[usemap="#'+mapName+'"]:first').offset();
388
+ target.position = {
389
+ left: Math.floor(imagePos.left + coords[0]),
390
+ top: Math.floor(imagePos.top + coords[1])
391
+ };
392
+
393
+ // Determine width and height of the area
394
+ switch(self.options.position.target.attr('shape').toLowerCase())
395
+ {
396
+ case 'rect':
397
+ target.dimensions = {
398
+ width: Math.ceil(Math.abs(coords[2] - coords[0])),
399
+ height: Math.ceil(Math.abs(coords[3] - coords[1]))
400
+ };
401
+ break;
402
+
403
+ case 'circle':
404
+ target.dimensions = {
405
+ width: coords[2] + 1,
406
+ height: coords[2] + 1
407
+ };
408
+ break;
409
+
410
+ case 'poly':
411
+ target.dimensions = {
412
+ width: coords[0],
413
+ height: coords[1]
414
+ };
415
+
416
+ for(i = 0; i < coords.length; i++)
417
+ {
418
+ if(i % 2 == 0)
419
+ {
420
+ if(coords[i] > target.dimensions.width)
421
+ target.dimensions.width = coords[i];
422
+ if(coords[i] < coords[0])
423
+ target.position.left = Math.floor(imagePos.left + coords[i]);
424
+ }
425
+ else
426
+ {
427
+ if(coords[i] > target.dimensions.height)
428
+ target.dimensions.height = coords[i];
429
+ if(coords[i] < coords[1])
430
+ target.position.top = Math.floor(imagePos.top + coords[i]);
431
+ };
432
+ };
433
+
434
+ target.dimensions.width = target.dimensions.width - (target.position.left - imagePos.left);
435
+ target.dimensions.height = target.dimensions.height - (target.position.top - imagePos.top);
436
+ break;
437
+
438
+ default:
439
+ return $.fn.qtip.log.error.call(self, 4, $.fn.qtip.constants.INVALID_AREA_SHAPE, 'updatePosition');
440
+ break;
441
+ };
442
+
443
+ // Adjust position by 2 pixels (Positioning bug?)
444
+ target.dimensions.width -= 2; target.dimensions.height -= 2;
445
+ }
446
+
447
+ // Target is the document
448
+ else if(self.options.position.target.add(document.body).length === 1)
449
+ {
450
+ target.position = { left: $(document).scrollLeft(), top: $(document).scrollTop() };
451
+ target.dimensions = { height: $(window).height(), width: $(window).width() };
452
+ }
453
+
454
+ // Target is a regular HTML element, find position normally
455
+ else
456
+ {
457
+ // Check if the target is another tooltip. If its animated, retrieve position from newPosition data
458
+ if(typeof self.options.position.target.attr('qtip') !== 'undefined')
459
+ target.position = self.options.position.target.qtip('api').cache.position;
460
+ else
461
+ target.position = self.options.position.target.offset();
462
+
463
+ // Setup dimensions objects
464
+ target.dimensions = {
465
+ height: self.options.position.target.outerHeight(),
466
+ width: self.options.position.target.outerWidth()
467
+ };
468
+ };
469
+
470
+ // Calculate correct target corner position
471
+ newPosition = $.extend({}, target.position);
472
+ if(target.corner.search(/right/i) !== -1)
473
+ newPosition.left += target.dimensions.width;
474
+
475
+ if(target.corner.search(/bottom/i) !== -1)
476
+ newPosition.top += target.dimensions.height;
477
+
478
+ if(target.corner.search(/((top|bottom)Middle)|center/) !== -1)
479
+ newPosition.left += (target.dimensions.width / 2);
480
+
481
+ if(target.corner.search(/((left|right)Middle)|center/) !== -1)
482
+ newPosition.top += (target.dimensions.height / 2);
483
+ }
484
+
485
+ // Mouse is the target, set position to current mouse coordinates
486
+ else
487
+ {
488
+ // Setup target position and dimensions objects
489
+ target.position = newPosition = { left: self.cache.mouse.x, top: self.cache.mouse.y };
490
+ target.dimensions = { height: 1, width: 1 };
491
+ };
492
+
493
+ // Calculate correct target corner position
494
+ if(tooltip.corner.search(/right/i) !== -1)
495
+ newPosition.left -= tooltip.dimensions.width;
496
+
497
+ if(tooltip.corner.search(/bottom/i) !== -1)
498
+ newPosition.top -= tooltip.dimensions.height;
499
+
500
+ if(tooltip.corner.search(/((top|bottom)Middle)|center/) !== -1)
501
+ newPosition.left -= (tooltip.dimensions.width / 2);
502
+
503
+ if(tooltip.corner.search(/((left|right)Middle)|center/) !== -1)
504
+ newPosition.top -= (tooltip.dimensions.height / 2);
505
+
506
+ // Setup IE adjustment variables (Pixel gap bugs)
507
+ ieAdjust = ($.browser.msie) ? 1 : 0; // And this is why I hate IE...
508
+ ie6Adjust = ($.browser.msie && parseInt($.browser.version.charAt(0)) === 6) ? 1 : 0; // ...and even more so IE6!
509
+
510
+ // Adjust for border radius
511
+ if(self.options.style.border.radius > 0)
512
+ {
513
+ if(tooltip.corner.search(/Left/) !== -1)
514
+ newPosition.left -= self.options.style.border.radius;
515
+ else if(tooltip.corner.search(/Right/) !== -1)
516
+ newPosition.left += self.options.style.border.radius;
517
+
518
+ if(tooltip.corner.search(/Top/) !== -1)
519
+ newPosition.top -= self.options.style.border.radius;
520
+ else if(tooltip.corner.search(/Bottom/) !== -1)
521
+ newPosition.top += self.options.style.border.radius;
522
+ };
523
+
524
+ // IE only adjustments (Pixel perfect!)
525
+ if(ieAdjust)
526
+ {
527
+ if(tooltip.corner.search(/top/) !== -1)
528
+ newPosition.top -= ieAdjust
529
+ else if(tooltip.corner.search(/bottom/) !== -1)
530
+ newPosition.top += ieAdjust
531
+
532
+ if(tooltip.corner.search(/left/) !== -1)
533
+ newPosition.left -= ieAdjust
534
+ else if(tooltip.corner.search(/right/) !== -1)
535
+ newPosition.left += ieAdjust
536
+
537
+ if(tooltip.corner.search(/leftMiddle|rightMiddle/) !== -1)
538
+ newPosition.top -= 1
539
+ };
540
+
541
+ // If screen adjustment is enabled, apply adjustments
542
+ if(self.options.position.adjust.screen === true)
543
+ newPosition = screenAdjust.call(self, newPosition, target, tooltip);
544
+
545
+ // If mouse is the target, prevent tooltip appearing directly under the mouse
546
+ if(self.options.position.target === 'mouse' && self.options.position.adjust.mouse === true)
547
+ {
548
+ if(self.options.position.adjust.screen === true && self.elements.tip)
549
+ mouseAdjust = self.elements.tip.attr('rel');
550
+ else
551
+ mouseAdjust = self.options.position.corner.tooltip;
552
+
553
+ newPosition.left += (mouseAdjust.search(/right/i) !== -1) ? -6 : 6;
554
+ newPosition.top += (mouseAdjust.search(/bottom/i) !== -1) ? -6 : 6;
555
+ }
556
+
557
+ // Initiate bgiframe plugin in IE6 if tooltip overlaps a select box or object element
558
+ if(!self.elements.bgiframe && $.browser.msie && parseInt($.browser.version.charAt(0)) == 6)
559
+ {
560
+ $('select, object').each(function()
561
+ {
562
+ offset = $(this).offset();
563
+ offset.bottom = offset.top + $(this).height();
564
+ offset.right = offset.left + $(this).width();
565
+
566
+ if(newPosition.top + tooltip.dimensions.height >= offset.top
567
+ && newPosition.left + tooltip.dimensions.width >= offset.left)
568
+ bgiframe.call(self);
569
+ });
570
+ };
571
+
572
+ // Add user xy adjustments
573
+ newPosition.left += self.options.position.adjust.x;
574
+ newPosition.top += self.options.position.adjust.y;
575
+
576
+ // Set new tooltip position if its moved, animate if enabled
577
+ curPosition = self.getPosition();
578
+ if(newPosition.left != curPosition.left || newPosition.top != curPosition.top)
579
+ {
580
+ // Call API method and if return value is false, halt
581
+ returned = self.beforePositionUpdate.call(self, event);
582
+ if(returned === false) return self;
583
+
584
+ // Cache new position
585
+ self.cache.position = newPosition;
586
+
587
+ // Check if animation is enabled
588
+ if(animate === true)
589
+ {
590
+ // Set animated status
591
+ self.status.animated = true;
592
+
593
+ // Animate and reset animated status on animation end
594
+ self.elements.tooltip.animate(newPosition, 200, 'swing', function(){ self.status.animated = false });
595
+ }
596
+
597
+ // Set new position via CSS
598
+ else self.elements.tooltip.css(newPosition);
599
+
600
+ // Call API method and log event if its not a mouse move
601
+ self.onPositionUpdate.call(self, event);
602
+ if(typeof event !== 'undefined' && event.type && event.type !== 'mousemove')
603
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_POSITION_UPDATED, 'updatePosition');
604
+ };
605
+
606
+ return self;
607
+ },
608
+
609
+ updateWidth: function(newWidth)
610
+ {
611
+ var hidden;
612
+
613
+ // Make sure tooltip is rendered and if not, return
614
+ if(!self.status.rendered)
615
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateWidth');
616
+
617
+ // Make sure supplied width is a number and if not, return
618
+ else if(newWidth && typeof newWidth !== 'number')
619
+ return $.fn.qtip.log.error.call(self, 2, 'newWidth must be of type number', 'updateWidth');
620
+
621
+ // Setup elements which must be hidden during width update
622
+ hidden = self.elements.contentWrapper.siblings().add(self.elements.tip).add(self.elements.button);
623
+
624
+ // Calculate the new width if one is not supplied
625
+ if(!newWidth)
626
+ {
627
+ // Explicit width is set
628
+ if(typeof self.options.style.width.value == 'number')
629
+ newWidth = self.options.style.width.value;
630
+
631
+ // No width is set, proceed with auto detection
632
+ else
633
+ {
634
+ // Set width to auto initally to determine new width and hide other elements
635
+ self.elements.tooltip.css({ width: 'auto' });
636
+ hidden.hide();
637
+
638
+ // Set position and zoom to defaults to prevent IE hasLayout bug
639
+ if($.browser.msie)
640
+ self.elements.wrapper.add(self.elements.contentWrapper.children()).css({ zoom: 'normal' });
641
+
642
+ // Set the new width
643
+ newWidth = self.getDimensions().width + 1;
644
+
645
+ // Make sure its within the maximum and minimum width boundries
646
+ if(!self.options.style.width.value)
647
+ {
648
+ if(newWidth > self.options.style.width.max) newWidth = self.options.style.width.max
649
+ if(newWidth < self.options.style.width.min) newWidth = self.options.style.width.min
650
+ };
651
+ };
652
+ };
653
+
654
+ // Adjust newWidth by 1px if width is odd (IE6 rounding bug fix)
655
+ if(newWidth % 2 !== 0) newWidth -= 1;
656
+
657
+ // Set the new calculated width and unhide other elements
658
+ self.elements.tooltip.width(newWidth);
659
+ hidden.show();
660
+
661
+ // Set the border width, if enabled
662
+ if(self.options.style.border.radius)
663
+ {
664
+ self.elements.tooltip.find('.qtip-betweenCorners').each(function(i)
665
+ {
666
+ $(this).width(newWidth - (self.options.style.border.radius * 2));
667
+ })
668
+ };
669
+
670
+ // IE only adjustments
671
+ if($.browser.msie)
672
+ {
673
+ // Reset position and zoom to give the wrapper layout (IE hasLayout bug)
674
+ self.elements.wrapper.add(self.elements.contentWrapper.children()).css({ zoom: '1' });
675
+
676
+ // Set the new width
677
+ self.elements.wrapper.width(newWidth);
678
+
679
+ // Adjust BGIframe height and width if enabled
680
+ if(self.elements.bgiframe) self.elements.bgiframe.width(newWidth).height(self.getDimensions.height);
681
+ };
682
+
683
+ // Log event and return
684
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_WIDTH_UPDATED, 'updateWidth');
685
+ },
686
+
687
+ updateStyle: function(name)
688
+ {
689
+ var tip, borders, context, corner, coordinates;
690
+
691
+ // Make sure tooltip is rendered and if not, return
692
+ if(!self.status.rendered)
693
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateStyle');
694
+
695
+ // Return if style is not defined or name is not a string
696
+ else if(typeof name !== 'string' || !$.fn.qtip.styles[name])
697
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.STYLE_NOT_DEFINED, 'updateStyle');
698
+
699
+ // Set the new style object
700
+ self.options.style = buildStyle.call(self, $.fn.qtip.styles[name], self.options.user.style);
701
+
702
+ // Update initial styles of content and title elements
703
+ self.elements.content.css( jQueryStyle(self.options.style) );
704
+ if(self.options.content.title.text !== false)
705
+ self.elements.title.css( jQueryStyle(self.options.style.title, true) );
706
+
707
+ // Update CSS border colour
708
+ self.elements.contentWrapper.css({ borderColor: self.options.style.border.color });
709
+
710
+ // Update tip color if enabled
711
+ if(self.options.style.tip.corner !== false)
712
+ {
713
+ if($('<canvas>').get(0).getContext)
714
+ {
715
+ // Retrieve canvas context and clear
716
+ tip = self.elements.tooltip.find('.qtip-tip canvas:first');
717
+ context = tip.get(0).getContext('2d');
718
+ context.clearRect(0,0,300,300);
719
+
720
+ // Draw new tip
721
+ corner = tip.parent('div[rel]:first').attr('rel');
722
+ coordinates = calculateTip(corner, self.options.style.tip.size.width, self.options.style.tip.size.height);
723
+ drawTip.call(self, tip, coordinates, self.options.style.tip.color || self.options.style.border.color);
724
+ }
725
+ else if($.browser.msie)
726
+ {
727
+ // Set new fillcolor attribute
728
+ tip = self.elements.tooltip.find('.qtip-tip [nodeName="shape"]');
729
+ tip.attr('fillcolor', self.options.style.tip.color || self.options.style.border.color);
730
+ };
731
+ };
732
+
733
+ // Update border colors if enabled
734
+ if(self.options.style.border.radius > 0)
735
+ {
736
+ self.elements.tooltip.find('.qtip-betweenCorners').css({ backgroundColor: self.options.style.border.color });
737
+
738
+ if($('<canvas>').get(0).getContext)
739
+ {
740
+ borders = calculateBorders(self.options.style.border.radius)
741
+ self.elements.tooltip.find('.qtip-wrapper canvas').each(function()
742
+ {
743
+ // Retrieve canvas context and clear
744
+ context = $(this).get(0).getContext('2d');
745
+ context.clearRect(0,0,300,300);
746
+
747
+ // Draw new border
748
+ corner = $(this).parent('div[rel]:first').attr('rel')
749
+ drawBorder.call(self, $(this), borders[corner],
750
+ self.options.style.border.radius, self.options.style.border.color);
751
+ });
752
+ }
753
+ else if($.browser.msie)
754
+ {
755
+ // Set new fillcolor attribute on each border corner
756
+ self.elements.tooltip.find('.qtip-wrapper [nodeName="arc"]').each(function()
757
+ {
758
+ $(this).attr('fillcolor', self.options.style.border.color)
759
+ });
760
+ };
761
+ };
762
+
763
+ // Log event and return
764
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_STYLE_UPDATED, 'updateStyle');
765
+ },
766
+
767
+ updateContent: function(content, reposition)
768
+ {
769
+ var parsedContent, images, loadedImages;
770
+
771
+ // Make sure tooltip is rendered and if not, return
772
+ if(!self.status.rendered)
773
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateContent');
774
+
775
+ // Make sure content is defined before update
776
+ else if(!content)
777
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.NO_CONTENT_PROVIDED, 'updateContent');
778
+
779
+ // Call API method and set new content if a string is returned
780
+ parsedContent = self.beforeContentUpdate.call(self, content);
781
+ if(typeof parsedContent == 'string') content = parsedContent;
782
+ else if(parsedContent === false) return;
783
+
784
+ // Set position and zoom to defaults to prevent IE hasLayout bug
785
+ if($.browser.msie) self.elements.contentWrapper.children().css({ zoom: 'normal' });
786
+
787
+ // Append new content if its a DOM array and show it if hidden
788
+ if(content.jquery && content.length > 0)
789
+ content.clone(true).appendTo(self.elements.content).show();
790
+
791
+ // Content is a regular string, insert the new content
792
+ else self.elements.content.html(content);
793
+
794
+ // Check if images need to be loaded before position is updated to prevent mis-positioning
795
+ images = self.elements.content.find('img[complete=false]');
796
+ if(images.length > 0)
797
+ {
798
+ loadedImages = 0;
799
+ images.each(function(i)
800
+ {
801
+ $('<img src="'+ $(this).attr('src') +'" />')
802
+ .load(function(){ if(++loadedImages == images.length) afterLoad(); });
803
+ });
804
+ }
805
+ else afterLoad();
806
+
807
+ function afterLoad()
808
+ {
809
+ // Update the tooltip width
810
+ self.updateWidth();
811
+
812
+ // If repositioning is enabled, update positions
813
+ if(reposition !== false)
814
+ {
815
+ // Update position if tooltip isn't static
816
+ if(self.options.position.type !== 'static')
817
+ self.updatePosition(self.elements.tooltip.is(':visible'), true);
818
+
819
+ // Reposition the tip if enabled
820
+ if(self.options.style.tip.corner !== false)
821
+ positionTip.call(self);
822
+ };
823
+ };
824
+
825
+ // Call API method and log event
826
+ self.onContentUpdate.call(self);
827
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_CONTENT_UPDATED, 'loadContent');
828
+ },
829
+
830
+ loadContent: function(url, data, method)
831
+ {
832
+ var returned;
833
+
834
+ // Make sure tooltip is rendered and if not, return
835
+ if(!self.status.rendered)
836
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'loadContent');
837
+
838
+ // Call API method and if return value is false, halt
839
+ returned = self.beforeContentLoad.call(self);
840
+ if(returned === false) return self;
841
+
842
+ // Load content using specified request type
843
+ if(method == 'post')
844
+ $.post(url, data, setupContent);
845
+ else
846
+ $.get(url, data, setupContent);
847
+
848
+ function setupContent(content)
849
+ {
850
+ // Call API method and log event
851
+ self.onContentLoad.call(self);
852
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_CONTENT_LOADED, 'loadContent');
853
+
854
+ // Update the content
855
+ self.updateContent(content);
856
+ };
857
+
858
+ return self;
859
+ },
860
+
861
+ updateTitle: function(content)
862
+ {
863
+ // Make sure tooltip is rendered and if not, return
864
+ if(!self.status.rendered)
865
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateTitle');
866
+
867
+ // Make sure content is defined before update
868
+ else if(!content)
869
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.NO_CONTENT_PROVIDED, 'updateTitle');
870
+
871
+ // Call API method and if return value is false, halt
872
+ returned = self.beforeTitleUpdate.call(self);
873
+ if(returned === false) return self;
874
+
875
+ // Set the new content and reappend the button if enabled
876
+ if(self.elements.button) self.elements.button = self.elements.button.clone(true);
877
+ self.elements.title.html(content)
878
+ if(self.elements.button) self.elements.title.prepend(self.elements.button);
879
+
880
+ // Call API method and log event
881
+ self.onTitleUpdate.call(self);
882
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_TITLE_UPDATED, 'updateTitle');
883
+ },
884
+
885
+ focus: function(event)
886
+ {
887
+ var curIndex, newIndex, elemIndex, returned;
888
+
889
+ // Make sure tooltip is rendered and if not, return
890
+ if(!self.status.rendered)
891
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'focus');
892
+
893
+ else if(self.options.position.type == 'static')
894
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.CANNOT_FOCUS_STATIC, 'focus');
895
+
896
+ // Set z-index variables
897
+ curIndex = parseInt( self.elements.tooltip.css('z-index') );
898
+ newIndex = 6000 + $('div.qtip[qtip]').length - 1;
899
+
900
+ // Only update the z-index if it has changed and tooltip is not already focused
901
+ if(!self.status.focused && curIndex !== newIndex)
902
+ {
903
+ // Call API method and if return value is false, halt
904
+ returned = self.beforeFocus.call(self, event);
905
+ if(returned === false) return self;
906
+
907
+ // Loop through all other tooltips
908
+ $('div.qtip[qtip]').not(self.elements.tooltip).each(function()
909
+ {
910
+ if($(this).qtip('api').status.rendered === true)
911
+ {
912
+ elemIndex = parseInt($(this).css('z-index'));
913
+
914
+ // Reduce all other tooltip z-index by 1
915
+ if(typeof elemIndex == 'number' && elemIndex > -1)
916
+ $(this).css({ zIndex: parseInt( $(this).css('z-index') ) - 1 });
917
+
918
+ // Set focused status to false
919
+ $(this).qtip('api').status.focused = false;
920
+ }
921
+ })
922
+
923
+ // Set the new z-index and set focus status to true
924
+ self.elements.tooltip.css({ zIndex: newIndex });
925
+ self.status.focused = true;
926
+
927
+ // Call API method and log event
928
+ self.onFocus.call(self, event);
929
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_FOCUSED, 'focus');
930
+ };
931
+
932
+ return self;
933
+ },
934
+
935
+ disable: function(state)
936
+ {
937
+ // Make sure tooltip is rendered and if not, return
938
+ if(!self.status.rendered)
939
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'disable');
940
+
941
+ if(state)
942
+ {
943
+ // Tooltip is not already disabled, proceed
944
+ if(!self.status.disabled)
945
+ {
946
+ // Set the disabled flag and log event
947
+ self.status.disabled = true;
948
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_DISABLED, 'disable');
949
+ }
950
+
951
+ // Tooltip is already disabled, inform user via log
952
+ else $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.TOOLTIP_ALREADY_DISABLED, 'disable');
953
+ }
954
+ else
955
+ {
956
+ // Tooltip is not already enabled, proceed
957
+ if(self.status.disabled)
958
+ {
959
+ // Reassign events, set disable status and log
960
+ self.status.disabled = false;
961
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_ENABLED, 'disable');
962
+ }
963
+
964
+ // Tooltip is already enabled, inform the user via log
965
+ else $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.TOOLTIP_ALREADY_ENABLED, 'disable');
966
+ };
967
+
968
+ return self;
969
+ },
970
+
971
+ destroy: function()
972
+ {
973
+ var i, returned, interfaces;
974
+
975
+ // Call API method and if return value is false, halt
976
+ returned = self.beforeDestroy.call(self);
977
+ if(returned === false) return self;
978
+
979
+ // Check if tooltip is rendered
980
+ if(self.status.rendered)
981
+ {
982
+ // Remove event handlers and remove element
983
+ self.options.show.when.target.unbind('mousemove.qtip', self.updatePosition);
984
+ self.options.show.when.target.unbind('mouseout.qtip', self.hide);
985
+ self.options.show.when.target.unbind(self.options.show.when.event + '.qtip');
986
+ self.options.hide.when.target.unbind(self.options.hide.when.event + '.qtip');
987
+ self.elements.tooltip.unbind(self.options.hide.when.event + '.qtip');
988
+ self.elements.tooltip.unbind('mouseover.qtip', self.focus);
989
+ self.elements.tooltip.remove();
990
+ }
991
+
992
+ // Tooltip isn't yet rendered, remove render event
993
+ else self.options.show.when.target.unbind(self.options.show.when.event+'.qtip-create');
994
+
995
+ // Check to make sure qTip data is present on target element
996
+ if(typeof self.elements.target.data('qtip') == 'object')
997
+ {
998
+ // Remove API references from interfaces object
999
+ interfaces = self.elements.target.data('qtip').interfaces;
1000
+ if(typeof interfaces == 'object' && interfaces.length > 0)
1001
+ {
1002
+ // Remove API from interfaces array
1003
+ for(i = 0; i < interfaces.length - 1; i++)
1004
+ if(interfaces[i].id == self.id) interfaces.splice(i, 1)
1005
+ }
1006
+ }
1007
+ delete $.fn.qtip.interfaces[self.id];
1008
+
1009
+ // Set qTip current id to previous tooltips API if available
1010
+ if(typeof interfaces == 'object' && interfaces.length > 0)
1011
+ self.elements.target.data('qtip').current = interfaces.length -1;
1012
+ else
1013
+ self.elements.target.removeData('qtip');
1014
+
1015
+ // Call API method and log destroy
1016
+ self.onDestroy.call(self);
1017
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_DESTROYED, 'destroy');
1018
+
1019
+ return self.elements.target
1020
+ },
1021
+
1022
+ getPosition: function()
1023
+ {
1024
+ var show, offset;
1025
+
1026
+ // Make sure tooltip is rendered and if not, return
1027
+ if(!self.status.rendered)
1028
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'getPosition');
1029
+
1030
+ show = (self.elements.tooltip.css('display') !== 'none') ? false : true;
1031
+
1032
+ // Show and hide tooltip to make sure coordinates are returned
1033
+ if(show) self.elements.tooltip.css({ visiblity: 'hidden' }).show();
1034
+ offset = self.elements.tooltip.offset();
1035
+ if(show) self.elements.tooltip.css({ visiblity: 'visible' }).hide();
1036
+
1037
+ return offset;
1038
+ },
1039
+
1040
+ getDimensions: function()
1041
+ {
1042
+ var show, dimensions;
1043
+
1044
+ // Make sure tooltip is rendered and if not, return
1045
+ if(!self.status.rendered)
1046
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'getDimensions');
1047
+
1048
+ show = (!self.elements.tooltip.is(':visible')) ? true : false;
1049
+
1050
+ // Show and hide tooltip to make sure dimensions are returned
1051
+ if(show) self.elements.tooltip.css({ visiblity: 'hidden' }).show();
1052
+ dimensions = {
1053
+ height: self.elements.tooltip.outerHeight(),
1054
+ width: self.elements.tooltip.outerWidth()
1055
+ };
1056
+ if(show) self.elements.tooltip.css({ visiblity: 'visible' }).hide();
1057
+
1058
+ return dimensions;
1059
+ }
1060
+ });
1061
+ };
1062
+
1063
+ // Define priamry construct function
1064
+ function construct()
1065
+ {
1066
+ var self, adjust, content, url, data, method, tempLength;
1067
+ self = this;
1068
+
1069
+ // Call API method
1070
+ self.beforeRender.call(self);
1071
+
1072
+ // Set rendered status to true
1073
+ self.status.rendered = true;
1074
+
1075
+ // Create initial tooltip elements
1076
+ self.elements.tooltip = '<div qtip="'+self.id+'" ' +
1077
+ 'class="qtip '+(self.options.style.classes.tooltip || self.options.style)+'"' +
1078
+ 'style="display:none; -moz-border-radius:0; -webkit-border-radius:0; border-radius:0;' +
1079
+ 'position:'+self.options.position.type+';">' +
1080
+ ' <div class="qtip-wrapper" style="position:relative; overflow:hidden; text-align:left;">' +
1081
+ ' <div class="qtip-contentWrapper" style="overflow:hidden;">' +
1082
+ ' <div class="qtip-content '+self.options.style.classes.content+'"></div>' +
1083
+ '</div></div></div>';
1084
+
1085
+ // Append to container element
1086
+ self.elements.tooltip = $(self.elements.tooltip);
1087
+ self.elements.tooltip.appendTo(self.options.position.container)
1088
+
1089
+ // Setup tooltip qTip data
1090
+ self.elements.tooltip.data('qtip', { current: 0, interfaces: [self] });
1091
+
1092
+ // Setup element references
1093
+ self.elements.wrapper = self.elements.tooltip.children('div:first');
1094
+ self.elements.contentWrapper = self.elements.wrapper.children('div:first').css({ background: self.options.style.background });
1095
+ self.elements.content = self.elements.contentWrapper.children('div:first').css( jQueryStyle(self.options.style) );
1096
+
1097
+ // Apply IE hasLayout fix to wrapper and content elements
1098
+ if($.browser.msie) self.elements.wrapper.add(self.elements.content).css({ zoom: 1 });
1099
+
1100
+ // Setup tooltip attributes
1101
+ if(self.options.hide.when.event == 'unfocus') self.elements.tooltip.attr('unfocus', true);
1102
+
1103
+ // If an explicit width is set, updateWidth prior to setting content to prevent dirty rendering
1104
+ if(typeof self.options.style.width.value == 'number') self.updateWidth();
1105
+
1106
+ // Create borders and tips if supported by the browser
1107
+ if($('<canvas>').get(0).getContext || $.browser.msie)
1108
+ {
1109
+ // Create border
1110
+ if(self.options.style.border.radius > 0)
1111
+ createBorder.call(self);
1112
+ else
1113
+ self.elements.contentWrapper.css({ border: self.options.style.border.width+'px solid '+self.options.style.border.color });
1114
+
1115
+ // Create tip if enabled
1116
+ if(self.options.style.tip.corner !== false)
1117
+ createTip.call(self);
1118
+ }
1119
+
1120
+ // Neither canvas or VML is supported, tips and borders cannot be drawn!
1121
+ else
1122
+ {
1123
+ // Set defined border width
1124
+ self.elements.contentWrapper.css({ border: self.options.style.border.width+'px solid '+self.options.style.border.color });
1125
+
1126
+ // Reset border radius and tip
1127
+ self.options.style.border.radius = 0;
1128
+ self.options.style.tip.corner = false;
1129
+
1130
+ // Inform via log
1131
+ $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.CANVAS_VML_NOT_SUPPORTED, 'render');
1132
+ };
1133
+
1134
+ // Use the provided content string or DOM array
1135
+ if((typeof self.options.content.text == 'string' && self.options.content.text.length > 0)
1136
+ || (self.options.content.text.jquery && self.options.content.text.length > 0))
1137
+ content = self.options.content.text;
1138
+
1139
+ // Use title string for content if present
1140
+ else if(typeof self.elements.target.attr('title') == 'string' && self.elements.target.attr('title').length > 0)
1141
+ {
1142
+ content = self.elements.target.attr('title').replace("\\n", '<br />');
1143
+ self.elements.target.attr('title', ''); // Remove title attribute to prevent default tooltip showing
1144
+ }
1145
+
1146
+ // No title is present, use alt attribute instead
1147
+ else if(typeof self.elements.target.attr('alt') == 'string' && self.elements.target.attr('alt').length > 0)
1148
+ {
1149
+ content = self.elements.target.attr('alt').replace("\\n", '<br />');
1150
+ self.elements.target.attr('alt', ''); // Remove alt attribute to prevent default tooltip showing
1151
+ }
1152
+
1153
+ // No valid content was provided, inform via log
1154
+ else
1155
+ {
1156
+ content = ' ';
1157
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.NO_VALID_CONTENT, 'render');
1158
+ };
1159
+
1160
+ // Set the tooltips content and create title if enabled
1161
+ if(self.options.content.title.text !== false) createTitle.call(self);
1162
+ self.updateContent(content);
1163
+
1164
+ // Assign events and toggle tooltip with focus
1165
+ assignEvents.call(self);
1166
+ if(self.options.show.ready === true) self.show();
1167
+
1168
+ // Retrieve ajax content if provided
1169
+ if(self.options.content.url !== false)
1170
+ {
1171
+ url = self.options.content.url;
1172
+ data = self.options.content.data;
1173
+ method = self.options.content.method || 'get';
1174
+ self.loadContent(url, data, method);
1175
+ };
1176
+
1177
+ // Call API method and log event
1178
+ self.onRender.call(self);
1179
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_RENDERED, 'render');
1180
+ };
1181
+
1182
+ // Create borders using canvas and VML
1183
+ function createBorder()
1184
+ {
1185
+ var self, i, width, radius, color, coordinates, containers, size, betweenWidth, betweenCorners, borderTop, borderBottom, borderCoord, sideWidth, vertWidth;
1186
+ self = this;
1187
+
1188
+ // Destroy previous border elements, if present
1189
+ self.elements.wrapper.find('.qtip-borderBottom, .qtip-borderTop').remove();
1190
+
1191
+ // Setup local variables
1192
+ width = self.options.style.border.width;
1193
+ radius = self.options.style.border.radius;
1194
+ color = self.options.style.border.color || self.options.style.tip.color;
1195
+
1196
+ // Calculate border coordinates
1197
+ coordinates = calculateBorders(radius);
1198
+
1199
+ // Create containers for the border shapes
1200
+ containers = {};
1201
+ for(i in coordinates)
1202
+ {
1203
+ // Create shape container
1204
+ containers[i] = '<div rel="'+i+'" style="'+((i.search(/Left/) !== -1) ? 'left' : 'right') + ':0; ' +
1205
+ 'position:absolute; height:'+radius+'px; width:'+radius+'px; overflow:hidden; line-height:0.1px; font-size:1px">';
1206
+
1207
+ // Canvas is supported
1208
+ if($('<canvas>').get(0).getContext)
1209
+ containers[i] += '<canvas height="'+radius+'" width="'+radius+'" style="vertical-align: top"></canvas>';
1210
+
1211
+ // No canvas, but if it's IE use VML
1212
+ else if($.browser.msie)
1213
+ {
1214
+ size = radius * 2 + 3;
1215
+ containers[i] += '<v:arc stroked="false" fillcolor="'+color+'" startangle="'+coordinates[i][0]+'" endangle="'+coordinates[i][1]+'" ' +
1216
+ 'style="width:'+size+'px; height:'+size+'px; margin-top:'+((i.search(/bottom/) !== -1) ? -2 : -1)+'px; ' +
1217
+ 'margin-left:'+((i.search(/Right/) !== -1) ? coordinates[i][2] - 3.5 : -1)+'px; ' +
1218
+ 'vertical-align:top; display:inline-block; behavior:url(#default#VML)"></v:arc>';
1219
+
1220
+ };
1221
+
1222
+ containers[i] += '</div>';
1223
+ };
1224
+
1225
+ // Create between corners elements
1226
+ betweenWidth = self.getDimensions().width - (Math.max(width, radius) * 2);
1227
+ betweenCorners = '<div class="qtip-betweenCorners" style="height:'+radius+'px; width:'+betweenWidth+'px; ' +
1228
+ 'overflow:hidden; background-color:'+color+'; line-height:0.1px; font-size:1px;">';
1229
+
1230
+ // Create top border container
1231
+ borderTop = '<div class="qtip-borderTop" dir="ltr" style="height:'+radius+'px; ' +
1232
+ 'margin-left:'+radius+'px; line-height:0.1px; font-size:1px; padding:0;">' +
1233
+ containers['topLeft'] + containers['topRight'] + betweenCorners;
1234
+ self.elements.wrapper.prepend(borderTop);
1235
+
1236
+ // Create bottom border container
1237
+ borderBottom = '<div class="qtip-borderBottom" dir="ltr" style="height:'+radius+'px; ' +
1238
+ 'margin-left:'+radius+'px; line-height:0.1px; font-size:1px; padding:0;">' +
1239
+ containers['bottomLeft'] + containers['bottomRight'] + betweenCorners;
1240
+ self.elements.wrapper.append(borderBottom);
1241
+
1242
+ // Draw the borders if canvas were used (Delayed til after DOM creation)
1243
+ if($('<canvas>').get(0).getContext)
1244
+ {
1245
+ self.elements.wrapper.find('canvas').each(function()
1246
+ {
1247
+ borderCoord = coordinates[ $(this).parent('[rel]:first').attr('rel') ];
1248
+ drawBorder.call(self, $(this), borderCoord, radius, color);
1249
+ })
1250
+ }
1251
+
1252
+ // Create a phantom VML element (IE won't show the last created VML element otherwise)
1253
+ else if($.browser.msie) self.elements.tooltip.append('<v:image style="behavior:url(#default#VML);"></v:image>');
1254
+
1255
+ // Setup contentWrapper border
1256
+ sideWidth = Math.max(radius, (radius + (width - radius)) )
1257
+ vertWidth = Math.max(width - radius, 0);
1258
+ self.elements.contentWrapper.css({
1259
+ border: '0px solid ' + color,
1260
+ borderWidth: vertWidth + 'px ' + sideWidth + 'px'
1261
+ })
1262
+ };
1263
+
1264
+ // Border canvas draw method
1265
+ function drawBorder(canvas, coordinates, radius, color)
1266
+ {
1267
+ // Create corner
1268
+ var context = canvas.get(0).getContext('2d');
1269
+ context.fillStyle = color;
1270
+ context.beginPath();
1271
+ context.arc(coordinates[0], coordinates[1], radius, 0, Math.PI * 2, false);
1272
+ context.fill();
1273
+ };
1274
+
1275
+ // Create tip using canvas and VML
1276
+ function createTip(corner)
1277
+ {
1278
+ var self, color, coordinates, coordsize, path;
1279
+ self = this;
1280
+
1281
+ // Destroy previous tip, if there is one
1282
+ if(self.elements.tip !== null) self.elements.tip.remove();
1283
+
1284
+ // Setup color and corner values
1285
+ color = self.options.style.tip.color || self.options.style.border.color;
1286
+ if(self.options.style.tip.corner === false) return;
1287
+ else if(!corner) corner = self.options.style.tip.corner;
1288
+
1289
+ // Calculate tip coordinates
1290
+ coordinates = calculateTip(corner, self.options.style.tip.size.width, self.options.style.tip.size.height);
1291
+
1292
+ // Create tip element
1293
+ self.elements.tip = '<div class="'+self.options.style.classes.tip+'" dir="ltr" rel="'+corner+'" style="position:absolute; ' +
1294
+ 'height:'+self.options.style.tip.size.height+'px; width:'+self.options.style.tip.size.width+'px; ' +
1295
+ 'margin:0 auto; line-height:0.1px; font-size:1px;">';
1296
+
1297
+ // Use canvas element if supported
1298
+ if($('<canvas>').get(0).getContext)
1299
+ self.elements.tip += '<canvas height="'+self.options.style.tip.size.height+'" width="'+self.options.style.tip.size.width+'"></canvas>';
1300
+
1301
+ // Canvas not supported - Use VML (IE)
1302
+ else if($.browser.msie)
1303
+ {
1304
+ // Create coordize and tip path using tip coordinates
1305
+ coordsize = self.options.style.tip.size.width + ',' + self.options.style.tip.size.height;
1306
+ path = 'm' + coordinates[0][0] + ',' + coordinates[0][1];
1307
+ path += ' l' + coordinates[1][0] + ',' + coordinates[1][1];
1308
+ path += ' ' + coordinates[2][0] + ',' + coordinates[2][1];
1309
+ path += ' xe';
1310
+
1311
+ // Create VML element
1312
+ self.elements.tip += '<v:shape fillcolor="'+color+'" stroked="false" filled="true" path="'+path+'" coordsize="'+coordsize+'" ' +
1313
+ 'style="width:'+self.options.style.tip.size.width+'px; height:'+self.options.style.tip.size.height+'px; ' +
1314
+ 'line-height:0.1px; display:inline-block; behavior:url(#default#VML); ' +
1315
+ 'vertical-align:'+((corner.search(/top/) !== -1) ? 'bottom' : 'top')+'"></v:shape>';
1316
+
1317
+ // Create a phantom VML element (IE won't show the last created VML element otherwise)
1318
+ self.elements.tip += '<v:image style="behavior:url(#default#VML);"></v:image>';
1319
+
1320
+ // Prevent tooltip appearing above the content (IE z-index bug)
1321
+ self.elements.contentWrapper.css('position', 'relative');
1322
+ };
1323
+
1324
+ // Attach new tip to tooltip element
1325
+ self.elements.tooltip.prepend(self.elements.tip + '</div>');
1326
+
1327
+ // Create element reference and draw the canvas tip (Delayed til after DOM creation)
1328
+ self.elements.tip = self.elements.tooltip.find('.'+self.options.style.classes.tip).eq(0);
1329
+ if($('<canvas>').get(0).getContext)
1330
+ drawTip.call(self, self.elements.tip.find('canvas:first'), coordinates, color);
1331
+
1332
+ // Fix IE small tip bug
1333
+ if(corner.search(/top/) !== -1 && $.browser.msie && parseInt($.browser.version.charAt(0)) === 6)
1334
+ self.elements.tip.css({ marginTop: -4 });
1335
+
1336
+ // Set the tip position
1337
+ positionTip.call(self, corner);
1338
+ };
1339
+
1340
+ // Canvas tip drawing method
1341
+ function drawTip(canvas, coordinates, color)
1342
+ {
1343
+ // Setup properties
1344
+ var context = canvas.get(0).getContext('2d');
1345
+ context.fillStyle = color;
1346
+
1347
+ // Create tip
1348
+ context.beginPath();
1349
+ context.moveTo(coordinates[0][0], coordinates[0][1]);
1350
+ context.lineTo(coordinates[1][0], coordinates[1][1]);
1351
+ context.lineTo(coordinates[2][0], coordinates[2][1]);
1352
+ context.fill();
1353
+ };
1354
+
1355
+ function positionTip(corner)
1356
+ {
1357
+ var self, ieAdjust, paddingCorner, paddingSize, newMargin;
1358
+ self = this;
1359
+
1360
+ // Return if tips are disabled or tip is not yet rendered
1361
+ if(self.options.style.tip.corner === false || !self.elements.tip) return;
1362
+ if(!corner) corner = self.elements.tip.attr('rel');
1363
+
1364
+ // Setup adjustment variables
1365
+ ieAdjust = positionAdjust = ($.browser.msie) ? 1 : 0;
1366
+
1367
+ // Set initial position
1368
+ self.elements.tip.css(corner.match(/left|right|top|bottom/)[0], 0);
1369
+
1370
+ // Set position of tip to correct side
1371
+ if(corner.search(/top|bottom/) !== -1)
1372
+ {
1373
+ // Adjustments for IE6 - 0.5px border gap bug
1374
+ if($.browser.msie)
1375
+ {
1376
+ if(parseInt($.browser.version.charAt(0)) === 6)
1377
+ positionAdjust = (corner.search(/top/) !== -1) ? -3 : 1;
1378
+ else
1379
+ positionAdjust = (corner.search(/top/) !== -1) ? 1 : 2;
1380
+ };
1381
+
1382
+ if(corner.search(/Middle/) !== -1)
1383
+ self.elements.tip.css({ left: '50%', marginLeft: -(self.options.style.tip.size.width / 2) });
1384
+
1385
+ else if(corner.search(/Left/) !== -1)
1386
+ self.elements.tip.css({ left: self.options.style.border.radius - ieAdjust });
1387
+
1388
+ else if(corner.search(/Right/) !== -1)
1389
+ self.elements.tip.css({ right: self.options.style.border.radius + ieAdjust });
1390
+
1391
+ if(corner.search(/top/) !== -1)
1392
+ self.elements.tip.css({ top: -positionAdjust });
1393
+ else
1394
+ self.elements.tip.css({ bottom: positionAdjust });
1395
+
1396
+ }
1397
+ else if(corner.search(/left|right/) !== -1)
1398
+ {
1399
+ // Adjustments for IE6 - 0.5px border gap bug
1400
+ if($.browser.msie)
1401
+ positionAdjust = (parseInt($.browser.version.charAt(0)) === 6) ? 1 : ((corner.search(/left/) !== -1) ? 1 : 2);
1402
+
1403
+ if(corner.search(/Middle/) !== -1)
1404
+ self.elements.tip.css({ top: '50%', marginTop: -(self.options.style.tip.size.height / 2) });
1405
+
1406
+ else if(corner.search(/Top/) !== -1)
1407
+ self.elements.tip.css({ top: self.options.style.border.radius - ieAdjust });
1408
+
1409
+ else if(corner.search(/Bottom/) !== -1)
1410
+ self.elements.tip.css({ bottom: self.options.style.border.radius + ieAdjust });
1411
+
1412
+ if(corner.search(/left/) !== -1)
1413
+ self.elements.tip.css({ left: -positionAdjust });
1414
+ else
1415
+ self.elements.tip.css({ right: positionAdjust });
1416
+ };
1417
+
1418
+ // Adjust tooltip padding to compensate for tip
1419
+ paddingCorner = 'padding-' + corner.match(/left|right|top|bottom/)[0];
1420
+ paddingSize = self.options.style.tip.size[ (paddingCorner.search(/left|right/) !== -1) ? 'width' : 'height' ];
1421
+ self.elements.tooltip.css('padding', 0);
1422
+ self.elements.tooltip.css(paddingCorner, paddingSize);
1423
+
1424
+ // Match content margin to prevent gap bug in IE6 ONLY
1425
+ if($.browser.msie && parseInt($.browser.version.charAt(0)) == 6)
1426
+ {
1427
+ newMargin = parseInt(self.elements.tip.css('margin-top')) || 0;
1428
+ newMargin += parseInt(self.elements.content.css('margin-top')) || 0;
1429
+
1430
+ self.elements.tip.css({ marginTop: newMargin });
1431
+ };
1432
+ };
1433
+
1434
+ // Create title bar for content
1435
+ function createTitle()
1436
+ {
1437
+ var self = this;
1438
+
1439
+ // Destroy previous title element, if present
1440
+ if(self.elements.title !== null) self.elements.title.remove();
1441
+
1442
+ // Create title element
1443
+ self.elements.title = $('<div class="'+self.options.style.classes.title+'">')
1444
+ .css( jQueryStyle(self.options.style.title, true) )
1445
+ .css({ zoom: ($.browser.msie) ? 1 : 0 })
1446
+ .prependTo(self.elements.contentWrapper);
1447
+
1448
+ // Update title with contents if enabled
1449
+ if(self.options.content.title.text) self.updateTitle.call(self, self.options.content.title.text);
1450
+
1451
+ // Create title close buttons if enabled
1452
+ if(self.options.content.title.button !== false
1453
+ && typeof self.options.content.title.button == 'string')
1454
+ {
1455
+ self.elements.button = $('<a class="'+self.options.style.classes.button+'" style="float:right; position: relative"></a>')
1456
+ .css( jQueryStyle(self.options.style.button, true) )
1457
+ .html(self.options.content.title.button)
1458
+ .prependTo(self.elements.title)
1459
+ .click(function(event){ if(!self.status.disabled) self.hide(event) });
1460
+ };
1461
+ };
1462
+
1463
+ // Assign hide and show events
1464
+ function assignEvents()
1465
+ {
1466
+ var self, showTarget, hideTarget, inactiveEvents;
1467
+ self = this;
1468
+
1469
+ // Setup event target variables
1470
+ showTarget = self.options.show.when.target;
1471
+ hideTarget = self.options.hide.when.target;
1472
+
1473
+ // Add tooltip as a hideTarget is its fixed
1474
+ if(self.options.hide.fixed) hideTarget = hideTarget.add(self.elements.tooltip);
1475
+
1476
+ // Check if the hide event is special 'inactive' type
1477
+ if(self.options.hide.when.event == 'inactive')
1478
+ {
1479
+ // Define events which reset the 'inactive' event handler
1480
+ inactiveEvents = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove',
1481
+ 'mouseout', 'mouseenter', 'mouseleave', 'mouseover' ];
1482
+
1483
+ // Define 'inactive' event timer method
1484
+ function inactiveMethod(event)
1485
+ {
1486
+ if(self.status.disabled === true) return;
1487
+
1488
+ //Clear and reset the timer
1489
+ clearTimeout(self.timers.inactive);
1490
+ self.timers.inactive = setTimeout(function()
1491
+ {
1492
+ // Unassign 'inactive' events
1493
+ $(inactiveEvents).each(function()
1494
+ {
1495
+ hideTarget.unbind(this+'.qtip-inactive');
1496
+ self.elements.content.unbind(this+'.qtip-inactive');
1497
+ });
1498
+
1499
+ // Hide the tooltip
1500
+ self.hide(event);
1501
+ }
1502
+ , self.options.hide.delay);
1503
+ };
1504
+ }
1505
+
1506
+ // Check if the tooltip is 'fixed'
1507
+ else if(self.options.hide.fixed === true)
1508
+ {
1509
+ self.elements.tooltip.bind('mouseover.qtip', function()
1510
+ {
1511
+ if(self.status.disabled === true) return;
1512
+
1513
+ // Reset the hide timer
1514
+ clearTimeout(self.timers.hide);
1515
+ });
1516
+ };
1517
+
1518
+ // Define show event method
1519
+ function showMethod(event)
1520
+ {
1521
+ if(self.status.disabled === true) return;
1522
+
1523
+ // If set, hide tooltip when inactive for delay period
1524
+ if(self.options.hide.when.event == 'inactive')
1525
+ {
1526
+ // Assign each reset event
1527
+ $(inactiveEvents).each(function()
1528
+ {
1529
+ hideTarget.bind(this+'.qtip-inactive', inactiveMethod);
1530
+ self.elements.content.bind(this+'.qtip-inactive', inactiveMethod);
1531
+ });
1532
+
1533
+ // Start the inactive timer
1534
+ inactiveMethod();
1535
+ };
1536
+
1537
+ // Clear hide timers
1538
+ clearTimeout(self.timers.show);
1539
+ clearTimeout(self.timers.hide);
1540
+
1541
+ // Start show timer
1542
+ self.timers.show = setTimeout(function(){ self.show(event); }, self.options.show.delay);
1543
+ };
1544
+
1545
+ // Define hide event method
1546
+ function hideMethod(event)
1547
+ {
1548
+ if(self.status.disabled === true) return;
1549
+
1550
+ // Prevent hiding if tooltip is fixed and event target is the tooltip
1551
+ if(self.options.hide.fixed === true
1552
+ && self.options.hide.when.event.search(/mouse(out|leave)/i) !== -1
1553
+ && $(event.relatedTarget).parents('div.qtip[qtip]').length > 0)
1554
+ {
1555
+ // Prevent default and popagation
1556
+ event.stopPropagation();
1557
+ event.preventDefault();
1558
+
1559
+ // Reset the hide timer
1560
+ clearTimeout(self.timers.hide);
1561
+ return false;
1562
+ };
1563
+
1564
+ // Clear timers and stop animation queue
1565
+ clearTimeout(self.timers.show);
1566
+ clearTimeout(self.timers.hide);
1567
+ self.elements.tooltip.stop(true, true);
1568
+
1569
+ // If tooltip has displayed, start hide timer
1570
+ self.timers.hide = setTimeout(function(){ self.hide(event); }, self.options.hide.delay);
1571
+ };
1572
+
1573
+ // Both events and targets are identical, apply events using a toggle
1574
+ if((self.options.show.when.target.add(self.options.hide.when.target).length === 1
1575
+ && self.options.show.when.event == self.options.hide.when.event
1576
+ && self.options.hide.when.event !== 'inactive')
1577
+ || self.options.hide.when.event == 'unfocus')
1578
+ {
1579
+ self.cache.toggle = 0;
1580
+ // Use a toggle to prevent hide/show conflicts
1581
+ showTarget.bind(self.options.show.when.event + '.qtip', function(event)
1582
+ {
1583
+ if(self.cache.toggle == 0) showMethod(event);
1584
+ else hideMethod(event);
1585
+ });
1586
+ }
1587
+
1588
+ // Events are not identical, bind normally
1589
+ else
1590
+ {
1591
+ showTarget.bind(self.options.show.when.event + '.qtip', showMethod);
1592
+
1593
+ // If the hide event is not 'inactive', bind the hide method
1594
+ if(self.options.hide.when.event !== 'inactive')
1595
+ hideTarget.bind(self.options.hide.when.event + '.qtip', hideMethod);
1596
+ };
1597
+
1598
+ // Focus the tooltip on mouseover
1599
+ if(self.options.position.type.search(/(fixed|absolute)/) !== -1)
1600
+ self.elements.tooltip.bind('mouseover.qtip', self.focus);
1601
+
1602
+ // If mouse is the target, update tooltip position on mousemove
1603
+ if(self.options.position.target === 'mouse' && self.options.position.type !== 'static')
1604
+ {
1605
+ showTarget.bind('mousemove.qtip', function(event)
1606
+ {
1607
+ // Set the new mouse positions if adjustment is enabled
1608
+ self.cache.mouse = { x: event.pageX, y: event.pageY };
1609
+
1610
+ // Update the tooltip position only if the tooltip is visible and adjustment is enabled
1611
+ if(self.status.disabled === false
1612
+ && self.options.position.adjust.mouse === true
1613
+ && self.options.position.type !== 'static'
1614
+ && self.elements.tooltip.css('display') !== 'none')
1615
+ self.updatePosition(event);
1616
+ });
1617
+ };
1618
+ };
1619
+
1620
+ // Screen position adjustment
1621
+ function screenAdjust(position, target, tooltip)
1622
+ {
1623
+ var self, adjustedPosition, adjust, newCorner, overflow, corner;
1624
+ self = this;
1625
+
1626
+ // Setup corner and adjustment variable
1627
+ if(tooltip.corner == 'center') return target.position // TODO: 'center' corner adjustment
1628
+ adjustedPosition = $.extend({}, position);
1629
+ newCorner = { x: false, y: false };
1630
+
1631
+ // Define overflow properties
1632
+ overflow = {
1633
+ left: (adjustedPosition.left < $.fn.qtip.cache.screen.scroll.left),
1634
+ right: (adjustedPosition.left + tooltip.dimensions.width + 2 >= $.fn.qtip.cache.screen.width + $.fn.qtip.cache.screen.scroll.left),
1635
+ top: (adjustedPosition.top < $.fn.qtip.cache.screen.scroll.top),
1636
+ bottom: (adjustedPosition.top + tooltip.dimensions.height + 2 >= $.fn.qtip.cache.screen.height + $.fn.qtip.cache.screen.scroll.top)
1637
+ };
1638
+
1639
+ // Determine new positioning properties
1640
+ adjust = {
1641
+ left: (overflow.left && (tooltip.corner.search(/right/i) != -1 || (tooltip.corner.search(/right/i) == -1 && !overflow.right))),
1642
+ right: (overflow.right && (tooltip.corner.search(/left/i) != -1 || (tooltip.corner.search(/left/i) == -1 && !overflow.left))),
1643
+ top: (overflow.top && tooltip.corner.search(/top/i) == -1),
1644
+ bottom: (overflow.bottom && tooltip.corner.search(/bottom/i) == -1)
1645
+ };
1646
+
1647
+ // Tooltip overflows off the left side of the screen
1648
+ if(adjust.left)
1649
+ {
1650
+ if(self.options.position.target !== 'mouse')
1651
+ adjustedPosition.left = target.position.left + target.dimensions.width;
1652
+ else
1653
+ adjustedPosition.left = self.cache.mouse.x
1654
+
1655
+ newCorner.x = 'Left';
1656
+ }
1657
+
1658
+ // Tooltip overflows off the right side of the screen
1659
+ else if(adjust.right)
1660
+ {
1661
+ if(self.options.position.target !== 'mouse')
1662
+ adjustedPosition.left = target.position.left - tooltip.dimensions.width;
1663
+ else
1664
+ adjustedPosition.left = self.cache.mouse.x - tooltip.dimensions.width;
1665
+
1666
+ newCorner.x = 'Right';
1667
+ };
1668
+
1669
+ // Tooltip overflows off the top of the screen
1670
+ if(adjust.top)
1671
+ {
1672
+ if(self.options.position.target !== 'mouse')
1673
+ adjustedPosition.top = target.position.top + target.dimensions.height;
1674
+ else
1675
+ adjustedPosition.top = self.cache.mouse.y
1676
+
1677
+ newCorner.y = 'top';
1678
+ }
1679
+
1680
+ // Tooltip overflows off the bottom of the screen
1681
+ else if(adjust.bottom)
1682
+ {
1683
+ if(self.options.position.target !== 'mouse')
1684
+ adjustedPosition.top = target.position.top - tooltip.dimensions.height;
1685
+ else
1686
+ adjustedPosition.top = self.cache.mouse.y - tooltip.dimensions.height;
1687
+
1688
+ newCorner.y = 'bottom';
1689
+ };
1690
+
1691
+ // Don't adjust if resulting position is negative
1692
+ if(adjustedPosition.left < 0)
1693
+ {
1694
+ adjustedPosition.left = position.left;
1695
+ newCorner.x = false;
1696
+ };
1697
+ if(adjustedPosition.top < 0)
1698
+ {
1699
+ adjustedPosition.top = position.top;
1700
+ newCorner.y = false;
1701
+ };
1702
+
1703
+ // Change tip corner if positioning has changed and tips are enabled
1704
+ if(self.options.style.tip.corner !== false)
1705
+ {
1706
+ // Determine new corner properties
1707
+ adjustedPosition.corner = new String(tooltip.corner);
1708
+ if(newCorner.x !== false) adjustedPosition.corner = adjustedPosition.corner.replace(/Left|Right|Middle/, newCorner.x);
1709
+ if(newCorner.y !== false) adjustedPosition.corner = adjustedPosition.corner.replace(/top|bottom/, newCorner.y);
1710
+
1711
+ // Adjust tip if position has changed and tips are enabled
1712
+ if(adjustedPosition.corner !== self.elements.tip.attr('rel'))
1713
+ createTip.call(self, adjustedPosition.corner);
1714
+ };
1715
+
1716
+ return adjustedPosition;
1717
+ };
1718
+
1719
+ // Build a jQuery style object from supplied style object
1720
+ function jQueryStyle(style, sub)
1721
+ {
1722
+ var styleObj, i;
1723
+
1724
+ styleObj = $.extend(true, {}, style);
1725
+ for(i in styleObj)
1726
+ {
1727
+ if(sub === true && i.search(/(tip|classes)/i) !== -1)
1728
+ delete styleObj[i];
1729
+ else if(!sub && i.search(/(width|border|tip|title|classes|user)/i) !== -1)
1730
+ delete styleObj[i];
1731
+ };
1732
+
1733
+ return styleObj;
1734
+ };
1735
+
1736
+ // Sanitize styles
1737
+ function sanitizeStyle(style)
1738
+ {
1739
+ if(typeof style.tip !== 'object') style.tip = { corner: style.tip };
1740
+ if(typeof style.tip.size !== 'object') style.tip.size = { width: style.tip.size, height: style.tip.size };
1741
+ if(typeof style.border !== 'object') style.border = { width: style.border };
1742
+ if(typeof style.width !== 'object') style.width = { value: style.width };
1743
+ if(typeof style.width.max == 'string') style.width.max = parseInt(style.width.max.replace(/([0-9]+)/i, "$1"));
1744
+ if(typeof style.width.min == 'string') style.width.min = parseInt(style.width.min.replace(/([0-9]+)/i, "$1"));
1745
+
1746
+ // Convert deprecated x and y tip values to width/height
1747
+ if(typeof style.tip.size.x == 'number')
1748
+ {
1749
+ style.tip.size.width = style.tip.size.x;
1750
+ delete style.tip.size.x;
1751
+ };
1752
+ if(typeof style.tip.size.y == 'number')
1753
+ {
1754
+ style.tip.size.height = style.tip.size.y;
1755
+ delete style.tip.size.y;
1756
+ };
1757
+
1758
+ return style;
1759
+ };
1760
+
1761
+ // Build styles recursively with inheritance
1762
+ function buildStyle()
1763
+ {
1764
+ var self, i, styleArray, styleExtend, finalStyle, ieAdjust;
1765
+ self = this;
1766
+
1767
+ // Build style options from supplied arguments
1768
+ styleArray = [true, {}];
1769
+ for(i = 0; i < arguments.length; i++)
1770
+ styleArray.push(arguments[i]);
1771
+ styleExtend = [ $.extend.apply($, styleArray) ];
1772
+
1773
+ // Loop through each named style inheritance
1774
+ while(typeof styleExtend[0].name == 'string')
1775
+ {
1776
+ // Sanitize style data and append to extend array
1777
+ styleExtend.unshift( sanitizeStyle($.fn.qtip.styles[ styleExtend[0].name ]) );
1778
+ };
1779
+
1780
+ // Make sure resulting tooltip className represents final style
1781
+ styleExtend.unshift(true, {classes:{ tooltip: 'qtip-' + (arguments[0].name || 'defaults') }}, $.fn.qtip.styles.defaults);
1782
+
1783
+ // Extend into a single style object
1784
+ finalStyle = $.extend.apply($, styleExtend);
1785
+
1786
+ // Adjust tip size if needed (IE 1px adjustment bug fix)
1787
+ ieAdjust = ($.browser.msie) ? 1 : 0;
1788
+ finalStyle.tip.size.width += ieAdjust;
1789
+ finalStyle.tip.size.height += ieAdjust;
1790
+
1791
+ // Force even numbers for pixel precision
1792
+ if(finalStyle.tip.size.width % 2 > 0) finalStyle.tip.size.width += 1;
1793
+ if(finalStyle.tip.size.height % 2 > 0) finalStyle.tip.size.height += 1;
1794
+
1795
+ // Sanitize final styles tip corner value
1796
+ if(finalStyle.tip.corner === true)
1797
+ finalStyle.tip.corner = (self.options.position.corner.tooltip === 'center') ? false : self.options.position.corner.tooltip;
1798
+
1799
+ return finalStyle;
1800
+ };
1801
+
1802
+ // Tip coordinates calculator
1803
+ function calculateTip(corner, width, height)
1804
+ {
1805
+ // Define tip coordinates in terms of height and width values
1806
+ var tips = {
1807
+ bottomRight: [[0,0], [width,height], [width,0]],
1808
+ bottomLeft: [[0,0], [width,0], [0,height]],
1809
+ topRight: [[0,height], [width,0], [width,height]],
1810
+ topLeft: [[0,0], [0,height], [width,height]],
1811
+ topMiddle: [[0,height], [width / 2,0], [width,height]],
1812
+ bottomMiddle: [[0,0], [width,0], [width / 2,height]],
1813
+ rightMiddle: [[0,0], [width,height / 2], [0,height]],
1814
+ leftMiddle: [[width,0], [width,height], [0,height / 2]]
1815
+ };
1816
+ tips.leftTop = tips.bottomRight;
1817
+ tips.rightTop = tips.bottomLeft;
1818
+ tips.leftBottom = tips.topRight;
1819
+ tips.rightBottom = tips.topLeft;
1820
+
1821
+ return tips[corner];
1822
+ };
1823
+
1824
+ // Border coordinates calculator
1825
+ function calculateBorders(radius)
1826
+ {
1827
+ var borders;
1828
+
1829
+ // Use canvas element if supported
1830
+ if($('<canvas>').get(0).getContext)
1831
+ {
1832
+ borders = {
1833
+ topLeft: [radius,radius], topRight: [0,radius],
1834
+ bottomLeft: [radius,0], bottomRight: [0,0]
1835
+ };
1836
+ }
1837
+
1838
+ // Canvas not supported - Use VML (IE)
1839
+ else if($.browser.msie)
1840
+ {
1841
+ borders = {
1842
+ topLeft: [-90,90,0], topRight: [-90,90,-radius],
1843
+ bottomLeft: [90,270,0], bottomRight: [90, 270,-radius]
1844
+ };
1845
+ };
1846
+
1847
+ return borders;
1848
+ };
1849
+
1850
+ // BGIFRAME JQUERY PLUGIN ADAPTION
1851
+ // Special thanks to Brandon Aaron for this plugin
1852
+ // http://plugins.jquery.com/project/bgiframe
1853
+ function bgiframe()
1854
+ {
1855
+ var self, html, dimensions;
1856
+ self = this;
1857
+ dimensions = self.getDimensions();
1858
+
1859
+ // Setup iframe HTML string
1860
+ html = '<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:false" '+
1861
+ 'style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=\'0\'); border: 1px solid red; ' +
1862
+ 'height:'+dimensions.height+'px; width:'+dimensions.width+'px" />';
1863
+
1864
+ // Append the new HTML and setup element reference
1865
+ self.elements.bgiframe = self.elements.wrapper.prepend(html).children('.qtip-bgiframe:first');
1866
+ };
1867
+
1868
+ // Assign cache and event initialisation on document load
1869
+ $(document).ready(function()
1870
+ {
1871
+ // Setup library cache with window scroll and dimensions of document
1872
+ $.fn.qtip.cache = {
1873
+ screen: {
1874
+ scroll: { left: $(window).scrollLeft(), top: $(window).scrollTop() },
1875
+ width: $(window).width(),
1876
+ height: $(window).height()
1877
+ }
1878
+ };
1879
+
1880
+ // Adjust positions of the tooltips on window resize or scroll if enabled
1881
+ var adjustTimer;
1882
+ $(window).bind('resize scroll', function(event)
1883
+ {
1884
+ clearTimeout(adjustTimer);
1885
+ adjustTimer = setTimeout(function()
1886
+ {
1887
+ // Readjust cached screen values
1888
+ if(event.type === 'scroll')
1889
+ $.fn.qtip.cache.screen.scroll = { left: $(window).scrollLeft(), top: $(window).scrollTop() };
1890
+ else
1891
+ {
1892
+ $.fn.qtip.cache.screen.width = $(window).width();
1893
+ $.fn.qtip.cache.screen.height = $(window).height();
1894
+ };
1895
+
1896
+ for(i = 0; i < $.fn.qtip.interfaces.length; i++)
1897
+ {
1898
+ // Access current elements API
1899
+ var api = $.fn.qtip.interfaces[i];
1900
+
1901
+ // Update position if resize or scroll adjustments are enabled
1902
+ if(api.status.rendered === true
1903
+ && (api.options.position.type !== 'static'
1904
+ || api.options.position.adjust.scroll && event.type === 'scroll'
1905
+ || api.options.position.adjust.resize && event.type === 'resize'))
1906
+ {
1907
+ // Queue the animation so positions are updated correctly
1908
+ api.updatePosition(event, true);
1909
+ }
1910
+ };
1911
+ }
1912
+ , 100);
1913
+ })
1914
+
1915
+ // Hide unfocus toolipts on document mousedown
1916
+ $(document).bind('mousedown.qtip', function(event)
1917
+ {
1918
+ if($(event.target).parents('div.qtip').length === 0)
1919
+ {
1920
+ $('.qtip[unfocus]').each(function()
1921
+ {
1922
+ var api = $(this).qtip("api");
1923
+
1924
+ // Only hide if its visible and not the tooltips target
1925
+ if($(this).is(':visible') && !api.status.disabled
1926
+ && $(event.target).add(api.elements.target).length > 1)
1927
+ api.hide(event);
1928
+ })
1929
+ };
1930
+ })
1931
+ });
1932
+
1933
+ // Define qTip API interfaces array
1934
+ $.fn.qtip.interfaces = []
1935
+
1936
+ // Define log and constant place holders
1937
+ $.fn.qtip.log = { error: function(){ return this; } };
1938
+ $.fn.qtip.constants = {};
1939
+
1940
+ // Define configuration defaults
1941
+ $.fn.qtip.defaults = {
1942
+ // Content
1943
+ content: {
1944
+ prerender: false,
1945
+ text: false,
1946
+ url: false,
1947
+ data: null,
1948
+ title: {
1949
+ text: false,
1950
+ button: false
1951
+ }
1952
+ },
1953
+ // Position
1954
+ position: {
1955
+ target: false,
1956
+ corner: {
1957
+ target: 'bottomRight',
1958
+ tooltip: 'topLeft'
1959
+ },
1960
+ adjust: {
1961
+ x: 0, y: 0,
1962
+ mouse: true,
1963
+ screen: false,
1964
+ scroll: true,
1965
+ resize: true
1966
+ },
1967
+ type: 'absolute',
1968
+ container: false
1969
+ },
1970
+ // Effects
1971
+ show: {
1972
+ when: {
1973
+ target: false,
1974
+ event: 'mouseover'
1975
+ },
1976
+ effect: {
1977
+ type: 'fade',
1978
+ length: 100
1979
+ },
1980
+ delay: 140,
1981
+ solo: false,
1982
+ ready: false
1983
+ },
1984
+ hide: {
1985
+ when: {
1986
+ target: false,
1987
+ event: 'mouseout'
1988
+ },
1989
+ effect: {
1990
+ type: 'fade',
1991
+ length: 100
1992
+ },
1993
+ delay: 0,
1994
+ fixed: false
1995
+ },
1996
+ // Callbacks
1997
+ api: {
1998
+ beforeRender: function(){},
1999
+ onRender: function(){},
2000
+ beforePositionUpdate: function(){},
2001
+ onPositionUpdate: function(){},
2002
+ beforeShow: function(){},
2003
+ onShow: function(){},
2004
+ beforeHide: function(){},
2005
+ onHide: function(){},
2006
+ beforeContentUpdate: function(){},
2007
+ onContentUpdate: function(){},
2008
+ beforeContentLoad: function(){},
2009
+ onContentLoad: function(){},
2010
+ beforeTitleUpdate: function(){},
2011
+ onTitleUpdate: function(){},
2012
+ beforeDestroy: function(){},
2013
+ onDestroy: function(){},
2014
+ beforeFocus: function(){},
2015
+ onFocus: function(){}
2016
+ }
2017
+ };
2018
+
2019
+ $.fn.qtip.styles = {
2020
+ defaults: {
2021
+ background: 'white',
2022
+ color: '#111',
2023
+ overflow: 'hidden',
2024
+ textAlign: 'left',
2025
+ width: {
2026
+ min: 0,
2027
+ max: 250
2028
+ },
2029
+ padding: '5px 9px',
2030
+ border: {
2031
+ width: 1,
2032
+ radius: 0,
2033
+ color: '#d3d3d3'
2034
+ },
2035
+ tip: {
2036
+ corner: false,
2037
+ color: false,
2038
+ size: { width: 13, height: 13 },
2039
+ opacity: 1
2040
+ },
2041
+ title: {
2042
+ background: '#e1e1e1',
2043
+ fontWeight: 'bold',
2044
+ padding: '7px 12px'
2045
+ },
2046
+ button: {
2047
+ cursor: 'pointer'
2048
+ },
2049
+ classes: {
2050
+ target: '',
2051
+ tip: 'qtip-tip',
2052
+ title: 'qtip-title',
2053
+ button: 'qtip-button',
2054
+ content: 'qtip-content',
2055
+ active: 'qtip-active'
2056
+ }
2057
+ },
2058
+ cream: {
2059
+ border: {
2060
+ width: 3,
2061
+ radius: 0,
2062
+ color: '#F9E98E'
2063
+ },
2064
+ title: {
2065
+ background: '#F0DE7D',
2066
+ color: '#A27D35'
2067
+ },
2068
+ background: '#FBF7AA',
2069
+ color: '#A27D35',
2070
+
2071
+ classes: { tooltip: 'qtip-cream' }
2072
+ },
2073
+ light: {
2074
+ border: {
2075
+ width: 3,
2076
+ radius: 0,
2077
+ color: '#E2E2E2'
2078
+ },
2079
+ title: {
2080
+ background: '#f1f1f1',
2081
+ color: '#454545'
2082
+ },
2083
+ background: 'white',
2084
+ color: '#454545',
2085
+
2086
+ classes: { tooltip: 'qtip-light' }
2087
+ },
2088
+ dark: {
2089
+ border: {
2090
+ width: 3,
2091
+ radius: 0,
2092
+ color: '#303030'
2093
+ },
2094
+ title: {
2095
+ background: '#404040',
2096
+ color: '#f3f3f3'
2097
+ },
2098
+ background: '#505050',
2099
+ color: '#f3f3f3',
2100
+
2101
+ classes: { tooltip: 'qtip-dark' }
2102
+ },
2103
+ red: {
2104
+ border: {
2105
+ width: 3,
2106
+ radius: 0,
2107
+ color: '#CE6F6F'
2108
+ },
2109
+ title: {
2110
+ background: '#f28279',
2111
+ color: '#9C2F2F'
2112
+ },
2113
+ background: '#F79992',
2114
+ color: '#9C2F2F',
2115
+
2116
+ classes: { tooltip: 'qtip-red' }
2117
+ },
2118
+ green: {
2119
+ border: {
2120
+ width: 3,
2121
+ radius: 0,
2122
+ color: '#A9DB66'
2123
+ },
2124
+ title: {
2125
+ background: '#b9db8c',
2126
+ color: '#58792E'
2127
+ },
2128
+ background: '#CDE6AC',
2129
+ color: '#58792E',
2130
+
2131
+ classes: { tooltip: 'qtip-green' }
2132
+ },
2133
+ blue: {
2134
+ border: {
2135
+ width: 3,
2136
+ radius: 0,
2137
+ color: '#ADD9ED'
2138
+ },
2139
+ title: {
2140
+ background: '#D0E9F5',
2141
+ color: '#5E99BD'
2142
+ },
2143
+ background: '#E5F6FE',
2144
+ color: '#4D9FBF',
2145
+
2146
+ classes: { tooltip: 'qtip-blue' }
2147
+ }
2148
+ };
2149
+ })(jQuery);
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: rosshanney
3
  Tags: google, google calendar, calendar, events, ajax, widget
4
  Requires at least: 2.9.2
5
  Tested up to: 3.0
6
- Stable tag: 0.1.4
7
 
8
  Parses Google Calendar feeds and displays the events as a calendar grid or list on a page, post or widget.
9
 
@@ -17,6 +17,7 @@ Parses Google Calendar feeds and displays the events as a calendar grid or list
17
  * Displays events as a list or within a calendar grid
18
  * Lists and grids can be displayed in posts, pages or within a widget
19
  * Options to change the number of events retrieved, date / time format, cache duration etc.
 
20
  * Calendar grids can have the ability to change month, utilising AJAX
21
 
22
  Please visit the plugin homepage for how to get started and other help:
@@ -27,6 +28,10 @@ There is also a demonstration page showing the plugin in action:
27
 
28
  * [Demo Page](http://www.rhanney.co.uk/plugins/google-calendar-events/gce-demo)
29
 
 
 
 
 
30
  == Installation ==
31
 
32
  Use the automatic installer from within the WordPress administration, or:
@@ -43,14 +48,17 @@ You can now start adding feeds. Visit the [plugin homepage](http://www.rhanney.c
43
 
44
  == Screenshots ==
45
 
46
- There is also a [demo page](http://www.rhanney.co.uk/plugins/google-calendar-events/gce-demo) where you can see the plugin in action.
47
-
48
  1. The main plugin admin screen.
49
  1. The add feed admin screen.
50
  1. A page showing a full page calendar grid and various widgets.
51
 
52
  == Changelog ==
53
 
 
 
 
 
 
54
  = 0.1.4 =
55
  * More bug fixes.
56
 
@@ -69,8 +77,8 @@ There is also a [demo page](http://www.rhanney.co.uk/plugins/google-calendar-eve
69
 
70
  == Upgrade Notice ==
71
 
72
- = 0.1.4 =
73
- Bug fixes.
74
 
75
  == Frequently Asked Questions ==
76
 
3
  Tags: google, google calendar, calendar, events, ajax, widget
4
  Requires at least: 2.9.2
5
  Tested up to: 3.0
6
+ Stable tag: 0.2
7
 
8
  Parses Google Calendar feeds and displays the events as a calendar grid or list on a page, post or widget.
9
 
17
  * Displays events as a list or within a calendar grid
18
  * Lists and grids can be displayed in posts, pages or within a widget
19
  * Options to change the number of events retrieved, date / time format, cache duration etc.
20
+ * Options to change the information displayed (start time, location, description etc.).
21
  * Calendar grids can have the ability to change month, utilising AJAX
22
 
23
  Please visit the plugin homepage for how to get started and other help:
28
 
29
  * [Demo Page](http://www.rhanney.co.uk/plugins/google-calendar-events/gce-demo)
30
 
31
+ For a summary of the new features in 0.2, visit:
32
+
33
+ * [0.2 Features](http://www.rhanney.co.uk/2010/07/09/google-calendar-events-0-2)
34
+
35
  == Installation ==
36
 
37
  Use the automatic installer from within the WordPress administration, or:
48
 
49
  == Screenshots ==
50
 
 
 
51
  1. The main plugin admin screen.
52
  1. The add feed admin screen.
53
  1. A page showing a full page calendar grid and various widgets.
54
 
55
  == Changelog ==
56
 
57
+ = 0.2 =
58
+ * Added customization options for how information is displayed.
59
+ * Can now display: start time, end time and date, location, description and event link.
60
+ * Tooltips now using qTip jQuery plugin.
61
+
62
  = 0.1.4 =
63
  * More bug fixes.
64
 
77
 
78
  == Upgrade Notice ==
79
 
80
+ = 0.2 =
81
+ Customization options for display of information added.
82
 
83
  == Frequently Asked Questions ==
84
 
widget/gce-widget.php CHANGED
@@ -99,6 +99,16 @@ function gce_widget_content_grid($feed_id, $widget_id, $ajaxified = false, $mont
99
  if($df == '') $df = get_option('date_format');
100
  if($tf == '') $tf = get_option('time_format');
101
 
 
 
 
 
 
 
 
 
 
 
102
  //Creates a new GCE_Parser object for $feed_id
103
  $widget_feed_data = new GCE_Parser(
104
  $options[$feed_id]['url'],
@@ -107,7 +117,9 @@ function gce_widget_content_grid($feed_id, $widget_id, $ajaxified = false, $mont
107
  $options[$feed_id]['cache_duration'],
108
  $df,
109
  $tf,
110
- get_option('start_of_week')
 
 
111
  );
112
 
113
  //Check that feed parsed ok
@@ -135,6 +147,16 @@ function gce_widget_content_list($id){
135
  if($df == '') $df = get_option('date_format');
136
  if($tf == '') $tf = get_option('time_format');
137
 
 
 
 
 
 
 
 
 
 
 
138
  //Creates a new GCE_Parser object for $feed_id
139
  $widget_feed_data = new GCE_Parser(
140
  $options[$id]['url'],
@@ -142,7 +164,10 @@ function gce_widget_content_list($id){
142
  $options[$id]['max_events'],
143
  $options[$id]['cache_duration'],
144
  $df,
145
- $tf
 
 
 
146
  );
147
 
148
  //Check that feed parsed ok
99
  if($df == '') $df = get_option('date_format');
100
  if($tf == '') $tf = get_option('time_format');
101
 
102
+ $display_options = array();
103
+
104
+ //Add display options text to array if they have been turned on (if turned off, don't add them)
105
+ if($options[$feed_id]['display_title'] == 'on') $display_options['title'] = $options[$feed_id]['display_title_text'];
106
+ if($options[$feed_id]['display_start'] == 'on') $display_options['start'] = $options[$feed_id]['display_start_text'];
107
+ if($options[$feed_id]['display_end'] == 'on') $display_options['end'] = $options[$feed_id]['display_end_text'];
108
+ if($options[$feed_id]['display_location'] == 'on') $display_options['location'] = $options[$feed_id]['display_location_text'];
109
+ if($options[$feed_id]['display_desc'] == 'on') $display_options['desc'] = $options[$feed_id]['display_desc_text'];
110
+ if($options[$feed_id]['display_link'] == 'on') $display_options['link'] = $options[$feed_id]['display_link_text'];
111
+
112
  //Creates a new GCE_Parser object for $feed_id
113
  $widget_feed_data = new GCE_Parser(
114
  $options[$feed_id]['url'],
117
  $options[$feed_id]['cache_duration'],
118
  $df,
119
  $tf,
120
+ //$options[$feed_id]['offset'],
121
+ get_option('start_of_week'),
122
+ $display_options
123
  );
124
 
125
  //Check that feed parsed ok
147
  if($df == '') $df = get_option('date_format');
148
  if($tf == '') $tf = get_option('time_format');
149
 
150
+ $display_options = array();
151
+
152
+ //Add display options text to array if they have been turned on (if turned off, don't add them)
153
+ if($options[$id]['display_title'] == 'on') $display_options['title'] = $options[$id]['display_title_text'];
154
+ if($options[$id]['display_start'] == 'on') $display_options['start'] = $options[$id]['display_start_text'];
155
+ if($options[$id]['display_end'] == 'on') $display_options['end'] = $options[$id]['display_end_text'];
156
+ if($options[$id]['display_location'] == 'on') $display_options['location'] = $options[$id]['display_location_text'];
157
+ if($options[$id]['display_desc'] == 'on') $display_options['desc'] = $options[$id]['display_desc_text'];
158
+ if($options[$id]['display_link'] == 'on') $display_options['link'] = $options[$id]['display_link_text'];
159
+
160
  //Creates a new GCE_Parser object for $feed_id
161
  $widget_feed_data = new GCE_Parser(
162
  $options[$id]['url'],
164
  $options[$id]['max_events'],
165
  $options[$id]['cache_duration'],
166
  $df,
167
+ $tf,
168
+ null,
169
+ $display_options
170
+ //$options[$id]['offset']
171
  );
172
 
173
  //Check that feed parsed ok