My Calendar - Version 3.2.0

Version Description

  • Auto-toggle admin time format if display time format set to European format.
  • Show API endpoint when API enabled.
  • Add alternate alias for API endpoint.
  • Add style variables with category colors to style output.
  • Add color output icon with CSS variables in style editor.
  • Add new default stylesheet: Twentytwenty.css
  • Move permalink setting to general settings panel.
  • Change event timestamps to use a real UTC timestamp for reference.
  • Switch from using date() to gmdate().
  • Update Pickadate to 3.6.4. Resolves some bugs, but introduces an accessibility issue.
    • Customizations to Pickadate 3.6.4 to repair accessibility
    • don't move focus to picker
    • add 'close' button to time picker.
    • Switch Pickadate to classic theme (modified).
  • Improvements to output code layout.
  • Eliminate empty HTML wrappers in content.
  • New filter: mc_get_users. Use custom arguments to get users.
  • New filters: mc_header_navigation, mc_footer_navigation
  • New template tags: {userstart}, {userend} - date/time in local users timezone.
  • Bug fix: Misc. ARIA/id relationships broken.
  • Bug fix: remote locations sometimes pulled from local database.
  • Bug fix: Long-standing issues in user input settings.
  • Bug fix: Don't duplicate .summary values.
  • Bug fix: Only render one close button in mini calendar.
  • Collapse 'View Calendar' and 'Add Event' adminbar menus into a single menu.
  • Remove upgrade path from 2.2.10.
  • Remove .mc-event-visible from style output. Unused since 2011.
  • Remove numerous deprecated functions.
  • Conformance with latest WordPress PHPCS ruleset.
Download this release

Release Info

Developer joedolson
Plugin Icon 128x128 My Calendar
Version 3.2.0
Comparing to
See all releases

Code changes from version 3.1.18 to 3.2.0

Files changed (95) hide show
  1. changelog.txt +188 -0
  2. css/mc-styles.css +54 -3
  3. css/reset.css +8 -2
  4. includes/date-utilities.php +55 -32
  5. includes/db.php +3 -3
  6. includes/deprecated.php +9 -214
  7. includes/general-utilities.php +16 -16
  8. includes/screen-options.php +15 -0
  9. includes/widgets/class-my-calendar-filters.php +5 -5
  10. includes/widgets/class-my-calendar-mini-widget.php +23 -21
  11. includes/widgets/class-my-calendar-simple-search.php +2 -2
  12. includes/widgets/class-my-calendar-today-widget.php +7 -7
  13. includes/widgets/class-my-calendar-upcoming-widget.php +12 -12
  14. js/mc-ajax.js +13 -0
  15. js/mc-grid.js +2 -2
  16. js/mc-mini.js +1 -1
  17. js/pickadate/legacy.js +123 -30
  18. js/pickadate/picker.date.js +1357 -304
  19. js/pickadate/picker.js +1224 -179
  20. js/pickadate/picker.time.js +1022 -216
  21. js/pickadate/themes/classic.css +74 -66
  22. js/pickadate/themes/classic.date.css +301 -263
  23. js/pickadate/themes/classic.time.css +132 -104
  24. js/pickadate/themes/default.css +129 -112
  25. js/pickadate/themes/default.date.css +301 -263
  26. js/pickadate/themes/default.time.css +126 -101
  27. js/pickadate/themes/rtl.css +17 -14
  28. js/pickadate/translations/FORMATTING.md +7 -0
  29. js/pickadate/translations/NAMING.md +21 -0
  30. js/pickadate/translations/ar.js +16 -10
  31. js/pickadate/translations/bg_BG.js +17 -11
  32. js/pickadate/translations/bs_BA.js +17 -11
  33. js/pickadate/translations/ca_ES.js +18 -11
  34. js/pickadate/translations/cs_CZ.js +18 -11
  35. js/pickadate/translations/da_DK.js +18 -11
  36. js/pickadate/translations/de_DE.js +19 -11
  37. js/pickadate/translations/el_GR.js +17 -11
  38. js/pickadate/translations/es_ES.js +18 -11
  39. js/pickadate/translations/et_EE.js +17 -11
  40. js/pickadate/translations/eu_ES.js +17 -11
  41. js/pickadate/translations/fa_IR.js +19 -0
  42. js/pickadate/translations/fi_FI.js +17 -11
  43. js/pickadate/translations/fr_FR.js +23 -11
  44. js/pickadate/translations/ge_GEO.js +17 -0
  45. js/pickadate/translations/gl_ES.js +17 -11
  46. js/pickadate/translations/he_IL.js +16 -10
  47. js/pickadate/translations/hi_IN.js +20 -0
  48. js/pickadate/translations/hr_HR.js +18 -11
  49. js/pickadate/translations/hu_HU.js +18 -11
  50. js/pickadate/translations/id_ID.js +17 -11
  51. js/pickadate/translations/is_IS.js +17 -11
  52. js/pickadate/translations/it_IT.js +24 -11
  53. js/pickadate/translations/ja_JP.js +18 -11
  54. js/pickadate/translations/km_KH.js +24 -0
  55. js/pickadate/translations/ko_KR.js +17 -11
  56. js/pickadate/translations/lt_LT.js +24 -0
  57. js/pickadate/translations/lv_LV.js +22 -0
  58. js/pickadate/translations/nb_NO.js +18 -0
  59. js/pickadate/translations/ne_NP.js +17 -0
  60. js/pickadate/translations/nl_NL.js +18 -11
  61. js/pickadate/translations/pl_PL.js +18 -11
  62. js/pickadate/translations/pt_BR.js +17 -10
  63. js/pickadate/translations/pt_PT.js +17 -10
  64. js/pickadate/translations/ro_RO.js +17 -11
  65. js/pickadate/translations/ru_RU.js +18 -11
  66. js/pickadate/translations/sk_SK.js +18 -11
  67. js/pickadate/translations/sl_SI.js +18 -11
  68. js/pickadate/translations/sr_RS_cy.js +22 -0
  69. js/pickadate/translations/sr_RS_lt.js +22 -0
  70. js/pickadate/translations/sv_SE.js +22 -11
  71. js/pickadate/translations/th_TH.js +16 -10
  72. js/pickadate/translations/tr_TR.js +18 -11
  73. js/pickadate/translations/uk_UA.js +17 -11
  74. js/pickadate/translations/vi_VN.js +18 -0
  75. js/pickadate/translations/zh_CN.js +18 -11
  76. js/pickadate/translations/zh_TW.js +18 -11
  77. my-calendar-api.php +8 -7
  78. my-calendar-categories.php +38 -35
  79. my-calendar-core.php +178 -82
  80. my-calendar-event-manager.php +236 -215
  81. my-calendar-events.php +105 -27
  82. my-calendar-generator.php +10 -10
  83. my-calendar-install.php +1 -3
  84. my-calendar-limits.php +2 -2
  85. my-calendar-location-manager.php +1 -1
  86. my-calendar-locations.php +17 -2
  87. my-calendar-output.php +276 -221
  88. my-calendar-settings.php +60 -35
  89. my-calendar-styles.php +6 -2
  90. my-calendar-templates.php +52 -46
  91. my-calendar-widgets.php +46 -46
  92. my-calendar.php +9 -9
  93. readme.txt +36 -192
  94. styles/twentytwenty.css +687 -0
  95. templates/twentytwenty.css +687 -0
changelog.txt CHANGED
@@ -1,3 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 2.5.17 =
2
 
3
  * Security: Authenticated XSS vulnerability resolved.
1
+ = 3.0.19 =
2
+
3
+ * Bug fix: Fatal error in export API when location object included.
4
+ * BUg fix: my calendar categories queried private categories instead of public.
5
+
6
+ = 3.0.18 =
7
+
8
+ * Bug fix: Invalid setting in bottom nav defaults.
9
+ * Bug fix: Generate feeds by date added rather than fixed number. If empty, get most recent regardless.
10
+ * Bug fix: Legitimate HTML escaped in visual editor in group event editor.
11
+
12
+ = 3.0.17 =
13
+
14
+ * Bug fix: Group event editing was broken.
15
+ * Bug fix: Eliminate four PHP notices in the Today's Events widget.
16
+ * Added: Filter to control whether CSS should be loaded on archives.
17
+
18
+ = 3.0.16 =
19
+
20
+ * Changed display UID to avoid duplicate IDs when multiple calendars shown.
21
+ * Add option to display heading in details pop-up.
22
+ * Unify position and size of close button in Twentyeighteen mini calendar.
23
+ * Eliminate multi category parameter from CSV output (doesn't support multidimensional data)
24
+ * Add GUID to export data.
25
+
26
+ = 3.0.15 =
27
+
28
+ * Bug fix: prevent some PHP notices when running Pro importer.
29
+ * Bug fix: Display of multidate time string when crossing months or years.
30
+ * Bug fix: Variable written as constant prevented event_span from saving correctly.
31
+ * Bug fix: Trash counter updated with incorrect values.
32
+ * Bug fix: Two cases where status counter not updated.
33
+ * Change: Add DB version to debugging info
34
+
35
+ = 3.0.14 =
36
+
37
+ * Bug fix: incorrect value passed for instance parameter on single event shortcode.
38
+ * Bug fix: hide HTML wrapper for category color when colors disabled.
39
+ * Bug fix: Remove transparent background in Twenty eighteen; blocks category colors
40
+ * Bug fix: Invalid ordering parameter for location lists
41
+ * Feature: Ability to select multiple categories (props Josef Fällman)
42
+ * Moved changelogs for 2.5 & earlier to changelog.txt
43
+
44
+ = 3.0.13 =
45
+
46
+ * Bug fix: missing function call when accessing custom mini templates
47
+ * Bug fix: Syntax error in SQL query checking for conflicts
48
+ * Change: pass short description to Akismet if long desc absent
49
+
50
+ = 3.0.12 =
51
+
52
+ * Bug fix: My Calendar could prevent canonical link from displaying if canonical link being filtered by another application.
53
+ * Modernize & improve Akismet integration.
54
+ * Add filter to disable Akismet checks.
55
+
56
+ = 3.0.11 =
57
+
58
+ * SECURITY: XSS - Canonical URL not properly sanitized. Affects 3.0.0 and up.
59
+
60
+ = 3.0.10 =
61
+
62
+ * Bug fix: invalid method used to sort location lists.
63
+ * Bug fix: shortcode generator missing input value
64
+ * Bug fix: datepicker did not reflect start of week settings
65
+ * Stylesheet CSS change
66
+
67
+ = 3.0.9 =
68
+
69
+ * Bug fix: Error thrown if Akismet had previously been configured, then deleted.
70
+ * Bug fix: location type was added to params if category key was set.
71
+ * Bug fix: remove a couple notices
72
+ * Bug fix: category relationships not carried over when recurring events split
73
+
74
+ = 3.0.8 =
75
+
76
+ * Bug fix: need to allow <a> elements in mc_strip_tags so calendar linkscan point to non-calendar URLs
77
+
78
+ = 3.0.7 =
79
+
80
+ * Bug fix: Case where events ending at midnight (AM) of current day were displayed
81
+ * Bug fix: trim spaces from values earlier when parsing filter elements
82
+ * Change: don't declare font-family in older stylesheets.
83
+
84
+ = 3.0.6 =
85
+
86
+ * Bug fix: Shortcode for locations forms always rendered as if in a group filter.
87
+ * Bug fix: If the default length 1 hr event pushes into next day, adjust length.
88
+ * Bug fix: Incorrectly nested parentheses caused math error in months-by-day recurrence
89
+
90
+ = 3.0.5 =
91
+
92
+ * Bug fix: If only one event on a day, event title did not show in list view with show title option.
93
+ * Bug fix: Incorrect array key for fallback parameter in widget
94
+ * Bug fix: custom template query expected 25 chars instead of 32
95
+ * Re-allow <br> in event titles.
96
+
97
+ = 3.0.4 =
98
+
99
+ * Bug fix: aria-current test was broken for current date
100
+ * Bug fix: Private categories not disambiguated in MySQL query when excluded
101
+ * Improve: Rewrite my_calendar_copyr backup functions to use WP core functions.
102
+
103
+ = 3.0.3 =
104
+
105
+ * Bug fix: Category key needed to use a 'WHERE' not an 'AND'; broke output if limiting by category
106
+ * Bug fix: Error thrown in style editor & category editor if custom directory did not exist
107
+
108
+ = 3.0.2 =
109
+
110
+ * 3.0.1 did not correct the right error. Correct fix.
111
+
112
+ = 3.0.1 =
113
+
114
+ * Bug fix: install error on update.
115
+
116
+ = 3.0.0 =
117
+
118
+ * Bug fix: If category deleted, set events with that category to default cat, not cat ID 1.
119
+ * Bug fix: Date/time comparison used front-end date value instead of dtstamp in upcoming events.
120
+ * Bug fix: Navigation issue if beginning of week is in previous month
121
+ * Bug fix: Event conflict didn't catch events 100% contained inside other events.
122
+ * Bug fix: Private categories should not be visible to public users in submission forms or category lists
123
+ * Bug fix: aria-current key term value was translatable
124
+ * Bug fix: If editing single instance, location is removed
125
+ * Bug fix: don't show location control notices on front-end
126
+ * Bug fix: correcting event recurrence did not always remove meta flag
127
+ * Bug fix: Only output map HTML if API key provided
128
+ * Bug fix: character set and collation determination on install & update
129
+ * Bug fix: When changing recurring events, only change instance IDs if the date of the instance has changed.
130
+ * Bug fix: Event post should not change post date on update
131
+ * Bug fix: All day events should export correctly to Outlook & Apple Calendar
132
+ * Bug fix: Location control accordion was not accessible.
133
+ * Bug fix: Term ID was not set in category manager if term already existed.
134
+ * Bug fix: Make sure that the 's' query var is not automatically added to My Calendar URLs
135
+
136
+ * Add: several new filters
137
+ * Add: notice to alert users if their calendar configured for remote event source.
138
+ * Add: map display to back-end location manager.
139
+ * Add: location search in location manager
140
+ * Add: ability to filter location lists used to submit data 'mc_get_locations'
141
+ * Add: Support for multiple categories on events.
142
+ * Add: stylesheet (Twenty Eighteen)
143
+ * Add: CSS variables support
144
+ * Add: list of problem events in Manage Events sidebar
145
+ * Add: add months shown in list view to shortcode parameters
146
+ * Add: support for auto-refresh of cache for a variety of caching plug-ins.
147
+ * Add: Option to remove event data on uninstall
148
+ * Add: filter to define events as private via custom methods
149
+ * Add: event preview
150
+ * Add: location support to mini calendar widget
151
+ * Add: CSS code editor available in Style editing
152
+ * Add: HTML code editor available in Template editing
153
+ * Add: Schema.org address markup
154
+ * Add: Schema.org event markup
155
+ * Add: Include event link in 'Add to Google Cal' content.
156
+ * Add: date format for multi-day dates in grid view.
157
+
158
+ * Removed: event open & event closed text settings
159
+ * Removed: event_open event status (little used and confusing; replaced by My Tickets)
160
+ * Removed: guessing calendar install location
161
+ * Removed: event cache code
162
+ * Removed: upgrade routines from 1.11.x
163
+ * Removed: mc_widget_defaults option
164
+ * Removed: user's guide references
165
+
166
+ * Change: default image sizes from 'medium' to 'large'
167
+ * Change: Remove ability to disable event approval; remap "approval" to "draft"
168
+ * Change: default number of results to show in advanced event search.
169
+ * Change: Switched from image to icon font for close button
170
+ * Change: Major changes to event fetching
171
+ * Change: Major changes to code organization
172
+ * Change: Added caching on database engine query
173
+ * Change: if event location set in dropdown, event will always display location as shown in location manager
174
+ * Change: changed argument style for major functions to arrays of arguments
175
+ * Change: move Location Manager to separate page; add location sorting.
176
+ * Change: Move exif_ fallback function into utilities include
177
+ * Change: Moved location & category specific settings
178
+ * Change: Simplified texts in several locations
179
+ * Change: Clearer UI on location input limits
180
+ * Change: autotoggle end date minimum input when start date set
181
+ * Change: Reorganized input fields
182
+ * Change: Generate separate iCal exports for Google Calendar or Outlook
183
+ * Change: Constrain tabbing within details pop-up
184
+ * Change: Close details pop-up with Esc key
185
+ * Change: Audited options to remove unused or unneeded options
186
+ * Change: Create a referential template when shortcode generated
187
+ * Change: Feeds nav panel now shows subscription links; exports are available in 'exports' panel.
188
+
189
  = 2.5.17 =
190
 
191
  * Security: Authenticated XSS vulnerability resolved.
css/mc-styles.css CHANGED
@@ -90,9 +90,8 @@ ul.links li {
90
  }
91
 
92
  span.mc-notice {
93
- padding: 3px;
94
  background: #ffc;
95
- font-weight: 700;
96
  border: 1px solid #900;
97
  }
98
 
@@ -125,6 +124,7 @@ span.mc-notice {
125
 
126
  .clonedInput {
127
  margin-bottom: 10px;
 
128
  border-bottom: 1px solid #ddd
129
  }
130
 
@@ -290,6 +290,15 @@ strong.label {
290
  display: inline-block;
291
  }
292
 
 
 
 
 
 
 
 
 
 
293
  .wp-picker-holder {
294
  position: absolute;
295
  z-index: 10;
@@ -299,6 +308,38 @@ strong.label {
299
  height: auto;
300
  }
301
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  .my-calendar-admin .counter {
303
  padding-right: 6px;
304
  border-right: 16px solid green;
@@ -622,6 +663,15 @@ select[name="event_recur"] {
622
  display: inline;
623
  }
624
 
 
 
 
 
 
 
 
 
 
625
  .locations-container {
626
  position: relative;
627
  }
@@ -719,9 +769,10 @@ select[name="event_recur"] {
719
  }
720
 
721
  .mc_response {
722
- padding: .25em;
723
  background: #ffa;
724
  color: #000;
 
725
  }
726
 
727
  tr.problem {
90
  }
91
 
92
  span.mc-notice {
93
+ padding: 5px;
94
  background: #ffc;
 
95
  border: 1px solid #900;
96
  }
97
 
124
 
125
  .clonedInput {
126
  margin-bottom: 10px;
127
+ padding-bottom: 10px;
128
  border-bottom: 1px solid #ddd
129
  }
130
 
290
  display: inline-block;
291
  }
292
 
293
+ .picker-container {
294
+ position: relative;
295
+ display: inline-block;
296
+ }
297
+
298
+ .picker {
299
+ min-width: 400px;
300
+ }
301
+
302
  .wp-picker-holder {
303
  position: absolute;
304
  z-index: 10;
308
  height: auto;
309
  }
310
 
311
+ .picker-container .picker__list {
312
+ padding: .75em 0 0;
313
+ }
314
+
315
+ .picker-container .picker__weekday {
316
+ font-size: .9em;
317
+ color: #333;
318
+ }
319
+
320
+ .picker-container .picker__holder .picker__button--today,
321
+ .picker-container .picker__holder .picker__button--close,
322
+ .picker-container .picker__holder .picker__button--clear {
323
+ font-size: 1.1em;
324
+ font-weight: 400;
325
+ color: #444;
326
+ padding: .5em 1em;
327
+ margin: 0;
328
+ }
329
+
330
+ .picker-container #mc_event_endtime_root .picker__holder .picker__button--clear,
331
+ .picker-container #mc_event_time_root .picker__holder .picker__button--clear,
332
+ .picker-container #mc_event_endtime_root .picker__holder .picker__button--close,
333
+ .picker-container #mc_event_time_root .picker__holder .picker__button--close {
334
+ width: 50% !important;
335
+ }
336
+
337
+ .picker-container #mc_event_endtime_root .picker__holder .picker__button--clear,
338
+ .picker-container #mc_event_time_root .picker__holder .picker__button--clear {
339
+ float: left;
340
+ text-transform: none;
341
+ }
342
+
343
  .my-calendar-admin .counter {
344
  padding-right: 6px;
345
  border-right: 16px solid green;
663
  display: inline;
664
  }
665
 
666
+ .checkboxes li .variable-color {
667
+ height: 1.75em;
668
+ width: 1.75em;
669
+ margin: 0 .25em;
670
+ border-radius: 1.75em;
671
+ vertical-align: middle;
672
+ display: inline-block;
673
+ }
674
+
675
  .locations-container {
676
  position: relative;
677
  }
769
  }
770
 
771
  .mc_response {
772
+ padding: .5em;
773
  background: #ffa;
774
  color: #000;
775
+ border: 1px solid burlywood;
776
  }
777
 
778
  tr.problem {
css/reset.css CHANGED
@@ -9,8 +9,8 @@
9
  }
10
 
11
  /* Override overflow:hidden */
12
- div.site-content {
13
- overflow: visible;
14
  }
15
 
16
  .mc-main {
@@ -57,6 +57,7 @@ div.site-content {
57
  .mc-main input[type=submit], .mc-main input[type=button], .mc-main button {
58
  margin: 0 !important;
59
  padding: 0 !important;
 
60
  }
61
 
62
  .mc-main input, .mc-main select, .mc-main a img {
@@ -87,6 +88,11 @@ div.site-content {
87
  color: inherit;
88
  }
89
 
 
 
 
 
 
90
  button.mc-toggle {
91
  border: 0;
92
  padding: 4px;
9
  }
10
 
11
  /* Override overflow:hidden */
12
+ div.site-content, table {
13
+ overflow: visible !important;
14
  }
15
 
16
  .mc-main {
57
  .mc-main input[type=submit], .mc-main input[type=button], .mc-main button {
58
  margin: 0 !important;
59
  padding: 0 !important;
60
+ text-transform: none;
61
  }
62
 
63
  .mc-main input, .mc-main select, .mc-main a img {
88
  color: inherit;
89
  }
90
 
91
+ .mc-adjacent .mc-event-date {
92
+ display: block;
93
+ font-size: 80%;
94
+ }
95
+
96
  button.mc-toggle {
97
  border: 0;
98
  padding: 4px;
includes/date-utilities.php CHANGED
@@ -21,11 +21,10 @@ if ( ! defined( 'ABSPATH' ) ) {
21
  * @return string classes
22
  */
23
  function mc_dateclass( $current ) {
24
- $now = current_time( 'timestamp' );
25
  $dayclass = sanitize_html_class( strtolower( date_i18n( 'l', $current ) ) ) . ' ' . sanitize_html_class( strtolower( date_i18n( 'D', $current ) ) );
26
- if ( date( 'Ymd', $now ) === date( 'Ymd', $current ) ) {
27
  $dateclass = 'current-day';
28
- } elseif ( my_calendar_date_comp( date( 'Y-m-d', $now ), date( 'Y-m-d', $current ) ) ) {
29
  $dateclass = 'future-day';
30
  } else {
31
  $dateclass = 'past-day past-date'; // stupid legacy classes.
@@ -46,7 +45,7 @@ function mc_dateclass( $current ) {
46
  */
47
  function my_calendar_add_date( $givendate, $day = 0, $mth = 0, $yr = 0 ) {
48
  $cd = strtotime( $givendate );
49
- $newdate = mktime( date( 'H', $cd ), date( 'i', $cd ), date( 's', $cd ), date( 'm', $cd ) + $mth, date( 'd', $cd ) + $day, date( 'Y', $cd ) + $yr );
50
 
51
  return $newdate;
52
  }
@@ -94,15 +93,15 @@ function my_calendar_date_xcomp( $early, $late ) {
94
  /**
95
  * Test if dates are the same with day precision
96
  *
97
- * @param string $early date string.
98
- * @param string $late date string.
99
  *
100
  * @return boolean true if first date equal to second
101
  */
102
  function my_calendar_date_equal( $early, $late ) {
103
  // convert full datetime to date only.
104
- $firstdate = strtotime( date( 'Y-m-d', strtotime( $early ) ) );
105
- $lastdate = strtotime( date( 'Y-m-d', strtotime( $late ) ) );
106
  if ( $firstdate === $lastdate ) {
107
 
108
  return true;
@@ -160,8 +159,8 @@ function mc_datetime_cmp( $a, $b ) {
160
  * @return integer (ternary value)
161
  */
162
  function mc_timediff_cmp( $a, $b ) {
163
- $a = $a . date( ' H:i:s', current_time( 'timestamp' ) );
164
- $b = $b . date( ' H:i:s', current_time( 'timestamp' ) );
165
  $event_dt_a = strtotime( $a );
166
  $event_dt_b = strtotime( $b );
167
  $diff_a = mc_date_diff_precise( $event_dt_a );
@@ -233,9 +232,9 @@ function week_of_month( $date_of_event ) {
233
  */
234
  function mc_checkdate( $date ) {
235
  $time = strtotime( $date );
236
- $m = date( 'n', $time );
237
- $d = date( 'j', $time );
238
- $y = date( 'Y', $time );
239
 
240
  return checkdate( $m, $d, $y );
241
  }
@@ -243,18 +242,18 @@ function mc_checkdate( $date ) {
243
  /**
244
  * Get the first day value of the current week.
245
  *
246
- * @param mixed int/boolean $date timestamp or false if now.
247
  *
248
  * @return array day and month
249
  */
250
- function mc_first_day_of_week( $date = false ) {
251
  $start_of_week = ( get_option( 'start_of_week' ) === '1' || get_option( 'start_of_week' ) === '0' ) ? absint( get_option( 'start_of_week' ) ) : 0;
252
- if ( $date ) {
253
- $today = date( 'w', $date );
254
- $now = date( 'Y-m-d', $date );
255
  } else {
256
- $today = date( 'w', current_time( 'timestamp' ) );
257
- $now = date( 'Y-m-d', current_time( 'timestamp' ) );
258
  }
259
  $month = 0;
260
  $sub = 0; // don't change month.
@@ -281,9 +280,9 @@ function mc_first_day_of_week( $date = false ) {
281
  $sub = ( 1 === $start_of_week ) ? 6 : 0;
282
  break; // sun.
283
  }
284
- $day = date( 'j', strtotime( $now . ' -' . $sub . ' day' ) );
285
  if ( 0 !== $sub ) {
286
- if ( date( 'n', strtotime( $now . ' -' . $sub . ' day' ) ) !== date( 'n', strtotime( $now ) ) ) {
287
  $month = - 1;
288
  } else {
289
  $month = 0;
@@ -347,13 +346,13 @@ function mc_name_days( $format ) {
347
  if ( 'mini' === $format ) {
348
  // PHP doesn't have a single letter abbreviation, so this has to be a translatable.
349
  $name_days = array(
350
- '<span aria-hidden="true">' . __( '<abbr title="Sunday">S</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Sunday' ) ) . '</span>',
351
- '<span aria-hidden="true">' . __( '<abbr title="Monday">M</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Monday' ) ) . '</span>',
352
- '<span aria-hidden="true">' . __( '<abbr title="Tuesday">T</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Tuesday' ) ) . '</span>',
353
- '<span aria-hidden="true">' . __( '<abbr title="Wednesday">W</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Wednesday' ) ) . '</span>',
354
- '<span aria-hidden="true">' . __( '<abbr title="Thursday">T</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Thursday' ) ) . '</span>',
355
- '<span aria-hidden="true">' . __( '<abbr title="Friday">F</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Friday' ) ) . '</span>',
356
- '<span aria-hidden="true">' . __( '<abbr title="Saturday">S</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Saturday' ) ) . '</span>',
357
  );
358
  }
359
 
@@ -375,9 +374,9 @@ function mc_exit_early( $event, $process_date ) {
375
  }
376
 
377
  $hide_days = apply_filters( 'mc_hide_additional_days', false, $event );
378
- $today = date( 'Y-m-d', strtotime( $event->occur_begin ) );
379
- $current = date( 'Y-m-d', strtotime( $process_date ) );
380
- $end = date( 'Y-m-d', strtotime( $event->occur_end ) );
381
  // if event ends at midnight today (e.g., very first thing of the day), exit without re-drawing.
382
  // or if event started yesterday & has event_hide_end checked.
383
  $ends_at_midnight = ( '00:00:00' === $event->event_endtime && $end === $process_date && $current !== $today ) ? true : false;
@@ -411,3 +410,27 @@ function mc_private_event( $event ) {
411
 
412
  return $status;
413
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  * @return string classes
22
  */
23
  function mc_dateclass( $current ) {
 
24
  $dayclass = sanitize_html_class( strtolower( date_i18n( 'l', $current ) ) ) . ' ' . sanitize_html_class( strtolower( date_i18n( 'D', $current ) ) );
25
+ if ( current_time( 'Ymd' ) === mc_date( 'Ymd', $current, false ) ) {
26
  $dateclass = 'current-day';
27
+ } elseif ( my_calendar_date_comp( current_time( 'Y-m-d' ), mc_date( 'Y-m-d', $current, false ) ) ) {
28
  $dateclass = 'future-day';
29
  } else {
30
  $dateclass = 'past-day past-date'; // stupid legacy classes.
45
  */
46
  function my_calendar_add_date( $givendate, $day = 0, $mth = 0, $yr = 0 ) {
47
  $cd = strtotime( $givendate );
48
+ $newdate = mktime( mc_date( 'H', $cd, false ), mc_date( 'i', $cd, false ), mc_date( 's', $cd, false ), mc_date( 'm', $cd, false ) + $mth, mc_date( 'd', $cd, false ) + $day, mc_date( 'Y', $cd, false ) + $yr );
49
 
50
  return $newdate;
51
  }
93
  /**
94
  * Test if dates are the same with day precision
95
  *
96
+ * @param string $early date string in current time zone.
97
+ * @param string $late date string in current time zone.
98
  *
99
  * @return boolean true if first date equal to second
100
  */
101
  function my_calendar_date_equal( $early, $late ) {
102
  // convert full datetime to date only.
103
+ $firstdate = strtotime( mc_date( 'Y-m-d', strtotime( $early ), false ) );
104
+ $lastdate = strtotime( mc_date( 'Y-m-d', strtotime( $late ), false ) );
105
  if ( $firstdate === $lastdate ) {
106
 
107
  return true;
159
  * @return integer (ternary value)
160
  */
161
  function mc_timediff_cmp( $a, $b ) {
162
+ $a = $a . current_time( ' H:i:s' );
163
+ $b = $b . current_time( ' H:i:s' );
164
  $event_dt_a = strtotime( $a );
165
  $event_dt_b = strtotime( $b );
166
  $diff_a = mc_date_diff_precise( $event_dt_a );
232
  */
233
  function mc_checkdate( $date ) {
234
  $time = strtotime( $date );
235
+ $m = mc_date( 'n', $time );
236
+ $d = mc_date( 'j', $time );
237
+ $y = mc_date( 'Y', $time );
238
 
239
  return checkdate( $m, $d, $y );
240
  }
242
  /**
243
  * Get the first day value of the current week.
244
  *
245
+ * @param mixed int/boolean $timestamp timestamp + offset or false if now.
246
  *
247
  * @return array day and month
248
  */
249
+ function mc_first_day_of_week( $timestamp = false ) {
250
  $start_of_week = ( get_option( 'start_of_week' ) === '1' || get_option( 'start_of_week' ) === '0' ) ? absint( get_option( 'start_of_week' ) ) : 0;
251
+ if ( $timestamp ) {
252
+ $today = mc_date( 'w', $timestamp, false );
253
+ $now = mc_date( 'Y-m-d', $timestamp, false );
254
  } else {
255
+ $today = current_time( 'w' );
256
+ $now = current_time( 'Y-m-d' );
257
  }
258
  $month = 0;
259
  $sub = 0; // don't change month.
280
  $sub = ( 1 === $start_of_week ) ? 6 : 0;
281
  break; // sun.
282
  }
283
+ $day = mc_date( 'j', strtotime( $now . ' -' . $sub . ' day' ), false );
284
  if ( 0 !== $sub ) {
285
+ if ( mc_date( 'n', strtotime( $now . ' -' . $sub . ' day' ), false ) !== mc_date( 'n', strtotime( $now ), false ) ) {
286
  $month = - 1;
287
  } else {
288
  $month = 0;
346
  if ( 'mini' === $format ) {
347
  // PHP doesn't have a single letter abbreviation, so this has to be a translatable.
348
  $name_days = array(
349
+ '<span aria-hidden="true">' . __( '<abbr title="Sunday">S</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Sunday' ) ) . '</span>', // phpcs:ignore WordPress.WP.I18n.NoHtmlWrappedStrings
350
+ '<span aria-hidden="true">' . __( '<abbr title="Monday">M</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Monday' ) ) . '</span>', // phpcs:ignore WordPress.WP.I18n.NoHtmlWrappedStrings
351
+ '<span aria-hidden="true">' . __( '<abbr title="Tuesday">T</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Tuesday' ) ) . '</span>', // phpcs:ignore WordPress.WP.I18n.NoHtmlWrappedStrings
352
+ '<span aria-hidden="true">' . __( '<abbr title="Wednesday">W</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Wednesday' ) ) . '</span>', // phpcs:ignore WordPress.WP.I18n.NoHtmlWrappedStrings
353
+ '<span aria-hidden="true">' . __( '<abbr title="Thursday">T</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Thursday' ) ) . '</span>', // phpcs:ignore WordPress.WP.I18n.NoHtmlWrappedStrings
354
+ '<span aria-hidden="true">' . __( '<abbr title="Friday">F</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Friday' ) ) . '</span>', // phpcs:ignore WordPress.WP.I18n.NoHtmlWrappedStrings
355
+ '<span aria-hidden="true">' . __( '<abbr title="Saturday">S</abbr>', 'my-calendar' ) . '</span><span class="screen-reader-text">' . date_i18n( 'l', strtotime( 'Saturday' ) ) . '</span>', // phpcs:ignore WordPress.WP.I18n.NoHtmlWrappedStrings
356
  );
357
  }
358
 
374
  }
375
 
376
  $hide_days = apply_filters( 'mc_hide_additional_days', false, $event );
377
+ $today = mc_date( 'Y-m-d', strtotime( $event->occur_begin ) );
378
+ $current = mc_date( 'Y-m-d', strtotime( $process_date ) );
379
+ $end = mc_date( 'Y-m-d', strtotime( $event->occur_end ) );
380
  // if event ends at midnight today (e.g., very first thing of the day), exit without re-drawing.
381
  // or if event started yesterday & has event_hide_end checked.
382
  $ends_at_midnight = ( '00:00:00' === $event->event_endtime && $end === $process_date && $current !== $today ) ? true : false;
410
 
411
  return $status;
412
  }
413
+
414
+ /**
415
+ * Wrapper for mc_date()
416
+ *
417
+ * @param string $format Format to use.
418
+ * @param int $timestamp Timestamp.
419
+ * @param bool $offset false to not add offset; if already a true timestamp.
420
+ *
421
+ * @return string Formatted date.
422
+ */
423
+ function mc_date( $format, $timestamp = false, $offset = true ) {
424
+ if ( ! $timestamp ) {
425
+ // Timestamp is UTC.
426
+ $timestamp = time();
427
+ }
428
+ if ( $offset ) {
429
+ $offset = intval( get_option( 'gmt_offset', 0 ) ) * 60 * 60;
430
+ } else {
431
+ $offset = 0;
432
+ }
433
+ $timestamp = $timestamp + $offset;
434
+
435
+ return gmdate( $format, $timestamp );
436
+ }
includes/db.php CHANGED
@@ -89,11 +89,11 @@ function my_calendar_select_table( $table = 'my_calendar_events', $site = false
89
  if ( 'global' === $site ) {
90
  return $wpdb->base_prefix . $table;
91
  }
92
- if ( false != $site && $site ) {
93
  $site = absint( $site );
94
  $wpdb->set_blog_id( $site );
95
  }
96
- $local = ( 1 == $show ) ? $wpdb->base_prefix . $table : $wpdb->prefix . $table;
97
  $global = $wpdb->base_prefix . $table;
98
 
99
  switch ( $option ) {
@@ -104,7 +104,7 @@ function my_calendar_select_table( $table = 'my_calendar_events', $site = false
104
  return $global;
105
  break;
106
  case 2:
107
- return ( 1 == $choice ) ? $global : $local;
108
  break;
109
  default:
110
  return $local;
89
  if ( 'global' === $site ) {
90
  return $wpdb->base_prefix . $table;
91
  }
92
+ if ( false !== $site && $site ) {
93
  $site = absint( $site );
94
  $wpdb->set_blog_id( $site );
95
  }
96
+ $local = ( 1 === $show ) ? $wpdb->base_prefix . $table : $wpdb->prefix . $table;
97
  $global = $wpdb->base_prefix . $table;
98
 
99
  switch ( $option ) {
104
  return $global;
105
  break;
106
  case 2:
107
+ return ( 1 === $choice ) ? $global : $local;
108
  break;
109
  default:
110
  return $local;
includes/deprecated.php CHANGED
@@ -32,105 +32,6 @@ if ( is_multisite() ) {
32
  define( 'MY_CALENDAR_GLOBAL_LOCATIONS_TABLE', $wpdb->base_prefix . 'my_calendar_locations' );
33
  }
34
 
35
- /**
36
- * Caching has been disabled by default with no option to enable for some time.
37
- * Leaving functions, but they will only return false.
38
- *
39
- * @param int $category Deprecated.
40
- * @param string $ltype Deprecated.
41
- * @param string $lvalue Deprecated.
42
- * @param string $author Deprecated.
43
- * @param int $host Deprecated.
44
- * @param int $hash Deprecated.
45
- *
46
- * @deprecated
47
- */
48
- function mc_check_cache( $category, $ltype, $lvalue, $author, $host, $hash ) {
49
- return false;
50
- }
51
-
52
- /**
53
- * Caching has been disabled by default with no option to enable for some time.
54
- * Leaving functions, but they will only return false.
55
- *
56
- * @param string $cache Deprecated.
57
- * @param int $category Deprecated.
58
- * @param string $ltype Deprecated.
59
- * @param string $lvalue Deprecated.
60
- * @param string $auth Deprecated.
61
- * @param int $host Deprecated.
62
- *
63
- * @deprecated
64
- */
65
- function mc_clean_cache( $cache, $category, $ltype, $lvalue, $auth, $host ) {
66
- return false;
67
- }
68
-
69
- /**
70
- * Caching has been disabled by default with no option to enable for some time.
71
- * Leaving functions, but they will only return false.
72
- *
73
- * @param array $arr_events Deprecated.
74
- * @param string $hash Deprecated.
75
- * @param int $category Deprecated.
76
- * @param string $ltype Deprecated.
77
- * @param string $lvalue Deprecated.
78
- * @param int $author Deprecated.
79
- * @param int $host Deprecated.
80
- *
81
- * @deprecated
82
- */
83
- function mc_create_cache( $arr_events, $hash, $category, $ltype, $lvalue, $author, $host ) {
84
- return false;
85
- }
86
-
87
- /**
88
- * Caching has been disabled by default with no option to enable for some time.
89
- * Leaving functions, but they will only return false.
90
- *
91
- * @deprecated
92
- */
93
- function mc_delete_cache() {
94
- // doesn't do anything anymore.
95
- }
96
-
97
- /**
98
- * Caching has been disabled by default with no option to enable for some time.
99
- * Leaving functions, but they will only return false.
100
- *
101
- * @param string $cache Deprecated.
102
- *
103
- * @deprecated
104
- */
105
- function mc_get_cache( $cache ) {
106
- return false;
107
- }
108
-
109
- /**
110
- * Caching has been disabled by default with no option to enable for some time.
111
- * Leaving functions, but they will only return false.
112
- *
113
- * @param string $cache Deprecated.
114
- * @param string $time Deprecated.
115
- *
116
- * @deprecated
117
- */
118
- function mc_set_cache( $cache, $time ) {
119
- // doesn't do anything.
120
- }
121
-
122
- /**
123
- * Caching has been disabled by default with no option to enable for some time.
124
- * Leaving functions, but they will only return false.
125
- *
126
- * @param string $cache Deprecated.
127
- *
128
- * @deprecated
129
- */
130
- function mc_remove_cache( $cache ) {
131
- // doesn't do anything.
132
- }
133
-
134
  /**
135
  * Old support box function
136
  *
@@ -138,20 +39,13 @@ function mc_remove_cache( $cache ) {
138
  * @deprecated
139
  */
140
  function jd_show_support_box() {
141
- mc_show_sidebar();
142
- }
143
-
144
- /**
145
- * Odd toggle. Unknown when last used.
146
- *
147
- * @param int $int Any integer.
148
- *
149
- * @deprecated
150
- *
151
- * @return boolean
152
- */
153
- function my_calendar_is_odd( $int ) {
154
- return ( $int & 1 );
155
  }
156
 
157
  /**
@@ -160,7 +54,7 @@ function my_calendar_is_odd( $int ) {
160
  * @param string $recur Recurrence string (single character).
161
  * @param int $repeats Number of occurrences to repeat.
162
  *
163
- * @deprecated 2.5.16
164
  *
165
  * @return string label
166
  */
@@ -208,7 +102,7 @@ if ( ! function_exists( 'is_ssl' ) ) {
208
  if ( '1' === $_SERVER['HTTPS'] ) {
209
  return true;
210
  }
211
- } elseif ( isset( $_SERVER['SERVER_PORT'] ) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
212
  return true;
213
  }
214
 
@@ -231,102 +125,3 @@ function jd_draw_template( $array, $template, $type = 'list' ) {
231
 
232
  return mc_draw_template( $array, $template, $type );
233
  }
234
-
235
- /**
236
- * Test whether two dates are day-consecutive
237
- * not used per audit 3/1/2018
238
- *
239
- * @param string $current date string.
240
- * @param string $last_date previous date.
241
- *
242
- * @return boolean
243
- */
244
- function mc_dates_consecutive( $current, $last_date ) {
245
- if ( strtotime( $last_date . '+ 1 day' ) === strtotime( $current ) ) {
246
-
247
- return true;
248
- } else {
249
-
250
- return false;
251
- }
252
- }
253
- /**
254
- * Reverse Function to compare datetime in event objects
255
- *
256
- * @param object $b Event object.
257
- * @param object $a Event object.
258
- *
259
- * @return int (ternary value)
260
- */
261
- function my_calendar_reverse_datetime_cmp( $b, $a ) {
262
- $event_dt_a = strtotime( $a->occur_begin );
263
- $event_dt_b = strtotime( $b->occur_begin );
264
- if ( $event_dt_a === $event_dt_b ) {
265
- return 0;
266
- }
267
-
268
- return ( $event_dt_a < $event_dt_b ) ? - 1 : 1;
269
- }
270
-
271
- /**
272
- * Compare two dates for diff
273
- *
274
- * @param string $start date string.
275
- * @param string $end datee string.
276
- *
277
- * @deprecated
278
- *
279
- * @return diff
280
- */
281
- function jd_date_diff( $start, $end = 'NOW' ) {
282
- $sdate = strtotime( $start );
283
- $edate = strtotime( $end );
284
-
285
- $time = $edate - $sdate;
286
- if ( $time < 86400 && $time > - 86400 ) {
287
- return false;
288
- } else {
289
- $pday = ( $edate - $sdate ) / 86400;
290
- $preday = explode( '.', $pday );
291
-
292
- return $preday[0];
293
- }
294
- }
295
-
296
- /**
297
- * Function to find the start date of a week in a year
298
- *
299
- * @param integer $week The week number of the year.
300
- * @param integer $year The year of the week we need to calculate on.
301
- *
302
- * @return integer The unix timestamp of the date is returned
303
- */
304
- function get_week_date( $week, $year ) {
305
- // Get the target week of the year with reference to the starting day of the year.
306
- $start_of_week = ( get_option( 'start_of_week' ) === '1' || get_option( 'start_of_week' ) === '0' ) ? get_option( 'start_of_week' ) : 0;
307
- $target_week = strtotime( "$week week", strtotime( "1 January $year" ) );
308
- $date_info = getdate( $target_week );
309
- $day_of_week = $date_info['wday'];
310
- // normal start day of the week is Monday.
311
- $adjusted_date = $day_of_week - $start_of_week;
312
- // Get the timestamp of that day.
313
- $first_day = strtotime( "-$adjusted_date day", $target_week );
314
-
315
- return $first_day;
316
- }
317
-
318
- /**
319
- * Add days to a given date
320
- *
321
- * @param string $givendate original date.
322
- * @param int $day days to add.
323
- *
324
- * @return new date
325
- */
326
- function add_days_to_date( $givendate, $day = 0 ) {
327
- $cd = strtotime( $givendate );
328
- $time = mktime( date( 'h', $cd ), date( 'i', $cd ), date( 's', $cd ), date( 'm', $cd ), date( 'd', $cd ) + $day, date( 'Y', $cd ) );
329
- $newdate = date( 'Y-m-d h:i:s', $time );
330
-
331
- return $newdate;
332
- }
32
  define( 'MY_CALENDAR_GLOBAL_LOCATIONS_TABLE', $wpdb->base_prefix . 'my_calendar_locations' );
33
  }
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  /**
36
  * Old support box function
37
  *
39
  * @deprecated
40
  */
41
  function jd_show_support_box() {
42
+ $purchase_url = 'https://www.joedolson.com/awesome/my-calendar-pro/';
43
+ $check_url = 'https://www.joedolson.com/login/';
44
+ $add = array(
45
+ // Translators: Purchase URL, account URL.
46
+ 'My Calendar Pro out of date!' => '<p>' . __( 'The version of My Calendar Pro (or My Calendar Submissions) you have installed is very out of date!', 'my-calendar' ) . '</p><p>' . __( 'The latest version of My Calendar Pro is the only version recommended for compatibility with My Calendar. Please <a href="%1$s">purchase an upgrade</a> or <a href="%2$s">login to check your license status</a>!', 'my-calendar' ) . '</p>',
47
+ );
48
+ mc_show_sidebar( '', $add, true );
 
 
 
 
 
 
 
49
  }
50
 
51
  /**
54
  * @param string $recur Recurrence string (single character).
55
  * @param int $repeats Number of occurrences to repeat.
56
  *
57
+ * @deprecated 2.5.16. Last used 2.4.21.
58
  *
59
  * @return string label
60
  */
102
  if ( '1' === $_SERVER['HTTPS'] ) {
103
  return true;
104
  }
105
+ } elseif ( isset( $_SERVER['SERVER_PORT'] ) && ( '443' === (string) $_SERVER['SERVER_PORT'] ) ) {
106
  return true;
107
  }
108
 
125
 
126
  return mc_draw_template( $array, $template, $type );
127
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/general-utilities.php CHANGED
@@ -20,12 +20,12 @@ if ( ! defined( 'ABSPATH' ) ) {
20
  */
21
  function mc_switch_sites() {
22
  if ( function_exists( 'is_multisite' ) && is_multisite() ) {
23
- if ( get_site_option( 'mc_multisite' ) == 2 && my_calendar_table() != my_calendar_table( 'global' ) ) {
24
- if ( get_option( 'mc_current_table' ) == '1' ) {
25
  // can post to either, but is currently set to post to central table.
26
  return true;
27
  }
28
- } elseif ( get_site_option( 'mc_multisite' ) == 1 && my_calendar_table() != my_calendar_table( 'global' ) ) {
29
  // can only post to central table.
30
  return true;
31
  }
@@ -41,8 +41,8 @@ function mc_switch_sites() {
41
  * @param string $new New status.
42
  */
43
  function mc_tweet_approval( $prev, $new ) {
44
- if ( function_exists( 'wpt_post_to_twitter' ) && isset( $_POST['mc_twitter'] ) && trim( $_POST['mc_twitter'] ) != '' ) {
45
- if ( ( 0 == $prev || 2 == $prev ) && 1 == $new ) {
46
  wpt_post_to_twitter( stripslashes( $_POST['mc_twitter'] ) );
47
  }
48
  }
@@ -87,11 +87,11 @@ function mc_add_inner_box() {
87
  $url = admin_url( 'admin.php?page=my-calendar&mode=edit&event_id=' . $event_id );
88
  $event = mc_get_first_event( $event_id );
89
  $content = '<p><strong>' . strip_tags( $event->event_title, mc_strip_tags() ) . '</strong><br />' . $event->event_begin . ' @ ' . $event->event_time . '</p>';
90
- if ( $event->event_recur != 'S' ) {
91
  $recur = mc_event_recur_string( $event, $event->event_begin );
92
  $content .= wpautop( $recur );
93
  }
94
- if ( '' != $event->event_label ) {
95
  // Translators: Name of event location.
96
  $content .= '<p>' . sprintf( __( '<strong>Location:</strong> %s', 'my-calendar' ), strip_tags( $event->event_label, mc_strip_tags() ) ) . '</p>';
97
  }
@@ -119,7 +119,7 @@ function mc_strip_tags() {
119
  */
120
  function mc_admin_strip_tags() {
121
 
122
- return '<strong><em><i><b><span><a><code><pre>';
123
  }
124
 
125
  /**
@@ -134,7 +134,7 @@ function mc_admin_strip_tags() {
134
  */
135
  function mc_is_checked( $field, $value, $array = '', $return = false ) {
136
  if ( ! is_array( get_option( $field ) ) ) {
137
- if ( get_option( $field ) == $value ) {
138
  if ( $return ) {
139
  return 'checked="checked"';
140
  } else {
@@ -143,7 +143,7 @@ function mc_is_checked( $field, $value, $array = '', $return = false ) {
143
  }
144
  } else {
145
  $setting = get_option( $field );
146
- if ( ! empty( $setting[ $array ]['enabled'] ) && $setting[ $array ]['enabled'] == $value ) {
147
  if ( $return ) {
148
  return 'checked="checked"';
149
  } else {
@@ -164,12 +164,12 @@ function mc_is_checked( $field, $value, $array = '', $return = false ) {
164
  */
165
  function mc_is_selected( $field, $value, $array = '' ) {
166
  if ( ! is_array( get_option( $field ) ) ) {
167
- if ( get_option( $field ) == $value ) {
168
  return 'selected="selected"';
169
  }
170
  } else {
171
  $setting = get_option( $field );
172
- if ( $setting[ $array ]['enabled'] == $value ) {
173
  return 'selected="selected"';
174
  }
175
  }
@@ -199,7 +199,7 @@ function mc_option_selected( $field, $value, $type = 'checkbox' ) {
199
  $result = '';
200
  break;
201
  }
202
- if ( $field == $value ) {
203
  $output = $result;
204
  } else {
205
  $output = '';
@@ -231,7 +231,7 @@ if ( ! function_exists( 'exif_imagetype' ) ) {
231
  * @return string type of file.
232
  */
233
  function exif_imagetype( $filename ) {
234
- if ( ! is_dir( $filename ) && ( list( $width, $height, $type, $attr ) = getimagesize( $filename ) ) !== false ) {
235
  return $type;
236
  }
237
 
@@ -248,7 +248,7 @@ if ( ! function_exists( 'exif_imagetype' ) ) {
248
  */
249
  function mc_inverse_color( $color ) {
250
  $color = str_replace( '#', '', $color );
251
- if ( strlen( $color ) != 6 ) {
252
  return '#000000';
253
  }
254
  $rgb = '';
@@ -274,7 +274,7 @@ function mc_inverse_color( $color ) {
274
  function mc_shift_color( $color ) {
275
  $color = str_replace( '#', '', $color );
276
  $rgb = '';
277
- $percent = ( mc_inverse_color( $color ) == '#ffffff' ) ? - 20 : 20;
278
  $per = $percent / 100 * 255;
279
  // Percentage to work with. Change middle figure to control color temperature.
280
  if ( $per < 0 ) {
20
  */
21
  function mc_switch_sites() {
22
  if ( function_exists( 'is_multisite' ) && is_multisite() ) {
23
+ if ( get_site_option( 'mc_multisite' ) === '2' && my_calendar_table() !== my_calendar_table( 'global' ) ) {
24
+ if ( get_option( 'mc_current_table' ) === '1' ) {
25
  // can post to either, but is currently set to post to central table.
26
  return true;
27
  }
28
+ } elseif ( get_site_option( 'mc_multisite' ) === '1' && my_calendar_table() !== my_calendar_table( 'global' ) ) {
29
  // can only post to central table.
30
  return true;
31
  }
41
  * @param string $new New status.
42
  */
43
  function mc_tweet_approval( $prev, $new ) {
44
+ if ( function_exists( 'wpt_post_to_twitter' ) && isset( $_POST['mc_twitter'] ) && trim( $_POST['mc_twitter'] ) !== '' ) {
45
+ if ( ( 0 === (int) $prev || 2 === (int) $prev ) && 1 === (int) $new ) {
46
  wpt_post_to_twitter( stripslashes( $_POST['mc_twitter'] ) );
47
  }
48
  }
87
  $url = admin_url( 'admin.php?page=my-calendar&mode=edit&event_id=' . $event_id );
88
  $event = mc_get_first_event( $event_id );
89
  $content = '<p><strong>' . strip_tags( $event->event_title, mc_strip_tags() ) . '</strong><br />' . $event->event_begin . ' @ ' . $event->event_time . '</p>';
90
+ if ( 'S' !== $event->event_recur ) {
91
  $recur = mc_event_recur_string( $event, $event->event_begin );
92
  $content .= wpautop( $recur );
93
  }
94
+ if ( '' !== $event->event_label ) {
95
  // Translators: Name of event location.
96
  $content .= '<p>' . sprintf( __( '<strong>Location:</strong> %s', 'my-calendar' ), strip_tags( $event->event_label, mc_strip_tags() ) ) . '</p>';
97
  }
119
  */
120
  function mc_admin_strip_tags() {
121
 
122
+ return '<strong><em><i><b><span><a><code><pre><br>';
123
  }
124
 
125
  /**
134
  */
135
  function mc_is_checked( $field, $value, $array = '', $return = false ) {
136
  if ( ! is_array( get_option( $field ) ) ) {
137
+ if ( get_option( $field ) === (string) $value ) {
138
  if ( $return ) {
139
  return 'checked="checked"';
140
  } else {
143
  }
144
  } else {
145
  $setting = get_option( $field );
146
+ if ( ! empty( $setting[ $array ]['enabled'] ) && (string) $setting[ $array ]['enabled'] === (string) $value ) {
147
  if ( $return ) {
148
  return 'checked="checked"';
149
  } else {
164
  */
165
  function mc_is_selected( $field, $value, $array = '' ) {
166
  if ( ! is_array( get_option( $field ) ) ) {
167
+ if ( get_option( $field ) === (string) $value ) {
168
  return 'selected="selected"';
169
  }
170
  } else {
171
  $setting = get_option( $field );
172
+ if ( (string) $setting[ $array ]['enabled'] === (string) $value ) {
173
  return 'selected="selected"';
174
  }
175
  }
199
  $result = '';
200
  break;
201
  }
202
+ if ( $field === $value ) {
203
  $output = $result;
204
  } else {
205
  $output = '';
231
  * @return string type of file.
232
  */
233
  function exif_imagetype( $filename ) {
234
+ if ( ! is_dir( $filename ) && ( list( $width, $height, $type, $attr ) = getimagesize( $filename ) ) !== false ) { // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.NonVariableAssignmentFound
235
  return $type;
236
  }
237
 
248
  */
249
  function mc_inverse_color( $color ) {
250
  $color = str_replace( '#', '', $color );
251
+ if ( strlen( $color ) !== 6 ) {
252
  return '#000000';
253
  }
254
  $rgb = '';
274
  function mc_shift_color( $color ) {
275
  $color = str_replace( '#', '', $color );
276
  $rgb = '';
277
+ $percent = ( mc_inverse_color( $color ) === '#ffffff' ) ? - 20 : 20;
278
  $per = $percent / 100 * 255;
279
  // Percentage to work with. Change middle figure to control color temperature.
280
  if ( $per < 0 ) {
includes/screen-options.php CHANGED
@@ -43,7 +43,22 @@ function mc_show_event_editing( $status, $args ) {
43
  if ( ! is_array( $input_options ) ) {
44
  $input_options = $settings_options;
45
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
 
47
  // cannot change these keys.
48
  $input_labels = array(
49
  'event_location_dropdown' => __( 'Event Location Dropdown Menu', 'my-calendar' ),
43
  if ( ! is_array( $input_options ) ) {
44
  $input_options = $settings_options;
45
  }
46
+ $defaults = array(
47
+ 'event_location_dropdown' => 'on',
48
+ 'event_short' => 'on',
49
+ 'event_desc' => 'on',
50
+ 'event_category' => 'on',
51
+ 'event_image' => 'on',
52
+ 'event_link' => 'on',
53
+ 'event_recurs' => 'on',
54
+ 'event_open' => 'on',
55
+ 'event_location' => 'off',
56
+ 'event_specials' => 'on',
57
+ 'event_access' => 'on',
58
+ 'event_host' => 'on',
59
+ );
60
 
61
+ $input_options = array_merge( $defaults, $input_options );
62
  // cannot change these keys.
63
  $input_labels = array(
64
  'event_location_dropdown' => __( 'Event Location Dropdown Menu', 'my-calendar' ),
includes/widgets/class-my-calendar-filters.php CHANGED
@@ -52,14 +52,14 @@ class My_Calendar_Filters extends WP_Widget {
52
  $after_title = $args['after_title'];
53
 
54
  $widget_title = apply_filters( 'widget_title', $instance['title'], $instance, $args );
55
- $widget_title = ( '' != $widget_title ) ? $before_title . $widget_title . $after_title : '';
56
  $widget_url = ( isset( $instance['url'] ) ) ? $instance['url'] : mc_get_uri();
57
  $ltype = ( isset( $instance['ltype'] ) ) ? $instance['ltype'] : false;
58
  $show = ( isset( $instance['show'] ) ) ? $instance['show'] : array();
59
  $show = implode( $show, ',' );
60
 
61
  echo $before_widget;
62
- echo ( '' != $instance['title'] ) ? $widget_title : '';
63
 
64
  echo mc_filters( $show, $widget_url, $ltype );
65
  echo $after_widget;
@@ -86,15 +86,15 @@ class My_Calendar_Filters extends WP_Widget {
86
  <input class="widefat" type="text" id="<?php echo $this->get_field_id( 'url' ); ?>" name="<?php echo $this->get_field_name( 'url' ); ?>" value="<?php echo esc_url( $widget_url ); ?>"/>
87
  </p>
88
  <ul>
89
- <?php $locations = in_array( 'locations', $show ) ? 'checked="checked"' : ''; ?>
90
  <li>
91
  <input type="checkbox" id="<?php echo $this->get_field_id( 'show' ); ?>_locations" name="<?php echo $this->get_field_name( 'show' ); ?>[]" value="locations" <?php echo $locations; ?> /> <label for="<?php echo $this->get_field_id( 'show' ); ?>_locations"><?php _e( 'Locations', 'my-calendar' ); ?></label>
92
  </li>
93
- <?php $categories = in_array( 'categories', $show ) ? 'checked="checked"' : ''; ?>
94
  <li>
95
  <input type="checkbox" id="<?php echo $this->get_field_id( 'show' ); ?>_categories" name="<?php echo $this->get_field_name( 'show' ); ?>[]" value="categories" <?php echo $categories; ?> /> <label for="<?php echo $this->get_field_id( 'show' ); ?>_categories"><?php _e( 'Categories', 'my-calendar' ); ?></label>
96
  </li>
97
- <?php $access = in_array( 'access', $show ) ? 'checked="checked"' : ''; ?>
98
  <li>
99
  <input type="checkbox" id="<?php echo $this->get_field_id( 'show' ); ?>_access" name="<?php echo $this->get_field_name( 'show' ); ?>[]" value="access" <?php echo $access; ?> /> <label for="<?php echo $this->get_field_id( 'show' ); ?>_access"><?php _e( 'Accessibility Features', 'my-calendar' ); ?></label>
100
  </li>
52
  $after_title = $args['after_title'];
53
 
54
  $widget_title = apply_filters( 'widget_title', $instance['title'], $instance, $args );
55
+ $widget_title = ( '' !== $widget_title ) ? $before_title . $widget_title . $after_title : '';
56
  $widget_url = ( isset( $instance['url'] ) ) ? $instance['url'] : mc_get_uri();
57
  $ltype = ( isset( $instance['ltype'] ) ) ? $instance['ltype'] : false;
58
  $show = ( isset( $instance['show'] ) ) ? $instance['show'] : array();
59
  $show = implode( $show, ',' );
60
 
61
  echo $before_widget;
62
+ echo ( '' !== $instance['title'] ) ? $widget_title : '';
63
 
64
  echo mc_filters( $show, $widget_url, $ltype );
65
  echo $after_widget;
86
  <input class="widefat" type="text" id="<?php echo $this->get_field_id( 'url' ); ?>" name="<?php echo $this->get_field_name( 'url' ); ?>" value="<?php echo esc_url( $widget_url ); ?>"/>
87
  </p>
88
  <ul>
89
+ <?php $locations = in_array( 'locations', $show, true ) ? 'checked="checked"' : ''; ?>
90
  <li>
91
  <input type="checkbox" id="<?php echo $this->get_field_id( 'show' ); ?>_locations" name="<?php echo $this->get_field_name( 'show' ); ?>[]" value="locations" <?php echo $locations; ?> /> <label for="<?php echo $this->get_field_id( 'show' ); ?>_locations"><?php _e( 'Locations', 'my-calendar' ); ?></label>
92
  </li>
93
+ <?php $categories = in_array( 'categories', $show, true ) ? 'checked="checked"' : ''; ?>
94
  <li>
95
  <input type="checkbox" id="<?php echo $this->get_field_id( 'show' ); ?>_categories" name="<?php echo $this->get_field_name( 'show' ); ?>[]" value="categories" <?php echo $categories; ?> /> <label for="<?php echo $this->get_field_id( 'show' ); ?>_categories"><?php _e( 'Categories', 'my-calendar' ); ?></label>
96
  </li>
97
+ <?php $access = in_array( 'access', $show, true ) ? 'checked="checked"' : ''; ?>
98
  <li>
99
  <input type="checkbox" id="<?php echo $this->get_field_id( 'show' ); ?>_access" name="<?php echo $this->get_field_name( 'show' ); ?>[]" value="access" <?php echo $access; ?> /> <label for="<?php echo $this->get_field_id( 'show' ); ?>_access"><?php _e( 'Accessibility Features', 'my-calendar' ); ?></label>
100
  </li>
includes/widgets/class-my-calendar-mini-widget.php CHANGED
@@ -53,17 +53,17 @@ class My_Calendar_Mini_Widget extends WP_Widget {
53
 
54
  if ( ! empty( $instance ) ) {
55
  $the_title = apply_filters( 'widget_title', $instance['my_calendar_mini_title'], $instance, $args );
56
- $category = ( '' == $instance['my_calendar_mini_category'] ) ? 'all' : $instance['my_calendar_mini_category'];
57
- $time = ( '' == $instance['my_calendar_mini_time'] ) ? 'month' : $instance['my_calendar_mini_time'];
58
- $widget_link = ( ! isset( $instance['mc_link'] ) || '' == $instance['mc_link'] ) ? '' : esc_url( $instance['mc_link'] );
59
  $above = ( empty( $instance['above'] ) ) ? 'none' : $instance['above'];
60
  $below = ( empty( $instance['below'] ) ) ? 'none' : $instance['below'];
61
- $author = ( ! isset( $instance['author'] ) || '' == $instance['author'] ) ? null : $instance['author'];
62
- $host = ( ! isset( $instance['host'] ) || '' == $instance['host'] ) ? null : $instance['host'];
63
- $ltype = ( ! isset( $instance['ltype'] ) || '' == $instance['ltype'] ) ? '' : $instance['ltype'];
64
- $lvalue = ( ! isset( $instance['lvalue'] ) || '' == $instance['lvalue'] ) ? '' : $instance['lvalue'];
65
- $site = ( ! isset( $instance['site'] ) || '' == $instance['site'] ) ? false : $instance['site'];
66
- $months = ( ! isset( $instance['months'] ) || '' == $instance['months'] ) ? false : $instance['months'];
67
  } else {
68
  $the_title = '';
69
  $category = '';
@@ -79,9 +79,9 @@ class My_Calendar_Mini_Widget extends WP_Widget {
79
  $months = '';
80
  }
81
 
82
- if ( '' != $the_title ) {
83
- $title = ( '' != $widget_link ) ? "<a href='$widget_link'>$the_title</a>" : $the_title;
84
- $title = ( '' != $title ) ? $before_title . $title . $after_title : '';
85
  } else {
86
  $title = '';
87
  }
@@ -104,7 +104,7 @@ class My_Calendar_Mini_Widget extends WP_Widget {
104
  );
105
 
106
  $the_events = my_calendar( $calendar );
107
- if ( '' != $the_events ) {
108
  echo $before_widget . $title . $the_events . $after_widget;
109
  }
110
  }
@@ -152,11 +152,11 @@ class My_Calendar_Mini_Widget extends WP_Widget {
152
  </p>
153
  <p>
154
  <label for="<?php echo $this->get_field_id( 'above' ); ?>"><?php _e( 'Navigation above calendar', 'my-calendar' ); ?></label>
155
- <input type="text" class="widefat" name="<?php echo $this->get_field_name( 'above' ); ?>" id="<?php echo $this->get_field_id( 'above' ); ?>" value="<?php echo ( '' == $above ) ? 'nav,jump,print' : esc_attr( $above ); ?>" aria-describedby='<?php echo $this->get_field_id( 'below' ); ?>-navigation-fields' />
156
  </p>
157
  <p>
158
  <label for="<?php echo $this->get_field_id( 'below' ); ?>"><?php _e( 'Navigation below calendar', 'my-calendar' ); ?></label>
159
- <input type="text" class="widefat" name="<?php echo $this->get_field_name( 'below' ); ?>" id="<?php echo $this->get_field_id( 'below' ); ?>" value="<?php echo ( '' == $below ) ? 'key' : esc_attr( $below ); ?>" aria-describedby='<?php echo $this->get_field_id( 'below' ); ?>-navigation-fields' />
160
  </p>
161
  <p id='<?php echo $this->get_field_id( 'below' ); ?>-navigation-fields'>
162
  <?php _e( 'Navigation options:', 'my-calendar' ); ?> <code>nav,jump,print,key,feeds,exports,none</code>
@@ -208,7 +208,7 @@ class My_Calendar_Mini_Widget extends WP_Widget {
208
  <p>
209
  <label
210
  for="<?php echo $this->get_field_id( 'months' ); ?>"><?php _e( 'Months to show in list view', 'my-calendar' ); ?></label>
211
- <input type="number" max="12" step="1" min="1" class="widefat" name="<?php echo $this->get_field_name( 'months' ); ?>" id="<?php echo $this->get_field_id( 'months' ); ?>" value="<?php echo ( '' == $months ) ? '' : esc_attr( $months ); ?>" />
212
  </p>
213
  <?php
214
  }
@@ -225,9 +225,9 @@ class My_Calendar_Mini_Widget extends WP_Widget {
225
  $instance['my_calendar_mini_title'] = mc_kses_post( $new['my_calendar_mini_title'] );
226
  $instance['my_calendar_mini_time'] = mc_kses_post( $new['my_calendar_mini_time'] );
227
  $instance['my_calendar_mini_category'] = mc_kses_post( $new['my_calendar_mini_category'] );
228
- $instance['above'] = ( isset( $new['above'] ) && '' != $new['above'] ) ? $new['above'] : 'none';
229
  $instance['mc_link'] = $new['mc_link'];
230
- $instance['below'] = ( isset( $new['below'] ) && '' != $new['below'] ) ? $new['below'] : 'none';
231
  $author = '';
232
  $host = '';
233
  if ( isset( $new['author'] ) ) {
@@ -238,9 +238,11 @@ class My_Calendar_Mini_Widget extends WP_Widget {
238
  }
239
  $instance['author'] = $author;
240
  $instance['host'] = $host;
241
- $instance['ltype'] = ( '' != $new['ltype'] && '' != $new['lvalue'] ) ? $new['ltype'] : '';
242
- $instance['lvalue'] = ( '' != $new['ltype'] && '' != $new['lvalue'] ) ? $new['lvalue'] : '';
243
- $instance['site'] = $new['site'];
 
 
244
  $instance['months'] = $new['months'];
245
 
246
  return $instance;
53
 
54
  if ( ! empty( $instance ) ) {
55
  $the_title = apply_filters( 'widget_title', $instance['my_calendar_mini_title'], $instance, $args );
56
+ $category = ( '' === $instance['my_calendar_mini_category'] ) ? 'all' : $instance['my_calendar_mini_category'];
57
+ $time = ( '' === $instance['my_calendar_mini_time'] ) ? 'month' : $instance['my_calendar_mini_time'];
58
+ $widget_link = ( ! isset( $instance['mc_link'] ) || '' === $instance['mc_link'] ) ? '' : esc_url( $instance['mc_link'] );
59
  $above = ( empty( $instance['above'] ) ) ? 'none' : $instance['above'];
60
  $below = ( empty( $instance['below'] ) ) ? 'none' : $instance['below'];
61
+ $author = ( ! isset( $instance['author'] ) || '' === $instance['author'] ) ? null : $instance['author'];
62
+ $host = ( ! isset( $instance['host'] ) || '' === $instance['host'] ) ? null : $instance['host'];
63
+ $ltype = ( ! isset( $instance['ltype'] ) || '' === $instance['ltype'] ) ? '' : $instance['ltype'];
64
+ $lvalue = ( ! isset( $instance['lvalue'] ) || '' === $instance['lvalue'] ) ? '' : $instance['lvalue'];
65
+ $site = ( ! isset( $instance['site'] ) || '' === $instance['site'] ) ? false : $instance['site'];
66
+ $months = ( ! isset( $instance['months'] ) || '' === $instance['months'] ) ? false : $instance['months'];
67
  } else {
68
  $the_title = '';
69
  $category = '';
79
  $months = '';
80
  }
81
 
82
+ if ( '' !== $the_title ) {
83
+ $title = ( '' !== $widget_link ) ? "<a href='$widget_link'>$the_title</a>" : $the_title;
84
+ $title = ( '' !== $title ) ? $before_title . $title . $after_title : '';
85
  } else {
86
  $title = '';
87
  }
104
  );
105
 
106
  $the_events = my_calendar( $calendar );
107
+ if ( '' !== $the_events ) {
108
  echo $before_widget . $title . $the_events . $after_widget;
109
  }
110
  }
152
  </p>
153
  <p>
154
  <label for="<?php echo $this->get_field_id( 'above' ); ?>"><?php _e( 'Navigation above calendar', 'my-calendar' ); ?></label>
155
+ <input type="text" class="widefat" name="<?php echo $this->get_field_name( 'above' ); ?>" id="<?php echo $this->get_field_id( 'above' ); ?>" value="<?php echo ( '' === $above ) ? 'nav,jump,print' : esc_attr( $above ); ?>" aria-describedby='<?php echo $this->get_field_id( 'below' ); ?>-navigation-fields' />
156
  </p>
157
  <p>
158
  <label for="<?php echo $this->get_field_id( 'below' ); ?>"><?php _e( 'Navigation below calendar', 'my-calendar' ); ?></label>
159
+ <input type="text" class="widefat" name="<?php echo $this->get_field_name( 'below' ); ?>" id="<?php echo $this->get_field_id( 'below' ); ?>" value="<?php echo ( '' === $below ) ? 'key' : esc_attr( $below ); ?>" aria-describedby='<?php echo $this->get_field_id( 'below' ); ?>-navigation-fields' />
160
  </p>
161
  <p id='<?php echo $this->get_field_id( 'below' ); ?>-navigation-fields'>
162
  <?php _e( 'Navigation options:', 'my-calendar' ); ?> <code>nav,jump,print,key,feeds,exports,none</code>
208
  <p>
209
  <label
210
  for="<?php echo $this->get_field_id( 'months' ); ?>"><?php _e( 'Months to show in list view', 'my-calendar' ); ?></label>
211
+ <input type="number" max="12" step="1" min="1" class="widefat" name="<?php echo $this->get_field_name( 'months' ); ?>" id="<?php echo $this->get_field_id( 'months' ); ?>" value="<?php echo ( '' === $months ) ? '' : esc_attr( $months ); ?>" />
212
  </p>
213
  <?php
214
  }
225
  $instance['my_calendar_mini_title'] = mc_kses_post( $new['my_calendar_mini_title'] );
226
  $instance['my_calendar_mini_time'] = mc_kses_post( $new['my_calendar_mini_time'] );
227
  $instance['my_calendar_mini_category'] = mc_kses_post( $new['my_calendar_mini_category'] );
228
+ $instance['above'] = ( isset( $new['above'] ) && '' !== $new['above'] ) ? $new['above'] : 'none';
229
  $instance['mc_link'] = $new['mc_link'];
230
+ $instance['below'] = ( isset( $new['below'] ) && '' !== $new['below'] ) ? $new['below'] : 'none';
231
  $author = '';
232
  $host = '';
233
  if ( isset( $new['author'] ) ) {
238
  }
239
  $instance['author'] = $author;
240
  $instance['host'] = $host;
241
+ $instance['ltype'] = ( '' !== $new['ltype'] && '' !== $new['lvalue'] ) ? $new['ltype'] : '';
242
+ $instance['lvalue'] = ( '' !== $new['ltype'] && '' !== $new['lvalue'] ) ? $new['lvalue'] : '';
243
+ if ( function_exists( 'is_multisite' ) && is_multisite() ) {
244
+ $instance['site'] = $new['site'];
245
+ }
246
  $instance['months'] = $new['months'];
247
 
248
  return $instance;
includes/widgets/class-my-calendar-simple-search.php CHANGED
@@ -52,10 +52,10 @@ class My_Calendar_Simple_Search extends WP_Widget {
52
  $after_title = $args['after_title'];
53
 
54
  $widget_title = apply_filters( 'widget_title', $instance['title'], $instance, $args );
55
- $widget_title = ( '' != $widget_title ) ? $before_title . $widget_title . $after_title : '';
56
  $widget_url = ( isset( $instance['url'] ) ) ? $instance['url'] : false;
57
  echo $before_widget;
58
- echo ( '' != $instance['title'] ) ? $widget_title : '';
59
 
60
  echo my_calendar_searchform( 'simple', $widget_url );
61
  echo $after_widget;
52
  $after_title = $args['after_title'];
53
 
54
  $widget_title = apply_filters( 'widget_title', $instance['title'], $instance, $args );
55
+ $widget_title = ( '' !== $widget_title ) ? $before_title . $widget_title . $after_title : '';
56
  $widget_url = ( isset( $instance['url'] ) ) ? $instance['url'] : false;
57
  echo $before_widget;
58
+ echo ( '' !== $instance['title'] ) ? $widget_title : '';
59
 
60
  echo my_calendar_searchform( 'simple', $widget_url );
61
  echo $after_widget;
includes/widgets/class-my-calendar-today-widget.php CHANGED
@@ -58,9 +58,9 @@ class My_Calendar_Today_Widget extends WP_Widget {
58
  $the_title = apply_filters( 'widget_title', $today_title, $instance, $args );
59
  $the_template = $template;
60
  $the_substitute = $no_events;
61
- $the_category = ( '' == $category ) ? 'default' : esc_attr( $instance['my_calendar_today_category'] );
62
- $author = ( ! isset( $instance['my_calendar_today_author'] ) || '' == $instance['my_calendar_today_author'] ) ? 'all' : esc_attr( $instance['my_calendar_today_author'] );
63
- $host = ( ! isset( $instance['mc_host'] ) || '' == $instance['mc_host'] ) ? 'all' : esc_attr( $instance['mc_host'] );
64
  $default_link = mc_get_uri( false, $args );
65
  $widget_link = ( ! empty( $instance['my_calendar_today_linked'] ) && 'yes' === $instance['my_calendar_today_linked'] ) ? $default_link : '';
66
  $widget_link = ( ! empty( $instance['mc_link'] ) ) ? esc_url( $instance['mc_link'] ) : $widget_link;
@@ -69,10 +69,10 @@ class My_Calendar_Today_Widget extends WP_Widget {
69
  $site = ( isset( $instance['mc_site'] ) ) ? $instance['mc_site'] : false;
70
 
71
  if ( false !== strpos( $widget_title, '{date}' ) ) {
72
- $widget_title = str_replace( '{date}', date_i18n( mc_date_format(), current_time( 'timestamp' ) ), $widget_title );
73
  }
74
- $widget_title = ( '' == $widget_link ) ? $widget_title : "<a href='$widget_link'>$widget_title</a>";
75
- $widget_title = ( '' != $widget_title ) ? $before_title . $widget_title . $after_title : '';
76
 
77
  $args = array(
78
  'category' => $the_category,
@@ -85,7 +85,7 @@ class My_Calendar_Today_Widget extends WP_Widget {
85
  );
86
 
87
  $the_events = my_calendar_todays_events( $args );
88
- if ( '' != $the_events ) {
89
  echo $before_widget;
90
  echo $widget_title;
91
  echo $the_events;
58
  $the_title = apply_filters( 'widget_title', $today_title, $instance, $args );
59
  $the_template = $template;
60
  $the_substitute = $no_events;
61
+ $the_category = ( '' === $category ) ? 'default' : esc_attr( $instance['my_calendar_today_category'] );
62
+ $author = ( ! isset( $instance['my_calendar_today_author'] ) || '' === $instance['my_calendar_today_author'] ) ? 'all' : esc_attr( $instance['my_calendar_today_author'] );
63
+ $host = ( ! isset( $instance['mc_host'] ) || '' === $instance['mc_host'] ) ? 'all' : esc_attr( $instance['mc_host'] );
64
  $default_link = mc_get_uri( false, $args );
65
  $widget_link = ( ! empty( $instance['my_calendar_today_linked'] ) && 'yes' === $instance['my_calendar_today_linked'] ) ? $default_link : '';
66
  $widget_link = ( ! empty( $instance['mc_link'] ) ) ? esc_url( $instance['mc_link'] ) : $widget_link;
69
  $site = ( isset( $instance['mc_site'] ) ) ? $instance['mc_site'] : false;
70
 
71
  if ( false !== strpos( $widget_title, '{date}' ) ) {
72
+ $widget_title = str_replace( '{date}', date_i18n( mc_date_format() ), $widget_title );
73
  }
74
+ $widget_title = ( '' === $widget_link ) ? $widget_title : "<a href='$widget_link'>$widget_title</a>";
75
+ $widget_title = ( '' !== $widget_title ) ? $before_title . $widget_title . $after_title : '';
76
 
77
  $args = array(
78
  'category' => $the_category,
85
  );
86
 
87
  $the_events = my_calendar_todays_events( $args );
88
+ if ( '' !== $the_events ) {
89
  echo $before_widget;
90
  echo $widget_title;
91
  echo $the_events;
includes/widgets/class-my-calendar-upcoming-widget.php CHANGED
@@ -63,23 +63,23 @@ class My_Calendar_Upcoming_Widget extends WP_Widget {
63
  $the_title = apply_filters( 'widget_title', $title, $instance, $args );
64
  $the_template = ( isset( $instance['my_calendar_upcoming_template'] ) ) ? $instance['my_calendar_upcoming_template'] : '';
65
  $the_substitute = ( isset( $instance['my_calendar_no_events_text'] ) ) ? $instance['my_calendar_no_events_text'] : '';
66
- $before = ( '' != $before ) ? esc_attr( $instance['my_calendar_upcoming_before'] ) : 3;
67
- $after = ( '' != $after ) ? esc_attr( $instance['my_calendar_upcoming_after'] ) : 3;
68
- $skip = ( '' != $skip ) ? esc_attr( $instance['my_calendar_upcoming_skip'] ) : 0;
69
  $show_today = ( 'no' === $show ) ? 'no' : 'yes';
70
  $type = esc_attr( $type );
71
  $order = esc_attr( $order );
72
- $the_category = ( '' == $cat ) ? 'default' : esc_attr( $instance['my_calendar_upcoming_category'] );
73
- $author = ( ! isset( $instance['my_calendar_upcoming_author'] ) || '' == $instance['my_calendar_upcoming_author'] ) ? 'default' : esc_attr( $instance['my_calendar_upcoming_author'] );
74
- $host = ( ! isset( $instance['mc_host'] ) || '' == $instance['mc_host'] ) ? 'default' : esc_attr( $instance['mc_host'] );
75
- $ltype = ( ! isset( $instance['ltype'] ) || '' == $instance['ltype'] ) ? '' : esc_attr( $instance['ltype'] );
76
- $lvalue = ( ! isset( $instance['lvalue'] ) || '' == $instance['lvalue'] ) ? '' : esc_attr( $instance['lvalue'] );
77
  $widget_link = ( isset( $instance['my_calendar_upcoming_linked'] ) && 'yes' === $instance['my_calendar_upcoming_linked'] ) ? mc_get_uri( false, $instance ) : '';
78
  $widget_link = ( ! empty( $instance['mc_link'] ) ) ? esc_url( $instance['mc_link'] ) : $widget_link;
79
  $widget_title = empty( $the_title ) ? '' : $the_title;
80
- $widget_title = ( '' == $widget_link ) ? $widget_title : "<a href='$widget_link'>$widget_title</a>";
81
- $widget_title = ( '' != $widget_title ) ? $before_title . $widget_title . $after_title : '';
82
- $month = ( 0 === strpos( $type, 'month+' ) ) ? date_i18n( 'F', strtotime( $type ) ) : date_i18n( 'F', current_time( 'timestamp' ) );
83
  $widget_title = str_replace( '{month}', $month, $widget_title );
84
  $from = ( isset( $instance['mc_from'] ) ) ? $instance['mc_from'] : false;
85
  $to = ( isset( $instance['mc_to'] ) ) ? $instance['mc_to'] : false;
@@ -105,7 +105,7 @@ class My_Calendar_Upcoming_Widget extends WP_Widget {
105
  );
106
 
107
  $the_events = my_calendar_upcoming_events( $args );
108
- if ( '' != $the_events ) {
109
  echo $before_widget;
110
  echo $widget_title;
111
  echo $the_events;
63
  $the_title = apply_filters( 'widget_title', $title, $instance, $args );
64
  $the_template = ( isset( $instance['my_calendar_upcoming_template'] ) ) ? $instance['my_calendar_upcoming_template'] : '';
65
  $the_substitute = ( isset( $instance['my_calendar_no_events_text'] ) ) ? $instance['my_calendar_no_events_text'] : '';
66
+ $before = ( '' !== $before ) ? esc_attr( $instance['my_calendar_upcoming_before'] ) : 3;
67
+ $after = ( '' !== $after ) ? esc_attr( $instance['my_calendar_upcoming_after'] ) : 3;
68
+ $skip = ( '' !== $skip ) ? esc_attr( $instance['my_calendar_upcoming_skip'] ) : 0;
69
  $show_today = ( 'no' === $show ) ? 'no' : 'yes';
70
  $type = esc_attr( $type );
71
  $order = esc_attr( $order );
72
+ $the_category = ( '' === $cat ) ? 'default' : esc_attr( $instance['my_calendar_upcoming_category'] );
73
+ $author = ( ! isset( $instance['my_calendar_upcoming_author'] ) || '' === $instance['my_calendar_upcoming_author'] ) ? 'default' : esc_attr( $instance['my_calendar_upcoming_author'] );
74
+ $host = ( ! isset( $instance['mc_host'] ) || '' === $instance['mc_host'] ) ? 'default' : esc_attr( $instance['mc_host'] );
75
+ $ltype = ( ! isset( $instance['ltype'] ) || '' === $instance['ltype'] ) ? '' : esc_attr( $instance['ltype'] );
76
+ $lvalue = ( ! isset( $instance['lvalue'] ) || '' === $instance['lvalue'] ) ? '' : esc_attr( $instance['lvalue'] );
77
  $widget_link = ( isset( $instance['my_calendar_upcoming_linked'] ) && 'yes' === $instance['my_calendar_upcoming_linked'] ) ? mc_get_uri( false, $instance ) : '';
78
  $widget_link = ( ! empty( $instance['mc_link'] ) ) ? esc_url( $instance['mc_link'] ) : $widget_link;
79
  $widget_title = empty( $the_title ) ? '' : $the_title;
80
+ $widget_title = ( '' === $widget_link ) ? $widget_title : "<a href='$widget_link'>$widget_title</a>";
81
+ $widget_title = ( '' !== $widget_title ) ? $before_title . $widget_title . $after_title : '';
82
+ $month = ( 0 === strpos( $type, 'month+' ) ) ? date_i18n( 'F', strtotime( $type ) ) : date_i18n( 'F' );
83
  $widget_title = str_replace( '{month}', $month, $widget_title );
84
  $from = ( isset( $instance['mc_from'] ) ) ? $instance['mc_from'] : false;
85
  $to = ( isset( $instance['mc_to'] ) ) ? $instance['mc_to'] : false;
105
  );
106
 
107
  $the_events = my_calendar_upcoming_events( $args );
108
+ if ( '' !== $the_events ) {
109
  echo $before_widget;
110
  echo $widget_title;
111
  echo $the_events;
js/mc-ajax.js CHANGED
@@ -1,6 +1,7 @@
1
  (function ($) {
2
  'use strict';
3
  $(function () {
 
4
  $(document).on('click', ".my-calendar-header a.mcajax, .my-calendar-footer a.mcajax", function (e) {
5
  e.preventDefault();
6
  var calendar = $( this ).closest( '.mc-main' );
@@ -29,8 +30,20 @@
29
  }
30
  // All views.
31
  $( '#' + ref ).attr('tabindex', '-1').focus();
 
32
  // Your Custom ajax load changes if needed.
33
  });
34
  });
35
  });
 
 
 
 
 
 
 
 
 
 
 
36
  }(jQuery));
1
  (function ($) {
2
  'use strict';
3
  $(function () {
4
+ mc_display_usertime();
5
  $(document).on('click', ".my-calendar-header a.mcajax, .my-calendar-footer a.mcajax", function (e) {
6
  e.preventDefault();
7
  var calendar = $( this ).closest( '.mc-main' );
30
  }
31
  // All views.
32
  $( '#' + ref ).attr('tabindex', '-1').focus();
33
+ mc_display_usertime();
34
  // Your Custom ajax load changes if needed.
35
  });
36
  });
37
  });
38
+
39
+ function mc_display_usertime() {
40
+ var utime = $( '.mc-user-time' );
41
+ utime.each(function() {
42
+ var time = $( this ).text();
43
+ var label = $( this ).attr( 'data-label' );
44
+ var utime = '<span class="mc-local-time-time">' + new Date( time ).toLocaleTimeString().replace( ':00 ', ' ' ) + '</span>';
45
+ var udate = '<span class="mc-local-time-date">' + new Date( time ).toLocaleDateString() + '</span>';
46
+ $( this ).html( '<span class="mc-local-time-label">' + label + '</span>' + ' ' + udate + '<span class="sep">, </span>' + utime ).attr( 'data-time', time );
47
+ });
48
+ }
49
  }(jQuery));
js/mc-grid.js CHANGED
@@ -1,7 +1,7 @@
1
  (function ($) {
2
  'use strict';
3
  $(function () {
4
- $('.calendar-event').children().not('.event-title').hide();
5
 
6
  $(document).on('click', '.calendar-event .event-title a',
7
  function (e) {
@@ -17,7 +17,7 @@
17
  var firstFocus = focusable.first();
18
  lastFocus.attr( 'data-action', 'shiftback' );
19
 
20
- $('.calendar-event').children().not('.event-title').not( current_date ).hide();
21
  });
22
 
23
  $(document).on('click', '.calendar-event .close',
1
  (function ($) {
2
  'use strict';
3
  $(function () {
4
+ $('.calendar-event').children().not('.event-title,.screen-reader-text').hide();
5
 
6
  $(document).on('click', '.calendar-event .event-title a',
7
  function (e) {
17
  var firstFocus = focusable.first();
18
  lastFocus.attr( 'data-action', 'shiftback' );
19
 
20
+ $('.calendar-event').children().not('.event-title,.screen-reader-text').not( current_date ).hide();
21
  });
22
 
23
  $(document).on('click', '.calendar-event .close',
js/mc-mini.js CHANGED
@@ -10,7 +10,7 @@
10
  $( '.mini .has-events' ).children().not( '.trigger, .mc-date, .event-date' ).not( current_date ).hide();
11
  $( this ).addClass( 'active-toggle' );
12
  } );
13
- $( document ).on( "click", ".mini-event .close", function (e) {
14
  e.preventDefault();
15
  $(this).closest( '.mini .has-events' ).children( '.trigger' ).removeClass( 'active-toggle' );
16
  $(this).closest( 'div.calendar-events' ).toggle();
10
  $( '.mini .has-events' ).children().not( '.trigger, .mc-date, .event-date' ).not( current_date ).hide();
11
  $( this ).addClass( 'active-toggle' );
12
  } );
13
+ $( document ).on( "click", ".calendar-events .close", function (e) {
14
  e.preventDefault();
15
  $(this).closest( '.mini .has-events' ).children( '.trigger' ).removeClass( 'active-toggle' );
16
  $(this).closest( 'div.calendar-events' ).toggle();
js/pickadate/legacy.js CHANGED
@@ -1,40 +1,133 @@
 
 
 
 
 
 
 
 
 
 
1
  /*!
2
  * Legacy browser support
3
  */
4
- [].map || (Array.prototype.map = function (a, b) {
5
- for (var c = this, d = c.length, e = new Array(d), f = 0; d > f; f++)f in c && (e[f] = a.call(b, c[f], f, c));
6
- return e
7
- }), [].filter || (Array.prototype.filter = function (a) {
8
- if (null == this)throw new TypeError;
9
- var b = Object(this), c = b.length >>> 0;
10
- if ("function" != typeof a)throw new TypeError;
11
- for (var d = [], e = arguments[1], f = 0; c > f; f++)if (f in b) {
12
- var g = b[f];
13
- a.call(e, g, f, b) && d.push(g)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  }
15
- return d
16
- }), [].indexOf || (Array.prototype.indexOf = function (a) {
17
- if (null == this)throw new TypeError;
18
- var b = Object(this), c = b.length >>> 0;
19
- if (0 === c)return -1;
20
- var d = 0;
21
- if (arguments.length > 1 && (d = Number(arguments[1]), d != d ? d = 0 : 0 !== d && 1 / 0 != d && d != -1 / 0 && (d = (d > 0 || -1) * Math.floor(Math.abs(d)))), d >= c)return -1;
22
- for (var e = d >= 0 ? d : Math.max(c - Math.abs(d), 0); c > e; e++)if (e in b && b[e] === a)return e;
23
- return -1
24
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  /*!
26
  * Cross-Browser Split 1.1.1
27
  * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
28
  * Available under the MIT License
29
  * http://blog.stevenlevithan.com/archives/cross-browser-split
30
  */
31
- var nativeSplit = String.prototype.split, compliantExecNpcg = void 0 === /()??/.exec("")[1];
32
- String.prototype.split = function (a, b) {
33
- var c = this;
34
- if ("[object RegExp]" !== Object.prototype.toString.call(a))return nativeSplit.call(c, a, b);
35
- var d, e, f, g, h = [], i = (a.ignoreCase ? "i" : "") + (a.multiline ? "m" : "") + (a.extended ? "x" : "") + (a.sticky ? "y" : ""), j = 0;
36
- for (a = new RegExp(a.source, i + "g"), c += "", compliantExecNpcg || (d = new RegExp("^" + a.source + "$(?!\\s)", i)), b = void 0 === b ? -1 >>> 0 : b >>> 0; (e = a.exec(c)) && (f = e.index + e[0].length, !(f > j && (h.push(c.slice(j, e.index)), !compliantExecNpcg && e.length > 1 && e[0].replace(d, function () {
37
- for (var a = 1; a < arguments.length - 2; a++)void 0 === arguments[a] && (e[a] = void 0)
38
- }), e.length > 1 && e.index < c.length && Array.prototype.push.apply(h, e.slice(1)), g = e[0].length, j = f, h.length >= b)));)a.lastIndex === e.index && a.lastIndex++;
39
- return j === c.length ? (g || !a.test("")) && h.push("") : h.push(c.slice(j)), h.length > b ? h.slice(0, b) : h
40
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ /*jshint
3
+ asi: true,
4
+ unused: true,
5
+ boss: true,
6
+ loopfunc: true,
7
+ eqnull: true
8
+ */
9
+
10
+
11
  /*!
12
  * Legacy browser support
13
  */
14
+
15
+
16
+ // Map array support
17
+ if ( ![].map ) {
18
+ Array.prototype.map = function ( callback, self ) {
19
+ var array = this, len = array.length, newArray = new Array( len )
20
+ for ( var i = 0; i < len; i++ ) {
21
+ if ( i in array ) {
22
+ newArray[ i ] = callback.call( self, array[ i ], i, array )
23
+ }
24
+ }
25
+ return newArray
26
+ }
27
+ }
28
+
29
+
30
+ // Filter array support
31
+ if ( ![].filter ) {
32
+ Array.prototype.filter = function( callback ) {
33
+ if ( this == null ) throw new TypeError()
34
+ var t = Object( this ), len = t.length >>> 0
35
+ if ( typeof callback != 'function' ) throw new TypeError()
36
+ var newArray = [], thisp = arguments[ 1 ]
37
+ for ( var i = 0; i < len; i++ ) {
38
+ if ( i in t ) {
39
+ var val = t[ i ]
40
+ if ( callback.call( thisp, val, i, t ) ) newArray.push( val )
41
+ }
42
+ }
43
+ return newArray
44
  }
45
+ }
46
+
47
+
48
+ // Index of array support
49
+ if ( ![].indexOf ) {
50
+ Array.prototype.indexOf = function( searchElement ) {
51
+ if ( this == null ) throw new TypeError()
52
+ var t = Object( this ), len = t.length >>> 0
53
+ if ( len === 0 ) return -1
54
+ var n = 0
55
+ if ( arguments.length > 1 ) {
56
+ n = Number( arguments[ 1 ] )
57
+ if ( n != n ) {
58
+ n = 0
59
+ }
60
+ else if ( n !== 0 && n != Infinity && n != -Infinity ) {
61
+ n = ( n > 0 || -1 ) * Math.floor( Math.abs( n ) )
62
+ }
63
+ }
64
+ if ( n >= len ) return -1
65
+ var k = n >= 0 ? n : Math.max( len - Math.abs( n ), 0 )
66
+ for ( ; k < len; k++ ) {
67
+ if ( k in t && t[ k ] === searchElement ) return k
68
+ }
69
+ return -1
70
+ }
71
+ }
72
+
73
+
74
  /*!
75
  * Cross-Browser Split 1.1.1
76
  * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
77
  * Available under the MIT License
78
  * http://blog.stevenlevithan.com/archives/cross-browser-split
79
  */
80
+ var nativeSplit = String.prototype.split, compliantExecNpcg = /()??/.exec('')[1] === undefined
81
+ String.prototype.split = function(separator, limit) {
82
+ var str = this
83
+ if (Object.prototype.toString.call(separator) !== '[object RegExp]') {
84
+ return nativeSplit.call(str, separator, limit)
85
+ }
86
+ var output = [],
87
+ flags = (separator.ignoreCase ? 'i' : '') +
88
+ (separator.multiline ? 'm' : '') +
89
+ (separator.extended ? 'x' : '') +
90
+ (separator.sticky ? 'y' : ''),
91
+ lastLastIndex = 0,
92
+ separator2, match, lastIndex, lastLength
93
+ separator = new RegExp(separator.source, flags + 'g')
94
+ str += ''
95
+ if (!compliantExecNpcg) {
96
+ separator2 = new RegExp('^' + separator.source + '$(?!\\s)', flags)
97
+ }
98
+ limit = limit === undefined ? -1 >>> 0 : limit >>> 0
99
+ while (match = separator.exec(str)) {
100
+ lastIndex = match.index + match[0].length
101
+ if (lastIndex > lastLastIndex) {
102
+ output.push(str.slice(lastLastIndex, match.index))
103
+ if (!compliantExecNpcg && match.length > 1) {
104
+ match[0].replace(separator2, function () {
105
+ for (var i = 1; i < arguments.length - 2; i++) {
106
+ if (arguments[i] === undefined) {
107
+ match[i] = undefined
108
+ }
109
+ }
110
+ })
111
+ }
112
+ if (match.length > 1 && match.index < str.length) {
113
+ Array.prototype.push.apply(output, match.slice(1))
114
+ }
115
+ lastLength = match[0].length
116
+ lastLastIndex = lastIndex
117
+ if (output.length >= limit) {
118
+ break
119
+ }
120
+ }
121
+ if (separator.lastIndex === match.index) {
122
+ separator.lastIndex++
123
+ }
124
+ }
125
+ if (lastLastIndex === str.length) {
126
+ if (lastLength || !separator.test('')) {
127
+ output.push('')
128
+ }
129
+ } else {
130
+ output.push(str.slice(lastLastIndex))
131
+ }
132
+ return output.length > limit ? output.slice(0, limit) : output
133
+ };
js/pickadate/picker.date.js CHANGED
@@ -1,304 +1,1357 @@
1
- /*!
2
- * Date picker for pickadate.js v3.4.0
3
- * http://amsul.github.io/pickadate.js/date.htm
4
- */
5
- !function (a) {
6
- "function" == typeof define && define.amd ? define(["picker", "jquery"], a) : a(Picker, jQuery)
7
- }(function (a, b) {
8
- function c(a, b) {
9
- var c = this, d = a.$node[0].value, e = a.$node.data("value"), f = e || d, g = e ? b.formatSubmit : b.format, h = function () {
10
- return "rtl" === getComputedStyle(a.$root[0]).direction
11
- };
12
- c.settings = b, c.$node = a.$node, c.queue = {
13
- min: "measure create",
14
- max: "measure create",
15
- now: "now create",
16
- select: "parse create validate",
17
- highlight: "parse navigate create validate",
18
- view: "parse create validate viewset",
19
- disable: "deactivate",
20
- enable: "activate"
21
- }, c.item = {}, c.item.disable = (b.disable || []).slice(0), c.item.enable = -function (a) {
22
- return a[0] === !0 ? a.shift() : -1
23
- }(c.item.disable), c.set("min", b.min).set("max", b.max).set("now"), f ? c.set("select", f, {
24
- format: g,
25
- fromValue: !!d
26
- }) : c.set("select", null).set("highlight", c.item.now), c.key = {
27
- 40: 7, 38: -7, 39: function () {
28
- return h() ? -1 : 1
29
- }, 37: function () {
30
- return h() ? 1 : -1
31
- }, go: function (a) {
32
- var b = c.item.highlight, d = new Date(b.year, b.month, b.date + a);
33
- c.set("highlight", [d.getFullYear(), d.getMonth(), d.getDate()], {interval: a}), this.render()
34
- }
35
- }, a.on("render", function () {
36
- a.$root.find("." + b.klass.selectMonth).on("change", function () {
37
- var c = this.value;
38
- c && (a.set("highlight", [a.get("view").year, c, a.get("highlight").date]), a.$root.find("." + b.klass.selectMonth).trigger("focus"))
39
- }), a.$root.find("." + b.klass.selectYear).on("change", function () {
40
- var c = this.value;
41
- c && (a.set("highlight", [c, a.get("view").month, a.get("highlight").date]), a.$root.find("." + b.klass.selectYear).trigger("focus"))
42
- })
43
- }).on("open", function () {
44
- a.$root.find("button, select").attr("disabled", !1)
45
- }).on("close", function () {
46
- a.$root.find("button, select").attr("disabled", !0)
47
- })
48
- }
49
-
50
- var d = 7, e = 6, f = a._;
51
- c.prototype.set = function (a, b, c) {
52
- var d = this, e = d.item;
53
- return null === b ? (e[a] = b, d) : (e["enable" == a ? "disable" : "flip" == a ? "enable" : a] = d.queue[a].split(" ").map(function (e) {
54
- return b = d[e](a, b, c)
55
- }).pop(), "select" == a ? d.set("highlight", e.select, c) : "highlight" == a ? d.set("view", e.highlight, c) : a.match(/^(flip|min|max|disable|enable)$/) && (e.select && d.disabled(e.select) && d.set("select", e.select, c), e.highlight && d.disabled(e.highlight) && d.set("highlight", e.highlight, c)), d)
56
- }, c.prototype.get = function (a) {
57
- return this.item[a]
58
- }, c.prototype.create = function (a, c, d) {
59
- var e, g = this;
60
- return c = void 0 === c ? a : c, c == -1 / 0 || 1 / 0 == c ? e = c : b.isPlainObject(c) && f.isInteger(c.pick) ? c = c.obj : b.isArray(c) ? (c = new Date(c[0], c[1], c[2]), c = f.isDate(c) ? c : g.create().obj) : c = f.isInteger(c) || f.isDate(c) ? g.normalize(new Date(c), d) : g.now(a, c, d), {
61
- year: e || c.getFullYear(),
62
- month: e || c.getMonth(),
63
- date: e || c.getDate(),
64
- day: e || c.getDay(),
65
- obj: e || c,
66
- pick: e || c.getTime()
67
- }
68
- }, c.prototype.createRange = function (a, c) {
69
- var d = this, e = function (a) {
70
- return a === !0 || b.isArray(a) || f.isDate(a) ? d.create(a) : a
71
- };
72
- return f.isInteger(a) || (a = e(a)), f.isInteger(c) || (c = e(c)), f.isInteger(a) && b.isPlainObject(c) ? a = [c.year, c.month, c.date + a] : f.isInteger(c) && b.isPlainObject(a) && (c = [a.year, a.month, a.date + c]), {
73
- from: e(a),
74
- to: e(c)
75
- }
76
- }, c.prototype.withinRange = function (a, b) {
77
- return a = this.createRange(a.from, a.to), b.pick >= a.from.pick && b.pick <= a.to.pick
78
- }, c.prototype.overlapRanges = function (a, b) {
79
- var c = this;
80
- return a = c.createRange(a.from, a.to), b = c.createRange(b.from, b.to), c.withinRange(a, b.from) || c.withinRange(a, b.to) || c.withinRange(b, a.from) || c.withinRange(b, a.to)
81
- }, c.prototype.now = function (a, b, c) {
82
- return b = new Date, c && c.rel && b.setDate(b.getDate() + c.rel), this.normalize(b, c)
83
- }, c.prototype.navigate = function (a, c, d) {
84
- var e, f, g, h, i = b.isArray(c), j = b.isPlainObject(c), k = this.item.view;
85
- if (i || j) {
86
- for (j ? (f = c.year, g = c.month, h = c.date) : (f = +c[0], g = +c[1], h = +c[2]), d && d.nav && k && k.month !== g && (f = k.year, g = k.month), e = new Date(f, g + (d && d.nav ? d.nav : 0), 1), f = e.getFullYear(), g = e.getMonth(); new Date(f, g, h).getMonth() !== g;)h -= 1;
87
- c = [f, g, h]
88
- }
89
- return c
90
- }, c.prototype.normalize = function (a) {
91
- return a.setHours(0, 0, 0, 0), a
92
- }, c.prototype.measure = function (a, b) {
93
- var c = this;
94
- return b ? f.isInteger(b) && (b = c.now(a, b, {rel: b})) : b = "min" == a ? -1 / 0 : 1 / 0, b
95
- }, c.prototype.viewset = function (a, b) {
96
- return this.create([b.year, b.month, 1])
97
- }, c.prototype.validate = function (a, c, d) {
98
- var e, g, h, i, j = this, k = c, l = d && d.interval ? d.interval : 1, m = -1 === j.item.enable, n = j.item.min, o = j.item.max, p = m && j.item.disable.filter(function (a) {
99
- if (b.isArray(a)) {
100
- var d = j.create(a).pick;
101
- d < c.pick ? e = !0 : d > c.pick && (g = !0)
102
- }
103
- return f.isInteger(a)
104
- }).length;
105
- if ((!d || !d.nav) && (!m && j.disabled(c) || m && j.disabled(c) && (p || e || g) || !m && (c.pick <= n.pick || c.pick >= o.pick)))for (m && !p && (!g && l > 0 || !e && 0 > l) && (l *= -1); j.disabled(c) && (Math.abs(l) > 1 && (c.month < k.month || c.month > k.month) && (c = k, l = l > 0 ? 1 : -1), c.pick <= n.pick ? (h = !0, l = 1, c = j.create([n.year, n.month, n.date - 1])) : c.pick >= o.pick && (i = !0, l = -1, c = j.create([o.year, o.month, o.date + 1])), !h || !i);)c = j.create([c.year, c.month, c.date + l]);
106
- return c
107
- }, c.prototype.disabled = function (a) {
108
- var c = this, d = c.item.disable.filter(function (d) {
109
- return f.isInteger(d) ? a.day === (c.settings.firstDay ? d : d - 1) % 7 : b.isArray(d) || f.isDate(d) ? a.pick === c.create(d).pick : b.isPlainObject(d) ? c.withinRange(d, a) : void 0
110
- });
111
- return d = d.length && !d.filter(function (a) {
112
- return b.isArray(a) && "inverted" == a[3] || b.isPlainObject(a) && a.inverted
113
- }).length, -1 === c.item.enable ? !d : d || a.pick < c.item.min.pick || a.pick > c.item.max.pick
114
- }, c.prototype.parse = function (a, c, d) {
115
- var e, g = this, h = {};
116
- return !c || f.isInteger(c) || b.isArray(c) || f.isDate(c) || b.isPlainObject(c) && f.isInteger(c.pick) ? c : (d && d.format || (d = d || {}, d.format = g.settings.format), e = "string" != typeof c || d.fromValue ? 0 : 1, g.formats.toArray(d.format).map(function (a) {
117
- var b = g.formats[a], d = b ? f.trigger(b, g, [c, h]) : a.replace(/^!/, "").length;
118
- b && (h[a] = c.substr(0, d)), c = c.substr(d)
119
- }), [h.yyyy || h.yy, +(h.mm || h.m) - e, h.dd || h.d])
120
- }, c.prototype.formats = function () {
121
- function a(a, b, c) {
122
- var d = a.match(/\w+/)[0];
123
- return c.mm || c.m || (c.m = b.indexOf(d)), d.length
124
- }
125
-
126
- function b(a) {
127
- return a.match(/\w+/)[0].length
128
- }
129
-
130
- return {
131
- d: function (a, b) {
132
- return a ? f.digits(a) : b.date
133
- }, dd: function (a, b) {
134
- return a ? 2 : f.lead(b.date)
135
- }, ddd: function (a, c) {
136
- return a ? b(a) : this.settings.weekdaysShort[c.day]
137
- }, dddd: function (a, c) {
138
- return a ? b(a) : this.settings.weekdaysFull[c.day]
139
- }, m: function (a, b) {
140
- return a ? f.digits(a) : b.month + 1
141
- }, mm: function (a, b) {
142
- return a ? 2 : f.lead(b.month + 1)
143
- }, mmm: function (b, c) {
144
- var d = this.settings.monthsShort;
145
- return b ? a(b, d, c) : d[c.month]
146
- }, mmmm: function (b, c) {
147
- var d = this.settings.monthsFull;
148
- return b ? a(b, d, c) : d[c.month]
149
- }, yy: function (a, b) {
150
- return a ? 2 : ("" + b.year).slice(2)
151
- }, yyyy: function (a, b) {
152
- return a ? 4 : b.year
153
- }, toArray: function (a) {
154
- return a.split(/(d{1,4}|m{1,4}|y{4}|yy|!.)/g)
155
- }, toString: function (a, b) {
156
- var c = this;
157
- return c.formats.toArray(a).map(function (a) {
158
- return f.trigger(c.formats[a], c, [0, b]) || a.replace(/^!/, "")
159
- }).join("")
160
- }
161
- }
162
- }(), c.prototype.isDateExact = function (a, c) {
163
- var d = this;
164
- return f.isInteger(a) && f.isInteger(c) || "boolean" == typeof a && "boolean" == typeof c ? a === c : (f.isDate(a) || b.isArray(a)) && (f.isDate(c) || b.isArray(c)) ? d.create(a).pick === d.create(c).pick : b.isPlainObject(a) && b.isPlainObject(c) ? d.isDateExact(a.from, c.from) && d.isDateExact(a.to, c.to) : !1
165
- }, c.prototype.isDateOverlap = function (a, c) {
166
- var d = this;
167
- return f.isInteger(a) && (f.isDate(c) || b.isArray(c)) ? a === d.create(c).day + 1 : f.isInteger(c) && (f.isDate(a) || b.isArray(a)) ? c === d.create(a).day + 1 : b.isPlainObject(a) && b.isPlainObject(c) ? d.overlapRanges(a, c) : !1
168
- }, c.prototype.flipEnable = function (a) {
169
- var b = this.item;
170
- b.enable = a || (-1 == b.enable ? 1 : -1)
171
- }, c.prototype.deactivate = function (a, c) {
172
- var d = this, e = d.item.disable.slice(0);
173
- return "flip" == c ? d.flipEnable() : c === !1 ? (d.flipEnable(1), e = []) : c === !0 ? (d.flipEnable(-1), e = []) : c.map(function (a) {
174
- for (var c, g = 0; g < e.length; g += 1)if (d.isDateExact(a, e[g])) {
175
- c = !0;
176
- break
177
- }
178
- c || (f.isInteger(a) || f.isDate(a) || b.isArray(a) || b.isPlainObject(a) && a.from && a.to) && e.push(a)
179
- }), e
180
- }, c.prototype.activate = function (a, c) {
181
- var d = this, e = d.item.disable, g = e.length;
182
- return "flip" == c ? d.flipEnable() : c === !0 ? (d.flipEnable(1), e = []) : c === !1 ? (d.flipEnable(-1), e = []) : c.map(function (a) {
183
- var c, h, i, j;
184
- for (i = 0; g > i; i += 1) {
185
- if (h = e[i], d.isDateExact(h, a)) {
186
- c = e[i] = null, j = !0;
187
- break
188
- }
189
- if (d.isDateOverlap(h, a)) {
190
- b.isPlainObject(a) ? (a.inverted = !0, c = a) : b.isArray(a) ? (c = a, c[3] || c.push("inverted")) : f.isDate(a) && (c = [a.getFullYear(), a.getMonth(), a.getDate(), "inverted"]);
191
- break
192
- }
193
- }
194
- if (c)for (i = 0; g > i; i += 1)if (d.isDateExact(e[i], a)) {
195
- e[i] = null;
196
- break
197
- }
198
- if (j)for (i = 0; g > i; i += 1)if (d.isDateOverlap(e[i], a)) {
199
- e[i] = null;
200
- break
201
- }
202
- c && e.push(c)
203
- }), e.filter(function (a) {
204
- return null != a
205
- })
206
- }, c.prototype.nodes = function (a) {
207
- var b = this, c = b.settings, g = b.item, h = g.now, i = g.select, j = g.highlight, k = g.view, l = g.disable, m = g.min, n = g.max, o = function (a) {
208
- return c.firstDay && a.push(a.shift()), f.node("thead", f.node("tr", f.group({
209
- min: 0,
210
- max: d - 1,
211
- i: 1,
212
- node: "th",
213
- item: function (b) {
214
- return [a[b], c.klass.weekdays]
215
- }
216
- })))
217
- }((c.showWeekdaysFull ? c.weekdaysFull : c.weekdaysShort).slice(0)), p = function (a) {
218
- return f.node("div", " ", c.klass["nav" + (a ? "Next" : "Prev")] + (a && k.year >= n.year && k.month >= n.month || !a && k.year <= m.year && k.month <= m.month ? " " + c.klass.navDisabled : ""), "data-nav=" + (a || -1))
219
- }, q = function (b) {
220
- return c.selectMonths ? f.node("select", f.group({
221
- min: 0,
222
- max: 11,
223
- i: 1,
224
- node: "option",
225
- item: function (a) {
226
- return [b[a], 0, "value=" + a + (k.month == a ? " selected" : "") + (k.year == m.year && a < m.month || k.year == n.year && a > n.month ? " disabled" : "")]
227
- }
228
- }), c.klass.selectMonth, a ? "" : "disabled") : f.node("div", b[k.month], c.klass.month)
229
- }, r = function () {
230
- var b = k.year, d = c.selectYears === !0 ? 5 : ~~(c.selectYears / 2);
231
- if (d) {
232
- var e = m.year, g = n.year, h = b - d, i = b + d;
233
- if (e > h && (i += e - h, h = e), i > g) {
234
- var j = h - e, l = i - g;
235
- h -= j > l ? l : j, i = g
236
- }
237
- return f.node("select", f.group({
238
- min: h, max: i, i: 1, node: "option", item: function (a) {
239
- return [a, 0, "value=" + a + (b == a ? " selected" : "")]
240
- }
241
- }), c.klass.selectYear, a ? "" : "disabled")
242
- }
243
- return f.node("div", b, c.klass.year)
244
- };
245
- return f.node("div", p() + p(1) + q(c.showMonthsShort ? c.monthsShort : c.monthsFull) + r(), c.klass.header) + f.node("table", o + f.node("tbody", f.group({
246
- min: 0,
247
- max: e - 1,
248
- i: 1,
249
- node: "tr",
250
- item: function (a) {
251
- var e = c.firstDay && 0 === b.create([k.year, k.month, 1]).day ? -7 : 0;
252
- return [f.group({
253
- min: d * a - k.day + e + 1, max: function () {
254
- return this.min + d - 1
255
- }, i: 1, node: "td", item: function (a) {
256
- a = b.create([k.year, k.month, a + (c.firstDay ? 1 : 0)]);
257
- var d = i && i.pick == a.pick, e = j && j.pick == a.pick, g = l && b.disabled(a) || a.pick < m.pick || a.pick > n.pick;
258
- return [f.node("div", a.date, function (b) {
259
- return b.push(k.month == a.month ? c.klass.infocus : c.klass.outfocus), h.pick == a.pick && b.push(c.klass.now), d && b.push(c.klass.selected), e && b.push(c.klass.highlighted), g && b.push(c.klass.disabled), b.join(" ")
260
- }([c.klass.day]), "data-pick=" + a.pick + " " + f.ariaAttr({
261
- role: "button",
262
- controls: b.$node[0].id,
263
- checked: d && b.$node.val() === f.trigger(b.formats.toString, b, [c.format, a]) ? !0 : null,
264
- activedescendant: e ? !0 : null,
265
- disabled: g ? !0 : null
266
- }))]
267
- }
268
- })]
269
- }
270
- })), c.klass.table) + f.node("div", f.node("button", c.today, c.klass.buttonToday, "type=button data-pick=" + h.pick + (a ? "" : " disabled")) + f.node("button", c.clear, c.klass.buttonClear, "type=button data-clear=1" + (a ? "" : " disabled")), c.klass.footer)
271
- }, c.defaults = function (a) {
272
- return {
273
- monthsFull: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
274
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
275
- weekdaysFull: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
276
- weekdaysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
277
- today: "Today",
278
- clear: "Clear",
279
- format: "d mmmm, yyyy",
280
- klass: {
281
- table: a + "table",
282
- header: a + "header",
283
- navPrev: a + "nav--prev",
284
- navNext: a + "nav--next",
285
- navDisabled: a + "nav--disabled",
286
- month: a + "month",
287
- year: a + "year",
288
- selectMonth: a + "select--month",
289
- selectYear: a + "select--year",
290
- weekdays: a + "weekday",
291
- day: a + "day",
292
- disabled: a + "day--disabled",
293
- selected: a + "day--selected",
294
- highlighted: a + "day--highlighted",
295
- now: a + "day--today",
296
- infocus: a + "day--infocus",
297
- outfocus: a + "day--outfocus",
298
- footer: a + "footer",
299
- buttonClear: a + "button--clear",
300
- buttonToday: a + "button--today"
301
- }
302
- }
303
- }(a.klasses().picker + "__"), a.extend("pickadate", c)
304
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Date picker for pickadate.js v3.6.4
3
+ * http://amsul.github.io/pickadate.js/date.htm
4
+ */
5
+
6
+ (function ( factory ) {
7
+
8
+ // AMD.
9
+ if ( typeof define == 'function' && define.amd )
10
+ define( ['./picker', 'jquery'], factory )
11
+
12
+ // Node.js/browserify.
13
+ else if ( typeof exports == 'object' )
14
+ module.exports = factory( require('./picker.js'), require('jquery') )
15
+
16
+ // Browser globals.
17
+ else factory( Picker, jQuery )
18
+
19
+ }(function( Picker, $ ) {
20
+
21
+
22
+ /**
23
+ * Globals and constants
24
+ */
25
+ var DAYS_IN_WEEK = 7,
26
+ WEEKS_IN_CALENDAR = 6,
27
+ _ = Picker._
28
+
29
+
30
+
31
+ /**
32
+ * The date picker constructor
33
+ */
34
+ function DatePicker( picker, settings ) {
35
+
36
+ var calendar = this,
37
+ element = picker.$node[ 0 ],
38
+ elementValue = element.value,
39
+ elementDataValue = picker.$node.data( 'value' ),
40
+ valueString = elementDataValue || elementValue,
41
+ formatString = elementDataValue ? settings.formatSubmit : settings.format,
42
+ isRTL = function() {
43
+
44
+ return element.currentStyle ?
45
+
46
+ // For IE.
47
+ element.currentStyle.direction == 'rtl' :
48
+
49
+ // For normal browsers.
50
+ getComputedStyle( picker.$root[0] ).direction == 'rtl'
51
+ }
52
+
53
+ calendar.settings = settings
54
+ calendar.$node = picker.$node
55
+
56
+ // The queue of methods that will be used to build item objects.
57
+ calendar.queue = {
58
+ min: 'measure create',
59
+ max: 'measure create',
60
+ now: 'now create',
61
+ select: 'parse create validate',
62
+ highlight: 'parse navigate create validate',
63
+ view: 'parse create validate viewset',
64
+ disable: 'deactivate',
65
+ enable: 'activate'
66
+ }
67
+
68
+ // The component's item object.
69
+ calendar.item = {}
70
+
71
+ calendar.item.clear = null
72
+ calendar.item.disable = ( settings.disable || [] ).slice( 0 )
73
+ calendar.item.enable = -(function( collectionDisabled ) {
74
+ return collectionDisabled[ 0 ] === true ? collectionDisabled.shift() : -1
75
+ })( calendar.item.disable )
76
+
77
+ calendar.
78
+ set( 'min', settings.min ).
79
+ set( 'max', settings.max ).
80
+ set( 'now' )
81
+
82
+ // When there’s a value, set the `select`, which in turn
83
+ // also sets the `highlight` and `view`.
84
+ if ( valueString ) {
85
+ calendar.set( 'select', valueString, {
86
+ format: formatString,
87
+ defaultValue: true
88
+ })
89
+ }
90
+
91
+ // If there’s no value, default to highlighting “today”.
92
+ else {
93
+ calendar.
94
+ set( 'select', null ).
95
+ set( 'highlight', calendar.item.now )
96
+ }
97
+
98
+
99
+ // The keycode to movement mapping.
100
+ calendar.key = {
101
+ 40: 7, // Down
102
+ 38: -7, // Up
103
+ 39: function() { return isRTL() ? -1 : 1 }, // Right
104
+ 37: function() { return isRTL() ? 1 : -1 }, // Left
105
+ go: function( timeChange ) {
106
+ var highlightedObject = calendar.item.highlight,
107
+ targetDate = new Date( highlightedObject.year, highlightedObject.month, highlightedObject.date + timeChange )
108
+ calendar.set(
109
+ 'highlight',
110
+ targetDate,
111
+ { interval: timeChange }
112
+ )
113
+ this.render()
114
+ }
115
+ }
116
+
117
+
118
+ // Bind some picker events.
119
+ picker.
120
+ on( 'render', function() {
121
+ picker.$root.find( '.' + settings.klass.selectMonth ).on( 'change', function() {
122
+ var value = this.value
123
+ if ( value ) {
124
+ picker.set( 'highlight', [ picker.get( 'view' ).year, value, picker.get( 'highlight' ).date ] )
125
+ picker.$root.find( '.' + settings.klass.selectMonth ).trigger( 'focus' )
126
+ }
127
+ })
128
+ picker.$root.find( '.' + settings.klass.selectYear ).on( 'change', function() {
129
+ var value = this.value
130
+ if ( value ) {
131
+ picker.set( 'highlight', [ value, picker.get( 'view' ).month, picker.get( 'highlight' ).date ] )
132
+ picker.$root.find( '.' + settings.klass.selectYear ).trigger( 'focus' )
133
+ }
134
+ })
135
+ }, 1 ).
136
+ on( 'open', function() {
137
+ var includeToday = ''
138
+ if ( calendar.disabled( calendar.get('now') ) ) {
139
+ includeToday = ':not(.' + settings.klass.buttonToday + ')'
140
+ }
141
+ picker.$root.find( 'button' + includeToday + ', select' ).attr( 'disabled', false )
142
+ }, 1 ).
143
+ on( 'close', function() {
144
+ picker.$root.find( 'button, select' ).attr( 'disabled', true )
145
+ }, 1 )
146
+
147
+ } //DatePicker
148
+
149
+
150
+ /**
151
+ * Set a datepicker item object.
152
+ */
153
+ DatePicker.prototype.set = function( type, value, options ) {
154
+
155
+ var calendar = this,
156
+ calendarItem = calendar.item
157
+
158
+ // If the value is `null` just set it immediately.
159
+ if ( value === null ) {
160
+ if ( type == 'clear' ) type = 'select'
161
+ calendarItem[ type ] = value
162
+ return calendar
163
+ }
164
+
165
+ // Otherwise go through the queue of methods, and invoke the functions.
166
+ // Update this as the time unit, and set the final value as this item.
167
+ // * In the case of `enable`, keep the queue but set `disable` instead.
168
+ // And in the case of `flip`, keep the queue but set `enable` instead.
169
+ calendarItem[ ( type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type ) ] = calendar.queue[ type ].split( ' ' ).map( function( method ) {
170
+ value = calendar[ method ]( type, value, options )
171
+ return value
172
+ }).pop()
173
+
174
+ // Check if we need to cascade through more updates.
175
+ if ( type == 'select' ) {
176
+ calendar.set( 'highlight', calendarItem.select, options )
177
+ }
178
+ else if ( type == 'highlight' ) {
179
+ calendar.set( 'view', calendarItem.highlight, options )
180
+ }
181
+ else if ( type.match( /^(flip|min|max|disable|enable)$/ ) ) {
182
+ if ( calendarItem.select && calendar.disabled( calendarItem.select ) ) {
183
+ calendar.set( 'select', calendarItem.select, options )
184
+ }
185
+ if ( calendarItem.highlight && calendar.disabled( calendarItem.highlight ) ) {
186
+ calendar.set( 'highlight', calendarItem.highlight, options )
187
+ }
188
+ }
189
+
190
+ return calendar
191
+ } //DatePicker.prototype.set
192
+
193
+
194
+ /**
195
+ * Get a datepicker item object.
196
+ */
197
+ DatePicker.prototype.get = function( type ) {
198
+ return this.item[ type ]
199
+ } //DatePicker.prototype.get
200
+
201
+
202
+ /**
203
+ * Create a picker date object.
204
+ */
205
+ DatePicker.prototype.create = function( type, value, options ) {
206
+
207
+ var isInfiniteValue,
208
+ calendar = this
209
+
210
+ // If there’s no value, use the type as the value.
211
+ value = value === undefined ? type : value
212
+
213
+
214
+ // If it’s infinity, update the value.
215
+ if ( value == -Infinity || value == Infinity ) {
216
+ isInfiniteValue = value
217
+ }
218
+
219
+ // If it’s an object, use the native date object.
220
+ else if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
221
+ value = value.obj
222
+ }
223
+
224
+ // If it’s an array, convert it into a date and make sure
225
+ // that it’s a valid date – otherwise default to today.
226
+ else if ( $.isArray( value ) ) {
227
+ value = new Date( value[ 0 ], value[ 1 ], value[ 2 ] )
228
+ value = _.isDate( value ) ? value : calendar.create().obj
229
+ }
230
+
231
+ // If it’s a number or date object, make a normalized date.
232
+ else if ( _.isInteger( value ) || _.isDate( value ) ) {
233
+ value = calendar.normalize( new Date( value ), options )
234
+ }
235
+
236
+ // If it’s a literal true or any other case, set it to now.
237
+ else /*if ( value === true )*/ {
238
+ value = calendar.now( type, value, options )
239
+ }
240
+
241
+ // Return the compiled object.
242
+ return {
243
+ year: isInfiniteValue || value.getFullYear(),
244
+ month: isInfiniteValue || value.getMonth(),
245
+ date: isInfiniteValue || value.getDate(),
246
+ day: isInfiniteValue || value.getDay(),
247
+ obj: isInfiniteValue || value,
248
+ pick: isInfiniteValue || value.getTime()
249
+ }
250
+ } //DatePicker.prototype.create
251
+
252
+
253
+ /**
254
+ * Create a range limit object using an array, date object,
255
+ * literal “true”, or integer relative to another time.
256
+ */
257
+ DatePicker.prototype.createRange = function( from, to ) {
258
+
259
+ var calendar = this,
260
+ createDate = function( date ) {
261
+ if ( date === true || $.isArray( date ) || _.isDate( date ) ) {
262
+ return calendar.create( date )
263
+ }
264
+ return date
265
+ }
266
+
267
+ // Create objects if possible.
268
+ if ( !_.isInteger( from ) ) {
269
+ from = createDate( from )
270
+ }
271
+ if ( !_.isInteger( to ) ) {
272
+ to = createDate( to )
273
+ }
274
+
275
+ // Create relative dates.
276
+ if ( _.isInteger( from ) && $.isPlainObject( to ) ) {
277
+ from = [ to.year, to.month, to.date + from ];
278
+ }
279
+ else if ( _.isInteger( to ) && $.isPlainObject( from ) ) {
280
+ to = [ from.year, from.month, from.date + to ];
281
+ }
282
+
283
+ return {
284
+ from: createDate( from ),
285
+ to: createDate( to )
286
+ }
287
+ } //DatePicker.prototype.createRange
288
+
289
+
290
+ /**
291
+ * Check if a date unit falls within a date range object.
292
+ */
293
+ DatePicker.prototype.withinRange = function( range, dateUnit ) {
294
+ range = this.createRange(range.from, range.to)
295
+ return dateUnit.pick >= range.from.pick && dateUnit.pick <= range.to.pick
296
+ }
297
+
298
+
299
+ /**
300
+ * Check if two date range objects overlap.
301
+ */
302
+ DatePicker.prototype.overlapRanges = function( one, two ) {
303
+
304
+ var calendar = this
305
+
306
+ // Convert the ranges into comparable dates.
307
+ one = calendar.createRange( one.from, one.to )
308
+ two = calendar.createRange( two.from, two.to )
309
+
310
+ return calendar.withinRange( one, two.from ) || calendar.withinRange( one, two.to ) ||
311
+ calendar.withinRange( two, one.from ) || calendar.withinRange( two, one.to )
312
+ }
313
+
314
+
315
+ /**
316
+ * Get the date today.
317
+ */
318
+ DatePicker.prototype.now = function( type, value, options ) {
319
+ value = new Date()
320
+ if ( options && options.rel ) {
321
+ value.setDate( value.getDate() + options.rel )
322
+ }
323
+ return this.normalize( value, options )
324
+ }
325
+
326
+
327
+ /**
328
+ * Navigate to next/prev month.
329
+ */
330
+ DatePicker.prototype.navigate = function( type, value, options ) {
331
+
332
+ var targetDateObject,
333
+ targetYear,
334
+ targetMonth,
335
+ targetDate,
336
+ isTargetArray = $.isArray( value ),
337
+ isTargetObject = $.isPlainObject( value ),
338
+ viewsetObject = this.item.view/*,
339
+ safety = 100*/
340
+
341
+
342
+ if ( isTargetArray || isTargetObject ) {
343
+
344
+ if ( isTargetObject ) {
345
+ targetYear = value.year
346
+ targetMonth = value.month
347
+ targetDate = value.date
348
+ }
349
+ else {
350
+ targetYear = +value[0]
351
+ targetMonth = +value[1]
352
+ targetDate = +value[2]
353
+ }
354
+
355
+ // If we’re navigating months but the view is in a different
356
+ // month, navigate to the view’s year and month.
357
+ if ( options && options.nav && viewsetObject && viewsetObject.month !== targetMonth ) {
358
+ targetYear = viewsetObject.year
359
+ targetMonth = viewsetObject.month
360
+ }
361
+
362
+ // Figure out the expected target year and month.
363
+ targetDateObject = new Date( targetYear, targetMonth + ( options && options.nav ? options.nav : 0 ), 1 )
364
+ targetYear = targetDateObject.getFullYear()
365
+ targetMonth = targetDateObject.getMonth()
366
+
367
+ // If the month we’re going to doesn’t have enough days,
368
+ // keep decreasing the date until we reach the month’s last date.
369
+ while ( /*safety &&*/ new Date( targetYear, targetMonth, targetDate ).getMonth() !== targetMonth ) {
370
+ targetDate -= 1
371
+ /*safety -= 1
372
+ if ( !safety ) {
373
+ throw 'Fell into an infinite loop while navigating to ' + new Date( targetYear, targetMonth, targetDate ) + '.'
374
+ }*/
375
+ }
376
+
377
+ value = [ targetYear, targetMonth, targetDate ]
378
+ }
379
+
380
+ return value
381
+ } //DatePicker.prototype.navigate
382
+
383
+
384
+ /**
385
+ * Normalize a date by setting the hours to midnight.
386
+ */
387
+ DatePicker.prototype.normalize = function( value/*, options*/ ) {
388
+ value.setHours( 0, 0, 0, 0 )
389
+ return value
390
+ }
391
+
392
+
393
+ /**
394
+ * Measure the range of dates.
395
+ */
396
+ DatePicker.prototype.measure = function( type, value/*, options*/ ) {
397
+
398
+ var calendar = this
399
+
400
+ // If it's an integer, get a date relative to today.
401
+ if ( _.isInteger( value ) ) {
402
+ value = calendar.now( type, value, { rel: value } )
403
+ }
404
+
405
+ // If it’s anything false-y, remove the limits.
406
+ else if ( !value ) {
407
+ value = type == 'min' ? -Infinity : Infinity
408
+ }
409
+
410
+ // If it’s a string, parse it.
411
+ else if ( typeof value == 'string' ) {
412
+ value = calendar.parse( type, value )
413
+ }
414
+
415
+ return value
416
+ } ///DatePicker.prototype.measure
417
+
418
+
419
+ /**
420
+ * Create a viewset object based on navigation.
421
+ */
422
+ DatePicker.prototype.viewset = function( type, dateObject/*, options*/ ) {
423
+ return this.create([ dateObject.year, dateObject.month, 1 ])
424
+ }
425
+
426
+
427
+ /**
428
+ * Validate a date as enabled and shift if needed.
429
+ */
430
+ DatePicker.prototype.validate = function( type, dateObject, options ) {
431
+
432
+ var calendar = this,
433
+
434
+ // Keep a reference to the original date.
435
+ originalDateObject = dateObject,
436
+
437
+ // Make sure we have an interval.
438
+ interval = options && options.interval ? options.interval : 1,
439
+
440
+ // Check if the calendar enabled dates are inverted.
441
+ isFlippedBase = calendar.item.enable === -1,
442
+
443
+ // Check if we have any enabled dates after/before now.
444
+ hasEnabledBeforeTarget, hasEnabledAfterTarget,
445
+
446
+ // The min & max limits.
447
+ minLimitObject = calendar.item.min,
448
+ maxLimitObject = calendar.item.max,
449
+
450
+ // Check if we’ve reached the limit during shifting.
451
+ reachedMin, reachedMax,
452
+
453
+ // Check if the calendar is inverted and at least one weekday is enabled.
454
+ hasEnabledWeekdays = isFlippedBase && calendar.item.disable.filter( function( value ) {
455
+
456
+ // If there’s a date, check where it is relative to the target.
457
+ if ( $.isArray( value ) ) {
458
+ var dateTime = calendar.create( value ).pick
459
+ if ( dateTime < dateObject.pick ) hasEnabledBeforeTarget = true
460
+ else if ( dateTime > dateObject.pick ) hasEnabledAfterTarget = true
461
+ }
462
+
463
+ // Return only integers for enabled weekdays.
464
+ return _.isInteger( value )
465
+ }).length/*,
466
+
467
+ safety = 100*/
468
+
469
+
470
+
471
+ // Cases to validate for:
472
+ // [1] Not inverted and date disabled.
473
+ // [2] Inverted and some dates enabled.
474
+ // [3] Not inverted and out of range.
475
+ //
476
+ // Cases to **not** validate for:
477
+ // • Navigating months.
478
+ // • Not inverted and date enabled.
479
+ // • Inverted and all dates disabled.
480
+ // • ..and anything else.
481
+ if ( !options || (!options.nav && !options.defaultValue) ) if (
482
+ /* 1 */ ( !isFlippedBase && calendar.disabled( dateObject ) ) ||
483
+ /* 2 */ ( isFlippedBase && calendar.disabled( dateObject ) && ( hasEnabledWeekdays || hasEnabledBeforeTarget || hasEnabledAfterTarget ) ) ||
484
+ /* 3 */ ( !isFlippedBase && (dateObject.pick <= minLimitObject.pick || dateObject.pick >= maxLimitObject.pick) )
485
+ ) {
486
+
487
+
488
+ // When inverted, flip the direction if there aren’t any enabled weekdays
489
+ // and there are no enabled dates in the direction of the interval.
490
+ if ( isFlippedBase && !hasEnabledWeekdays && ( ( !hasEnabledAfterTarget && interval > 0 ) || ( !hasEnabledBeforeTarget && interval < 0 ) ) ) {
491
+ interval *= -1
492
+ }
493
+
494
+
495
+ // Keep looping until we reach an enabled date.
496
+ while ( /*safety &&*/ calendar.disabled( dateObject ) ) {
497
+
498
+ /*safety -= 1
499
+ if ( !safety ) {
500
+ throw 'Fell into an infinite loop while validating ' + dateObject.obj + '.'
501
+ }*/
502
+
503
+
504
+ // If we’ve looped into the next/prev month with a large interval, return to the original date and flatten the interval.
505
+ if ( Math.abs( interval ) > 1 && ( dateObject.month < originalDateObject.month || dateObject.month > originalDateObject.month ) ) {
506
+ dateObject = originalDateObject
507
+ interval = interval > 0 ? 1 : -1
508
+ }
509
+
510
+
511
+ // If we’ve reached the min/max limit, reverse the direction, flatten the interval and set it to the limit.
512
+ if ( dateObject.pick <= minLimitObject.pick ) {
513
+ reachedMin = true
514
+ interval = 1
515
+ dateObject = calendar.create([
516
+ minLimitObject.year,
517
+ minLimitObject.month,
518
+ minLimitObject.date + (dateObject.pick === minLimitObject.pick ? 0 : -1)
519
+ ])
520
+ }
521
+ else if ( dateObject.pick >= maxLimitObject.pick ) {
522
+ reachedMax = true
523
+ interval = -1
524
+ dateObject = calendar.create([
525
+ maxLimitObject.year,
526
+ maxLimitObject.month,
527
+ maxLimitObject.date + (dateObject.pick === maxLimitObject.pick ? 0 : 1)
528
+ ])
529
+ }
530
+
531
+
532
+ // If we’ve reached both limits, just break out of the loop.
533
+ if ( reachedMin && reachedMax ) {
534
+ break
535
+ }
536
+
537
+
538
+ // Finally, create the shifted date using the interval and keep looping.
539
+ dateObject = calendar.create([ dateObject.year, dateObject.month, dateObject.date + interval ])
540
+ }
541
+
542
+ } //endif
543
+
544
+
545
+ // Return the date object settled on.
546
+ return dateObject
547
+ } //DatePicker.prototype.validate
548
+
549
+
550
+ /**
551
+ * Check if a date is disabled.
552
+ */
553
+ DatePicker.prototype.disabled = function( dateToVerify ) {
554
+
555
+ var
556
+ calendar = this,
557
+
558
+ // Filter through the disabled dates to check if this is one.
559
+ isDisabledMatch = calendar.item.disable.filter( function( dateToDisable ) {
560
+
561
+ // If the date is a number, match the weekday with 0index and `firstDay` check.
562
+ if ( _.isInteger( dateToDisable ) ) {
563
+ return dateToVerify.day === ( calendar.settings.firstDay ? dateToDisable : dateToDisable - 1 ) % 7
564
+ }
565
+
566
+ // If it’s an array or a native JS date, create and match the exact date.
567
+ if ( $.isArray( dateToDisable ) || _.isDate( dateToDisable ) ) {
568
+ return dateToVerify.pick === calendar.create( dateToDisable ).pick
569
+ }
570
+
571
+ // If it’s an object, match a date within the “from” and “to” range.
572
+ if ( $.isPlainObject( dateToDisable ) ) {
573
+ return calendar.withinRange( dateToDisable, dateToVerify )
574
+ }
575
+ })
576
+
577
+ // If this date matches a disabled date, confirm it’s not inverted.
578
+ isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function( dateToDisable ) {
579
+ return $.isArray( dateToDisable ) && dateToDisable[3] == 'inverted' ||
580
+ $.isPlainObject( dateToDisable ) && dateToDisable.inverted
581
+ }).length
582
+
583
+ // Check the calendar “enabled” flag and respectively flip the
584
+ // disabled state. Then also check if it’s beyond the min/max limits.
585
+ return calendar.item.enable === -1 ? !isDisabledMatch : isDisabledMatch ||
586
+ dateToVerify.pick < calendar.item.min.pick ||
587
+ dateToVerify.pick > calendar.item.max.pick
588
+
589
+ } //DatePicker.prototype.disabled
590
+
591
+
592
+ /**
593
+ * Parse a string into a usable type.
594
+ */
595
+ DatePicker.prototype.parse = function( type, value, options ) {
596
+
597
+ var calendar = this,
598
+ parsingObject = {}
599
+
600
+ // If it’s already parsed, we’re good.
601
+ if ( !value || typeof value != 'string' ) {
602
+ return value
603
+ }
604
+
605
+ // We need a `.format` to parse the value with.
606
+ if ( !( options && options.format ) ) {
607
+ options = options || {}
608
+ options.format = calendar.settings.format
609
+ }
610
+
611
+ // Convert the format into an array and then map through it.
612
+ calendar.formats.toArray( options.format ).map( function( label ) {
613
+
614
+ var
615
+ // Grab the formatting label.
616
+ formattingLabel = calendar.formats[ label ],
617
+
618
+ // The format length is from the formatting label function or the
619
+ // label length without the escaping exclamation (!) mark.
620
+ formatLength = formattingLabel ? _.trigger( formattingLabel, calendar, [ value, parsingObject ] ) : label.replace( /^!/, '' ).length
621
+
622
+ // If there's a format label, split the value up to the format length.
623
+ // Then add it to the parsing object with appropriate label.
624
+ if ( formattingLabel ) {
625
+ parsingObject[ label ] = value.substr( 0, formatLength )
626
+ }
627
+
628
+ // Update the value as the substring from format length to end.
629
+ value = value.substr( formatLength )
630
+ })
631
+
632
+ // Compensate for month 0index.
633
+ return [
634
+ parsingObject.yyyy || parsingObject.yy,
635
+ +( parsingObject.mm || parsingObject.m ) - 1,
636
+ parsingObject.dd || parsingObject.d
637
+ ]
638
+ } //DatePicker.prototype.parse
639
+
640
+
641
+ /**
642
+ * Various formats to display the object in.
643
+ */
644
+ DatePicker.prototype.formats = (function() {
645
+
646
+ // Return the length of the first word in a collection.
647
+ function getWordLengthFromCollection( string, collection, dateObject ) {
648
+
649
+ // Grab the first word from the string.
650
+ // Regex pattern from http://stackoverflow.com/q/150033
651
+ var word = string.match( /[^\x00-\x7F]+|\w+/ )[ 0 ]
652
+
653
+ // If there's no month index, add it to the date object
654
+ if ( !dateObject.mm && !dateObject.m ) {
655
+ dateObject.m = collection.indexOf( word ) + 1
656
+ }
657
+
658
+ // Return the length of the word.
659
+ return word.length
660
+ }
661
+
662
+ // Get the length of the first word in a string.
663
+ function getFirstWordLength( string ) {
664
+ return string.match( /\w+/ )[ 0 ].length
665
+ }
666
+
667
+ return {
668
+
669
+ d: function( string, dateObject ) {
670
+
671
+ // If there's string, then get the digits length.
672
+ // Otherwise return the selected date.
673
+ return string ? _.digits( string ) : dateObject.date
674
+ },
675
+ dd: function( string, dateObject ) {
676
+
677
+ // If there's a string, then the length is always 2.
678
+ // Otherwise return the selected date with a leading zero.
679
+ return string ? 2 : _.lead( dateObject.date )
680
+ },
681
+ ddd: function( string, dateObject ) {
682
+
683
+ // If there's a string, then get the length of the first word.
684
+ // Otherwise return the short selected weekday.
685
+ return string ? getFirstWordLength( string ) : this.settings.weekdaysShort[ dateObject.day ]
686
+ },
687
+ dddd: function( string, dateObject ) {
688
+
689
+ // If there's a string, then get the length of the first word.
690
+ // Otherwise return the full selected weekday.
691
+ return string ? getFirstWordLength( string ) : this.settings.weekdaysFull[ dateObject.day ]
692
+ },
693
+ m: function( string, dateObject ) {
694
+
695
+ // If there's a string, then get the length of the digits
696
+ // Otherwise return the selected month with 0index compensation.
697
+ return string ? _.digits( string ) : dateObject.month + 1
698
+ },
699
+ mm: function( string, dateObject ) {
700
+
701
+ // If there's a string, then the length is always 2.
702
+ // Otherwise return the selected month with 0index and leading zero.
703
+ return string ? 2 : _.lead( dateObject.month + 1 )
704
+ },
705
+ mmm: function( string, dateObject ) {
706
+
707
+ var collection = this.settings.monthsShort
708
+
709
+ // If there's a string, get length of the relevant month from the short
710
+ // months collection. Otherwise return the selected month from that collection.
711
+ return string ? getWordLengthFromCollection( string, collection, dateObject ) : collection[ dateObject.month ]
712
+ },
713
+ mmmm: function( string, dateObject ) {
714
+
715
+ var collection = this.settings.monthsFull
716
+
717
+ // If there's a string, get length of the relevant month from the full
718
+ // months collection. Otherwise return the selected month from that collection.
719
+ return string ? getWordLengthFromCollection( string, collection, dateObject ) : collection[ dateObject.month ]
720
+ },
721
+ yy: function( string, dateObject ) {
722
+
723
+ // If there's a string, then the length is always 2.
724
+ // Otherwise return the selected year by slicing out the first 2 digits.
725
+ return string ? 2 : ( '' + dateObject.year ).slice( 2 )
726
+ },
727
+ yyyy: function( string, dateObject ) {
728
+
729
+ // If there's a string, then the length is always 4.
730
+ // Otherwise return the selected year.
731
+ return string ? 4 : dateObject.year
732
+ },
733
+
734
+ // Create an array by splitting the formatting string passed.
735
+ toArray: function( formatString ) { return formatString.split( /(d{1,4}|m{1,4}|y{4}|yy|!.)/g ) },
736
+
737
+ // Format an object into a string using the formatting options.
738
+ toString: function ( formatString, itemObject ) {
739
+ var calendar = this
740
+ return calendar.formats.toArray( formatString ).map( function( label ) {
741
+ return _.trigger( calendar.formats[ label ], calendar, [ 0, itemObject ] ) || label.replace( /^!/, '' )
742
+ }).join( '' )
743
+ }
744
+ }
745
+ })() //DatePicker.prototype.formats
746
+
747
+
748
+
749
+
750
+ /**
751
+ * Check if two date units are the exact.
752
+ */
753
+ DatePicker.prototype.isDateExact = function( one, two ) {
754
+
755
+ var calendar = this
756
+
757
+ // When we’re working with weekdays, do a direct comparison.
758
+ if (
759
+ ( _.isInteger( one ) && _.isInteger( two ) ) ||
760
+ ( typeof one == 'boolean' && typeof two == 'boolean' )
761
+ ) {
762
+ return one === two
763
+ }
764
+
765
+ // When we’re working with date representations, compare the “pick” value.
766
+ if (
767
+ ( _.isDate( one ) || $.isArray( one ) ) &&
768
+ ( _.isDate( two ) || $.isArray( two ) )
769
+ ) {
770
+ return calendar.create( one ).pick === calendar.create( two ).pick
771
+ }
772
+
773
+ // When we’re working with range objects, compare the “from” and “to”.
774
+ if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
775
+ return calendar.isDateExact( one.from, two.from ) && calendar.isDateExact( one.to, two.to )
776
+ }
777
+
778
+ return false
779
+ }
780
+
781
+
782
+ /**
783
+ * Check if two date units overlap.
784
+ */
785
+ DatePicker.prototype.isDateOverlap = function( one, two ) {
786
+
787
+ var calendar = this,
788
+ firstDay = calendar.settings.firstDay ? 1 : 0
789
+
790
+ // When we’re working with a weekday index, compare the days.
791
+ if ( _.isInteger( one ) && ( _.isDate( two ) || $.isArray( two ) ) ) {
792
+ one = one % 7 + firstDay
793
+ return one === calendar.create( two ).day + 1
794
+ }
795
+ if ( _.isInteger( two ) && ( _.isDate( one ) || $.isArray( one ) ) ) {
796
+ two = two % 7 + firstDay
797
+ return two === calendar.create( one ).day + 1
798
+ }
799
+
800
+ // When we’re working with range objects, check if the ranges overlap.
801
+ if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
802
+ return calendar.overlapRanges( one, two )
803
+ }
804
+
805
+ return false
806
+ }
807
+
808
+
809
+ /**
810
+ * Flip the “enabled” state.
811
+ */
812
+ DatePicker.prototype.flipEnable = function(val) {
813
+ var itemObject = this.item
814
+ itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1)
815
+ }
816
+
817
+
818
+ /**
819
+ * Mark a collection of dates as “disabled”.
820
+ */
821
+ DatePicker.prototype.deactivate = function( type, datesToDisable ) {
822
+
823
+ var calendar = this,
824
+ disabledItems = calendar.item.disable.slice(0)
825
+
826
+
827
+ // If we’re flipping, that’s all we need to do.
828
+ if ( datesToDisable == 'flip' ) {
829
+ calendar.flipEnable()
830
+ }
831
+
832
+ else if ( datesToDisable === false ) {
833
+ calendar.flipEnable(1)
834
+ disabledItems = []
835
+ }
836
+
837
+ else if ( datesToDisable === true ) {
838
+ calendar.flipEnable(-1)
839
+ disabledItems = []
840
+ }
841
+
842
+ // Otherwise go through the dates to disable.
843
+ else {
844
+
845
+ datesToDisable.map(function( unitToDisable ) {
846
+
847
+ var matchFound
848
+
849
+ // When we have disabled items, check for matches.
850
+ // If something is matched, immediately break out.
851
+ for ( var index = 0; index < disabledItems.length; index += 1 ) {
852
+ if ( calendar.isDateExact( unitToDisable, disabledItems[index] ) ) {
853
+ matchFound = true
854
+ break
855
+ }
856
+ }
857
+
858
+ // If nothing was found, add the validated unit to the collection.
859
+ if ( !matchFound ) {
860
+ if (
861
+ _.isInteger( unitToDisable ) ||
862
+ _.isDate( unitToDisable ) ||
863
+ $.isArray( unitToDisable ) ||
864
+ ( $.isPlainObject( unitToDisable ) && unitToDisable.from && unitToDisable.to )
865
+ ) {
866
+ disabledItems.push( unitToDisable )
867
+ }
868
+ }
869
+ })
870
+ }
871
+
872
+ // Return the updated collection.
873
+ return disabledItems
874
+ } //DatePicker.prototype.deactivate
875
+
876
+
877
+ /**
878
+ * Mark a collection of dates as “enabled”.
879
+ */
880
+ DatePicker.prototype.activate = function( type, datesToEnable ) {
881
+
882
+ var calendar = this,
883
+ disabledItems = calendar.item.disable,
884
+ disabledItemsCount = disabledItems.length
885
+
886
+ // If we’re flipping, that’s all we need to do.
887
+ if ( datesToEnable == 'flip' ) {
888
+ calendar.flipEnable()
889
+ }
890
+
891
+ else if ( datesToEnable === true ) {
892
+ calendar.flipEnable(1)
893
+ disabledItems = []
894
+ }
895
+
896
+ else if ( datesToEnable === false ) {
897
+ calendar.flipEnable(-1)
898
+ disabledItems = []
899
+ }
900
+
901
+ // Otherwise go through the disabled dates.
902
+ else {
903
+
904
+ datesToEnable.map(function( unitToEnable ) {
905
+
906
+ var matchFound,
907
+ disabledUnit,
908
+ index,
909
+ isExactRange
910
+
911
+ // Go through the disabled items and try to find a match.
912
+ for ( index = 0; index < disabledItemsCount; index += 1 ) {
913
+
914
+ disabledUnit = disabledItems[index]
915
+
916
+ // When an exact match is found, remove it from the collection.
917
+ if ( calendar.isDateExact( disabledUnit, unitToEnable ) ) {
918
+ matchFound = disabledItems[index] = null
919
+ isExactRange = true
920
+ break
921
+ }
922
+
923
+ // When an overlapped match is found, add the “inverted” state to it.
924
+ else if ( calendar.isDateOverlap( disabledUnit, unitToEnable ) ) {
925
+ if ( $.isPlainObject( unitToEnable ) ) {
926
+ unitToEnable.inverted = true
927
+ matchFound = unitToEnable
928
+ }
929
+ else if ( $.isArray( unitToEnable ) ) {
930
+ matchFound = unitToEnable
931
+ if ( !matchFound[3] ) matchFound.push( 'inverted' )
932
+ }
933
+ else if ( _.isDate( unitToEnable ) ) {
934
+ matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), 'inverted' ]
935
+ }
936
+ break
937
+ }
938
+ }
939
+
940
+ // If a match was found, remove a previous duplicate entry.
941
+ if ( matchFound ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
942
+ if ( calendar.isDateExact( disabledItems[index], unitToEnable ) ) {
943
+ disabledItems[index] = null
944
+ break
945
+ }
946
+ }
947
+
948
+ // In the event that we’re dealing with an exact range of dates,
949
+ // make sure there are no “inverted” dates because of it.
950
+ if ( isExactRange ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
951
+ if ( calendar.isDateOverlap( disabledItems[index], unitToEnable ) ) {
952
+ disabledItems[index] = null
953
+ break
954
+ }
955
+ }
956
+
957
+ // If something is still matched, add it into the collection.
958
+ if ( matchFound ) {
959
+ disabledItems.push( matchFound )
960
+ }
961
+ })
962
+ }
963
+
964
+ // Return the updated collection.
965
+ return disabledItems.filter(function( val ) { return val != null })
966
+ } //DatePicker.prototype.activate
967
+
968
+
969
+ /**
970
+ * Create a string for the nodes in the picker.
971
+ */
972
+ DatePicker.prototype.nodes = function( isOpen ) {
973
+
974
+ var
975
+ calendar = this,
976
+ settings = calendar.settings,
977
+ calendarItem = calendar.item,
978
+ nowObject = calendarItem.now,
979
+ selectedObject = calendarItem.select,
980
+ highlightedObject = calendarItem.highlight,
981
+ viewsetObject = calendarItem.view,
982
+ disabledCollection = calendarItem.disable,
983
+ minLimitObject = calendarItem.min,
984
+ maxLimitObject = calendarItem.max,
985
+
986
+
987
+ // Create the calendar table head using a copy of weekday labels collection.
988
+ // * We do a copy so we don't mutate the original array.
989
+ tableHead = (function( collection, fullCollection ) {
990
+
991
+ // If the first day should be Monday, move Sunday to the end.
992
+ if ( settings.firstDay ) {
993
+ collection.push( collection.shift() )
994
+ fullCollection.push( fullCollection.shift() )
995
+ }
996
+
997
+ // Create and return the table head group.
998
+ return _.node(
999
+ 'thead',
1000
+ _.node(
1001
+ 'tr',
1002
+ _.group({
1003
+ min: 0,
1004
+ max: DAYS_IN_WEEK - 1,
1005
+ i: 1,
1006
+ node: 'th',
1007
+ item: function( counter ) {
1008
+ return [
1009
+ collection[ counter ],
1010
+ settings.klass.weekdays,
1011
+ 'scope=col title="' + fullCollection[ counter ] + '"'
1012
+ ]
1013
+ }
1014
+ })
1015
+ )
1016
+ ) //endreturn
1017
+ })( ( settings.showWeekdaysFull ? settings.weekdaysFull : settings.weekdaysShort ).slice( 0 ), settings.weekdaysFull.slice( 0 ) ), //tableHead
1018
+
1019
+
1020
+ // Create the nav for next/prev month.
1021
+ createMonthNav = function( next ) {
1022
+
1023
+ // Otherwise, return the created month tag.
1024
+ return _.node(
1025
+ 'div',
1026
+ ' ',
1027
+ settings.klass[ 'nav' + ( next ? 'Next' : 'Prev' ) ] + (
1028
+
1029
+ // If the focused month is outside the range, disabled the button.
1030
+ ( next && viewsetObject.year >= maxLimitObject.year && viewsetObject.month >= maxLimitObject.month ) ||
1031
+ ( !next && viewsetObject.year <= minLimitObject.year && viewsetObject.month <= minLimitObject.month ) ?
1032
+ ' ' + settings.klass.navDisabled : ''
1033
+ ),
1034
+ 'data-nav=' + ( next || -1 ) + ' ' +
1035
+ _.ariaAttr({
1036
+ role: 'button',
1037
+ controls: calendar.$node[0].id + '_table'
1038
+ }) + ' ' +
1039
+ 'title="' + (next ? settings.labelMonthNext : settings.labelMonthPrev ) + '"'
1040
+ ) //endreturn
1041
+ }, //createMonthNav
1042
+
1043
+
1044
+ // Create the month label.
1045
+ createMonthLabel = function() {
1046
+
1047
+ var monthsCollection = settings.showMonthsShort ? settings.monthsShort : settings.monthsFull
1048
+
1049
+ // If there are months to select, add a dropdown menu.
1050
+ if ( settings.selectMonths ) {
1051
+
1052
+ return _.node( 'select',
1053
+ _.group({
1054
+ min: 0,
1055
+ max: 11,
1056
+ i: 1,
1057
+ node: 'option',
1058
+ item: function( loopedMonth ) {
1059
+
1060
+ return [
1061
+
1062
+ // The looped month and no classes.
1063
+ monthsCollection[ loopedMonth ], 0,
1064
+
1065
+ // Set the value and selected index.
1066
+ 'value=' + loopedMonth +
1067
+ ( viewsetObject.month == loopedMonth ? ' selected' : '' ) +
1068
+ (
1069
+ (
1070
+ ( viewsetObject.year == minLimitObject.year && loopedMonth < minLimitObject.month ) ||
1071
+ ( viewsetObject.year == maxLimitObject.year && loopedMonth > maxLimitObject.month )
1072
+ ) ?
1073
+ ' disabled' : ''
1074
+ )
1075
+ ]
1076
+ }
1077
+ }),
1078
+ settings.klass.selectMonth,
1079
+ ( isOpen ? '' : 'disabled' ) + ' ' +
1080
+ _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' +
1081
+ 'title="' + settings.labelMonthSelect + '"'
1082
+ )
1083
+ }
1084
+
1085
+ // If there's a need for a month selector
1086
+ return _.node( 'div', monthsCollection[ viewsetObject.month ], settings.klass.month )
1087
+ }, //createMonthLabel
1088
+
1089
+
1090
+ // Create the year label.
1091
+ createYearLabel = function() {
1092
+
1093
+ var focusedYear = viewsetObject.year,
1094
+
1095
+ // If years selector is set to a literal "true", set it to 5. Otherwise
1096
+ // divide in half to get half before and half after focused year.
1097
+ numberYears = settings.selectYears === true ? 5 : ~~( settings.selectYears / 2 )
1098
+
1099
+ // If there are years to select, add a dropdown menu.
1100
+ if ( numberYears ) {
1101
+
1102
+ var
1103
+ minYear = minLimitObject.year,
1104
+ maxYear = maxLimitObject.year,
1105
+ lowestYear = focusedYear - numberYears,
1106
+ highestYear = focusedYear + numberYears
1107
+
1108
+ // If the min year is greater than the lowest year, increase the highest year
1109
+ // by the difference and set the lowest year to the min year.
1110
+ if ( minYear > lowestYear ) {
1111
+ highestYear += minYear - lowestYear
1112
+ lowestYear = minYear
1113
+ }
1114
+
1115
+ // If the max year is less than the highest year, decrease the lowest year
1116
+ // by the lower of the two: available and needed years. Then set the
1117
+ // highest year to the max year.
1118
+ if ( maxYear < highestYear ) {
1119
+
1120
+ var availableYears = lowestYear - minYear,
1121
+ neededYears = highestYear - maxYear
1122
+
1123
+ lowestYear -= availableYears > neededYears ? neededYears : availableYears
1124
+ highestYear = maxYear
1125
+ }
1126
+
1127
+ return _.node( 'select',
1128
+ _.group({
1129
+ min: lowestYear,
1130
+ max: highestYear,
1131
+ i: 1,
1132
+ node: 'option',
1133
+ item: function( loopedYear ) {
1134
+ return [
1135
+
1136
+ // The looped year and no classes.
1137
+ loopedYear, 0,
1138
+
1139
+ // Set the value and selected index.
1140
+ 'value=' + loopedYear + ( focusedYear == loopedYear ? ' selected' : '' )
1141
+ ]
1142
+ }
1143
+ }),
1144
+ settings.klass.selectYear,
1145
+ ( isOpen ? '' : 'disabled' ) + ' ' + _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' +
1146
+ 'title="' + settings.labelYearSelect + '"'
1147
+ )
1148
+ }
1149
+
1150
+ // Otherwise just return the year focused
1151
+ return _.node( 'div', focusedYear, settings.klass.year )
1152
+ } //createYearLabel
1153
+
1154
+
1155
+ // Create and return the entire calendar.
1156
+ return _.node(
1157
+ 'div',
1158
+ ( settings.selectYears ? createYearLabel() + createMonthLabel() : createMonthLabel() + createYearLabel() ) +
1159
+ createMonthNav() + createMonthNav( 1 ),
1160
+ settings.klass.header
1161
+ ) + _.node(
1162
+ 'table',
1163
+ tableHead +
1164
+ _.node(
1165
+ 'tbody',
1166
+ _.group({
1167
+ min: 0,
1168
+ max: WEEKS_IN_CALENDAR - 1,
1169
+ i: 1,
1170
+ node: 'tr',
1171
+ item: function( rowCounter ) {
1172
+
1173
+ // If Monday is the first day and the month starts on Sunday, shift the date back a week.
1174
+ var shiftDateBy = settings.firstDay && calendar.create([ viewsetObject.year, viewsetObject.month, 1 ]).day === 0 ? -7 : 0
1175
+
1176
+ return [
1177
+ _.group({
1178
+ min: DAYS_IN_WEEK * rowCounter - viewsetObject.day + shiftDateBy + 1, // Add 1 for weekday 0index
1179
+ max: function() {
1180
+ return this.min + DAYS_IN_WEEK - 1
1181
+ },
1182
+ i: 1,
1183
+ node: 'td',
1184
+ item: function( targetDate ) {
1185
+
1186
+ // Convert the time date from a relative date to a target date.
1187
+ targetDate = calendar.create([ viewsetObject.year, viewsetObject.month, targetDate + ( settings.firstDay ? 1 : 0 ) ])
1188
+
1189
+ var isSelected = selectedObject && selectedObject.pick == targetDate.pick,
1190
+ isHighlighted = highlightedObject && highlightedObject.pick == targetDate.pick,
1191
+ isDisabled = disabledCollection && calendar.disabled( targetDate ) || targetDate.pick < minLimitObject.pick || targetDate.pick > maxLimitObject.pick,
1192
+ formattedDate = _.trigger( calendar.formats.toString, calendar, [ settings.format, targetDate ] )
1193
+
1194
+ return [
1195
+ _.node(
1196
+ 'div',
1197
+ targetDate.date,
1198
+ (function( klasses ) {
1199
+
1200
+ // Add the `infocus` or `outfocus` classes based on month in view.
1201
+ klasses.push( viewsetObject.month == targetDate.month ? settings.klass.infocus : settings.klass.outfocus )
1202
+
1203
+ // Add the `today` class if needed.
1204
+ if ( nowObject.pick == targetDate.pick ) {
1205
+ klasses.push( settings.klass.now )
1206
+ }
1207
+
1208
+ // Add the `selected` class if something's selected and the time matches.
1209
+ if ( isSelected ) {
1210
+ klasses.push( settings.klass.selected )
1211
+ }
1212
+
1213
+ // Add the `highlighted` class if something's highlighted and the time matches.
1214
+ if ( isHighlighted ) {
1215
+ klasses.push( settings.klass.highlighted )
1216
+ }
1217
+
1218
+ // Add the `disabled` class if something's disabled and the object matches.
1219
+ if ( isDisabled ) {
1220
+ klasses.push( settings.klass.disabled )
1221
+ }
1222
+
1223
+ return klasses.join( ' ' )
1224
+ })([ settings.klass.day ]),
1225
+ 'data-pick=' + targetDate.pick + ' ' + _.ariaAttr({
1226
+ role: 'gridcell',
1227
+ label: formattedDate,
1228
+ selected: isSelected && calendar.$node.val() === formattedDate ? true : null,
1229
+ activedescendant: isHighlighted ? true : null,
1230
+ disabled: isDisabled ? true : null
1231
+ })
1232
+ ),
1233
+ '',
1234
+ _.ariaAttr({ role: 'presentation' })
1235
+ ] //endreturn
1236
+ }
1237
+ })
1238
+ ] //endreturn
1239
+ }
1240
+ })
1241
+ ),
1242
+ settings.klass.table,
1243
+ 'id="' + calendar.$node[0].id + '_table' + '" ' + _.ariaAttr({
1244
+ role: 'grid',
1245
+ controls: calendar.$node[0].id,
1246
+ readonly: true
1247
+ })
1248
+ ) +
1249
+
1250
+ // * For Firefox forms to submit, make sure to set the buttons’ `type` attributes as “button”.
1251
+ _.node(
1252
+ 'div',
1253
+ _.node( 'button', settings.today, settings.klass.buttonToday,
1254
+ 'type=button data-pick=' + nowObject.pick +
1255
+ ( isOpen && !calendar.disabled(nowObject) ? '' : ' disabled' ) + ' ' +
1256
+ _.ariaAttr({ controls: calendar.$node[0].id }) ) +
1257
+ _.node( 'button', settings.clear, settings.klass.buttonClear,
1258
+ 'type=button data-clear=1' +
1259
+ ( isOpen ? '' : ' disabled' ) + ' ' +
1260
+ _.ariaAttr({ controls: calendar.$node[0].id }) ) +
1261
+ _.node('button', settings.close, settings.klass.buttonClose,
1262
+ 'type=button data-close=true ' +
1263
+ ( isOpen ? '' : ' disabled' ) + ' ' +
1264
+ _.ariaAttr({ controls: calendar.$node[0].id }) ),
1265
+ settings.klass.footer
1266
+ ) //endreturn
1267
+ } //DatePicker.prototype.nodes
1268
+
1269
+
1270
+
1271
+
1272
+ /**
1273
+ * The date picker defaults.
1274
+ */
1275
+ DatePicker.defaults = (function( prefix ) {
1276
+
1277
+ return {
1278
+
1279
+ // The title label to use for the month nav buttons
1280
+ labelMonthNext: 'Next month',
1281
+ labelMonthPrev: 'Previous month',
1282
+
1283
+ // The title label to use for the dropdown selectors
1284
+ labelMonthSelect: 'Select a month',
1285
+ labelYearSelect: 'Select a year',
1286
+
1287
+ // Months and weekdays
1288
+ monthsFull: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ],
1289
+ monthsShort: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
1290
+ weekdaysFull: [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ],
1291
+ weekdaysShort: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ],
1292
+
1293
+ // Today and clear
1294
+ today: 'Today',
1295
+ clear: 'Clear',
1296
+ close: 'Close',
1297
+
1298
+ // Picker close behavior
1299
+ closeOnSelect: true,
1300
+ closeOnClear: true,
1301
+
1302
+ // Update input value on select/clear
1303
+ updateInput: true,
1304
+
1305
+ // The format to show on the `input` element
1306
+ format: 'd mmmm, yyyy',
1307
+
1308
+ // Classes
1309
+ klass: {
1310
+
1311
+ table: prefix + 'table',
1312
+
1313
+ header: prefix + 'header',
1314
+
1315
+ navPrev: prefix + 'nav--prev',
1316
+ navNext: prefix + 'nav--next',
1317
+ navDisabled: prefix + 'nav--disabled',
1318
+
1319
+ month: prefix + 'month',
1320
+ year: prefix + 'year',
1321
+
1322
+ selectMonth: prefix + 'select--month',
1323
+ selectYear: prefix + 'select--year',
1324
+
1325
+ weekdays: prefix + 'weekday',
1326
+
1327
+ day: prefix + 'day',
1328
+ disabled: prefix + 'day--disabled',
1329
+ selected: prefix + 'day--selected',
1330
+ highlighted: prefix + 'day--highlighted',
1331
+ now: prefix + 'day--today',
1332
+ infocus: prefix + 'day--infocus',
1333
+ outfocus: prefix + 'day--outfocus',
1334
+
1335
+ footer: prefix + 'footer',
1336
+
1337
+ buttonClear: prefix + 'button--clear',
1338
+ buttonToday: prefix + 'button--today',
1339
+ buttonClose: prefix + 'button--close'
1340
+ }
1341
+ }
1342
+ })( Picker.klasses().picker + '__' )
1343
+
1344
+
1345
+
1346
+
1347
+
1348
+ /**
1349
+ * Extend the picker to add the date picker.
1350
+ */
1351
+ Picker.extend( 'pickadate', DatePicker )
1352
+
1353
+
1354
+ }));
1355
+
1356
+
1357
+
js/pickadate/picker.js CHANGED
@@ -1,179 +1,1224 @@
1
- /*!
2
- * pickadate.js v3.4.0, 2014/02/15
3
- * By Amsul, http://amsul.ca
4
- * Hosted on http://amsul.github.io/pickadate.js
5
- * Licensed under MIT
6
- */
7
- !function (a) {
8
- "function" == typeof define && define.amd ? define("picker", ["jquery"], a) : this.Picker = a(jQuery)
9
- }(function (a) {
10
- function b(d, e, g, h) {
11
- function i() {
12
- return b._.node("div", b._.node("div", b._.node("div", b._.node("div", s.component.nodes(n.open), p.box), p.wrap), p.frame), p.holder)
13
- }
14
-
15
- function j() {
16
- q.data(e, s).addClass(p.input).val(q.data("value") ? s.get("select", o.format) : d.value).on("focus." + n.id + " click." + n.id, m), o.editable || q.on("keydown." + n.id, function (a) {
17
- var b = a.keyCode, c = /^(8|46)$/.test(b);
18
- return 27 == b ? (s.close(), !1) : void((32 == b || c || !n.open && s.component.key[b]) && (a.preventDefault(), a.stopPropagation(), c ? s.clear().close() : s.open()))
19
- }), c(d, {
20
- haspopup: !0,
21
- expanded: !1,
22
- readonly: !1,
23
- owns: d.id + "_root" + (s._hidden ? " " + s._hidden.id : "")
24
- })
25
- }
26
-
27
- function k() {
28
- s.$root.on({
29
- focusin: function (a) {
30
- s.$root.removeClass(p.focused), c(s.$root[0], "selected", !1), a.stopPropagation()
31
- }, "mousedown click": function (b) {
32
- var c = b.target;
33
- c != s.$root.children()[0] && (b.stopPropagation(), "mousedown" != b.type || a(c).is(":input") || "OPTION" == c.nodeName || (b.preventDefault(), d.focus()))
34
- }
35
- }).on("click", "[data-pick], [data-nav], [data-clear]", function () {
36
- var c = a(this), e = c.data(), f = c.hasClass(p.navDisabled) || c.hasClass(p.disabled), g = document.activeElement;
37
- g = g && (g.type || g.href) && g, (f || g && !a.contains(s.$root[0], g)) && d.focus(), e.nav && !f ? s.set("highlight", s.component.item.highlight, {nav: e.nav}) : b._.isInteger(e.pick) && !f ? s.set("select", e.pick).close(!0) : e.clear && s.clear().close(!0)
38
- }), c(s.$root[0], "hidden", !0)
39
- }
40
-
41
- function l() {
42
- var b = ["string" == typeof o.hiddenPrefix ? o.hiddenPrefix : "", "string" == typeof o.hiddenSuffix ? o.hiddenSuffix : "_submit"];
43
- s._hidden = a('<input type=hidden name="' + b[0] + d.name + b[1] + '"id="' + b[0] + d.id + b[1] + '"' + (q.data("value") || d.value ? ' value="' + s.get("select", o.formatSubmit) + '"' : "") + ">")[0], q.on("change." + n.id, function () {
44
- s._hidden.value = d.value ? s.get("select", o.formatSubmit) : ""
45
- }).after(s._hidden)
46
- }
47
-
48
- function m(a) {
49
- a.stopPropagation(), "focus" == a.type && (s.$root.addClass(p.focused), c(s.$root[0], "selected", !0)), s.open()
50
- }
51
-
52
- if (!d)return b;
53
- var n = {id: d.id || "P" + Math.abs(~~(Math.random() * new Date))}, o = g ? a.extend(!0, {}, g.defaults, h) : h || {}, p = a.extend({}, b.klasses(), o.klass), q = a(d), r = function () {
54
- return this.start()
55
- }, s = r.prototype = {
56
- constructor: r, $node: q, start: function () {
57
- return n && n.start ? s : (n.methods = {}, n.start = !0, n.open = !1, n.type = d.type, d.autofocus = d == document.activeElement, d.type = "text", d.readOnly = !o.editable, d.id = d.id || n.id, s.component = new g(s, o), s.$root = a(b._.node("div", i(), p.picker, 'id="' + d.id + '_root"')), k(), o.formatSubmit && l(), j(), o.container ? a(o.container).append(s.$root) : q.after(s.$root), s.on({
58
- start: s.component.onStart,
59
- render: s.component.onRender,
60
- stop: s.component.onStop,
61
- open: s.component.onOpen,
62
- close: s.component.onClose,
63
- set: s.component.onSet
64
- }).on({
65
- start: o.onStart,
66
- render: o.onRender,
67
- stop: o.onStop,
68
- open: o.onOpen,
69
- close: o.onClose,
70
- set: o.onSet
71
- }), d.autofocus && s.open(), s.trigger("start").trigger("render"))
72
- }, render: function (a) {
73
- return a ? s.$root.html(i()) : s.$root.find("." + p.box).html(s.component.nodes(n.open)), s.trigger("render")
74
- }, stop: function () {
75
- return n.start ? (s.close(), s._hidden && s._hidden.parentNode.removeChild(s._hidden), s.$root.remove(), q.removeClass(p.input).removeData(e), setTimeout(function () {
76
- q.off("." + n.id)
77
- }, 0), d.type = n.type, d.readOnly = !1, s.trigger("stop"), n.methods = {}, n.start = !1, s) : s
78
- }, open: function (e) {
79
- return n.open ? s : (q.addClass(p.active), c(d, "expanded", !0), s.$root.addClass(p.opened), c(s.$root[0], "hidden", !1), e !== !1 && (n.open = !0, q.trigger("focus"), f.on("click." + n.id + " focusin." + n.id, function (a) {
80
- var b = a.target;
81
- b != d && b != document && 3 != a.which && s.close(b === s.$root.children()[0])
82
- }).on("keydown." + n.id, function (c) {
83
- var e = c.keyCode, f = s.component.key[e], g = c.target;
84
- 27 == e ? s.close(!0) : g != d || !f && 13 != e ? a.contains(s.$root[0], g) && 13 == e && (c.preventDefault(), g.click()) : (c.preventDefault(), f ? b._.trigger(s.component.key.go, s, [b._.trigger(f)]) : s.$root.find("." + p.highlighted).hasClass(p.disabled) || s.set("select", s.component.item.highlight).close())
85
- })), s.trigger("open"))
86
- }, close: function (a) {
87
- return a && (q.off("focus." + n.id).trigger("focus"), setTimeout(function () {
88
- q.on("focus." + n.id, m)
89
- }, 0)), q.removeClass(p.active), c(d, "expanded", !1), s.$root.removeClass(p.opened + " " + p.focused), c(s.$root[0], "hidden", !0), c(s.$root[0], "selected", !1), n.open ? (n.open = !1, f.off("." + n.id), s.trigger("close")) : s
90
- }, clear: function () {
91
- return s.set("clear")
92
- }, set: function (b, c, d) {
93
- var e, f, g = a.isPlainObject(b), h = g ? b : {};
94
- if (d = g && a.isPlainObject(c) ? c : d || {}, b) {
95
- g || (h[b] = c);
96
- for (e in h)f = h[e], e in s.component.item && s.component.set(e, f, d), ("select" == e || "clear" == e) && q.val("clear" == e ? "" : s.get(e, o.format)).trigger("change");
97
- s.render()
98
- }
99
- return d.muted ? s : s.trigger("set", h)
100
- }, get: function (a, c) {
101
- return a = a || "value", null != n[a] ? n[a] : "value" == a ? d.value : a in s.component.item ? "string" == typeof c ? b._.trigger(s.component.formats.toString, s.component, [c, s.component.get(a)]) : s.component.get(a) : void 0
102
- }, on: function (b, c) {
103
- var d, e, f = a.isPlainObject(b), g = f ? b : {};
104
- if (b) {
105
- f || (g[b] = c);
106
- for (d in g)e = g[d], n.methods[d] = n.methods[d] || [], n.methods[d].push(e)
107
- }
108
- return s
109
- }, off: function () {
110
- var a, b, c = arguments;
111
- for (a = 0, namesCount = c.length; namesCount > a; a += 1)b = c[a], b in n.methods && delete n.methods[b];
112
- return s
113
- }, trigger: function (a, c) {
114
- var d = n.methods[a];
115
- return d && d.map(function (a) {
116
- b._.trigger(a, s, [c])
117
- }), s
118
- }
119
- };
120
- return new r
121
- }
122
-
123
- function c(b, c, e) {
124
- if (a.isPlainObject(c))for (var f in c)d(b, f, c[f]); else d(b, c, e)
125
- }
126
-
127
- function d(a, b, c) {
128
- a.setAttribute(("role" == b ? "" : "aria-") + b, c)
129
- }
130
-
131
- function e(b, c) {
132
- a.isPlainObject(b) || (b = {attribute: c}), c = "";
133
- for (var d in b) {
134
- var e = ("role" == d ? "" : "aria-") + d, f = b[d];
135
- c += null == f ? "" : e + '="' + b[d] + '"'
136
- }
137
- return c
138
- }
139
-
140
- var f = a(document);
141
- return b.klasses = function (a) {
142
- return a = a || "picker", {
143
- picker: a,
144
- opened: a + "--opened",
145
- focused: a + "--focused",
146
- input: a + "__input",
147
- active: a + "__input--active",
148
- holder: a + "__holder",
149
- frame: a + "__frame",
150
- wrap: a + "__wrap",
151
- box: a + "__box"
152
- }
153
- }, b._ = {
154
- group: function (a) {
155
- for (var c, d = "", e = b._.trigger(a.min, a); e <= b._.trigger(a.max, a, [e]); e += a.i)c = b._.trigger(a.item, a, [e]), d += b._.node(a.node, c[0], c[1], c[2]);
156
- return d
157
- }, node: function (b, c, d, e) {
158
- return c ? (c = a.isArray(c) ? c.join("") : c, d = d ? ' class="' + d + '"' : "", e = e ? " " + e : "", "<" + b + d + e + ">" + c + "</" + b + ">") : ""
159
- }, lead: function (a) {
160
- return (10 > a ? "0" : "") + a
161
- }, trigger: function (a, b, c) {
162
- return "function" == typeof a ? a.apply(b, c || []) : a
163
- }, digits: function (a) {
164
- return /\d/.test(a[1]) ? 2 : 1
165
- }, isDate: function (a) {
166
- return {}.toString.call(a).indexOf("Date") > -1 && this.isInteger(a.getDate())
167
- }, isInteger: function (a) {
168
- return {}.toString.call(a).indexOf("Number") > -1 && a % 1 === 0
169
- }, ariaAttr: e
170
- }, b.extend = function (c, d) {
171
- a.fn[c] = function (e, f) {
172
- var g = this.data(c);
173
- return "picker" == e ? g : g && "string" == typeof e ? (b._.trigger(g[e], g, [f]), this) : this.each(function () {
174
- var f = a(this);
175
- f.data(c) || new b(this, c, d, e)
176
- })
177
- }, a.fn[c].defaults = d.defaults
178
- }, b
179
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * pickadate.js v3.6.4, 2019/05/25
3
+ * By Amsul, http://amsul.ca
4
+ * Hosted on http://amsul.github.io/pickadate.js
5
+ * Licensed under MIT
6
+ */
7
+
8
+ (function ( factory ) {
9
+
10
+ // AMD.
11
+ if ( typeof define == 'function' && define.amd )
12
+ define( 'picker', ['jquery'], factory )
13
+
14
+ // Node.js/browserify.
15
+ else if ( typeof exports == 'object' )
16
+ module.exports = factory( require('jquery') )
17
+
18
+ // Browser globals.
19
+ else if ( typeof window == 'object' )
20
+ window.Picker = factory( jQuery )
21
+
22
+ else this.Picker = factory( jQuery )
23
+
24
+ }(function( $ ) {
25
+
26
+ var $window = $( window )
27
+ var $document = $( document )
28
+ var $html = $( document.documentElement )
29
+ var supportsTransitions = document.documentElement.style.transition != null
30
+
31
+
32
+ /**
33
+ * The picker constructor that creates a blank picker.
34
+ */
35
+ function PickerConstructor( ELEMENT, NAME, COMPONENT, OPTIONS ) {
36
+
37
+ // If there’s no element, return the picker constructor.
38
+ if ( !ELEMENT ) return PickerConstructor
39
+
40
+
41
+ var
42
+ IS_DEFAULT_THEME = false,
43
+
44
+
45
+ // The state of the picker.
46
+ STATE = {
47
+ id: ELEMENT.id || 'P' + Math.abs( ~~(Math.random() * new Date()) ),
48
+ handlingOpen: false,
49
+ },
50
+
51
+
52
+ // Merge the defaults and options passed.
53
+ SETTINGS = COMPONENT ? $.extend( true, {}, COMPONENT.defaults, OPTIONS ) : OPTIONS || {},
54
+
55
+
56
+ // Merge the default classes with the settings classes.
57
+ CLASSES = $.extend( {}, PickerConstructor.klasses(), SETTINGS.klass ),
58
+
59
+
60
+ // The element node wrapper into a jQuery object.
61
+ $ELEMENT = $( ELEMENT ),
62
+
63
+
64
+ // Pseudo picker constructor.
65
+ PickerInstance = function() {
66
+ return this.start()
67
+ },
68
+
69
+
70
+ // The picker prototype.
71
+ P = PickerInstance.prototype = {
72
+
73
+ constructor: PickerInstance,
74
+
75
+ $node: $ELEMENT,
76
+
77
+
78
+ /**
79
+ * Initialize everything
80
+ */
81
+ start: function() {
82
+
83
+ // If it’s already started, do nothing.
84
+ if ( STATE && STATE.start ) return P
85
+
86
+
87
+ // Update the picker states.
88
+ STATE.methods = {}
89
+ STATE.start = true
90
+ STATE.open = false
91
+ STATE.type = ELEMENT.type
92
+
93
+
94
+ // Confirm focus state, convert into text input to remove UA stylings,
95
+ // and set as readonly to prevent keyboard popup.
96
+ ELEMENT.autofocus = ELEMENT == getActiveElement()
97
+ ELEMENT.readOnly = !SETTINGS.editable
98
+ ELEMENT.id = ELEMENT.id || STATE.id
99
+ if ( ELEMENT.type != 'text' ) {
100
+ ELEMENT.type = 'text'
101
+ }
102
+
103
+
104
+ // Create a new picker component with the settings.
105
+ P.component = new COMPONENT(P, SETTINGS)
106
+
107
+
108
+ // Create the picker root and then prepare it.
109
+ P.$root = $( '<div class="' + CLASSES.picker + '" id="' + ELEMENT.id + '_root" />' )
110
+ prepareElementRoot()
111
+
112
+
113
+ // Create the picker holder and then prepare it.
114
+ P.$holder = $( createWrappedComponent() ).appendTo( P.$root )
115
+ prepareElementHolder()
116
+
117
+
118
+ // If there’s a format for the hidden input element, create the element.
119
+ if ( SETTINGS.formatSubmit ) {
120
+ prepareElementHidden()
121
+ }
122
+
123
+
124
+ // Prepare the input element.
125
+ prepareElement()
126
+
127
+
128
+ // Insert the hidden input as specified in the settings.
129
+ if ( SETTINGS.containerHidden ) $( SETTINGS.containerHidden ).append( P._hidden )
130
+ else $ELEMENT.after( P._hidden )
131
+
132
+
133
+ // Insert the root as specified in the settings.
134
+ if ( SETTINGS.container ) $( SETTINGS.container ).append( P.$root )
135
+ else $ELEMENT.after( P.$root )
136
+
137
+
138
+ // Bind the default component and settings events.
139
+ P.on({
140
+ start: P.component.onStart,
141
+ render: P.component.onRender,
142
+ stop: P.component.onStop,
143
+ open: P.component.onOpen,
144
+ close: P.component.onClose,
145
+ set: P.component.onSet
146
+ }).on({
147
+ start: SETTINGS.onStart,
148
+ render: SETTINGS.onRender,
149
+ stop: SETTINGS.onStop,
150
+ open: SETTINGS.onOpen,
151
+ close: SETTINGS.onClose,
152
+ set: SETTINGS.onSet
153
+ })
154
+
155
+
156
+ // Once we’re all set, check the theme in use.
157
+ IS_DEFAULT_THEME = isUsingDefaultTheme( P.$holder[0] )
158
+
159
+
160
+ // If the element has autofocus, open the picker.
161
+ if ( ELEMENT.autofocus ) {
162
+ P.open()
163
+ }
164
+
165
+
166
+ // Trigger queued the “start” and “render” events.
167
+ return P.trigger( 'start' ).trigger( 'render' )
168
+ }, //start
169
+
170
+
171
+ /**
172
+ * Render a new picker
173
+ */
174
+ render: function( entireComponent ) {
175
+
176
+ // Insert a new component holder in the root or box.
177
+ if ( entireComponent ) {
178
+ P.$holder = $( createWrappedComponent() )
179
+ prepareElementHolder()
180
+ P.$root.html( P.$holder )
181
+ }
182
+ else P.$root.find( '.' + CLASSES.box ).html( P.component.nodes( STATE.open ) )
183
+
184
+ // Trigger the queued “render” events.
185
+ return P.trigger( 'render' )
186
+ }, //render
187
+
188
+
189
+ /**
190
+ * Destroy everything
191
+ */
192
+ stop: function() {
193
+
194
+ // If it’s already stopped, do nothing.
195
+ if ( !STATE.start ) return P
196
+
197
+ // Then close the picker.
198
+ P.close()
199
+
200
+ // Remove the hidden field.
201
+ if ( P._hidden ) {
202
+ P._hidden.parentNode.removeChild( P._hidden )
203
+ }
204
+
205
+ // Remove the root.
206
+ P.$root.remove()
207
+
208
+ // Remove the input class, remove the stored data, and unbind
209
+ // the events (after a tick for IE - see `P.close`).
210
+ $ELEMENT.removeClass( CLASSES.input ).removeData( NAME )
211
+ setTimeout( function() {
212
+ $ELEMENT.off( '.' + STATE.id )
213
+ }, 0)
214
+
215
+ // Restore the element state
216
+ ELEMENT.type = STATE.type
217
+ ELEMENT.readOnly = false
218
+
219
+ // Trigger the queued “stop” events.
220
+ P.trigger( 'stop' )
221
+
222
+ // Reset the picker states.
223
+ STATE.methods = {}
224
+ STATE.start = false
225
+
226
+ return P
227
+ }, //stop
228
+
229
+
230
+ /**
231
+ * Open up the picker
232
+ */
233
+ open: function( dontGiveFocus ) {
234
+
235
+ // If it’s already open, do nothing.
236
+ if ( STATE.open ) return P
237
+
238
+ // Add the “active” class.
239
+ $ELEMENT.addClass( CLASSES.active )
240
+ aria( ELEMENT, 'expanded', true )
241
+
242
+ // * A Firefox bug, when `html` has `overflow:hidden`, results in
243
+ // killing transitions :(. So add the “opened” state on the next tick.
244
+ // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289
245
+ setTimeout( function() {
246
+
247
+ // Add the “opened” class to the picker root.
248
+ P.$root.addClass( CLASSES.opened )
249
+ aria( P.$root[0], 'hidden', false )
250
+
251
+ }, 0 )
252
+
253
+ // If we have to give focus, bind the element and doc events.
254
+ if ( dontGiveFocus !== false ) {
255
+
256
+ // Set it as open.
257
+ STATE.open = true
258
+
259
+ // Prevent the page from scrolling.
260
+ if ( IS_DEFAULT_THEME ) {
261
+ $('body').
262
+ css( 'overflow', 'hidden' ).
263
+ css( 'padding-right', '+=' + getScrollbarWidth() )
264
+ }
265
+
266
+ // Pass focus to the root element’s jQuery object.
267
+ focusPickerOnceOpened()
268
+
269
+ // Bind the document events.
270
+ $document.on( 'click.' + STATE.id + ' focusin.' + STATE.id, function( event ) {
271
+ // If the picker is currently midway through processing
272
+ // the opening sequence of events then don't handle clicks
273
+ // on any part of the DOM. This is caused by a bug in Chrome 73
274
+ // where a click event is being generated with the incorrect
275
+ // path in it.
276
+ // In short, if someone does a click that finishes after the
277
+ // new element is created then the path contains only the
278
+ // parent element and not the input element itself.
279
+ if (STATE.handlingOpen) {
280
+ return;
281
+ }
282
+
283
+ var target = getRealEventTarget( event, ELEMENT )
284
+
285
+ // If the target of the event is not the element, close the picker picker.
286
+ // * Don’t worry about clicks or focusins on the root because those don’t bubble up.
287
+ // Also, for Firefox, a click on an `option` element bubbles up directly
288
+ // to the doc. So make sure the target wasn't the doc.
289
+ // * In Firefox stopPropagation() doesn’t prevent right-click events from bubbling,
290
+ // which causes the picker to unexpectedly close when right-clicking it. So make
291
+ // sure the event wasn’t a right-click.
292
+ // * In Chrome 62 and up, password autofill causes a simulated focusin event which
293
+ // closes the picker.
294
+ if ( ! event.isSimulated && target != ELEMENT && target != document && event.which != 3 ) {
295
+
296
+ // If the target was the holder that covers the screen,
297
+ // keep the element focused to maintain tabindex.
298
+ P.close( target === P.$holder[0] )
299
+ }
300
+
301
+ }).on( 'keydown.' + STATE.id, function( event ) {
302
+
303
+ var
304
+ // Get the keycode.
305
+ keycode = event.keyCode,
306
+
307
+ // Translate that to a selection change.
308
+ keycodeToMove = P.component.key[ keycode ],
309
+
310
+ // Grab the target.
311
+ target = getRealEventTarget( event, ELEMENT )
312
+
313
+
314
+ // On escape, close the picker and give focus.
315
+ if ( keycode == 27 ) {
316
+ P.close( true )
317
+ }
318
+
319
+
320
+ // Check if there is a key movement or “enter” keypress on the element.
321
+ else if ( target == P.$holder[0] && ( keycodeToMove || keycode == 13 ) ) {
322
+
323
+ // Prevent the default action to stop page movement.
324
+ event.preventDefault()
325
+
326
+ // Trigger the key movement action.
327
+ if ( keycodeToMove ) {
328
+ PickerConstructor._.trigger( P.component.key.go, P, [ PickerConstructor._.trigger( keycodeToMove ) ] )
329
+ }
330
+
331
+ // On “enter”, if the highlighted item isn’t disabled, set the value and close.
332
+ else if ( !P.$root.find( '.' + CLASSES.highlighted ).hasClass( CLASSES.disabled ) ) {
333
+ P.set( 'select', P.component.item.highlight )
334
+ if ( SETTINGS.closeOnSelect ) {
335
+ P.close( true )
336
+ }
337
+ }
338
+ }
339
+
340
+
341
+ // If the target is within the root and “enter” is pressed,
342
+ // prevent the default action and trigger a click on the target instead.
343
+ else if ( $.contains( P.$root[0], target ) && keycode == 13 ) {
344
+ event.preventDefault()
345
+ target.click()
346
+ }
347
+ })
348
+ }
349
+
350
+ // Trigger the queued “open” events.
351
+ return P.trigger( 'open' )
352
+ }, //open
353
+
354
+
355
+ /**
356
+ * Close the picker
357
+ */
358
+ close: function( giveFocus ) {
359
+
360
+ // If we need to give focus, do it before changing states.
361
+ if ( giveFocus ) {
362
+ if ( SETTINGS.editable ) {
363
+ ELEMENT.focus()
364
+ }
365
+ else {
366
+ // ....ah yes! It would’ve been incomplete without a crazy workaround for IE :|
367
+ // The focus is triggered *after* the close has completed - causing it
368
+ // to open again. So unbind and rebind the event at the next tick.
369
+ P.$holder.off( 'focus.toOpen' ).focus()
370
+ setTimeout( function() {
371
+ P.$holder.on( 'focus.toOpen', handleFocusToOpenEvent )
372
+ }, 0 )
373
+ }
374
+ }
375
+
376
+ // Remove the “active” class.
377
+ $ELEMENT.removeClass( CLASSES.active )
378
+ aria( ELEMENT, 'expanded', false )
379
+
380
+ // * A Firefox bug, when `html` has `overflow:hidden`, results in
381
+ // killing transitions :(. So remove the “opened” state on the next tick.
382
+ // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289
383
+ setTimeout( function() {
384
+
385
+ // Remove the “opened” and “focused” class from the picker root.
386
+ P.$root.removeClass( CLASSES.opened + ' ' + CLASSES.focused )
387
+ aria( P.$root[0], 'hidden', true )
388
+
389
+ }, 0 )
390
+
391
+ // If it’s already closed, do nothing more.
392
+ if ( !STATE.open ) return P
393
+
394
+ // Set it as closed.
395
+ STATE.open = false
396
+
397
+ // Allow the page to scroll.
398
+ if ( IS_DEFAULT_THEME ) {
399
+ $('body').
400
+ css( 'overflow', '' ).
401
+ css( 'padding-right', '-=' + getScrollbarWidth() )
402
+ }
403
+
404
+ // Unbind the document events.
405
+ $document.off( '.' + STATE.id )
406
+
407
+ // Trigger the queued “close” events.
408
+ return P.trigger( 'close' )
409
+ }, //close
410
+
411
+
412
+ /**
413
+ * Clear the values
414
+ */
415
+ clear: function( options ) {
416
+ return P.set( 'clear', null, options )
417
+ }, //clear
418
+
419
+
420
+ /**
421
+ * Set something
422
+ */
423
+ set: function( thing, value, options ) {
424
+
425
+ var thingItem, thingValue,
426
+ thingIsObject = $.isPlainObject( thing ),
427
+ thingObject = thingIsObject ? thing : {}
428
+
429
+ // Make sure we have usable options.
430
+ options = thingIsObject && $.isPlainObject( value ) ? value : options || {}
431
+
432
+ if ( thing ) {
433
+
434
+ // If the thing isn’t an object, make it one.
435
+ if ( !thingIsObject ) {
436
+ thingObject[ thing ] = value
437
+ }
438
+
439
+ // Go through the things of items to set.
440
+ for ( thingItem in thingObject ) {
441
+
442
+ // Grab the value of the thing.
443
+ thingValue = thingObject[ thingItem ]
444
+
445
+ // First, if the item exists and there’s a value, set it.
446
+ if ( thingItem in P.component.item ) {
447
+ if ( thingValue === undefined ) thingValue = null
448
+ P.component.set( thingItem, thingValue, options )
449
+ }
450
+
451
+ // Then, check to update the element value and broadcast a change.
452
+ if ( ( thingItem == 'select' || thingItem == 'clear' ) && SETTINGS.updateInput ) {
453
+ $ELEMENT.
454
+ val( thingItem == 'clear' ? '' : P.get( thingItem, SETTINGS.format ) ).
455
+ trigger( 'change' )
456
+ }
457
+ }
458
+
459
+ // Render a new picker.
460
+ P.render()
461
+ }
462
+
463
+ // When the method isn’t muted, trigger queued “set” events and pass the `thingObject`.
464
+ return options.muted ? P : P.trigger( 'set', thingObject )
465
+ }, //set
466
+
467
+
468
+ /**
469
+ * Get something
470
+ */
471
+ get: function( thing, format ) {
472
+
473
+ // Make sure there’s something to get.
474
+ thing = thing || 'value'
475
+
476
+ // If a picker state exists, return that.
477
+ if ( STATE[ thing ] != null ) {
478
+ return STATE[ thing ]
479
+ }
480
+
481
+ // Return the submission value, if that.
482
+ if ( thing == 'valueSubmit' ) {
483
+ if ( P._hidden ) {
484
+ return P._hidden.value
485
+ }
486
+ thing = 'value'
487
+ }
488
+
489
+ // Return the value, if that.
490
+ if ( thing == 'value' ) {
491
+ return ELEMENT.value
492
+ }
493
+
494
+ // Check if a component item exists, return that.
495
+ if ( thing in P.component.item ) {
496
+ if ( typeof format == 'string' ) {
497
+ var thingValue = P.component.get( thing )
498
+ return thingValue ?
499
+ PickerConstructor._.trigger(
500
+ P.component.formats.toString,
501
+ P.component,
502
+ [ format, thingValue ]
503
+ ) : ''
504
+ }
505
+ return P.component.get( thing )
506
+ }
507
+ }, //get
508
+
509
+
510
+
511
+ /**
512
+ * Bind events on the things.
513
+ */
514
+ on: function( thing, method, internal ) {
515
+
516
+ var thingName, thingMethod,
517
+ thingIsObject = $.isPlainObject( thing ),
518
+ thingObject = thingIsObject ? thing : {}
519
+
520
+ if ( thing ) {
521
+
522
+ // If the thing isn’t an object, make it one.
523
+ if ( !thingIsObject ) {
524
+ thingObject[ thing ] = method
525
+ }
526
+
527
+ // Go through the things to bind to.
528
+ for ( thingName in thingObject ) {
529
+
530
+ // Grab the method of the thing.
531
+ thingMethod = thingObject[ thingName ]
532
+
533
+ // If it was an internal binding, prefix it.
534
+ if ( internal ) {
535
+ thingName = '_' + thingName
536
+ }
537
+
538
+ // Make sure the thing methods collection exists.
539
+ STATE.methods[ thingName ] = STATE.methods[ thingName ] || []
540
+
541
+ // Add the method to the relative method collection.
542
+ STATE.methods[ thingName ].push( thingMethod )
543
+ }
544
+ }
545
+
546
+ return P
547
+ }, //on
548
+
549
+
550
+
551
+ /**
552
+ * Unbind events on the things.
553
+ */
554
+ off: function() {
555
+ var i, thingName,
556
+ names = arguments;
557
+ for ( i = 0, namesCount = names.length; i < namesCount; i += 1 ) {
558
+ thingName = names[i]
559
+ if ( thingName in STATE.methods ) {
560
+ delete STATE.methods[thingName]
561
+ }
562
+ }
563
+ return P
564
+ },
565
+
566
+
567
+ /**
568
+ * Fire off method events.
569
+ */
570
+ trigger: function( name, data ) {
571
+ var _trigger = function( name ) {
572
+ var methodList = STATE.methods[ name ]
573
+ if ( methodList ) {
574
+ methodList.map( function( method ) {
575
+ PickerConstructor._.trigger( method, P, [ data ] )
576
+ })
577
+ }
578
+ }
579
+ _trigger( '_' + name )
580
+ _trigger( name )
581
+ return P
582
+ } //trigger
583
+ } //PickerInstance.prototype
584
+
585
+
586
+ /**
587
+ * Wrap the picker holder components together.
588
+ */
589
+ function createWrappedComponent() {
590
+
591
+ // Create a picker wrapper holder
592
+ return PickerConstructor._.node( 'div',
593
+
594
+ // Create a picker wrapper node
595
+ PickerConstructor._.node( 'div',
596
+
597
+ // Create a picker frame
598
+ PickerConstructor._.node( 'div',
599
+
600
+ // Create a picker box node
601
+ PickerConstructor._.node( 'div',
602
+
603
+ // Create the components nodes.
604
+ P.component.nodes( STATE.open ),
605
+
606
+ // The picker box class
607
+ CLASSES.box
608
+ ),
609
+
610
+ // Picker wrap class
611
+ CLASSES.wrap
612
+ ),
613
+
614
+ // Picker frame class
615
+ CLASSES.frame
616
+ ),
617
+
618
+ // Picker holder class
619
+ CLASSES.holder,
620
+
621
+ 'tabindex="-1"'
622
+ ) //endreturn
623
+ } //createWrappedComponent
624
+
625
+ /**
626
+ * Prepare the input element with all bindings.
627
+ */
628
+ function prepareElement() {
629
+
630
+ $ELEMENT.
631
+
632
+ // Store the picker data by component name.
633
+ data(NAME, P).
634
+
635
+ // Add the “input” class name.
636
+ addClass(CLASSES.input).
637
+
638
+ // If there’s a `data-value`, update the value of the element.
639
+ val( $ELEMENT.data('value') ?
640
+ P.get('select', SETTINGS.format) :
641
+ ELEMENT.value
642
+ ).
643
+
644
+ // On focus/click, open the picker.
645
+ on( 'focus.' + STATE.id + ' click.' + STATE.id,
646
+ function(event) {
647
+ event.preventDefault()
648
+ P.open()
649
+ }
650
+ )
651
+
652
+ // Mousedown handler to capture when the user starts interacting
653
+ // with the picker. This is used in working around a bug in Chrome 73.
654
+ .on('mousedown', function() {
655
+ STATE.handlingOpen = true;
656
+ var handler = function() {
657
+ // By default mouseup events are fired before a click event.
658
+ // By using a timeout we can force the mouseup to be handled
659
+ // after the corresponding click event is handled.
660
+ setTimeout(function() {
661
+ $(document).off('mouseup', handler);
662
+ STATE.handlingOpen = false;
663
+ }, 0);
664
+ };
665
+ $(document).on('mouseup', handler);
666
+ });
667
+
668
+
669
+ // Only bind keydown events if the element isn’t editable.
670
+ if ( !SETTINGS.editable ) {
671
+
672
+ $ELEMENT.
673
+
674
+ // Handle keyboard event based on the picker being opened or not.
675
+ on( 'keydown.' + STATE.id, handleKeydownEvent )
676
+ }
677
+
678
+
679
+ // Update the aria attributes.
680
+ aria(ELEMENT, {
681
+ haspopup: true,
682
+ expanded: false,
683
+ readonly: false,
684
+ owns: ELEMENT.id + '_root'
685
+ })
686
+ }
687
+
688
+
689
+ /**
690
+ * Prepare the root picker element with all bindings.
691
+ */
692
+ function prepareElementRoot() {
693
+ aria( P.$root[0], 'hidden', true )
694
+ }
695
+
696
+
697
+ /**
698
+ * Prepare the holder picker element with all bindings.
699
+ */
700
+ function prepareElementHolder() {
701
+
702
+ P.$holder.
703
+
704
+ on({
705
+
706
+ // For iOS8.
707
+ keydown: handleKeydownEvent,
708
+
709
+ 'focus.toOpen': handleFocusToOpenEvent,
710
+
711
+ blur: function() {
712
+ // Remove the “target” class.
713
+ $ELEMENT.removeClass( CLASSES.target )
714
+ },
715
+
716
+ // When something within the holder is focused, stop from bubbling
717
+ // to the doc and remove the “focused” state from the root.
718
+ focusin: function( event ) {
719
+ P.$root.removeClass( CLASSES.focused )
720
+ event.stopPropagation()
721
+ },
722
+
723
+ // When something within the holder is clicked, stop it
724
+ // from bubbling to the doc.
725
+ 'mousedown click': function( event ) {
726
+
727
+ var target = getRealEventTarget( event, ELEMENT )
728
+
729
+ // Make sure the target isn’t the root holder so it can bubble up.
730
+ if ( target != P.$holder[0] ) {
731
+
732
+ event.stopPropagation()
733
+
734
+ // * For mousedown events, cancel the default action in order to
735
+ // prevent cases where focus is shifted onto external elements
736
+ // when using things like jQuery mobile or MagnificPopup (ref: #249 & #120).
737
+ // Also, for Firefox, don’t prevent action on the `option` element.
738
+ if ( event.type == 'mousedown' && !$( target ).is( 'input, select, textarea, button, option' )) {
739
+
740
+ event.preventDefault()
741
+
742
+ // Re-focus onto the holder so that users can click away
743
+ // from elements focused within the picker.
744
+ P.$holder.eq(0).focus()
745
+ }
746
+ }
747
+ }
748
+
749
+ }).
750
+
751
+ // If there’s a click on an actionable element, carry out the actions.
752
+ on( 'click', '[data-pick], [data-nav], [data-clear], [data-close]', function() {
753
+
754
+ var $target = $( this ),
755
+ targetData = $target.data(),
756
+ targetDisabled = $target.hasClass( CLASSES.navDisabled ) || $target.hasClass( CLASSES.disabled ),
757
+
758
+ // * For IE, non-focusable elements can be active elements as well
759
+ // (http://stackoverflow.com/a/2684561).
760
+ activeElement = getActiveElement()
761
+ activeElement = activeElement && ( (activeElement.type || activeElement.href ) ? activeElement : null);
762
+
763
+ // If it’s disabled or nothing inside is actively focused, re-focus the element.
764
+ if ( targetDisabled || activeElement && !$.contains( P.$root[0], activeElement ) ) {
765
+ P.$holder.eq(0).focus()
766
+ }
767
+
768
+ // If something is superficially changed, update the `highlight` based on the `nav`.
769
+ if ( !targetDisabled && targetData.nav ) {
770
+ P.set( 'highlight', P.component.item.highlight, { nav: targetData.nav } )
771
+ }
772
+
773
+ // If something is picked, set `select` then close with focus.
774
+ else if ( !targetDisabled && 'pick' in targetData ) {
775
+ P.set( 'select', targetData.pick )
776
+ if ( SETTINGS.closeOnSelect ) {
777
+ P.close( true )
778
+ }
779
+ }
780
+
781
+ // If a “clear” button is pressed, empty the values and close with focus.
782
+ else if ( targetData.clear ) {
783
+ P.clear()
784
+ if ( SETTINGS.closeOnClear ) {
785
+ P.close( true )
786
+ }
787
+ }
788
+
789
+ else if ( targetData.close ) {
790
+ P.close( true )
791
+ }
792
+
793
+ }) //P.$holder
794
+
795
+ }
796
+
797
+
798
+ /**
799
+ * Prepare the hidden input element along with all bindings.
800
+ */
801
+ function prepareElementHidden() {
802
+
803
+ var name
804
+
805
+ if ( SETTINGS.hiddenName === true ) {
806
+ name = ELEMENT.name
807
+ ELEMENT.name = ''
808
+ }
809
+ else {
810
+ name = [
811
+ typeof SETTINGS.hiddenPrefix == 'string' ? SETTINGS.hiddenPrefix : '',
812
+ typeof SETTINGS.hiddenSuffix == 'string' ? SETTINGS.hiddenSuffix : '_submit'
813
+ ]
814
+ name = name[0] + ELEMENT.name + name[1]
815
+ }
816
+
817
+ P._hidden = $(
818
+ '<input ' +
819
+ 'type=hidden ' +
820
+
821
+ // Create the name using the original input’s with a prefix and suffix.
822
+ 'name="' + name + '"' +
823
+
824
+ // If the element has a value, set the hidden value as well.
825
+ (
826
+ $ELEMENT.data('value') || ELEMENT.value ?
827
+ ' value="' + P.get('select', SETTINGS.formatSubmit) + '"' :
828
+ ''
829
+ ) +
830
+ '>'
831
+ )[0]
832
+
833
+ $ELEMENT.
834
+
835
+ // If the value changes, update the hidden input with the correct format.
836
+ on('change.' + STATE.id, function() {
837
+ P._hidden.value = ELEMENT.value ?
838
+ P.get('select', SETTINGS.formatSubmit) :
839
+ ''
840
+ })
841
+ }
842
+
843
+
844
+ // Wait for transitions to end before focusing the holder. Otherwise, while
845
+ // using the `container` option, the view jumps to the container.
846
+ function focusPickerOnceOpened() {
847
+
848
+ if (IS_DEFAULT_THEME && supportsTransitions) {
849
+ P.$holder.find('.' + CLASSES.frame).one('transitionend', function() {
850
+ P.$holder.eq(0).focus()
851
+ })
852
+ }
853
+ else {
854
+ setTimeout(function() {
855
+ // Mod by JCD. Prevent focus from moving to calendar input, which is not accessible.
856
+ // P.$holder.eq(0).focus()
857
+ }, 0)
858
+ }
859
+ }
860
+
861
+
862
+ function handleFocusToOpenEvent(event) {
863
+
864
+ // Stop the event from propagating to the doc.
865
+ event.stopPropagation()
866
+
867
+ // Add the “target” class.
868
+ $ELEMENT.addClass( CLASSES.target )
869
+
870
+ // Add the “focused” class to the root.
871
+ P.$root.addClass( CLASSES.focused )
872
+
873
+ // And then finally open the picker.
874
+ P.open()
875
+ }
876
+
877
+
878
+ // For iOS8.
879
+ function handleKeydownEvent( event ) {
880
+
881
+ var keycode = event.keyCode,
882
+
883
+ // Check if one of the delete keys was pressed.
884
+ isKeycodeDelete = /^(8|46)$/.test(keycode)
885
+
886
+ // For some reason IE clears the input value on “escape”.
887
+ if ( keycode == 27 ) {
888
+ P.close( true )
889
+ return false
890
+ }
891
+
892
+ // Check if `space` or `delete` was pressed or the picker is closed with a key movement.
893
+ if ( keycode == 32 || isKeycodeDelete || !STATE.open && P.component.key[keycode] ) {
894
+
895
+ // Prevent it from moving the page and bubbling to doc.
896
+ event.preventDefault()
897
+ event.stopPropagation()
898
+
899
+ // If `delete` was pressed, clear the values and close the picker.
900
+ // Otherwise open the picker.
901
+ if ( isKeycodeDelete ) { P.clear().close() }
902
+ else { P.open() }
903
+ }
904
+ }
905
+
906
+
907
+ // Return a new picker instance.
908
+ return new PickerInstance()
909
+ } //PickerConstructor
910
+
911
+
912
+
913
+ /**
914
+ * The default classes and prefix to use for the HTML classes.
915
+ */
916
+ PickerConstructor.klasses = function( prefix ) {
917
+ prefix = prefix || 'picker'
918
+ return {
919
+
920
+ picker: prefix,
921
+ opened: prefix + '--opened',
922
+ focused: prefix + '--focused',
923
+
924
+ input: prefix + '__input',
925
+ active: prefix + '__input--active',
926
+ target: prefix + '__input--target',
927
+
928
+ holder: prefix + '__holder',
929
+
930
+ frame: prefix + '__frame',
931
+ wrap: prefix + '__wrap',
932
+
933
+ box: prefix + '__box'
934
+ }
935
+ } //PickerConstructor.klasses
936
+
937
+
938
+
939
+ /**
940
+ * Check if the default theme is being used.
941
+ */
942
+ function isUsingDefaultTheme( element ) {
943
+
944
+ var theme,
945
+ prop = 'position'
946
+
947
+ // For IE.
948
+ if ( element.currentStyle ) {
949
+ theme = element.currentStyle[prop]
950
+ }
951
+
952
+ // For normal browsers.
953
+ else if ( window.getComputedStyle ) {
954
+ theme = getComputedStyle( element )[prop]
955
+ }
956
+
957
+ return theme == 'fixed'
958
+ }
959
+
960
+
961
+
962
+ /**
963
+ * Get the width of the browser’s scrollbar.
964
+ * Taken from: https://github.com/VodkaBears/Remodal/blob/master/src/jquery.remodal.js
965
+ */
966
+ function getScrollbarWidth() {
967
+
968
+ if ( $html.height() <= $window.height() ) {
969
+ return 0
970
+ }
971
+
972
+ var $outer = $( '<div style="visibility:hidden;width:100px" />' ).
973
+ appendTo( 'body' )
974
+
975
+ // Get the width without scrollbars.
976
+ var widthWithoutScroll = $outer[0].offsetWidth
977
+
978
+ // Force adding scrollbars.
979
+ $outer.css( 'overflow', 'scroll' )
980
+
981
+ // Add the inner div.
982
+ var $inner = $( '<div style="width:100%" />' ).appendTo( $outer )
983
+
984
+ // Get the width with scrollbars.
985
+ var widthWithScroll = $inner[0].offsetWidth
986
+
987
+ // Remove the divs.
988
+ $outer.remove()
989
+
990
+ // Return the difference between the widths.
991
+ return widthWithoutScroll - widthWithScroll
992
+ }
993
+
994
+
995
+
996
+ /**
997
+ * Get the target element from the event.
998
+ * If ELEMENT is supplied and present in the event path (ELEMENT is ancestor of the target),
999
+ * returns ELEMENT instead
1000
+ */
1001
+ function getRealEventTarget( event, ELEMENT ) {
1002
+
1003
+ var path = []
1004
+
1005
+ if ( event.path ) {
1006
+ path = event.path
1007
+ }
1008
+
1009
+ if ( event.originalEvent && event.originalEvent.path ) {
1010
+ path = event.originalEvent.path
1011
+ }
1012
+
1013
+ if ( path && path.length > 0 ) {
1014
+ if ( ELEMENT && path.indexOf( ELEMENT ) >= 0 ) {
1015
+ return ELEMENT
1016
+ } else {
1017
+ return path[0]
1018
+ }
1019
+ }
1020
+
1021
+ return event.target
1022
+ }
1023
+
1024
+ /**
1025
+ * PickerConstructor helper methods.
1026
+ */
1027
+ PickerConstructor._ = {
1028
+
1029
+ /**
1030
+ * Create a group of nodes. Expects:
1031
+ * `
1032
+ {
1033
+ min: {Integer},
1034
+ max: {Integer},
1035
+ i: {Integer},
1036
+ node: {String},
1037
+ item: {Function}
1038
+ }
1039
+ * `
1040
+ */
1041
+ group: function( groupObject ) {
1042
+
1043
+ var
1044
+ // Scope for the looped object
1045
+ loopObjectScope,
1046
+
1047
+ // Create the nodes list
1048
+ nodesList = '',
1049
+
1050
+ // The counter starts from the `min`
1051
+ counter = PickerConstructor._.trigger( groupObject.min, groupObject )
1052
+
1053
+
1054
+ // Loop from the `min` to `max`, incrementing by `i`
1055
+ for ( ; counter <= PickerConstructor._.trigger( groupObject.max, groupObject, [ counter ] ); counter += groupObject.i ) {
1056
+
1057
+ // Trigger the `item` function within scope of the object
1058
+ loopObjectScope = PickerConstructor._.trigger( groupObject.item, groupObject, [ counter ] )
1059
+
1060
+ // Splice the subgroup and create nodes out of the sub nodes
1061
+ nodesList += PickerConstructor._.node(
1062
+ groupObject.node,
1063
+ loopObjectScope[ 0 ], // the node
1064
+ loopObjectScope[ 1 ], // the classes
1065
+ loopObjectScope[ 2 ] // the attributes
1066
+ )
1067
+ }
1068
+
1069
+ // Return the list of nodes
1070
+ return nodesList
1071
+ }, //group
1072
+
1073
+
1074
+ /**
1075
+ * Create a dom node string
1076
+ */
1077
+ node: function( wrapper, item, klass, attribute ) {
1078
+
1079
+ // If the item is false-y, just return an empty string
1080
+ if ( !item ) return ''
1081
+
1082
+ // If the item is an array, do a join
1083
+ item = $.isArray( item ) ? item.join( '' ) : item
1084
+
1085
+ // Check for the class
1086
+ klass = klass ? ' class="' + klass + '"' : ''
1087
+
1088
+ // Check for any attributes
1089
+ attribute = attribute ? ' ' + attribute : ''
1090
+
1091
+ // Return the wrapped item
1092
+ return '<' + wrapper + klass + attribute + '>' + item + '</' + wrapper + '>'
1093
+ }, //node
1094
+
1095
+
1096
+ /**
1097
+ * Lead numbers below 10 with a zero.
1098
+ */
1099
+ lead: function( number ) {
1100
+ return ( number < 10 ? '0': '' ) + number
1101
+ },
1102
+
1103
+
1104
+ /**
1105
+ * Trigger a function otherwise return the value.
1106
+ */
1107
+ trigger: function( callback, scope, args ) {
1108
+ return typeof callback == 'function' ? callback.apply( scope, args || [] ) : callback
1109
+ },
1110
+
1111
+
1112
+ /**
1113
+ * If the second character is a digit, length is 2 otherwise 1.
1114
+ */
1115
+ digits: function( string ) {
1116
+ return ( /\d/ ).test( string[ 1 ] ) ? 2 : 1
1117
+ },
1118
+
1119
+
1120
+ /**
1121
+ * Tell if something is a date object.
1122
+ */
1123
+ isDate: function( value ) {
1124
+ return {}.toString.call( value ).indexOf( 'Date' ) > -1 && this.isInteger( value.getDate() )
1125
+ },
1126
+
1127
+
1128
+ /**
1129
+ * Tell if something is an integer.
1130
+ */
1131
+ isInteger: function( value ) {
1132
+ return {}.toString.call( value ).indexOf( 'Number' ) > -1 && value % 1 === 0
1133
+ },
1134
+
1135
+
1136
+ /**
1137
+ * Create ARIA attribute strings.
1138
+ */
1139
+ ariaAttr: ariaAttr
1140
+ } //PickerConstructor._
1141
+
1142
+
1143
+
1144
+ /**
1145
+ * Extend the picker with a component and defaults.
1146
+ */
1147
+ PickerConstructor.extend = function( name, Component ) {
1148
+
1149
+ // Extend jQuery.
1150
+ $.fn[ name ] = function( options, action ) {
1151
+
1152
+ // Grab the component data.
1153
+ var componentData = this.data( name )
1154
+
1155
+ // If the picker is requested, return the data object.
1156
+ if ( options == 'picker' ) {
1157
+ return componentData
1158
+ }
1159
+
1160
+ // If the component data exists and `options` is a string, carry out the action.
1161
+ if ( componentData && typeof options == 'string' ) {
1162
+ return PickerConstructor._.trigger( componentData[ options ], componentData, [ action ] )
1163
+ }
1164
+
1165
+ // Otherwise go through each matched element and if the component
1166
+ // doesn’t exist, create a new picker using `this` element
1167
+ // and merging the defaults and options with a deep copy.
1168
+ return this.each( function() {
1169
+ var $this = $( this )
1170
+ if ( !$this.data( name ) ) {
1171
+ new PickerConstructor( this, name, Component, options )
1172
+ }
1173
+ })
1174
+ }
1175
+
1176
+ // Set the defaults.
1177
+ $.fn[ name ].defaults = Component.defaults
1178
+ } //PickerConstructor.extend
1179
+
1180
+
1181
+
1182
+ function aria(element, attribute, value) {
1183
+ if ( $.isPlainObject(attribute) ) {
1184
+ for ( var key in attribute ) {
1185
+ ariaSet(element, key, attribute[key])
1186
+ }
1187
+ }
1188
+ else {
1189
+ ariaSet(element, attribute, value)
1190
+ }
1191
+ }
1192
+ function ariaSet(element, attribute, value) {
1193
+ element.setAttribute(
1194
+ (attribute == 'role' ? '' : 'aria-') + attribute,
1195
+ value
1196
+ )
1197
+ }
1198
+ function ariaAttr(attribute, data) {
1199
+ if ( !$.isPlainObject(attribute) ) {
1200
+ attribute = { attribute: data }
1201
+ }
1202
+ data = ''
1203
+ for ( var key in attribute ) {
1204
+ var attr = (key == 'role' ? '' : 'aria-') + key,
1205
+ attrVal = attribute[key]
1206
+ data += attrVal == null ? '' : attr + '="' + attribute[key] + '"'
1207
+ }
1208
+ return data
1209
+ }
1210
+
1211
+ // IE8 bug throws an error for activeElements within iframes.
1212
+ function getActiveElement() {
1213
+ try {
1214
+ return document.activeElement
1215
+ } catch ( err ) { }
1216
+ }
1217
+
1218
+
1219
+
1220
+ // Expose the picker constructor.
1221
+ return PickerConstructor
1222
+
1223
+
1224
+ }));
js/pickadate/picker.time.js CHANGED
@@ -1,216 +1,1022 @@
1
- /*!
2
- * Time picker for pickadate.js v3.4.0
3
- * http://amsul.github.io/pickadate.js/time.htm
4
- */
5
- !function (a) {
6
- "function" == typeof define && define.amd ? define(["picker", "jquery"], a) : a(Picker, jQuery)
7
- }(function (a, b) {
8
- function c(a, b) {
9
- var c = this, d = a.$node[0].value, e = a.$node.data("value"), f = e || d, g = e ? b.formatSubmit : b.format;
10
- c.settings = b, c.$node = a.$node, c.queue = {
11
- interval: "i",
12
- min: "measure create",
13
- max: "measure create",
14
- now: "now create",
15
- select: "parse create validate",
16
- highlight: "parse create validate",
17
- view: "parse create validate",
18
- disable: "deactivate",
19
- enable: "activate"
20
- }, c.item = {}, c.item.interval = b.interval || 30, c.item.disable = (b.disable || []).slice(0), c.item.enable = -function (a) {
21
- return a[0] === !0 ? a.shift() : -1
22
- }(c.item.disable), c.set("min", b.min).set("max", b.max).set("now"), f ? c.set("select", f, {
23
- format: g,
24
- fromValue: !!d
25
- }) : c.set("select", null).set("highlight", c.item.now), c.key = {
26
- 40: 1,
27
- 38: -1,
28
- 39: 1,
29
- 37: -1,
30
- go: function (a) {
31
- c.set("highlight", c.item.highlight.pick + a * c.item.interval, {interval: a * c.item.interval}), this.render()
32
- }
33
- }, a.on("render", function () {
34
- var c = a.$root.children(), d = c.find("." + b.klass.viewset);
35
- d.length && (c[0].scrollTop = ~~d.position().top - 2 * d[0].clientHeight)
36
- }).on("open", function () {
37
- a.$root.find("button").attr("disable", !1)
38
- }).on("close", function () {
39
- a.$root.find("button").attr("disable", !0)
40
- })
41
- }
42
-
43
- var d = 24, e = 60, f = 12, g = d * e, h = a._;
44
- c.prototype.set = function (a, b, c) {
45
- var d = this, e = d.item;
46
- return null === b ? (e[a] = b, d) : (e["enable" == a ? "disable" : "flip" == a ? "enable" : a] = d.queue[a].split(" ").map(function (e) {
47
- return b = d[e](a, b, c)
48
- }).pop(), "select" == a ? d.set("highlight", e.select, c) : "highlight" == a ? d.set("view", e.highlight, c) : "interval" == a ? d.set("min", e.min, c).set("max", e.max, c) : a.match(/^(flip|min|max|disable|enable)$/) && ("min" == a && d.set("max", e.max, c), e.select && d.disabled(e.select) && d.set("select", e.select, c), e.highlight && d.disabled(e.highlight) && d.set("highlight", e.highlight, c)), d)
49
- }, c.prototype.get = function (a) {
50
- return this.item[a]
51
- }, c.prototype.create = function (a, c, f) {
52
- var i = this;
53
- return c = void 0 === c ? a : c, h.isDate(c) && (c = [c.getHours(), c.getMinutes()]), b.isPlainObject(c) && h.isInteger(c.pick) ? c = c.pick : b.isArray(c) ? c = +c[0] * e + +c[1] : h.isInteger(c) || (c = i.now(a, c, f)), "max" == a && c < i.item.min.pick && (c += g), "min" != a && "max" != a && (c - i.item.min.pick) % i.item.interval !== 0 && (c += i.item.interval), c = i.normalize(a, c, f), {
54
- hour: ~~(d + c / e) % d,
55
- mins: (e + c % e) % e,
56
- time: (g + c) % g,
57
- pick: c
58
- }
59
- }, c.prototype.createRange = function (a, c) {
60
- var d = this, e = function (a) {
61
- return a === !0 || b.isArray(a) || h.isDate(a) ? d.create(a) : a
62
- };
63
- return h.isInteger(a) || (a = e(a)), h.isInteger(c) || (c = e(c)), h.isInteger(a) && b.isPlainObject(c) ? a = [c.hour, c.mins + a * d.settings.interval] : h.isInteger(c) && b.isPlainObject(a) && (c = [a.hour, a.mins + c * d.settings.interval]), {
64
- from: e(a),
65
- to: e(c)
66
- }
67
- }, c.prototype.withinRange = function (a, b) {
68
- return a = this.createRange(a.from, a.to), b.pick >= a.from.pick && b.pick <= a.to.pick
69
- }, c.prototype.overlapRanges = function (a, b) {
70
- var c = this;
71
- return a = c.createRange(a.from, a.to), b = c.createRange(b.from, b.to), c.withinRange(a, b.from) || c.withinRange(a, b.to) || c.withinRange(b, a.from) || c.withinRange(b, a.to)
72
- }, c.prototype.now = function (a, b) {
73
- var c, d = this.item.interval, f = new Date, g = f.getHours() * e + f.getMinutes(), i = h.isInteger(b);
74
- return g -= g % d, c = 0 > b && -d >= d * b + g, g += "min" == a && c ? 0 : d, i && (g += d * (c && "max" != a ? b + 1 : b)), g
75
- }, c.prototype.normalize = function (a, b) {
76
- var c = this.item.interval, d = this.item.min && this.item.min.pick || 0;
77
- return b -= "min" == a ? 0 : (b - d) % c
78
- }, c.prototype.measure = function (a, c, f) {
79
- var g = this;
80
- return c ? c === !0 || h.isInteger(c) ? c = g.now(a, c, f) : b.isPlainObject(c) && h.isInteger(c.pick) && (c = g.normalize(a, c.pick, f)) : c = "min" == a ? [0, 0] : [d - 1, e - 1], c
81
- }, c.prototype.validate = function (a, b, c) {
82
- var d = this, e = c && c.interval ? c.interval : d.item.interval;
83
- return d.disabled(b) && (b = d.shift(b, e)), b = d.scope(b), d.disabled(b) && (b = d.shift(b, -1 * e)), b
84
- }, c.prototype.disabled = function (a) {
85
- var c = this, d = c.item.disable.filter(function (d) {
86
- return h.isInteger(d) ? a.hour == d : b.isArray(d) || h.isDate(d) ? a.pick == c.create(d).pick : b.isPlainObject(d) ? c.withinRange(d, a) : void 0
87
- });
88
- return d = d.length && !d.filter(function (a) {
89
- return b.isArray(a) && "inverted" == a[2] || b.isPlainObject(a) && a.inverted
90
- }).length, -1 === c.item.enable ? !d : d || a.pick < c.item.min.pick || a.pick > c.item.max.pick
91
- }, c.prototype.shift = function (a, b) {
92
- var c = this, d = c.item.min.pick, e = c.item.max.pick;
93
- for (b = b || c.item.interval; c.disabled(a) && (a = c.create(a.pick += b), !(a.pick <= d || a.pick >= e)););
94
- return a
95
- }, c.prototype.scope = function (a) {
96
- var b = this.item.min.pick, c = this.item.max.pick;
97
- return this.create(a.pick > c ? c : a.pick < b ? b : a)
98
- }, c.prototype.parse = function (a, c, d) {
99
- var f, g, i, j, k, l = this, m = {};
100
- if (!c || h.isInteger(c) || b.isArray(c) || h.isDate(c) || b.isPlainObject(c) && h.isInteger(c.pick))return c;
101
- d && d.format || (d = d || {}, d.format = l.settings.format), l.formats.toArray(d.format).map(function (a) {
102
- var b, d = l.formats[a], e = d ? h.trigger(d, l, [c, m]) : a.replace(/^!/, "").length;
103
- d && (b = c.substr(0, e), m[a] = b.match(/^\d+$/) ? +b : b), c = c.substr(e)
104
- });
105
- for (j in m)k = m[j], h.isInteger(k) ? j.match(/^(h|hh)$/i) ? (f = k, ("h" == j || "hh" == j) && (f %= 12)) : "i" == j && (g = k) : j.match(/^a$/i) && k.match(/^p/i) && ("h"in m || "hh"in m) && (i = !0);
106
- return (i ? f + 12 : f) * e + g
107
- }, c.prototype.formats = {
108
- h: function (a, b) {
109
- return a ? h.digits(a) : b.hour % f || f
110
- }, hh: function (a, b) {
111
- return a ? 2 : h.lead(b.hour % f || f)
112
- }, H: function (a, b) {
113
- return a ? h.digits(a) : "" + b.hour % 24
114
- }, HH: function (a, b) {
115
- return a ? h.digits(a) : h.lead(b.hour % 24)
116
- }, i: function (a, b) {
117
- return a ? 2 : h.lead(b.mins)
118
- }, a: function (a, b) {
119
- return a ? 4 : g / 2 > b.time % g ? "a.m." : "p.m."
120
- }, A: function (a, b) {
121
- return a ? 2 : g / 2 > b.time % g ? "AM" : "PM"
122
- }, toArray: function (a) {
123
- return a.split(/(h{1,2}|H{1,2}|i|a|A|!.)/g)
124
- }, toString: function (a, b) {
125
- var c = this;
126
- return c.formats.toArray(a).map(function (a) {
127
- return h.trigger(c.formats[a], c, [0, b]) || a.replace(/^!/, "")
128
- }).join("")
129
- }
130
- }, c.prototype.isTimeExact = function (a, c) {
131
- var d = this;
132
- return h.isInteger(a) && h.isInteger(c) || "boolean" == typeof a && "boolean" == typeof c ? a === c : (h.isDate(a) || b.isArray(a)) && (h.isDate(c) || b.isArray(c)) ? d.create(a).pick === d.create(c).pick : b.isPlainObject(a) && b.isPlainObject(c) ? d.isTimeExact(a.from, c.from) && d.isTimeExact(a.to, c.to) : !1
133
- }, c.prototype.isTimeOverlap = function (a, c) {
134
- var d = this;
135
- return h.isInteger(a) && (h.isDate(c) || b.isArray(c)) ? a === d.create(c).hour : h.isInteger(c) && (h.isDate(a) || b.isArray(a)) ? c === d.create(a).hour : b.isPlainObject(a) && b.isPlainObject(c) ? d.overlapRanges(a, c) : !1
136
- }, c.prototype.flipEnable = function (a) {
137
- var b = this.item;
138
- b.enable = a || (-1 == b.enable ? 1 : -1)
139
- }, c.prototype.deactivate = function (a, c) {
140
- var d = this, e = d.item.disable.slice(0);
141
- return "flip" == c ? d.flipEnable() : c === !1 ? (d.flipEnable(1), e = []) : c === !0 ? (d.flipEnable(-1), e = []) : c.map(function (a) {
142
- for (var c, f = 0; f < e.length; f += 1)if (d.isTimeExact(a, e[f])) {
143
- c = !0;
144
- break
145
- }
146
- c || (h.isInteger(a) || h.isDate(a) || b.isArray(a) || b.isPlainObject(a) && a.from && a.to) && e.push(a)
147
- }), e
148
- }, c.prototype.activate = function (a, c) {
149
- var d = this, e = d.item.disable, f = e.length;
150
- return "flip" == c ? d.flipEnable() : c === !0 ? (d.flipEnable(1), e = []) : c === !1 ? (d.flipEnable(-1), e = []) : c.map(function (a) {
151
- var c, g, i, j;
152
- for (i = 0; f > i; i += 1) {
153
- if (g = e[i], d.isTimeExact(g, a)) {
154
- c = e[i] = null, j = !0;
155
- break
156
- }
157
- if (d.isTimeOverlap(g, a)) {
158
- b.isPlainObject(a) ? (a.inverted = !0, c = a) : b.isArray(a) ? (c = a, c[2] || c.push("inverted")) : h.isDate(a) && (c = [a.getFullYear(), a.getMonth(), a.getDate(), "inverted"]);
159
- break
160
- }
161
- }
162
- if (c)for (i = 0; f > i; i += 1)if (d.isTimeExact(e[i], a)) {
163
- e[i] = null;
164
- break
165
- }
166
- if (j)for (i = 0; f > i; i += 1)if (d.isTimeOverlap(e[i], a)) {
167
- e[i] = null;
168
- break
169
- }
170
- c && e.push(c)
171
- }), e.filter(function (a) {
172
- return null != a
173
- })
174
- }, c.prototype.i = function (a, b) {
175
- return h.isInteger(b) && b > 0 ? b : this.item.interval
176
- }, c.prototype.nodes = function (a) {
177
- var b = this, c = b.settings, d = b.item.select, e = b.item.highlight, f = b.item.view, g = b.item.disable;
178
- return h.node("ul", h.group({
179
- min: b.item.min.pick,
180
- max: b.item.max.pick,
181
- i: b.item.interval,
182
- node: "li",
183
- item: function (a) {
184
- a = b.create(a);
185
- var i = a.pick, j = d && d.pick == i, k = e && e.pick == i, l = g && b.disabled(a);
186
- return [h.trigger(b.formats.toString, b, [h.trigger(c.formatLabel, b, [a]) || c.format, a]), function (a) {
187
- return j && a.push(c.klass.selected), k && a.push(c.klass.highlighted), f && f.pick == i && a.push(c.klass.viewset), l && a.push(c.klass.disabled), a.join(" ")
188
- }([c.klass.listItem]), "data-pick=" + a.pick + " " + h.ariaAttr({
189
- role: "button",
190
- controls: b.$node[0].id,
191
- checked: j && b.$node.val() === h.trigger(b.formats.toString, b, [c.format, a]) ? !0 : null,
192
- activedescendant: k ? !0 : null,
193
- disabled: l ? !0 : null
194
- })]
195
- }
196
- }) + h.node("li", h.node("button", c.clear, c.klass.buttonClear, "type=button data-clear=1" + (a ? "" : " disable"))), c.klass.list)
197
- }, c.defaults = function (a) {
198
- return {
199
- clear: "Clear",
200
- format: "h:i A",
201
- interval: 30,
202
- klass: {
203
- picker: a + " " + a + "--time",
204
- holder: a + "__holder",
205
- list: a + "__list",
206
- listItem: a + "__list-item",
207
- disabled: a + "__list-item--disabled",
208
- selected: a + "__list-item--selected",
209
- highlighted: a + "__list-item--highlighted",
210
- viewset: a + "__list-item--viewset",
211
- now: a + "__list-item--now",
212
- buttonClear: a + "__button--clear"
213
- }
214
- }
215
- }(a.klasses().picker), a.extend("pickatime", c)
216
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Time picker for pickadate.js v3.6.4
3
+ * http://amsul.github.io/pickadate.js/time.htm
4
+ */
5
+
6
+ (function ( factory ) {
7
+
8
+ // AMD.
9
+ if ( typeof define == 'function' && define.amd )
10
+ define( ['./picker', 'jquery'], factory )
11
+
12
+ // Node.js/browserify.
13
+ else if ( typeof exports == 'object' )
14
+ module.exports = factory( require('./picker.js'), require('jquery') )
15
+
16
+ // Browser globals.
17
+ else factory( Picker, jQuery )
18
+
19
+ }(function( Picker, $ ) {
20
+
21
+
22
+ /**
23
+ * Globals and constants
24
+ */
25
+ var HOURS_IN_DAY = 24,
26
+ MINUTES_IN_HOUR = 60,
27
+ HOURS_TO_NOON = 12,
28
+ MINUTES_IN_DAY = HOURS_IN_DAY * MINUTES_IN_HOUR,
29
+ _ = Picker._
30
+
31
+
32
+
33
+ /**
34
+ * The time picker constructor
35
+ */
36
+ function TimePicker( picker, settings ) {
37
+
38
+ var clock = this,
39
+ elementValue = picker.$node[ 0 ].value,
40
+ elementDataValue = picker.$node.data( 'value' ),
41
+ valueString = elementDataValue || elementValue,
42
+ formatString = elementDataValue ? settings.formatSubmit : settings.format
43
+
44
+ clock.settings = settings
45
+ clock.$node = picker.$node
46
+
47
+ // The queue of methods that will be used to build item objects.
48
+ clock.queue = {
49
+ interval: 'i',
50
+ min: 'measure create',
51
+ max: 'measure create',
52
+ now: 'now create',
53
+ select: 'parse create validate',
54
+ highlight: 'parse create validate',
55
+ view: 'parse create validate',
56
+ disable: 'deactivate',
57
+ enable: 'activate'
58
+ }
59
+
60
+ // The component's item object.
61
+ clock.item = {}
62
+
63
+ clock.item.clear = null
64
+ clock.item.interval = settings.interval || 30
65
+ clock.item.disable = ( settings.disable || [] ).slice( 0 )
66
+ clock.item.enable = -(function( collectionDisabled ) {
67
+ return collectionDisabled[ 0 ] === true ? collectionDisabled.shift() : -1
68
+ })( clock.item.disable )
69
+
70
+ clock.
71
+ set( 'min', settings.min ).
72
+ set( 'max', settings.max ).
73
+ set( 'now' )
74
+
75
+ // When there’s a value, set the `select`, which in turn
76
+ // also sets the `highlight` and `view`.
77
+ if ( valueString ) {
78
+ clock.set( 'select', valueString, {
79
+ format: formatString
80
+ })
81
+ }
82
+
83
+ // If there’s no value, default to highlighting “today”.
84
+ else {
85
+ clock.
86
+ set( 'select', null ).
87
+ set( 'highlight', clock.item.now )
88
+ }
89
+
90
+ // The keycode to movement mapping.
91
+ clock.key = {
92
+ 40: 1, // Down
93
+ 38: -1, // Up
94
+ 39: 1, // Right
95
+ 37: -1, // Left
96
+ go: function( timeChange ) {
97
+ clock.set(
98
+ 'highlight',
99
+ clock.item.highlight.pick + timeChange * clock.item.interval,
100
+ { interval: timeChange * clock.item.interval }
101
+ )
102
+ this.render()
103
+ }
104
+ }
105
+
106
+
107
+ // Bind some picker events.
108
+ picker.
109
+ on( 'render', function() {
110
+ var $pickerHolder = picker.$root.children(),
111
+ $viewset = $pickerHolder.find( '.' + settings.klass.viewset ),
112
+ vendors = function( prop ) {
113
+ return ['webkit', 'moz', 'ms', 'o', ''].map(function( vendor ) {
114
+ return ( vendor ? '-' + vendor + '-' : '' ) + prop
115
+ })
116
+ },
117
+ animations = function( $el, state ) {
118
+ vendors( 'transform' ).map(function( prop ) {
119
+ $el.css( prop, state )
120
+ })
121
+ vendors( 'transition' ).map(function( prop ) {
122
+ $el.css( prop, state )
123
+ })
124
+ }
125
+ if ( $viewset.length ) {
126
+ animations( $pickerHolder, 'none' )
127
+ $pickerHolder[ 0 ].scrollTop = ~~$viewset.position().top - ( $viewset[ 0 ].clientHeight * 2 )
128
+ animations( $pickerHolder, '' )
129
+ }
130
+ }, 1 ).
131
+ on( 'open', function() {
132
+ picker.$root.find( 'button' ).attr( 'disabled', false )
133
+ }, 1 ).
134
+ on( 'close', function() {
135
+ picker.$root.find( 'button' ).attr( 'disabled', true )
136
+ }, 1 )
137
+
138
+ } //TimePicker
139
+
140
+
141
+ /**
142
+ * Set a timepicker item object.
143
+ */
144
+ TimePicker.prototype.set = function( type, value, options ) {
145
+
146
+ var clock = this,
147
+ clockItem = clock.item
148
+
149
+ // If the value is `null` just set it immediately.
150
+ if ( value === null ) {
151
+ if ( type == 'clear' ) type = 'select'
152
+ clockItem[ type ] = value
153
+ return clock
154
+ }
155
+
156
+ // Otherwise go through the queue of methods, and invoke the functions.
157
+ // Update this as the time unit, and set the final value as this item.
158
+ // * In the case of `enable`, keep the queue but set `disable` instead.
159
+ // And in the case of `flip`, keep the queue but set `enable` instead.
160
+ clockItem[ ( type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type ) ] = clock.queue[ type ].split( ' ' ).map( function( method ) {
161
+ value = clock[ method ]( type, value, options )
162
+ return value
163
+ }).pop()
164
+
165
+ // Check if we need to cascade through more updates.
166
+ if ( type == 'select' ) {
167
+ clock.set( 'highlight', clockItem.select, options )
168
+ }
169
+ else if ( type == 'highlight' ) {
170
+ clock.set( 'view', clockItem.highlight, options )
171
+ }
172
+ else if ( type == 'interval' ) {
173
+ clock.
174
+ set( 'min', clockItem.min, options ).
175
+ set( 'max', clockItem.max, options )
176
+ }
177
+ else if ( type.match( /^(flip|min|max|disable|enable)$/ ) ) {
178
+ if ( clockItem.select && clock.disabled( clockItem.select ) ) {
179
+ clock.set( 'select', value, options )
180
+ }
181
+ if ( clockItem.highlight && clock.disabled( clockItem.highlight ) ) {
182
+ clock.set( 'highlight', value, options )
183
+ }
184
+ if ( type == 'min' ) {
185
+ clock.set( 'max', clockItem.max, options )
186
+ }
187
+ }
188
+
189
+ return clock
190
+ } //TimePicker.prototype.set
191
+
192
+
193
+ /**
194
+ * Get a timepicker item object.
195
+ */
196
+ TimePicker.prototype.get = function( type ) {
197
+ return this.item[ type ]
198
+ } //TimePicker.prototype.get
199
+
200
+
201
+ /**
202
+ * Create a picker time object.
203
+ */
204
+ TimePicker.prototype.create = function( type, value, options ) {
205
+
206
+ var clock = this
207
+
208
+ // If there’s no value, use the type as the value.
209
+ value = value === undefined ? type : value
210
+
211
+ // If it’s a date object, convert it into an array.
212
+ if ( _.isDate( value ) ) {
213
+ value = [ value.getHours(), value.getMinutes() ]
214
+ }
215
+
216
+ // If it’s an object, use the “pick” value.
217
+ if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
218
+ value = value.pick
219
+ }
220
+
221
+ // If it’s an array, convert it into minutes.
222
+ else if ( $.isArray( value ) ) {
223
+ value = +value[ 0 ] * MINUTES_IN_HOUR + (+value[ 1 ])
224
+ }
225
+
226
+ // If no valid value is passed, set it to “now”.
227
+ else if ( !_.isInteger( value ) ) {
228
+ value = clock.now( type, value, options )
229
+ }
230
+
231
+ // If we’re setting the max, make sure it’s greater than the min.
232
+ if ( type == 'max' && value < clock.item.min.pick ) {
233
+ value += MINUTES_IN_DAY
234
+ }
235
+
236
+ // If the value doesn’t fall directly on the interval,
237
+ // add one interval to indicate it as “passed”.
238
+ if ( type != 'min' && type != 'max' && (value - clock.item.min.pick) % clock.item.interval !== 0 ) {
239
+ value += clock.item.interval
240
+ }
241
+
242
+ // Normalize it into a “reachable” interval.
243
+ value = clock.normalize( type, value, options )
244
+
245
+ // Return the compiled object.
246
+ return {
247
+
248
+ // Divide to get hours from minutes.
249
+ hour: ~~( HOURS_IN_DAY + value / MINUTES_IN_HOUR ) % HOURS_IN_DAY,
250
+
251
+ // The remainder is the minutes.
252
+ mins: ( MINUTES_IN_HOUR + value % MINUTES_IN_HOUR ) % MINUTES_IN_HOUR,
253
+
254
+ // The time in total minutes.
255
+ time: ( MINUTES_IN_DAY + value ) % MINUTES_IN_DAY,
256
+
257
+ // Reference to the “relative” value to pick.
258
+ pick: value % MINUTES_IN_DAY
259
+ }
260
+ } //TimePicker.prototype.create
261
+
262
+
263
+ /**
264
+ * Create a range limit object using an array, date object,
265
+ * literal “true”, or integer relative to another time.
266
+ */
267
+ TimePicker.prototype.createRange = function( from, to ) {
268
+
269
+ var clock = this,
270
+ createTime = function( time ) {
271
+ if ( time === true || $.isArray( time ) || _.isDate( time ) ) {
272
+ return clock.create( time )
273
+ }
274
+ return time
275
+ }
276
+
277
+ // Create objects if possible.
278
+ if ( !_.isInteger( from ) ) {
279
+ from = createTime( from )
280
+ }
281
+ if ( !_.isInteger( to ) ) {
282
+ to = createTime( to )
283
+ }
284
+
285
+ // Create relative times.
286
+ if ( _.isInteger( from ) && $.isPlainObject( to ) ) {
287
+ from = [ to.hour, to.mins + ( from * clock.settings.interval ) ];
288
+ }
289
+ else if ( _.isInteger( to ) && $.isPlainObject( from ) ) {
290
+ to = [ from.hour, from.mins + ( to * clock.settings.interval ) ];
291
+ }
292
+
293
+ return {
294
+ from: createTime( from ),
295
+ to: createTime( to )
296
+ }
297
+ } //TimePicker.prototype.createRange
298
+
299
+
300
+ /**
301
+ * Check if a time unit falls within a time range object.
302
+ */
303
+ TimePicker.prototype.withinRange = function( range, timeUnit ) {
304
+ range = this.createRange(range.from, range.to)
305
+ return timeUnit.pick >= range.from.pick && timeUnit.pick <= range.to.pick
306
+ }
307
+
308
+
309
+ /**
310
+ * Check if two time range objects overlap.
311
+ */
312
+ TimePicker.prototype.overlapRanges = function( one, two ) {
313
+
314
+ var clock = this
315
+
316
+ // Convert the ranges into comparable times.
317
+ one = clock.createRange( one.from, one.to )
318
+ two = clock.createRange( two.from, two.to )
319
+
320
+ return clock.withinRange( one, two.from ) || clock.withinRange( one, two.to ) ||
321
+ clock.withinRange( two, one.from ) || clock.withinRange( two, one.to )
322
+ }
323
+
324
+
325
+ /**
326
+ * Get the time relative to now.
327
+ */
328
+ TimePicker.prototype.now = function( type, value/*, options*/ ) {
329
+
330
+ var interval = this.item.interval,
331
+ date = new Date(),
332
+ nowMinutes = date.getHours() * MINUTES_IN_HOUR + date.getMinutes(),
333
+ isValueInteger = _.isInteger( value ),
334
+ isBelowInterval
335
+
336
+ // Make sure “now” falls within the interval range.
337
+ nowMinutes -= nowMinutes % interval
338
+
339
+ // Check if the difference is less than the interval itself.
340
+ isBelowInterval = value < 0 && interval * value + nowMinutes <= -interval
341
+
342
+ // Add an interval because the time has “passed”.
343
+ nowMinutes += type == 'min' && isBelowInterval ? 0 : interval
344
+
345
+ // If the value is a number, adjust by that many intervals.
346
+ if ( isValueInteger ) {
347
+ nowMinutes += interval * (
348
+ isBelowInterval && type != 'max' ?
349
+ value + 1 :
350
+ value
351
+ )
352
+ }
353
+
354
+ // Return the final calculation.
355
+ return nowMinutes
356
+ } //TimePicker.prototype.now
357
+
358
+
359
+ /**
360
+ * Normalize minutes to be “reachable” based on the min and interval.
361
+ */
362
+ TimePicker.prototype.normalize = function( type, value/*, options*/ ) {
363
+
364
+ var interval = this.item.interval,
365
+ minTime = this.item.min && this.item.min.pick || 0
366
+
367
+ // If setting min time, don’t shift anything.
368
+ // Otherwise get the value and min difference and then
369
+ // normalize the difference with the interval.
370
+ value -= type == 'min' ? 0 : ( value - minTime ) % interval
371
+
372
+ // Return the adjusted value.
373
+ return value
374
+ } //TimePicker.prototype.normalize
375
+
376
+
377
+ /**
378
+ * Measure the range of minutes.
379
+ */
380
+ TimePicker.prototype.measure = function( type, value, options ) {
381
+
382
+ var clock = this
383
+
384
+ // If it’s anything false-y, set it to the default.
385
+ if ( !value ) {
386
+ value = type == 'min' ? [ 0, 0 ] : [ HOURS_IN_DAY - 1, MINUTES_IN_HOUR - 1 ]
387
+ }
388
+
389
+ // If it’s a string, parse it.
390
+ if ( typeof value == 'string' ) {
391
+ value = clock.parse( type, value )
392
+ }
393
+
394
+ // If it’s a literal true, or an integer, make it relative to now.
395
+ else if ( value === true || _.isInteger( value ) ) {
396
+ value = clock.now( type, value, options )
397
+ }
398
+
399
+ // If it’s an object already, just normalize it.
400
+ else if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
401
+ value = clock.normalize( type, value.pick, options )
402
+ }
403
+
404
+ return value
405
+ } ///TimePicker.prototype.measure
406
+
407
+
408
+ /**
409
+ * Validate an object as enabled.
410
+ */
411
+ TimePicker.prototype.validate = function( type, timeObject, options ) {
412
+
413
+ var clock = this,
414
+ interval = options && options.interval ? options.interval : clock.item.interval
415
+
416
+ // Check if the object is disabled.
417
+ if ( clock.disabled( timeObject ) ) {
418
+
419
+ // Shift with the interval until we reach an enabled time.
420
+ timeObject = clock.shift( timeObject, interval )
421
+ }
422
+
423
+ // Scope the object into range.
424
+ timeObject = clock.scope( timeObject )
425
+
426
+ // Do a second check to see if we landed on a disabled min/max.
427
+ // In that case, shift using the opposite interval as before.
428
+ if ( clock.disabled( timeObject ) ) {
429
+ timeObject = clock.shift( timeObject, interval * -1 )
430
+ }
431
+
432
+ // Return the final object.
433
+ return timeObject
434
+ } //TimePicker.prototype.validate
435
+
436
+
437
+ /**
438
+ * Check if an object is disabled.
439
+ */
440
+ TimePicker.prototype.disabled = function( timeToVerify ) {
441
+
442
+ var clock = this,
443
+
444
+ // Filter through the disabled times to check if this is one.
445
+ isDisabledMatch = clock.item.disable.filter( function( timeToDisable ) {
446
+
447
+ // If the time is a number, match the hours.
448
+ if ( _.isInteger( timeToDisable ) ) {
449
+ return timeToVerify.hour == timeToDisable
450
+ }
451
+
452
+ // If it’s an array, create the object and match the times.
453
+ if ( $.isArray( timeToDisable ) || _.isDate( timeToDisable ) ) {
454
+ return timeToVerify.pick == clock.create( timeToDisable ).pick
455
+ }
456
+
457
+ // If it’s an object, match a time within the “from” and “to” range.
458
+ if ( $.isPlainObject( timeToDisable ) ) {
459
+ return clock.withinRange( timeToDisable, timeToVerify )
460
+ }
461
+ })
462
+
463
+ // If this time matches a disabled time, confirm it’s not inverted.
464
+ isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function( timeToDisable ) {
465
+ return $.isArray( timeToDisable ) && timeToDisable[2] == 'inverted' ||
466
+ $.isPlainObject( timeToDisable ) && timeToDisable.inverted
467
+ }).length
468
+
469
+ // If the clock is "enabled" flag is flipped, flip the condition.
470
+ return clock.item.enable === -1 ? !isDisabledMatch : isDisabledMatch ||
471
+ timeToVerify.pick < clock.item.min.pick ||
472
+ timeToVerify.pick > clock.item.max.pick
473
+ } //TimePicker.prototype.disabled
474
+
475
+
476
+ /**
477
+ * Shift an object by an interval until we reach an enabled object.
478
+ */
479
+ TimePicker.prototype.shift = function( timeObject, interval ) {
480
+
481
+ var clock = this,
482
+ minLimit = clock.item.min.pick,
483
+ maxLimit = clock.item.max.pick/*,
484
+ safety = 1000*/
485
+
486
+ interval = interval || clock.item.interval
487
+
488
+ // Keep looping as long as the time is disabled.
489
+ while ( /*safety &&*/ clock.disabled( timeObject ) ) {
490
+
491
+ /*safety -= 1
492
+ if ( !safety ) {
493
+ throw 'Fell into an infinite loop while shifting to ' + timeObject.hour + ':' + timeObject.mins + '.'
494
+ }*/
495
+
496
+ // Increase/decrease the time by the interval and keep looping.
497
+ timeObject = clock.create( timeObject.pick += interval )
498
+
499
+ // If we've looped beyond the limits, break out of the loop.
500
+ if ( timeObject.pick <= minLimit || timeObject.pick >= maxLimit ) {
501
+ break
502
+ }
503
+ }
504
+
505
+ // Return the final object.
506
+ return timeObject
507
+ } //TimePicker.prototype.shift
508
+
509
+
510
+ /**
511
+ * Scope an object to be within range of min and max.
512
+ */
513
+ TimePicker.prototype.scope = function( timeObject ) {
514
+ var minLimit = this.item.min.pick,
515
+ maxLimit = this.item.max.pick
516
+ return this.create( timeObject.pick > maxLimit ? maxLimit : timeObject.pick < minLimit ? minLimit : timeObject )
517
+ } //TimePicker.prototype.scope
518
+
519
+
520
+ /**
521
+ * Parse a string into a usable type.
522
+ */
523
+ TimePicker.prototype.parse = function( type, value, options ) {
524
+
525
+ var hour, minutes, isPM, item, parseValue,
526
+ clock = this,
527
+ parsingObject = {}
528
+
529
+ // If it’s already parsed, we’re good.
530
+ if ( !value || typeof value != 'string' ) {
531
+ return value
532
+ }
533
+
534
+ // We need a `.format` to parse the value with.
535
+ if ( !( options && options.format ) ) {
536
+ options = options || {}
537
+ options.format = clock.settings.format
538
+ }
539
+
540
+ // Convert the format into an array and then map through it.
541
+ clock.formats.toArray( options.format ).map( function( label ) {
542
+
543
+ var
544
+ substring,
545
+
546
+ // Grab the formatting label.
547
+ formattingLabel = clock.formats[ label ],
548
+
549
+ // The format length is from the formatting label function or the
550
+ // label length without the escaping exclamation (!) mark.
551
+ formatLength = formattingLabel ?
552
+ _.trigger( formattingLabel, clock, [ value, parsingObject ] ) :
553
+ label.replace( /^!/, '' ).length
554
+
555
+ // If there's a format label, split the value up to the format length.
556
+ // Then add it to the parsing object with appropriate label.
557
+ if ( formattingLabel ) {
558
+ substring = value.substr( 0, formatLength )
559
+ parsingObject[ label ] = substring.match(/^\d+$/) ? +substring : substring
560
+ }
561
+
562
+ // Update the time value as the substring from format length to end.
563
+ value = value.substr( formatLength )
564
+ })
565
+
566
+ // Grab the hour and minutes from the parsing object.
567
+ for ( item in parsingObject ) {
568
+ parseValue = parsingObject[item]
569
+ if ( _.isInteger(parseValue) ) {
570
+ if ( item.match(/^(h|hh)$/i) ) {
571
+ hour = parseValue
572
+ if ( item == 'h' || item == 'hh' ) {
573
+ hour %= 12
574
+ }
575
+ }
576
+ else if ( item == 'i' ) {
577
+ minutes = parseValue
578
+ }
579
+ }
580
+ else if ( item.match(/^a$/i) && parseValue.match(/^p/i) && ('h' in parsingObject || 'hh' in parsingObject) ) {
581
+ isPM = true
582
+ }
583
+ }
584
+
585
+ // Calculate it in minutes and return.
586
+ return (isPM ? hour + 12 : hour) * MINUTES_IN_HOUR + minutes
587
+ } //TimePicker.prototype.parse
588
+
589
+
590
+ /**
591
+ * Various formats to display the object in.
592
+ */
593
+ TimePicker.prototype.formats = {
594
+
595
+ h: function( string, timeObject ) {
596
+
597
+ // If there's string, then get the digits length.
598
+ // Otherwise return the selected hour in "standard" format.
599
+ return string ? _.digits( string ) : timeObject.hour % HOURS_TO_NOON || HOURS_TO_NOON
600
+ },
601
+ hh: function( string, timeObject ) {
602
+
603
+ // If there's a string, then the length is always 2.
604
+ // Otherwise return the selected hour in "standard" format with a leading zero.
605
+ return string ? 2 : _.lead( timeObject.hour % HOURS_TO_NOON || HOURS_TO_NOON )
606
+ },
607
+ H: function( string, timeObject ) {
608
+
609
+ // If there's string, then get the digits length.
610
+ // Otherwise return the selected hour in "military" format as a string.
611
+ return string ? _.digits( string ) : '' + ( timeObject.hour % 24 )
612
+ },
613
+ HH: function( string, timeObject ) {
614
+
615
+ // If there's string, then get the digits length.
616
+ // Otherwise return the selected hour in "military" format with a leading zero.
617
+ return string ? _.digits( string ) : _.lead( timeObject.hour % 24 )
618
+ },
619
+ i: function( string, timeObject ) {
620
+
621
+ // If there's a string, then the length is always 2.
622
+ // Otherwise return the selected minutes.
623
+ return string ? 2 : _.lead( timeObject.mins )
624
+ },
625
+ a: function( string, timeObject ) {
626
+
627
+ // If there's a string, then the length is always 4.
628
+ // Otherwise check if it's more than "noon" and return either am/pm.
629
+ return string ? 4 : MINUTES_IN_DAY / 2 > timeObject.time % MINUTES_IN_DAY ? 'a.m.' : 'p.m.'
630
+ },
631
+ A: function( string, timeObject ) {
632
+
633
+ // If there's a string, then the length is always 2.
634
+ // Otherwise check if it's more than "noon" and return either am/pm.
635
+ return string ? 2 : MINUTES_IN_DAY / 2 > timeObject.time % MINUTES_IN_DAY ? 'AM' : 'PM'
636
+ },
637
+
638
+ // Create an array by splitting the formatting string passed.
639
+ toArray: function( formatString ) { return formatString.split( /(h{1,2}|H{1,2}|i|a|A|!.)/g ) },
640
+
641
+ // Format an object into a string using the formatting options.
642
+ toString: function ( formatString, itemObject ) {
643
+ var clock = this
644
+ return clock.formats.toArray( formatString ).map( function( label ) {
645
+ return _.trigger( clock.formats[ label ], clock, [ 0, itemObject ] ) || label.replace( /^!/, '' )
646
+ }).join( '' )
647
+ }
648
+ } //TimePicker.prototype.formats
649
+
650
+
651
+
652
+
653
+ /**
654
+ * Check if two time units are the exact.
655
+ */
656
+ TimePicker.prototype.isTimeExact = function( one, two ) {
657
+
658
+ var clock = this
659
+
660
+ // When we’re working with minutes, do a direct comparison.
661
+ if (
662
+ ( _.isInteger( one ) && _.isInteger( two ) ) ||
663
+ ( typeof one == 'boolean' && typeof two == 'boolean' )
664
+ ) {
665
+ return one === two
666
+ }
667
+
668
+ // When we’re working with time representations, compare the “pick” value.
669
+ if (
670
+ ( _.isDate( one ) || $.isArray( one ) ) &&
671
+ ( _.isDate( two ) || $.isArray( two ) )
672
+ ) {
673
+ return clock.create( one ).pick === clock.create( two ).pick
674
+ }
675
+
676
+ // When we’re working with range objects, compare the “from” and “to”.
677
+ if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
678
+ return clock.isTimeExact( one.from, two.from ) && clock.isTimeExact( one.to, two.to )
679
+ }
680
+
681
+ return false
682
+ }
683
+
684
+
685
+ /**
686
+ * Check if two time units overlap.
687
+ */
688
+ TimePicker.prototype.isTimeOverlap = function( one, two ) {
689
+
690
+ var clock = this
691
+
692
+ // When we’re working with an integer, compare the hours.
693
+ if ( _.isInteger( one ) && ( _.isDate( two ) || $.isArray( two ) ) ) {
694
+ return one === clock.create( two ).hour
695
+ }
696
+ if ( _.isInteger( two ) && ( _.isDate( one ) || $.isArray( one ) ) ) {
697
+ return two === clock.create( one ).hour
698
+ }
699
+
700
+ // When we’re working with range objects, check if the ranges overlap.
701
+ if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
702
+ return clock.overlapRanges( one, two )
703
+ }
704
+
705
+ return false
706
+ }
707
+
708
+
709
+ /**
710
+ * Flip the “enabled” state.
711
+ */
712
+ TimePicker.prototype.flipEnable = function(val) {
713
+ var itemObject = this.item
714
+ itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1)
715
+ }
716
+
717
+
718
+ /**
719
+ * Mark a collection of times as “disabled”.
720
+ */
721
+ TimePicker.prototype.deactivate = function( type, timesToDisable ) {
722
+
723
+ var clock = this,
724
+ disabledItems = clock.item.disable.slice(0)
725
+
726
+
727
+ // If we’re flipping, that’s all we need to do.
728
+ if ( timesToDisable == 'flip' ) {
729
+ clock.flipEnable()
730
+ }
731
+
732
+ else if ( timesToDisable === false ) {
733
+ clock.flipEnable(1)
734
+ disabledItems = []
735
+ }
736
+
737
+ else if ( timesToDisable === true ) {
738
+ clock.flipEnable(-1)
739
+ disabledItems = []
740
+ }
741
+
742
+ // Otherwise go through the times to disable.
743
+ else {
744
+
745
+ timesToDisable.map(function( unitToDisable ) {
746
+
747
+ var matchFound
748
+
749
+ // When we have disabled items, check for matches.
750
+ // If something is matched, immediately break out.
751
+ for ( var index = 0; index < disabledItems.length; index += 1 ) {
752
+ if ( clock.isTimeExact( unitToDisable, disabledItems[index] ) ) {
753
+ matchFound = true
754
+ break
755
+ }
756
+ }
757
+
758
+ // If nothing was found, add the validated unit to the collection.
759
+ if ( !matchFound ) {
760
+ if (
761
+ _.isInteger( unitToDisable ) ||
762
+ _.isDate( unitToDisable ) ||
763
+ $.isArray( unitToDisable ) ||
764
+ ( $.isPlainObject( unitToDisable ) && unitToDisable.from && unitToDisable.to )
765
+ ) {
766
+ disabledItems.push( unitToDisable )
767
+ }
768
+ }
769
+ })
770
+ }
771
+
772
+ // Return the updated collection.
773
+ return disabledItems
774
+ } //TimePicker.prototype.deactivate
775
+
776
+
777
+ /**
778
+ * Mark a collection of times as “enabled”.
779
+ */
780
+ TimePicker.prototype.activate = function( type, timesToEnable ) {
781
+
782
+ var clock = this,
783
+ disabledItems = clock.item.disable,
784
+ disabledItemsCount = disabledItems.length
785
+
786
+ // If we’re flipping, that’s all we need to do.
787
+ if ( timesToEnable == 'flip' ) {
788
+ clock.flipEnable()
789
+ }
790
+
791
+ else if ( timesToEnable === true ) {
792
+ clock.flipEnable(1)
793
+ disabledItems = []
794
+ }
795
+
796
+ else if ( timesToEnable === false ) {
797
+ clock.flipEnable(-1)
798
+ disabledItems = []
799
+ }
800
+
801
+ // Otherwise go through the disabled times.
802
+ else {
803
+
804
+ timesToEnable.map(function( unitToEnable ) {
805
+
806
+ var matchFound,
807
+ disabledUnit,
808
+ index,
809
+ isRangeMatched
810
+
811
+ // Go through the disabled items and try to find a match.
812
+ for ( index = 0; index < disabledItemsCount; index += 1 ) {
813
+
814
+ disabledUnit = disabledItems[index]
815
+
816
+ // When an exact match is found, remove it from the collection.
817
+ if ( clock.isTimeExact( disabledUnit, unitToEnable ) ) {
818
+ matchFound = disabledItems[index] = null
819
+ isRangeMatched = true
820
+ break
821
+ }
822
+
823
+ // When an overlapped match is found, add the “inverted” state to it.
824
+ else if ( clock.isTimeOverlap( disabledUnit, unitToEnable ) ) {
825
+ if ( $.isPlainObject( unitToEnable ) ) {
826
+ unitToEnable.inverted = true
827
+ matchFound = unitToEnable
828
+ }
829
+ else if ( $.isArray( unitToEnable ) ) {
830
+ matchFound = unitToEnable
831
+ if ( !matchFound[2] ) matchFound.push( 'inverted' )
832
+ }
833
+ else if ( _.isDate( unitToEnable ) ) {
834
+ matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), 'inverted' ]
835
+ }
836
+ break
837
+ }
838
+ }
839
+
840
+ // If a match was found, remove a previous duplicate entry.
841
+ if ( matchFound ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
842
+ if ( clock.isTimeExact( disabledItems[index], unitToEnable ) ) {
843
+ disabledItems[index] = null
844
+ break
845
+ }
846
+ }
847
+
848
+ // In the event that we’re dealing with an overlap of range times,
849
+ // make sure there are no “inverted” times because of it.
850
+ if ( isRangeMatched ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
851
+ if ( clock.isTimeOverlap( disabledItems[index], unitToEnable ) ) {
852
+ disabledItems[index] = null
853
+ break
854
+ }
855
+ }
856
+
857
+ // If something is still matched, add it into the collection.
858
+ if ( matchFound ) {
859
+ disabledItems.push( matchFound )
860
+ }
861
+ })
862
+ }
863
+
864
+ // Return the updated collection.
865
+ return disabledItems.filter(function( val ) { return val != null })
866
+ } //TimePicker.prototype.activate
867
+
868
+
869
+ /**
870
+ * The division to use for the range intervals.
871
+ */
872
+ TimePicker.prototype.i = function( type, value/*, options*/ ) {
873
+ return _.isInteger( value ) && value > 0 ? value : this.item.interval
874
+ }
875
+
876
+
877
+ /**
878
+ * Create a string for the nodes in the picker.
879
+ */
880
+ TimePicker.prototype.nodes = function( isOpen ) {
881
+
882
+ var
883
+ clock = this,
884
+ settings = clock.settings,
885
+ selectedObject = clock.item.select,
886
+ highlightedObject = clock.item.highlight,
887
+ viewsetObject = clock.item.view,
888
+ disabledCollection = clock.item.disable
889
+
890
+ return _.node(
891
+ 'ul',
892
+ _.group({
893
+ min: clock.item.min.pick,
894
+ max: clock.item.max.pick,
895
+ i: clock.item.interval,
896
+ node: 'li',
897
+ item: function( loopedTime ) {
898
+ loopedTime = clock.create( loopedTime )
899
+ var timeMinutes = loopedTime.pick,
900
+ isSelected = selectedObject && selectedObject.pick == timeMinutes,
901
+ isHighlighted = highlightedObject && highlightedObject.pick == timeMinutes,
902
+ isDisabled = disabledCollection && clock.disabled( loopedTime ),
903
+ formattedTime = _.trigger( clock.formats.toString, clock, [ settings.format, loopedTime ] )
904
+ return [
905
+ _.trigger( clock.formats.toString, clock, [ _.trigger( settings.formatLabel, clock, [ loopedTime ] ) || settings.format, loopedTime ] ),
906
+ (function( klasses ) {
907
+
908
+ if ( isSelected ) {
909
+ klasses.push( settings.klass.selected )
910
+ }
911
+
912
+ if ( isHighlighted ) {
913
+ klasses.push( settings.klass.highlighted )
914
+ }
915
+
916
+ if ( viewsetObject && viewsetObject.pick == timeMinutes ) {
917
+ klasses.push( settings.klass.viewset )
918
+ }
919
+
920
+ if ( isDisabled ) {
921
+ klasses.push( settings.klass.disabled )
922
+ }
923
+
924
+ return klasses.join( ' ' )
925
+ })( [ settings.klass.listItem ] ),
926
+ 'data-pick=' + loopedTime.pick + ' ' + _.ariaAttr({
927
+ role: 'option',
928
+ label: formattedTime,
929
+ selected: isSelected && clock.$node.val() === formattedTime ? true : null,
930
+ activedescendant: isHighlighted ? true : null,
931
+ disabled: isDisabled ? true : null
932
+ })
933
+ ]
934
+ }
935
+ }) +
936
+
937
+ // * For Firefox forms to submit, make sure to set the button’s `type` attribute as “button”.
938
+ _.node(
939
+ 'li',
940
+ _.node(
941
+ 'button',
942
+ settings.clear,
943
+ settings.klass.buttonClear,
944
+ 'type=button data-clear=1' + ( isOpen ? '' : ' disabled' ) + ' ' +
945
+ _.ariaAttr({ controls: clock.$node[0].id }) ) +
946
+ _.node(
947
+ 'button',
948
+ 'Close',
949
+ 'picker__button--close',
950
+ 'type=button data-close=1' + ( isOpen ? '' : ' disabled' ) + ' ' +
951
+ _.ariaAttr({ controls: clock.$node[0].id })
952
+ ),
953
+ '', _.ariaAttr({ role: 'presentation' })
954
+ ),
955
+ settings.klass.list,
956
+ _.ariaAttr({ role: 'listbox', controls: clock.$node[0].id })
957
+ )
958
+ } //TimePicker.prototype.nodes
959
+
960
+
961
+
962
+
963
+
964
+
965
+
966
+ /**
967
+ * Extend the picker to add the component with the defaults.
968
+ */
969
+ TimePicker.defaults = (function( prefix ) {
970
+
971
+ return {
972
+
973
+ // Clear
974
+ clear: 'Clear',
975
+
976
+ // The format to show on the `input` element
977
+ format: 'h:i A',
978
+
979
+ // The interval between each time
980
+ interval: 30,
981
+
982
+ // Picker close behavior
983
+ closeOnSelect: true,
984
+ closeOnClear: true,
985
+
986
+ // Update input value on select/clear
987
+ updateInput: true,
988
+
989
+ // Classes
990
+ klass: {
991
+
992
+ picker: prefix + ' ' + prefix + '--time',
993
+ holder: prefix + '__holder',
994
+
995
+ list: prefix + '__list',
996
+ listItem: prefix + '__list-item',
997
+
998
+ disabled: prefix + '__list-item--disabled',
999
+ selected: prefix + '__list-item--selected',
1000
+ highlighted: prefix + '__list-item--highlighted',
1001
+ viewset: prefix + '__list-item--viewset',
1002
+ now: prefix + '__list-item--now',
1003
+
1004
+ buttonClear: prefix + '__button--clear'
1005
+ }
1006
+ }
1007
+ })( Picker.klasses().picker )
1008
+
1009
+
1010
+
1011
+
1012
+
1013
+ /**
1014
+ * Extend the picker to add the time picker.
1015
+ */
1016
+ Picker.extend( 'pickatime', TimePicker )
1017
+
1018
+
1019
+ }));
1020
+
1021
+
1022
+
js/pickadate/themes/classic.css CHANGED
@@ -1,88 +1,96 @@
 
 
 
 
 
 
1
  .picker {
2
- font-size: 16px;
3
- text-align: left;
4
- line-height: 1.2;
5
- color: #000;
6
- position: absolute;
7
- z-index: 10000;
8
- -webkit-user-select: none;
9
- -moz-user-select: none;
10
- -ms-user-select: none;
11
- user-select: none
 
12
  }
13
-
 
 
14
  .picker__input {
15
- cursor: default
16
  }
17
-
 
 
18
  .picker__input.picker__input--active {
19
- border-color: #0089ec
20
  }
21
-
 
 
22
  .picker__holder {
23
- width: 100%;
24
- overflow-y: auto;
25
- -webkit-overflow-scrolling: touch
26
  }
27
 
28
  /*!
29
  * Classic picker styling for pickadate.js
30
  * Demo: http://amsul.github.io/pickadate.js
31
  */
 
 
 
32
  .picker {
33
- width: 100%
34
  }
35
-
 
 
36
  .picker__holder {
37
- position: absolute;
38
- background: #fff;
39
- border: 1px solid #aaa;
40
- border-top-width: 0;
41
- border-bottom-width: 0;
42
- -webkit-border-radius: 0 0 5px 5px;
43
- -moz-border-radius: 0 0 5px 5px;
44
- border-radius: 0 0 5px 5px;
45
- -webkit-box-sizing: border-box;
46
- -moz-box-sizing: border-box;
47
- box-sizing: border-box;
48
- min-width: 176px;
49
- max-width: 466px;
50
- max-height: 0;
51
- -ms-filter: "alpha(Opacity=0)";
52
- filter: alpha(opacity=0);
53
- -moz-opacity: 0;
54
- opacity: 0;
55
- -webkit-transform: translateY(-1em) perspective(600px) rotateX(10deg);
56
- -moz-transform: translateY(-1em) perspective(600px) rotateX(10deg);
57
- transform: translateY(-1em) perspective(600px) rotateX(10deg);
58
- -webkit-transition: all .15s ease-out, max-height 0 .15s, border-width 0 .15s;
59
- -moz-transition: all .15s ease-out, max-height 0 .15s, border-width 0 .15s;
60
- transition: all .15s ease-out, max-height 0 .15s, border-width 0 .15s
61
  }
62
-
 
 
 
63
  .picker__frame {
64
- padding: 1px
65
  }
66
-
67
  .picker__wrap {
68
- margin: -1px
69
  }
70
-
 
 
71
  .picker--opened .picker__holder {
72
- max-height: 25em;
73
- -ms-filter: "alpha(Opacity=100)";
74
- filter: alpha(opacity=100);
75
- -moz-opacity: 1;
76
- opacity: 1;
77
- border-top-width: 1px;
78
- border-bottom-width: 1px;
79
- -webkit-transform: translateY(0) perspective(600px) rotateX(0);
80
- -moz-transform: translateY(0) perspective(600px) rotateX(0);
81
- transform: translateY(0) perspective(600px) rotateX(0);
82
- -webkit-transition: all .15s ease-out, max-height 0, border-width 0;
83
- -moz-transition: all .15s ease-out, max-height 0, border-width 0;
84
- transition: all .15s ease-out, max-height 0, border-width 0;
85
- -webkit-box-shadow: 0 6px 18px 1px rgba(0, 0, 0, .12);
86
- -moz-box-shadow: 0 6px 18px 1px rgba(0, 0, 0, .12);
87
- box-shadow: 0 6px 18px 1px rgba(0, 0, 0, .12)
88
- }
1
+ /* ==========================================================================
2
+ $BASE-PICKER
3
+ ========================================================================== */
4
+ /**
5
+ * Note: the root picker element should *NOT* be styled more than what’s here.
6
+ */
7
  .picker {
8
+ font-size: 16px;
9
+ text-align: left;
10
+ line-height: 1.2;
11
+ color: #000;
12
+ position: absolute;
13
+ z-index: 10000;
14
+ -webkit-user-select: none;
15
+ -moz-user-select: none;
16
+ -ms-user-select: none;
17
+ user-select: none;
18
+ outline: none;
19
  }
20
+ /**
21
+ * The picker input element.
22
+ */
23
  .picker__input {
24
+ cursor: default;
25
  }
26
+ /**
27
+ * When the picker is opened, the input element is “activated”.
28
+ */
29
  .picker__input.picker__input--active {
30
+ border-color: #0089ec;
31
  }
32
+ /**
33
+ * The holder is the only “scrollable” top-level container element.
34
+ */
35
  .picker__holder {
36
+ width: 100%;
37
+ overflow-y: auto;
38
+ -webkit-overflow-scrolling: touch;
39
  }
40
 
41
  /*!
42
  * Classic picker styling for pickadate.js
43
  * Demo: http://amsul.github.io/pickadate.js
44
  */
45
+ /**
46
+ * Note: the root picker element should *NOT* be styled more than what’s here.
47
+ */
48
  .picker {
49
+ width: 100%;
50
  }
51
+ /**
52
+ * The holder is the base of the picker.
53
+ */
54
  .picker__holder {
55
+ position: absolute;
56
+ background: #fff;
57
+ border: 1px solid #aaaaaa;
58
+ border-top-width: 0;
59
+ border-bottom-width: 0;
60
+ border-radius: 0 0 5px 5px;
61
+ box-sizing: border-box;
62
+ min-width: 176px;
63
+ max-width: 466px;
64
+ max-height: 0;
65
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
66
+ filter: alpha(opacity=0);
67
+ -moz-opacity: 0;
68
+ opacity: 0;
69
+ transform: translateY(-1em) perspective(600px) rotateX(10deg);
70
+ transition: transform 0.15s ease-out, opacity 0.15s ease-out, max-height 0s 0.15s, border-width 0s 0.15s;
 
 
 
 
 
 
 
 
71
  }
72
+ /**
73
+ * The frame and wrap work together to ensure that
74
+ * clicks within the picker don’t reach the holder.
75
+ */
76
  .picker__frame {
77
+ padding: 1px;
78
  }
 
79
  .picker__wrap {
80
+ margin: -1px;
81
  }
82
+ /**
83
+ * When the picker opens...
84
+ */
85
  .picker--opened .picker__holder {
86
+ max-height: 25em;
87
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
88
+ filter: alpha(opacity=100);
89
+ -moz-opacity: 1;
90
+ opacity: 1;
91
+ border-top-width: 1px;
92
+ border-bottom-width: 1px;
93
+ transform: translateY(0) perspective(600px) rotateX(0);
94
+ transition: transform 0.15s ease-out, opacity 0.15s ease-out, max-height 0s, border-width 0s;
95
+ box-shadow: 0 6px 18px 1px rgba(0, 0, 0, 0.12);
96
+ }
 
 
 
 
 
 
js/pickadate/themes/classic.date.css CHANGED
@@ -1,263 +1,301 @@
1
- .picker__box {
2
- padding: 0 1em
3
- }
4
-
5
- .picker__header {
6
- text-align: center;
7
- position: relative;
8
- margin-top: .75em
9
- }
10
-
11
- .picker__month, .picker__year {
12
- font-weight: 500;
13
- display: inline-block;
14
- margin-left: .25em;
15
- margin-right: .25em
16
- }
17
-
18
- .picker__year {
19
- color: #999;
20
- font-size: .8em;
21
- font-style: italic
22
- }
23
-
24
- .picker__select--month, .picker__select--year {
25
- border: 1px solid #b7b7b7;
26
- height: 2.5em;
27
- padding: .5em .25em;
28
- margin-left: .25em;
29
- margin-right: .25em;
30
- font-size: .6em
31
- }
32
-
33
- @media (min-width: 24.5em) {
34
- .picker__select--month, .picker__select--year {
35
- font-size: .8em;
36
- margin-top: -.5em
37
- }
38
- }
39
-
40
- .picker__select--month {
41
- width: 35%
42
- }
43
-
44
- .picker__select--year {
45
- width: 22.5%
46
- }
47
-
48
- .picker__select--month:focus, .picker__select--year:focus {
49
- border-color: #0089ec
50
- }
51
-
52
- .picker__nav--next, .picker__nav--prev {
53
- position: absolute;
54
- padding: .5em 1.25em;
55
- width: 1em;
56
- height: 1em;
57
- top: -.25em
58
- }
59
-
60
- @media (min-width: 24.5em) {
61
- .picker__nav--next, .picker__nav--prev {
62
- top: -.33em
63
- }
64
- }
65
-
66
- .picker__nav--prev {
67
- left: -1em;
68
- padding-right: 1.25em
69
- }
70
-
71
- @media (min-width: 24.5em) {
72
- .picker__nav--prev {
73
- padding-right: 1.5em
74
- }
75
- }
76
-
77
- .picker__nav--next {
78
- right: -1em;
79
- padding-left: 1.25em
80
- }
81
-
82
- @media (min-width: 24.5em) {
83
- .picker__nav--next {
84
- padding-left: 1.5em
85
- }
86
- }
87
-
88
- .picker__nav--next:before, .picker__nav--prev:before {
89
- content: " ";
90
- border-top: .5em solid transparent;
91
- border-bottom: .5em solid transparent;
92
- border-right: .75em solid #000;
93
- width: 0;
94
- height: 0;
95
- display: block;
96
- margin: 0 auto
97
- }
98
-
99
- .picker__nav--next:before {
100
- border-right: 0;
101
- border-left: .75em solid #000
102
- }
103
-
104
- .picker__nav--next:hover, .picker__nav--prev:hover {
105
- cursor: pointer;
106
- color: #000;
107
- background: #b1dcfb
108
- }
109
-
110
- .picker__nav--disabled, .picker__nav--disabled:before, .picker__nav--disabled:before:hover, .picker__nav--disabled:hover {
111
- cursor: default;
112
- background: 0 0;
113
- border-right-color: #f5f5f5;
114
- border-left-color: #f5f5f5
115
- }
116
-
117
- .picker__table {
118
- text-align: center;
119
- border-collapse: collapse;
120
- border-spacing: 0;
121
- table-layout: fixed;
122
- font-size: inherit;
123
- width: 100%;
124
- margin-top: .75em;
125
- margin-bottom: .5em
126
- }
127
-
128
- @media (min-height: 33.875em) {
129
- .picker__table {
130
- margin-bottom: .75em
131
- }
132
- }
133
-
134
- .picker__table td {
135
- margin: 0;
136
- padding: 0
137
- }
138
-
139
- .picker__weekday {
140
- width: 14.285714286%;
141
- font-size: .75em;
142
- padding-bottom: .25em;
143
- color: #999;
144
- font-weight: 500
145
- }
146
-
147
- @media (min-height: 33.875em) {
148
- .picker__weekday {
149
- padding-bottom: .5em
150
- }
151
- }
152
-
153
- .picker__day {
154
- padding: .3125em 0;
155
- font-weight: 200;
156
- border: 1px solid transparent
157
- }
158
-
159
- .picker__day--today {
160
- color: #0089ec;
161
- position: relative
162
- }
163
-
164
- .picker__day--today:before {
165
- content: " ";
166
- position: absolute;
167
- top: 2px;
168
- right: 2px;
169
- width: 0;
170
- height: 0;
171
- border-top: .5em solid #0059bc;
172
- border-left: .5em solid transparent
173
- }
174
-
175
- .picker__day--selected, .picker__day--selected:hover {
176
- border-color: #0089ec
177
- }
178
-
179
- .picker__day--highlighted {
180
- background: #b1dcfb
181
- }
182
-
183
- .picker__day--disabled:before {
184
- border-top-color: #aaa
185
- }
186
-
187
- .picker__day--outfocus {
188
- color: #ddd
189
- }
190
-
191
- .picker__day--infocus:hover, .picker__day--outfocus:hover {
192
- cursor: pointer;
193
- color: #000;
194
- background: #b1dcfb
195
- }
196
-
197
- .picker--focused .picker__day--highlighted, .picker__day--highlighted:hover {
198
- background: #0089ec;
199
- color: #fff
200
- }
201
-
202
- .picker__day--disabled, .picker__day--disabled:hover {
203
- background: #f5f5f5;
204
- border-color: #f5f5f5;
205
- color: #ddd;
206
- cursor: default
207
- }
208
-
209
- .picker__day--highlighted.picker__day--disabled, .picker__day--highlighted.picker__day--disabled:hover {
210
- background: #bbb
211
- }
212
-
213
- .picker__footer {
214
- text-align: center
215
- }
216
-
217
- .picker__button--clear, .picker__button--today {
218
- border: 1px solid #fff;
219
- background: #fff;
220
- font-size: .8em;
221
- padding: .66em 0;
222
- font-weight: 700;
223
- width: 50%;
224
- display: inline-block;
225
- vertical-align: bottom
226
- }
227
-
228
- .picker__button--clear:hover, .picker__button--today:hover {
229
- cursor: pointer;
230
- color: #000;
231
- background: #b1dcfb;
232
- border-bottom-color: #b1dcfb
233
- }
234
-
235
- .picker__button--clear:focus, .picker__button--today:focus {
236
- background: #b1dcfb;
237
- border-color: #0089ec;
238
- outline: 0
239
- }
240
-
241
- .picker__button--clear:before, .picker__button--today:before {
242
- position: relative;
243
- display: inline-block;
244
- height: 0
245
- }
246
-
247
- .picker__button--today:before {
248
- content: " ";
249
- margin-right: .45em;
250
- top: -.05em;
251
- width: 0;
252
- border-top: .66em solid #0059bc;
253
- border-left: .66em solid transparent
254
- }
255
-
256
- .picker__button--clear:before {
257
- content: "\D7";
258
- margin-right: .35em;
259
- top: -.1em;
260
- color: #e20;
261
- vertical-align: top;
262
- font-size: 1.1em
263
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ==========================================================================
2
+ $BASE-DATE-PICKER
3
+ ========================================================================== */
4
+ /**
5
+ * The picker box.
6
+ */
7
+ .picker__box {
8
+ padding: 0 1em;
9
+ }
10
+ /**
11
+ * The header containing the month and year stuff.
12
+ */
13
+ .picker__header {
14
+ text-align: center;
15
+ position: relative;
16
+ margin-top: .75em;
17
+ }
18
+ /**
19
+ * The month and year labels.
20
+ */
21
+ .picker__month,
22
+ .picker__year {
23
+ font-weight: 500;
24
+ display: inline-block;
25
+ margin-left: .25em;
26
+ margin-right: .25em;
27
+ }
28
+ .picker__year {
29
+ color: #999;
30
+ font-size: .8em;
31
+ font-style: italic;
32
+ }
33
+ /**
34
+ * The month and year selectors.
35
+ */
36
+ .picker__select--month,
37
+ .picker__select--year {
38
+ border: 1px solid #b7b7b7;
39
+ height: 2em;
40
+ padding: .5em;
41
+ margin-left: .25em;
42
+ margin-right: .25em;
43
+ }
44
+ @media (min-width: 24.5em) {
45
+ .picker__select--month,
46
+ .picker__select--year {
47
+ margin-top: -0.5em;
48
+ }
49
+ }
50
+ .picker__select--month {
51
+ width: 35%;
52
+ }
53
+ .picker__select--year {
54
+ width: 22.5%;
55
+ }
56
+ .picker__select--month:focus,
57
+ .picker__select--year:focus {
58
+ border-color: #0089ec;
59
+ }
60
+ /**
61
+ * The month navigation buttons.
62
+ */
63
+ .picker__nav--prev,
64
+ .picker__nav--next {
65
+ position: absolute;
66
+ padding: .5em 1.25em;
67
+ width: 1em;
68
+ height: 1em;
69
+ box-sizing: content-box;
70
+ top: -0.25em;
71
+ }
72
+ @media (min-width: 24.5em) {
73
+ .picker__nav--prev,
74
+ .picker__nav--next {
75
+ top: -0.33em;
76
+ }
77
+ }
78
+ .picker__nav--prev {
79
+ left: -1em;
80
+ padding-right: 1.25em;
81
+ }
82
+ @media (min-width: 24.5em) {
83
+ .picker__nav--prev {
84
+ padding-right: 1.5em;
85
+ }
86
+ }
87
+ .picker__nav--next {
88
+ right: -1em;
89
+ padding-left: 1.25em;
90
+ }
91
+ @media (min-width: 24.5em) {
92
+ .picker__nav--next {
93
+ padding-left: 1.5em;
94
+ }
95
+ }
96
+ .picker__nav--prev:before,
97
+ .picker__nav--next:before {
98
+ content: " ";
99
+ border-top: .5em solid transparent;
100
+ border-bottom: .5em solid transparent;
101
+ border-right: 0.75em solid #000;
102
+ width: 0;
103
+ height: 0;
104
+ display: block;
105
+ margin: 0 auto;
106
+ }
107
+ .picker__nav--next:before {
108
+ border-right: 0;
109
+ border-left: 0.75em solid #000;
110
+ }
111
+ .picker__nav--prev:hover,
112
+ .picker__nav--next:hover {
113
+ cursor: pointer;
114
+ color: #000;
115
+ background: #b1dcfb;
116
+ }
117
+ .picker__nav--disabled,
118
+ .picker__nav--disabled:hover,
119
+ .picker__nav--disabled:before,
120
+ .picker__nav--disabled:before:hover {
121
+ cursor: default;
122
+ background: none;
123
+ border-right-color: #f5f5f5;
124
+ border-left-color: #f5f5f5;
125
+ }
126
+ /**
127
+ * The calendar table of dates
128
+ */
129
+ .picker__table {
130
+ text-align: center;
131
+ border-collapse: collapse;
132
+ border-spacing: 0;
133
+ table-layout: fixed;
134
+ font-size: inherit;
135
+ width: 100%;
136
+ margin-top: .75em;
137
+ margin-bottom: .5em;
138
+ }
139
+ @media (min-height: 33.875em) {
140
+ .picker__table {
141
+ margin-bottom: .75em;
142
+ }
143
+ }
144
+ .picker__table td {
145
+ margin: 0;
146
+ padding: 0;
147
+ }
148
+ /**
149
+ * The weekday labels
150
+ */
151
+ .picker__weekday {
152
+ width: 14.285714286%;
153
+ font-size: .75em;
154
+ padding-bottom: .25em;
155
+ color: #999;
156
+ font-weight: 500;
157
+ /* Increase the spacing a tad */
158
+ }
159
+ @media (min-height: 33.875em) {
160
+ .picker__weekday {
161
+ padding-bottom: .5em;
162
+ }
163
+ }
164
+ /**
165
+ * The days on the calendar
166
+ */
167
+ .picker__day {
168
+ padding: .3125em 0;
169
+ font-weight: 200;
170
+ border: 1px solid transparent;
171
+ }
172
+ .picker__day--today {
173
+ position: relative;
174
+ }
175
+ .picker__day--today:before {
176
+ content: " ";
177
+ position: absolute;
178
+ top: 2px;
179
+ right: 2px;
180
+ width: 0;
181
+ height: 0;
182
+ border-top: 0.5em solid #0059bc;
183
+ border-left: .5em solid transparent;
184
+ }
185
+ .picker__day--disabled:before {
186
+ border-top-color: #aaa;
187
+ }
188
+ .picker__day--outfocus {
189
+ color: #ddd;
190
+ }
191
+ .picker__day--infocus:hover,
192
+ .picker__day--outfocus:hover {
193
+ cursor: pointer;
194
+ color: #000;
195
+ background: #b1dcfb;
196
+ }
197
+ .picker__day--highlighted {
198
+ border-color: #0089ec;
199
+ }
200
+ .picker__day--highlighted:hover,
201
+ .picker--focused .picker__day--highlighted {
202
+ cursor: pointer;
203
+ color: #000;
204
+ background: #b1dcfb;
205
+ }
206
+ .picker__day--selected,
207
+ .picker__day--selected:hover,
208
+ .picker--focused .picker__day--selected {
209
+ background: #0089ec;
210
+ color: #fff;
211
+ }
212
+ .picker__day--disabled,
213
+ .picker__day--disabled:hover,
214
+ .picker--focused .picker__day--disabled {
215
+ background: #f5f5f5;
216
+ border-color: #f5f5f5;
217
+ color: #ddd;
218
+ cursor: default;
219
+ }
220
+ .picker__day--highlighted.picker__day--disabled,
221
+ .picker__day--highlighted.picker__day--disabled:hover {
222
+ background: #bbb;
223
+ }
224
+ /**
225
+ * The footer containing the "today", "clear", and "close" buttons.
226
+ */
227
+ .picker__footer {
228
+ text-align: center;
229
+ }
230
+ .picker__button--today,
231
+ .picker__button--clear,
232
+ .picker__button--close {
233
+ border: 1px solid #fff;
234
+ background: #fff;
235
+ font-size: .8em;
236
+ padding: .66em 0;
237
+ font-weight: bold;
238
+ width: 33%;
239
+ display: inline-block;
240
+ vertical-align: bottom;
241
+ }
242
+ .picker__button--today:hover,
243
+ .picker__button--clear:hover,
244
+ .picker__button--close:hover {
245
+ cursor: pointer;
246
+ color: #000;
247
+ background: #b1dcfb;
248
+ border-bottom-color: #b1dcfb;
249
+ }
250
+ .picker__button--today:focus,
251
+ .picker__button--clear:focus,
252
+ .picker__button--close:focus {
253
+ background: #b1dcfb;
254
+ border-color: #0089ec;
255
+ outline: none;
256
+ }
257
+ .picker__button--today:before,
258
+ .picker__button--clear:before,
259
+ .picker__button--close:before {
260
+ position: relative;
261
+ display: inline-block;
262
+ height: 0;
263
+ }
264
+ .picker__button--today:before,
265
+ .picker__button--clear:before {
266
+ content: " ";
267
+ margin-right: .45em;
268
+ }
269
+ .picker__button--today:before {
270
+ top: -0.05em;
271
+ width: 0;
272
+ border-top: 0.66em solid #0059bc;
273
+ border-left: .66em solid transparent;
274
+ }
275
+ .picker__button--clear:before {
276
+ top: -0.25em;
277
+ width: .66em;
278
+ border-top: 3px solid #e20;
279
+ }
280
+ .picker__button--close:before {
281
+ content: "\D7";
282
+ top: -0.1em;
283
+ vertical-align: top;
284
+ font-size: 1.1em;
285
+ margin-right: .35em;
286
+ color: #777;
287
+ }
288
+ .picker__button--today[disabled],
289
+ .picker__button--today[disabled]:hover {
290
+ background: #f5f5f5;
291
+ border-color: #f5f5f5;
292
+ color: #ddd;
293
+ cursor: default;
294
+ }
295
+ .picker__button--today[disabled]:before {
296
+ border-top-color: #aaa;
297
+ }
298
+
299
+ /* ==========================================================================
300
+ $CLASSIC-DATE-PICKER
301
+ ========================================================================== */
js/pickadate/themes/classic.time.css CHANGED
@@ -1,104 +1,132 @@
1
- .picker__list {
2
- list-style: none;
3
- padding: .75em 0 4.2em;
4
- margin: 0
5
- }
6
-
7
- .picker__list-item {
8
- border-bottom: 1px solid #ddd;
9
- border-top: 1px solid #ddd;
10
- margin-bottom: -1px;
11
- position: relative;
12
- background: #fff;
13
- padding: .75em 1.25em
14
- }
15
-
16
- @media (min-height: 46.75em) {
17
- .picker__list-item {
18
- padding: .5em 1em
19
- }
20
- }
21
-
22
- .picker__list-item:hover {
23
- cursor: pointer;
24
- color: #000;
25
- background: #b1dcfb;
26
- border-color: #0089ec;
27
- z-index: 10
28
- }
29
-
30
- .picker__list-item--selected, .picker__list-item--selected:hover {
31
- border-color: #0089ec;
32
- z-index: 10
33
- }
34
-
35
- .picker__list-item--highlighted {
36
- background: #b1dcfb
37
- }
38
-
39
- .picker--focused .picker__list-item--highlighted, .picker__list-item--highlighted:hover {
40
- background: #0089ec;
41
- color: #fff
42
- }
43
-
44
- .picker--focused .picker__list-item--disabled, .picker__list-item--disabled, .picker__list-item--disabled:hover {
45
- background: #f5f5f5;
46
- color: #ddd;
47
- cursor: default;
48
- border-color: #ddd;
49
- z-index: auto
50
- }
51
-
52
- .picker--time .picker__button--clear {
53
- display: block;
54
- width: 80%;
55
- margin: 1em auto 0;
56
- padding: 1em 1.25em;
57
- background: 0 0;
58
- border: 0;
59
- font-weight: 500;
60
- font-size: .67em;
61
- text-align: center;
62
- text-transform: uppercase;
63
- color: #666
64
- }
65
-
66
- .picker--time .picker__button--clear:focus, .picker--time .picker__button--clear:hover {
67
- background: #b1dcfb;
68
- background: #e20;
69
- border-color: #e20;
70
- cursor: pointer;
71
- color: #fff;
72
- outline: 0
73
- }
74
-
75
- .picker--time .picker__button--clear:before {
76
- top: -.25em;
77
- color: #666;
78
- font-size: 1.25em;
79
- font-weight: 700
80
- }
81
-
82
- .picker--time .picker__button--clear:focus:before, .picker--time .picker__button--clear:hover:before {
83
- color: #fff
84
- }
85
-
86
- .picker--time {
87
- min-width: 256px;
88
- max-width: 320px
89
- }
90
-
91
- .picker--time .picker__holder {
92
- background: #f2f2f2
93
- }
94
-
95
- @media (min-height: 40.125em) {
96
- .picker--time .picker__holder {
97
- font-size: .875em
98
- }
99
- }
100
-
101
- .picker--time .picker__box {
102
- padding: 0;
103
- position: relative
104
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ==========================================================================
2
+ $BASE-TIME-PICKER
3
+ ========================================================================== */
4
+ /**
5
+ * The list of times.
6
+ */
7
+ .picker__list {
8
+ list-style: none;
9
+ padding: 0.75em 0 4.2em;
10
+ margin: 0;
11
+ }
12
+ /**
13
+ * The times on the clock.
14
+ */
15
+ .picker__list-item {
16
+ border-bottom: 1px solid #ddd;
17
+ border-top: 1px solid #ddd;
18
+ margin-bottom: -1px;
19
+ position: relative;
20
+ background: #fff;
21
+ padding: .75em 1.25em;
22
+ }
23
+ @media (min-height: 46.75em) {
24
+ .picker__list-item {
25
+ padding: .5em 1em;
26
+ }
27
+ }
28
+ /* Hovered time */
29
+ .picker__list-item:hover {
30
+ cursor: pointer;
31
+ color: #000;
32
+ background: #b1dcfb;
33
+ border-color: #0089ec;
34
+ z-index: 10;
35
+ }
36
+ /* Highlighted and hovered/focused time */
37
+ .picker__list-item--highlighted {
38
+ border-color: #0089ec;
39
+ z-index: 10;
40
+ }
41
+ .picker__list-item--highlighted:hover,
42
+ .picker--focused .picker__list-item--highlighted {
43
+ cursor: pointer;
44
+ color: #000;
45
+ background: #b1dcfb;
46
+ }
47
+ /* Selected and hovered/focused time */
48
+ .picker__list-item--selected,
49
+ .picker__list-item--selected:hover,
50
+ .picker--focused .picker__list-item--selected {
51
+ background: #0089ec;
52
+ color: #fff;
53
+ z-index: 10;
54
+ }
55
+ /* Disabled time */
56
+ .picker__list-item--disabled,
57
+ .picker__list-item--disabled:hover,
58
+ .picker--focused .picker__list-item--disabled {
59
+ background: #f5f5f5;
60
+ border-color: #f5f5f5;
61
+ color: #ddd;
62
+ cursor: default;
63
+ border-color: #ddd;
64
+ z-index: auto;
65
+ }
66
+ /**
67
+ * The clear button
68
+ */
69
+ .picker--time .picker__button--clear {
70
+ display: block;
71
+ width: 80%;
72
+ margin: 1em auto 0;
73
+ padding: 1em 1.25em;
74
+ background: none;
75
+ border: 0;
76
+ font-weight: 500;
77
+ font-size: .67em;
78
+ text-align: center;
79
+ text-transform: uppercase;
80
+ color: #666;
81
+ }
82
+ .picker--time .picker__button--clear:hover,
83
+ .picker--time .picker__button--clear:focus {
84
+ color: #000;
85
+ background: #b1dcfb;
86
+ background: #e20;
87
+ border-color: #e20;
88
+ cursor: pointer;
89
+ color: #fff;
90
+ outline: none;
91
+ }
92
+ .picker--time .picker__button--clear:before {
93
+ top: -0.25em;
94
+ color: #666;
95
+ font-size: 1.25em;
96
+ font-weight: bold;
97
+ }
98
+ .picker--time .picker__button--clear:hover:before,
99
+ .picker--time .picker__button--clear:focus:before {
100
+ color: #fff;
101
+ border-color: #fff;
102
+ }
103
+
104
+ /* ==========================================================================
105
+ $CLASSIC-TIME-PICKER
106
+ ========================================================================== */
107
+ /**
108
+ * Note: the root picker element should __NOT__ be styled
109
+ * more than what’s here. Style the `.picker__holder` instead.
110
+ */
111
+ .picker--time {
112
+ min-width: 256px;
113
+ max-width: 320px;
114
+ }
115
+ /**
116
+ * The holder is the base of the picker.
117
+ */
118
+ .picker--time .picker__holder {
119
+ background: #f2f2f2;
120
+ }
121
+ @media (min-height: 40.125em) {
122
+ .picker--time .picker__holder {
123
+ font-size: .875em;
124
+ }
125
+ }
126
+ /**
127
+ * The box contains the list of times.
128
+ */
129
+ .picker--time .picker__box {
130
+ padding: 0;
131
+ position: relative;
132
+ }
js/pickadate/themes/default.css CHANGED
@@ -1,148 +1,165 @@
 
 
 
 
 
 
1
  .picker {
2
- font-size: 16px;
3
- text-align: left;
4
- line-height: 1.2;
5
- color: #000;
6
- position: absolute;
7
- z-index: 10000;
8
- -webkit-user-select: none;
9
- -moz-user-select: none;
10
- -ms-user-select: none;
11
- user-select: none
12
- }
13
-
 
 
 
14
  .picker__input {
15
- cursor: default
16
  }
17
-
 
 
18
  .picker__input.picker__input--active {
19
- border-color: #0089ec
20
  }
21
-
 
 
22
  .picker__holder {
23
- width: 100%;
24
- overflow-y: auto;
25
- -webkit-overflow-scrolling: touch
26
  }
27
 
28
  /*!
29
  * Default mobile-first, responsive styling for pickadate.js
30
  * Demo: http://amsul.github.io/pickadate.js
31
  */
32
- .picker__frame, .picker__holder {
33
- bottom: 0;
34
- left: 0;
35
- right: 0;
36
- top: 100%
37
- }
38
-
 
 
 
 
 
 
 
 
 
 
 
39
  .picker__holder {
40
- position: fixed;
41
- -webkit-transition: background .15s ease-out, top 0s .15s;
42
- -moz-transition: background .15s ease-out, top 0s .15s;
43
- transition: background .15s ease-out, top 0s .15s
44
  }
45
-
 
 
46
  .picker__frame {
47
- position: absolute;
48
- margin: 0 auto;
49
- min-width: 256px;
50
- max-width: 666px;
51
- width: 100%;
52
- -ms-filter: "alpha(Opacity=0)";
53
- filter: alpha(opacity=0);
54
- -moz-opacity: 0;
55
- opacity: 0;
56
- -webkit-transition: all .15s ease-out;
57
- -moz-transition: all .15s ease-out;
58
- transition: all .15s ease-out
59
  }
60
-
61
  @media (min-height: 33.875em) {
62
- .picker__frame {
63
- overflow: visible;
64
- top: auto;
65
- bottom: -100%;
66
- max-height: 80%
67
- }
68
  }
69
-
70
  @media (min-height: 40.125em) {
71
- .picker__frame {
72
- margin-bottom: 7.5%
73
- }
74
  }
75
-
 
 
76
  .picker__wrap {
77
- display: table;
78
- width: 100%;
79
- height: 100%
80
  }
81
-
82
  @media (min-height: 33.875em) {
83
- .picker__wrap {
84
- display: block
85
- }
86
  }
87
-
 
 
88
  .picker__box {
89
- background: #fff;
90
- display: table-cell;
91
- vertical-align: middle
92
  }
93
-
94
  @media (min-height: 26.5em) {
95
- .picker__box {
96
- font-size: 1.25em
97
- }
98
  }
99
-
100
  @media (min-height: 33.875em) {
101
- .picker__box {
102
- display: block;
103
- font-size: 1.33em;
104
- border: 1px solid #777;
105
- border-top-color: #898989;
106
- border-bottom-width: 0;
107
- -webkit-border-radius: 5px 5px 0 0;
108
- -moz-border-radius: 5px 5px 0 0;
109
- border-radius: 5px 5px 0 0;
110
- -webkit-box-shadow: 0 12px 36px 16px rgba(0, 0, 0, .24);
111
- -moz-box-shadow: 0 12px 36px 16px rgba(0, 0, 0, .24);
112
- box-shadow: 0 12px 36px 16px rgba(0, 0, 0, .24)
113
- }
114
  }
115
-
116
  @media (min-height: 40.125em) {
117
- .picker__box {
118
- font-size: 1.5em;
119
- border-bottom-width: 1px;
120
- -webkit-border-radius: 5px;
121
- -moz-border-radius: 5px;
122
- border-radius: 5px
123
- }
124
- }
125
-
126
  .picker--opened .picker__holder {
127
- top: 0;
128
- zoom: 1;
129
- background: rgba(0, 0, 0, .32);
130
- -webkit-transition: background .15s ease-out;
131
- -moz-transition: background .15s ease-out;
132
- transition: background .15s ease-out
 
133
  }
134
-
135
  .picker--opened .picker__frame {
136
- top: 0;
137
- -ms-filter: "alpha(Opacity=100)";
138
- filter: alpha(opacity=100);
139
- -moz-opacity: 1;
140
- opacity: 1
 
141
  }
142
-
143
  @media (min-height: 33.875em) {
144
- .picker--opened .picker__frame {
145
- top: auto;
146
- bottom: 0
147
- }
148
- }
1
+ /* ==========================================================================
2
+ $BASE-PICKER
3
+ ========================================================================== */
4
+ /**
5
+ * Note: the root picker element should *NOT* be styled more than what’s here.
6
+ */
7
  .picker {
8
+ font-size: 16px;
9
+ text-align: left;
10
+ line-height: 1.2;
11
+ color: #000;
12
+ position: absolute;
13
+ z-index: 10000;
14
+ -webkit-user-select: none;
15
+ -moz-user-select: none;
16
+ -ms-user-select: none;
17
+ user-select: none;
18
+ outline: none;
19
+ }
20
+ /**
21
+ * The picker input element.
22
+ */
23
  .picker__input {
24
+ cursor: default;
25
  }
26
+ /**
27
+ * When the picker is opened, the input element is “activated”.
28
+ */
29
  .picker__input.picker__input--active {
30
+ border-color: #0089ec;
31
  }
32
+ /**
33
+ * The holder is the only “scrollable” top-level container element.
34
+ */
35
  .picker__holder {
36
+ width: 100%;
37
+ overflow-y: auto;
38
+ -webkit-overflow-scrolling: touch;
39
  }
40
 
41
  /*!
42
  * Default mobile-first, responsive styling for pickadate.js
43
  * Demo: http://amsul.github.io/pickadate.js
44
  */
45
+ /**
46
+ * Note: the root picker element should *NOT* be styled more than what’s here.
47
+ */
48
+ /**
49
+ * Make the holder and frame fullscreen.
50
+ */
51
+ .picker__holder,
52
+ .picker__frame {
53
+ top: 0;
54
+ bottom: 0;
55
+ left: 0;
56
+ right: 0;
57
+ -ms-transform: translateY(100%);
58
+ transform: translateY(100%);
59
+ }
60
+ /**
61
+ * The holder should overlay the entire screen.
62
+ */
63
  .picker__holder {
64
+ position: fixed;
65
+ transition: background 0.15s ease-out, transform 0s 0.15s;
66
+ -webkit-backface-visibility: hidden;
 
67
  }
68
+ /**
69
+ * The frame that bounds the box contents of the picker.
70
+ */
71
  .picker__frame {
72
+ position: absolute;
73
+ margin: 0 auto;
74
+ min-width: 256px;
75
+ max-width: 666px;
76
+ width: 100%;
77
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
78
+ filter: alpha(opacity=0);
79
+ -moz-opacity: 0;
80
+ opacity: 0;
81
+ transition: all 0.15s ease-out;
 
 
82
  }
 
83
  @media (min-height: 33.875em) {
84
+ .picker__frame {
85
+ overflow: visible;
86
+ top: auto;
87
+ bottom: -100%;
88
+ max-height: 80%;
89
+ }
90
  }
 
91
  @media (min-height: 40.125em) {
92
+ .picker__frame {
93
+ margin-bottom: 7.5%;
94
+ }
95
  }
96
+ /**
97
+ * The wrapper sets the stage to vertically align the box contents.
98
+ */
99
  .picker__wrap {
100
+ display: table;
101
+ width: 100%;
102
+ height: 100%;
103
  }
 
104
  @media (min-height: 33.875em) {
105
+ .picker__wrap {
106
+ display: block;
107
+ }
108
  }
109
+ /**
110
+ * The box contains all the picker contents.
111
+ */
112
  .picker__box {
113
+ background: #fff;
114
+ display: table-cell;
115
+ vertical-align: middle;
116
  }
 
117
  @media (min-height: 26.5em) {
118
+ .picker__box {
119
+ font-size: 1.25em;
120
+ }
121
  }
 
122
  @media (min-height: 33.875em) {
123
+ .picker__box {
124
+ display: block;
125
+ font-size: 1.33em;
126
+ border: 1px solid #777;
127
+ border-top-color: #898989;
128
+ border-bottom-width: 0;
129
+ border-radius: 5px 5px 0 0;
130
+ box-shadow: 0 12px 36px 16px rgba(0, 0, 0, 0.24);
131
+ }
 
 
 
 
132
  }
 
133
  @media (min-height: 40.125em) {
134
+ .picker__box {
135
+ font-size: 1.5em;
136
+ border-bottom-width: 1px;
137
+ border-radius: 5px;
138
+ }
139
+ }
140
+ /**
141
+ * When the picker opens...
142
+ */
143
  .picker--opened .picker__holder {
144
+ -ms-transform: translateY(0);
145
+ transform: translateY(0);
146
+ background: transparent;
147
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#1E000000,endColorstr=#1E000000)";
148
+ zoom: 1;
149
+ background: rgba(0, 0, 0, 0.32);
150
+ transition: background 0.15s ease-out;
151
  }
 
152
  .picker--opened .picker__frame {
153
+ -ms-transform: translateY(0);
154
+ transform: translateY(0);
155
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
156
+ filter: alpha(opacity=100);
157
+ -moz-opacity: 1;
158
+ opacity: 1;
159
  }
 
160
  @media (min-height: 33.875em) {
161
+ .picker--opened .picker__frame {
162
+ top: auto;
163
+ bottom: 0;
164
+ }
165
+ }
js/pickadate/themes/default.date.css CHANGED
@@ -1,263 +1,301 @@
1
- .picker__box {
2
- padding: 0 1em
3
- }
4
-
5
- .picker__header {
6
- text-align: center;
7
- position: relative;
8
- margin-top: .75em
9
- }
10
-
11
- .picker__month, .picker__year {
12
- font-weight: 500;
13
- display: inline-block;
14
- margin-left: .25em;
15
- margin-right: .25em
16
- }
17
-
18
- .picker__year {
19
- color: #999;
20
- font-size: .8em;
21
- font-style: italic
22
- }
23
-
24
- .picker__select--month, .picker__select--year {
25
- border: 1px solid #b7b7b7;
26
- height: 2.5em;
27
- padding: .5em .25em;
28
- margin-left: .25em;
29
- margin-right: .25em;
30
- font-size: .6em
31
- }
32
-
33
- @media (min-width: 24.5em) {
34
- .picker__select--month, .picker__select--year {
35
- font-size: .8em;
36
- margin-top: -.5em
37
- }
38
- }
39
-
40
- .picker__holder .picker__box .picker__select--month {
41
- width: 35%
42
- }
43
-
44
- .picker__holder .picker__box .picker__select--year {
45
- width: 22.5%
46
- }
47
-
48
- .picker__select--month:focus, .picker__select--year:focus {
49
- border-color: #0089ec
50
- }
51
-
52
- .picker__nav--next, .picker__nav--prev {
53
- position: absolute;
54
- padding: .5em 1.25em;
55
- width: 1em;
56
- height: 1em;
57
- top: -.25em
58
- }
59
-
60
- @media (min-width: 24.5em) {
61
- .picker__nav--next, .picker__nav--prev {
62
- top: -.33em
63
- }
64
- }
65
-
66
- .picker__nav--prev {
67
- left: -1em;
68
- padding-right: 1.25em
69
- }
70
-
71
- @media (min-width: 24.5em) {
72
- .picker__nav--prev {
73
- padding-right: 1.5em
74
- }
75
- }
76
-
77
- .picker__nav--next {
78
- right: -1em;
79
- padding-left: 1.25em
80
- }
81
-
82
- @media (min-width: 24.5em) {
83
- .picker__nav--next {
84
- padding-left: 1.5em
85
- }
86
- }
87
-
88
- .picker__nav--next:before, .picker__nav--prev:before {
89
- content: " ";
90
- border-top: .5em solid transparent;
91
- border-bottom: .5em solid transparent;
92
- border-right: .75em solid #000;
93
- width: 0;
94
- height: 0;
95
- display: block;
96
- margin: 0 auto
97
- }
98
-
99
- .picker__nav--next:before {
100
- border-right: 0;
101
- border-left: .75em solid #000
102
- }
103
-
104
- .picker__nav--next:hover, .picker__nav--prev:hover {
105
- cursor: pointer;
106
- color: #000;
107
- background: #b1dcfb
108
- }
109
-
110
- .picker__nav--disabled, .picker__nav--disabled:before, .picker__nav--disabled:before:hover, .picker__nav--disabled:hover {
111
- cursor: default;
112
- background: 0 0;
113
- border-right-color: #f5f5f5;
114
- border-left-color: #f5f5f5
115
- }
116
-
117
- .picker__table {
118
- text-align: center;
119
- border-collapse: collapse;
120
- border-spacing: 0;
121
- table-layout: fixed;
122
- font-size: inherit;
123
- width: 100%;
124
- margin-top: .75em;
125
- margin-bottom: .5em
126
- }
127
-
128
- @media (min-height: 33.875em) {
129
- .picker__table {
130
- margin-bottom: .75em
131
- }
132
- }
133
-
134
- .picker__table td {
135
- margin: 0;
136
- padding: 0
137
- }
138
-
139
- .picker__weekday {
140
- width: 14.285714286%;
141
- font-size: .75em;
142
- padding-bottom: .25em;
143
- color: #999;
144
- font-weight: 500
145
- }
146
-
147
- @media (min-height: 33.875em) {
148
- .picker__weekday {
149
- padding-bottom: .5em
150
- }
151
- }
152
-
153
- .picker__day {
154
- padding: .3125em 0;
155
- font-weight: 200;
156
- border: 1px solid transparent
157
- }
158
-
159
- .picker__day--today {
160
- color: #0089ec;
161
- position: relative
162
- }
163
-
164
- .picker__day--today:before {
165
- content: " ";
166
- position: absolute;
167
- top: 2px;
168
- right: 2px;
169
- width: 0;
170
- height: 0;
171
- border-top: .5em solid #0059bc;
172
- border-left: .5em solid transparent
173
- }
174
-
175
- .picker__day--selected, .picker__day--selected:hover {
176
- border-color: #0089ec
177
- }
178
-
179
- .picker__day--highlighted {
180
- background: #b1dcfb
181
- }
182
-
183
- .picker__day--disabled:before {
184
- border-top-color: #aaa
185
- }
186
-
187
- .picker__day--outfocus {
188
- color: #ddd
189
- }
190
-
191
- .picker__day--infocus:hover, .picker__day--outfocus:hover {
192
- cursor: pointer;
193
- color: #000;
194
- background: #b1dcfb
195
- }
196
-
197
- .picker--focused .picker__day--highlighted, .picker__day--highlighted:hover {
198
- background: #0089ec;
199
- color: #fff
200
- }
201
-
202
- .picker__day--disabled, .picker__day--disabled:hover {
203
- background: #f5f5f5;
204
- border-color: #f5f5f5;
205
- color: #ddd;
206
- cursor: default
207
- }
208
-
209
- .picker__day--highlighted.picker__day--disabled, .picker__day--highlighted.picker__day--disabled:hover {
210
- background: #bbb
211
- }
212
-
213
- .picker__footer {
214
- text-align: center
215
- }
216
-
217
- .picker__button--clear, .picker__button--today {
218
- border: 1px solid #fff;
219
- background: #fff;
220
- font-size: .8em;
221
- padding: .66em 0;
222
- font-weight: 700;
223
- width: 50%;
224
- display: inline-block;
225
- vertical-align: bottom
226
- }
227
-
228
- .picker__button--clear:hover, .picker__button--today:hover {
229
- cursor: pointer;
230
- color: #000;
231
- background: #b1dcfb;
232
- border-bottom-color: #b1dcfb
233
- }
234
-
235
- .picker__button--clear:focus, .picker__button--today:focus {
236
- background: #b1dcfb;
237
- border-color: #0089ec;
238
- outline: 0
239
- }
240
-
241
- .picker__button--clear:before, .picker__button--today:before {
242
- position: relative;
243
- display: inline-block;
244
- height: 0
245
- }
246
-
247
- .picker__button--today:before {
248
- content: " ";
249
- margin-right: .45em;
250
- top: -.05em;
251
- width: 0;
252
- border-top: .66em solid #0059bc;
253
- border-left: .66em solid transparent
254
- }
255
-
256
- .picker__button--clear:before {
257
- content: "\D7";
258
- margin-right: .35em;
259
- top: -.1em;
260
- color: #e20;
261
- vertical-align: top;
262
- font-size: 1.1em
263
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ==========================================================================
2
+ $BASE-DATE-PICKER
3
+ ========================================================================== */
4
+ /**
5
+ * The picker box.
6
+ */
7
+ .picker__box {
8
+ padding: 0 1em;
9
+ }
10
+ /**
11
+ * The header containing the month and year stuff.
12
+ */
13
+ .picker__header {
14
+ text-align: center;
15
+ position: relative;
16
+ margin-top: .75em;
17
+ }
18
+ /**
19
+ * The month and year labels.
20
+ */
21
+ .picker__month,
22
+ .picker__year {
23
+ font-weight: 500;
24
+ display: inline-block;
25
+ margin-left: .25em;
26
+ margin-right: .25em;
27
+ }
28
+ .picker__year {
29
+ color: #999;
30
+ font-size: .8em;
31
+ font-style: italic;
32
+ }
33
+ /**
34
+ * The month and year selectors.
35
+ */
36
+ .picker__select--month,
37
+ .picker__select--year {
38
+ border: 1px solid #b7b7b7;
39
+ height: 2em;
40
+ padding: .5em;
41
+ margin-left: .25em;
42
+ margin-right: .25em;
43
+ }
44
+ @media (min-width: 24.5em) {
45
+ .picker__select--month,
46
+ .picker__select--year {
47
+ margin-top: -0.5em;
48
+ }
49
+ }
50
+ .picker__select--month {
51
+ width: 35%;
52
+ }
53
+ .picker__select--year {
54
+ width: 22.5%;
55
+ }
56
+ .picker__select--month:focus,
57
+ .picker__select--year:focus {
58
+ border-color: #0089ec;
59
+ }
60
+ /**
61
+ * The month navigation buttons.
62
+ */
63
+ .picker__nav--prev,
64
+ .picker__nav--next {
65
+ position: absolute;
66
+ padding: .5em 1.25em;
67
+ width: 1em;
68
+ height: 1em;
69
+ box-sizing: content-box;
70
+ top: -0.25em;
71
+ }
72
+ @media (min-width: 24.5em) {
73
+ .picker__nav--prev,
74
+ .picker__nav--next {
75
+ top: -0.33em;
76
+ }
77
+ }
78
+ .picker__nav--prev {
79
+ left: -1em;
80
+ padding-right: 1.25em;
81
+ }
82
+ @media (min-width: 24.5em) {
83
+ .picker__nav--prev {
84
+ padding-right: 1.5em;
85
+ }
86
+ }
87
+ .picker__nav--next {
88
+ right: -1em;
89
+ padding-left: 1.25em;
90
+ }
91
+ @media (min-width: 24.5em) {
92
+ .picker__nav--next {
93
+ padding-left: 1.5em;
94
+ }
95
+ }
96
+ .picker__nav--prev:before,
97
+ .picker__nav--next:before {
98
+ content: " ";
99
+ border-top: .5em solid transparent;
100
+ border-bottom: .5em solid transparent;
101
+ border-right: 0.75em solid #000;
102
+ width: 0;
103
+ height: 0;
104
+ display: block;
105
+ margin: 0 auto;
106
+ }
107
+ .picker__nav--next:before {
108
+ border-right: 0;
109
+ border-left: 0.75em solid #000;
110
+ }
111
+ .picker__nav--prev:hover,
112
+ .picker__nav--next:hover {
113
+ cursor: pointer;
114
+ color: #000;
115
+ background: #b1dcfb;
116
+ }
117
+ .picker__nav--disabled,
118
+ .picker__nav--disabled:hover,
119
+ .picker__nav--disabled:before,
120
+ .picker__nav--disabled:before:hover {
121
+ cursor: default;
122
+ background: none;
123
+ border-right-color: #f5f5f5;
124
+ border-left-color: #f5f5f5;
125
+ }
126
+ /**
127
+ * The calendar table of dates
128
+ */
129
+ .picker__table {
130
+ text-align: center;
131
+ border-collapse: collapse;
132
+ border-spacing: 0;
133
+ table-layout: fixed;
134
+ font-size: inherit;
135
+ width: 100%;
136
+ margin-top: .75em;
137
+ margin-bottom: .5em;
138
+ }
139
+ @media (min-height: 33.875em) {
140
+ .picker__table {
141
+ margin-bottom: .75em;
142
+ }
143
+ }
144
+ .picker__table td {
145
+ margin: 0;
146
+ padding: 0;
147
+ }
148
+ /**
149
+ * The weekday labels
150
+ */
151
+ .picker__weekday {
152
+ width: 14.285714286%;
153
+ font-size: .75em;
154
+ padding-bottom: .25em;
155
+ color: #999;
156
+ font-weight: 500;
157
+ /* Increase the spacing a tad */
158
+ }
159
+ @media (min-height: 33.875em) {
160
+ .picker__weekday {
161
+ padding-bottom: .5em;
162
+ }
163
+ }
164
+ /**
165
+ * The days on the calendar
166
+ */
167
+ .picker__day {
168
+ padding: .3125em 0;
169
+ font-weight: 200;
170
+ border: 1px solid transparent;
171
+ }
172
+ .picker__day--today {
173
+ position: relative;
174
+ }
175
+ .picker__day--today:before {
176
+ content: " ";
177
+ position: absolute;
178
+ top: 2px;
179
+ right: 2px;
180
+ width: 0;
181
+ height: 0;
182
+ border-top: 0.5em solid #0059bc;
183
+ border-left: .5em solid transparent;
184
+ }
185
+ .picker__day--disabled:before {
186
+ border-top-color: #aaa;
187
+ }
188
+ .picker__day--outfocus {
189
+ color: #ddd;
190
+ }
191
+ .picker__day--infocus:hover,
192
+ .picker__day--outfocus:hover {
193
+ cursor: pointer;
194
+ color: #000;
195
+ background: #b1dcfb;
196
+ }
197
+ .picker__day--highlighted {
198
+ border-color: #0089ec;
199
+ }
200
+ .picker__day--highlighted:hover,
201
+ .picker--focused .picker__day--highlighted {
202
+ cursor: pointer;
203
+ color: #000;
204
+ background: #b1dcfb;
205
+ }
206
+ .picker__day--selected,
207
+ .picker__day--selected:hover,
208
+ .picker--focused .picker__day--selected {
209
+ background: #0089ec;
210
+ color: #fff;
211
+ }
212
+ .picker__day--disabled,
213
+ .picker__day--disabled:hover,
214
+ .picker--focused .picker__day--disabled {
215
+ background: #f5f5f5;
216
+ border-color: #f5f5f5;
217
+ color: #ddd;
218
+ cursor: default;
219
+ }
220
+ .picker__day--highlighted.picker__day--disabled,
221
+ .picker__day--highlighted.picker__day--disabled:hover {
222
+ background: #bbb;
223
+ }
224
+ /**
225
+ * The footer containing the "today", "clear", and "close" buttons.
226
+ */
227
+ .picker__footer {
228
+ text-align: center;
229
+ }
230
+ .picker__button--today,
231
+ .picker__button--clear,
232
+ .picker__button--close {
233
+ border: 1px solid #fff;
234
+ background: #fff;
235
+ font-size: .8em;
236
+ padding: .66em 0;
237
+ font-weight: bold;
238
+ width: 33%;
239
+ display: inline-block;
240
+ vertical-align: bottom;
241
+ }
242
+ .picker__button--today:hover,
243
+ .picker__button--clear:hover,
244
+ .picker__button--close:hover {
245
+ cursor: pointer;
246
+ color: #000;
247
+ background: #b1dcfb;
248
+ border-bottom-color: #b1dcfb;
249
+ }
250
+ .picker__button--today:focus,
251
+ .picker__button--clear:focus,
252
+ .picker__button--close:focus {
253
+ background: #b1dcfb;
254
+ border-color: #0089ec;
255
+ outline: none;
256
+ }
257
+ .picker__button--today:before,
258
+ .picker__button--clear:before,
259
+ .picker__button--close:before {
260
+ position: relative;
261
+ display: inline-block;
262
+ height: 0;
263
+ }
264
+ .picker__button--today:before,
265
+ .picker__button--clear:before {
266
+ content: " ";
267
+ margin-right: .45em;
268
+ }
269
+ .picker__button--today:before {
270
+ top: -0.05em;
271
+ width: 0;
272
+ border-top: 0.66em solid #0059bc;
273
+ border-left: .66em solid transparent;
274
+ }
275
+ .picker__button--clear:before {
276
+ top: -0.25em;
277
+ width: .66em;
278
+ border-top: 3px solid #e20;
279
+ }
280
+ .picker__button--close:before {
281
+ content: "\D7";
282
+ top: -0.1em;
283
+ vertical-align: top;
284
+ font-size: 1.1em;
285
+ margin-right: .35em;
286
+ color: #777;
287
+ }
288
+ .picker__button--today[disabled],
289
+ .picker__button--today[disabled]:hover {
290
+ background: #f5f5f5;
291
+ border-color: #f5f5f5;
292
+ color: #ddd;
293
+ cursor: default;
294
+ }
295
+ .picker__button--today[disabled]:before {
296
+ border-top-color: #aaa;
297
+ }
298
+
299
+ /* ==========================================================================
300
+ $DEFAULT-DATE-PICKER
301
+ ========================================================================== */
js/pickadate/themes/default.time.css CHANGED
@@ -1,101 +1,126 @@
1
- .picker__list {
2
- list-style: none;
3
- padding: .75em 0 4.2em;
4
- margin: 0
5
- }
6
-
7
- .picker__list-item {
8
- border-bottom: 1px solid #ddd;
9
- border-top: 1px solid #ddd;
10
- margin-bottom: -1px;
11
- position: relative;
12
- background: #fff;
13
- padding: .75em 1.25em
14
- }
15
-
16
- @media (min-height: 46.75em) {
17
- .picker__list-item {
18
- padding: .5em 1em
19
- }
20
- }
21
-
22
- .picker__list-item:hover {
23
- cursor: pointer;
24
- color: #000;
25
- background: #b1dcfb;
26
- border-color: #0089ec;
27
- z-index: 10
28
- }
29
-
30
- .picker__list-item--selected, .picker__list-item--selected:hover {
31
- border-color: #0089ec;
32
- z-index: 10
33
- }
34
-
35
- .picker__list-item--highlighted {
36
- background: #b1dcfb
37
- }
38
-
39
- .picker--focused .picker__list-item--highlighted, .picker__list-item--highlighted:hover {
40
- background: #0089ec;
41
- color: #fff
42
- }
43
-
44
- .picker--focused .picker__list-item--disabled, .picker__list-item--disabled, .picker__list-item--disabled:hover {
45
- background: #f5f5f5;
46
- color: #ddd;
47
- cursor: default;
48
- border-color: #ddd;
49
- z-index: auto
50
- }
51
-
52
- .picker--time .picker__button--clear {
53
- display: block;
54
- width: 80%;
55
- margin: 1em auto 0;
56
- padding: 1em 1.25em;
57
- background: 0 0;
58
- border: 0;
59
- font-weight: 500;
60
- font-size: .67em;
61
- text-align: center;
62
- text-transform: uppercase;
63
- color: #666
64
- }
65
-
66
- .picker--time .picker__button--clear:focus, .picker--time .picker__button--clear:hover {
67
- background: #b1dcfb;
68
- background: #e20;
69
- border-color: #e20;
70
- cursor: pointer;
71
- color: #fff;
72
- outline: 0
73
- }
74
-
75
- .picker--time .picker__button--clear:before {
76
- top: -.25em;
77
- color: #666;
78
- font-size: 1.25em;
79
- font-weight: 700
80
- }
81
-
82
- .picker--time .picker__button--clear:focus:before, .picker--time .picker__button--clear:hover:before {
83
- color: #fff
84
- }
85
-
86
- .picker--time .picker__frame {
87
- min-width: 256px;
88
- max-width: 320px
89
- }
90
-
91
- .picker--time .picker__box {
92
- font-size: 1em;
93
- background: #f2f2f2;
94
- padding: 0
95
- }
96
-
97
- @media (min-height: 40.125em) {
98
- .picker--time .picker__box {
99
- margin-bottom: 5em
100
- }
101
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ==========================================================================
2
+ $BASE-TIME-PICKER
3
+ ========================================================================== */
4
+ /**
5
+ * The list of times.
6
+ */
7
+ .picker__list {
8
+ list-style: none;
9
+ padding: 0.75em 0 4.2em;
10
+ margin: 0;
11
+ }
12
+ /**
13
+ * The times on the clock.
14
+ */
15
+ .picker__list-item {
16
+ border-bottom: 1px solid #ddd;
17
+ border-top: 1px solid #ddd;
18
+ margin-bottom: -1px;
19
+ position: relative;
20
+ background: #fff;
21
+ padding: .75em 1.25em;
22
+ }
23
+ @media (min-height: 46.75em) {
24
+ .picker__list-item {
25
+ padding: .5em 1em;
26
+ }
27
+ }
28
+ /* Hovered time */
29
+ .picker__list-item:hover {
30
+ cursor: pointer;
31
+ color: #000;
32
+ background: #b1dcfb;
33
+ border-color: #0089ec;
34
+ z-index: 10;
35
+ }
36
+ /* Highlighted and hovered/focused time */
37
+ .picker__list-item--highlighted {
38
+ border-color: #0089ec;
39
+ z-index: 10;
40
+ }
41
+ .picker__list-item--highlighted:hover,
42
+ .picker--focused .picker__list-item--highlighted {
43
+ cursor: pointer;
44
+ color: #000;
45
+ background: #b1dcfb;
46
+ }
47
+ /* Selected and hovered/focused time */
48
+ .picker__list-item--selected,
49
+ .picker__list-item--selected:hover,
50
+ .picker--focused .picker__list-item--selected {
51
+ background: #0089ec;
52
+ color: #fff;
53
+ z-index: 10;
54
+ }
55
+ /* Disabled time */
56
+ .picker__list-item--disabled,
57
+ .picker__list-item--disabled:hover,
58
+ .picker--focused .picker__list-item--disabled {
59
+ background: #f5f5f5;
60
+ border-color: #f5f5f5;
61
+ color: #ddd;
62
+ cursor: default;
63
+ border-color: #ddd;
64
+ z-index: auto;
65
+ }
66
+ /**
67
+ * The clear button
68
+ */
69
+ .picker--time .picker__button--clear {
70
+ display: block;
71
+ width: 80%;
72
+ margin: 1em auto 0;
73
+ padding: 1em 1.25em;
74
+ background: none;
75
+ border: 0;
76
+ font-weight: 500;
77
+ font-size: .67em;
78
+ text-align: center;
79
+ text-transform: uppercase;
80
+ color: #666;
81
+ }
82
+ .picker--time .picker__button--clear:hover,
83
+ .picker--time .picker__button--clear:focus {
84
+ color: #000;
85
+ background: #b1dcfb;
86
+ background: #e20;
87
+ border-color: #e20;
88
+ cursor: pointer;
89
+ color: #fff;
90
+ outline: none;
91
+ }
92
+ .picker--time .picker__button--clear:before {
93
+ top: -0.25em;
94
+ color: #666;
95
+ font-size: 1.25em;
96
+ font-weight: bold;
97
+ }
98
+ .picker--time .picker__button--clear:hover:before,
99
+ .picker--time .picker__button--clear:focus:before {
100
+ color: #fff;
101
+ border-color: #fff;
102
+ }
103
+
104
+ /* ==========================================================================
105
+ $DEFAULT-TIME-PICKER
106
+ ========================================================================== */
107
+ /**
108
+ * The frame the bounds the time picker.
109
+ */
110
+ .picker--time .picker__frame {
111
+ min-width: 256px;
112
+ max-width: 320px;
113
+ }
114
+ /**
115
+ * The picker box.
116
+ */
117
+ .picker--time .picker__box {
118
+ font-size: 1em;
119
+ background: #f2f2f2;
120
+ padding: 0;
121
+ }
122
+ @media (min-height: 40.125em) {
123
+ .picker--time .picker__box {
124
+ margin-bottom: 5em;
125
+ }
126
+ }
js/pickadate/themes/rtl.css CHANGED
@@ -1,26 +1,29 @@
1
  /*!
2
  * Styling for RTL (right-to-left) languages using pickadate.js
3
  */
 
 
 
 
4
  .picker {
5
- direction: rtl
6
  }
7
-
 
 
8
  .picker__nav--next {
9
- right: auto;
10
- left: -1em
11
  }
12
-
13
  .picker__nav--prev {
14
- left: auto;
15
- right: -1em
16
  }
17
-
18
  .picker__nav--next:before {
19
- border-left: 0;
20
- border-right: .75em solid #000
21
  }
22
-
23
  .picker__nav--prev:before {
24
- border-right: 0;
25
- border-left: .75em solid #000
26
- }
1
  /*!
2
  * Styling for RTL (right-to-left) languages using pickadate.js
3
  */
4
+ /**
5
+ * Switch the direction - only really necessary if
6
+ * it hasn’t already been applied higher up in the DOM.
7
+ */
8
  .picker {
9
+ direction: rtl;
10
  }
11
+ /**
12
+ * Flip around the “next” and “previous” buttons.
13
+ */
14
  .picker__nav--next {
15
+ right: auto;
16
+ left: -1em;
17
  }
 
18
  .picker__nav--prev {
19
+ left: auto;
20
+ right: -1em;
21
  }
 
22
  .picker__nav--next:before {
23
+ border-left: 0;
24
+ border-right: 0.75em solid #000;
25
  }
 
26
  .picker__nav--prev:before {
27
+ border-right: 0;
28
+ border-left: 0.75em solid #000;
29
+ }
js/pickadate/translations/FORMATTING.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ ### The following convention is used for choosing a format for the translation files:
2
+
3
+ 1. Google for “Microsoft Style Guide LANGUAGE COUNTRY”.
4
+ 2. Check the standard suggestions for Long Date Formats.
5
+ 3. Set this as the `format` option using [pickadate’s formatting rules](http://amsul.ca/pickadate.js/date.htm#formatting-rules).
6
+
7
+ Make sure `formatSubmit` is always `yyyy/mm/dd` to ensure our servers always get the value formatted the same.
js/pickadate/translations/NAMING.md ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### The following convention is used for naming the translation files:
2
+
3
+ ```
4
+ LANGUAGE_COUNTRY.js
5
+ ```
6
+
7
+ #### Where:
8
+
9
+ ```
10
+ LANGUAGE = The lowercase ISO 639-1 language code.
11
+ ```
12
+
13
+ > See http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
14
+
15
+ ```
16
+ COUNTRY = The uppercase ISO 3166-1 country code.
17
+ ```
18
+
19
+ > See http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements
20
+
21
+ When there is no `COUNTRY` in the filename, it is assumed the generic language is used in multiple countries.
js/pickadate/translations/ar.js CHANGED
@@ -1,10 +1,16 @@
1
- $.extend($.fn.pickadate.defaults, {
2
- monthsFull: ["يناير", "فبراير", "مارس", "ابريل", "مايو", "يونيو", "يوليو", "اغسطس", "سبتمبر", "اكتوبر", "نوفمبر", "ديسمبر"],
3
- monthsShort: ["يناير", "فبراير", "مارس", "ابريل", "مايو", "يونيو", "يوليو", "اغسطس", "سبتمبر", "اكتوبر", "نوفمبر", "ديسمبر"],
4
- weekdaysFull: ["الاحد", "الاثنين", "الثلاثاء", "الاربعاء", "الخميس", "الجمعة", "السبت"],
5
- weekdaysShort: ["الاحد", "الاثنين", "الثلاثاء", "الاربعاء", "الخميس", "الجمعة", "السبت"],
6
- today: "اليوم",
7
- clear: "مسح",
8
- format: "yyyy mmmm dd",
9
- formatSubmit: "yyyy/mm/dd"
10
- });
 
 
 
 
 
 
1
+ // Arabic
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'يناير', 'فبراير', 'مارس', 'ابريل', 'مايو', 'يونيو', 'يوليو', 'اغسطس', 'سبتمبر', 'اكتوبر', 'نوفمبر', 'ديسمبر' ],
5
+ monthsShort: [ 'يناير', 'فبراير', 'مارس', 'ابريل', 'مايو', 'يونيو', 'يوليو', 'اغسطس', 'سبتمبر', 'اكتوبر', 'نوفمبر', 'ديسمبر' ],
6
+ weekdaysFull: [ 'الاحد', 'الاثنين', 'الثلاثاء', 'الاربعاء', 'الخميس', 'الجمعة', 'السبت' ],
7
+ weekdaysShort: [ 'الاحد', 'الاثنين', 'الثلاثاء', 'الاربعاء', 'الخميس', 'الجمعة', 'السبت' ],
8
+ today: 'اليوم',
9
+ clear: 'مسح',
10
+ format: 'yyyy mmmm dd',
11
+ formatSubmit: 'yyyy/mm/dd'
12
+ });
13
+
14
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
15
+ clear: 'مسح'
16
+ });
js/pickadate/translations/bg_BG.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["януари", "февруари", "март", "април", "май", "юни", "юли", "август", "септември", "октомври", "ноември", "декември"],
3
- monthsShort: ["янр", "фев", "мар", "апр", "май", "юни", "юли", "авг", "сеп", "окт", "ное", "дек"],
4
- weekdaysFull: ["неделя", "понеделник", "вторник", "сряда", "четвъртък", "петък", "събота"],
5
- weekdaysShort: ["нд", "пн", "вт", "ср", "чт", "пт", "сб"],
6
- today: "днес",
7
- clear: "изтривам",
8
- firstDay: 1,
9
- format: "d mmmm yyyy г.",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Bulgarian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'януари','февруари','март','април','май','юни','юли','август','септември','октомври','ноември','декември' ],
5
+ monthsShort: [ 'янр','фев','мар','апр','май','юни','юли','авг','сеп','окт','ное','дек' ],
6
+ weekdaysFull: [ 'неделя', 'понеделник', 'вторник', 'сряда', 'четвъртък', 'петък', 'събота' ],
7
+ weekdaysShort: [ 'нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб' ],
8
+ today: 'днес',
9
+ clear: 'изтривам',
10
+ firstDay: 1,
11
+ format: 'd mmmm yyyy г.',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'изтривам'
17
+ });
js/pickadate/translations/bs_BA.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["januar", "februar", "mart", "april", "maj", "juni", "juli", "august", "septembar", "oktobar", "novembar", "decembar"],
3
- monthsShort: ["jan", "feb", "mar", "apr", "maj", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
4
- weekdaysFull: ["nedjelja", "ponedjeljak", "utorak", "srijeda", "cetvrtak", "petak", "subota"],
5
- weekdaysShort: ["ne", "po", "ut", "sr", "če", "pe", "su"],
6
- today: "danas",
7
- clear: "izbrisati",
8
- firstDay: 1,
9
- format: "dd. mmmm yyyy.",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Bosnian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'januar', 'februar', 'mart', 'april', 'maj', 'juni', 'juli', 'august', 'septembar', 'oktobar', 'novembar', 'decembar' ],
5
+ monthsShort: [ 'jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec' ],
6
+ weekdaysFull: [ 'nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'cetvrtak', 'petak', 'subota' ],
7
+ weekdaysShort: [ 'ne', 'po', 'ut', 'sr', 'če', 'pe', 'su' ],
8
+ today: 'danas',
9
+ clear: 'izbrisati',
10
+ firstDay: 1,
11
+ format: 'dd. mmmm yyyy.',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'izbrisati'
17
+ });
js/pickadate/translations/ca_ES.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["Gener", "Febrer", "Març", "Abril", "Maig", "juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre"],
3
- monthsShort: ["Gen", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Des"],
4
- weekdaysFull: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"],
5
- weekdaysShort: ["diu", "dil", "dim", "dmc", "dij", "div", "dis"],
6
- today: "avui",
7
- clear: "esborrar",
8
- firstDay: 1,
9
- format: "dddd d !de mmmm !de yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Catalan
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Gener', 'Febrer', 'Març', 'Abril', 'Maig', 'juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Desembre' ],
5
+ monthsShort: [ 'Gen', 'Feb', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Oct', 'Nov', 'Des' ],
6
+ weekdaysFull: [ 'diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous', 'divendres', 'dissabte' ],
7
+ weekdaysShort: [ 'diu', 'dil', 'dim', 'dmc', 'dij', 'div', 'dis' ],
8
+ today: 'avui',
9
+ clear: 'esborra',
10
+ close: 'tanca',
11
+ firstDay: 1,
12
+ format: 'dddd d !de mmmm !de yyyy',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'esborra'
18
+ });
js/pickadate/translations/cs_CZ.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["leden", "únor", "březen", "duben", "květen", "červen", "červenec", "srpen", "září", "říjen", "listopad", "prosinec"],
3
- monthsShort: ["led", "úno", "bře", "dub", "kvě", "čer", "čvc", "srp", "zář", "říj", "lis", "pro"],
4
- weekdaysFull: ["neděle", "pondělí", "úterý", "středa", "čtvrtek", "pátek", "sobota"],
5
- weekdaysShort: ["ne", "po", "út", "st", "čt", "pá", "so"],
6
- today: "dnes",
7
- clear: "vymazat",
8
- firstDay: 1,
9
- format: "d. mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Czech
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'leden', 'únor', 'březen', 'duben', 'květen', 'červen', 'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec' ],
5
+ monthsShort: [ 'led', 'úno', 'bře', 'dub', 'kvě', 'čer', 'čvc', 'srp', 'zář', 'říj', 'lis', 'pro' ],
6
+ weekdaysFull: [ 'neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota' ],
7
+ weekdaysShort: [ 'ne', 'po', 'út', 'st', 'čt', 'pá', 'so' ],
8
+ today: 'dnes',
9
+ clear: 'vymazat',
10
+ firstDay: 1,
11
+ format: 'd. mmmm yyyy',
12
+ formatSubmit: 'yyyy/mm/dd',
13
+ close: 'zavřít'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'vymazat'
18
+ });
js/pickadate/translations/da_DK.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["januar", "februar", "marts", "april", "maj", "juni", "juli", "august", "september", "oktober", "november", "december"],
3
- monthsShort: ["jan", "feb", "mar", "apr", "maj", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
4
- weekdaysFull: ["søndag", "mandag", "tirsdag", "onsdag", "torsdag", "fredag", "lørdag"],
5
- weekdaysShort: ["søn", "man", "tir", "ons", "tor", "fre", "lør"],
6
- today: "i dag",
7
- clear: "slet",
8
- firstDay: 1,
9
- format: "d. mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Danish
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'januar', 'februar', 'marts', 'april', 'maj', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'december' ],
5
+ monthsShort: [ 'jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec' ],
6
+ weekdaysFull: [ 'søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag' ],
7
+ weekdaysShort: [ 'søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør' ],
8
+ today: 'i dag',
9
+ clear: 'slet',
10
+ close: 'luk',
11
+ firstDay: 1,
12
+ format: 'd. mmmm yyyy',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'slet'
18
+ });
js/pickadate/translations/de_DE.js CHANGED
@@ -1,11 +1,19 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
3
- monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"],
4
- weekdaysFull: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
5
- weekdaysShort: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
6
- today: "Heute",
7
- clear: "Löschen",
8
- firstDay: 1,
9
- format: "dddd, dd. mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
 
1
+ // German
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ],
5
+ monthsShort: [ 'Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez' ],
6
+ weekdaysFull: [ 'Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag' ],
7
+ weekdaysShort: [ 'So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa' ],
8
+ today: 'Heute',
9
+ clear: 'Löschen',
10
+ close: 'Schließen',
11
+ firstDay: 1,
12
+ format: 'dddd, dd. mmmm yyyy',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'Löschen',
18
+ format: 'H:i'
19
+ });
js/pickadate/translations/el_GR.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"],
3
- monthsShort: ["Ιαν", "Φεβ", "Μαρ", "Απρ", "Μαι", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ"],
4
- weekdaysFull: ["Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο"],
5
- weekdaysShort: ["Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ"],
6
- today: "σήμερα",
7
- clear: "Διαγραφή",
8
- firstDay: 1,
9
- format: "d mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Greek
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Ιανουάριος', 'Φεβρουάριος', 'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος', 'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος', 'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος' ],
5
+ monthsShort: [ 'Ιαν', 'Φεβ', 'Μαρ', 'Απρ', 'Μαι', 'Ιουν', 'Ιουλ', 'Αυγ', 'Σεπ', 'Οκτ', 'Νοε', 'Δεκ' ],
6
+ weekdaysFull: [ 'Κυριακή', 'Δευτέρα', 'Τρίτη', 'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σάββατο' ],
7
+ weekdaysShort: [ 'Κυρ', 'Δευ', 'Τρι', 'Τετ', 'Πεμ', 'Παρ', 'Σαβ' ],
8
+ today: 'σήμερα',
9
+ clear: 'Διαγραφή',
10
+ firstDay: 1,
11
+ format: 'd mmmm yyyy',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'Διαγραφή'
17
+ });
js/pickadate/translations/es_ES.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
3
- monthsShort: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"],
4
- weekdaysFull: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
5
- weekdaysShort: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"],
6
- today: "hoy",
7
- clear: "borrar",
8
- firstDay: 1,
9
- format: "dddd d !de mmmm !de yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Spanish
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre' ],
5
+ monthsShort: [ 'ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic' ],
6
+ weekdaysFull: [ 'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado' ],
7
+ weekdaysShort: [ 'dom', 'lun', 'mar', 'mié', 'jue', 'vie', 'sáb' ],
8
+ today: 'Hoy',
9
+ clear: 'Borrar',
10
+ close: 'Cerrar',
11
+ firstDay: 1,
12
+ format: 'dddd d !de mmmm !de yyyy',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'Borrar'
18
+ });
js/pickadate/translations/et_EE.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["jaanuar", "veebruar", "märts", "aprill", "mai", "juuni", "juuli", "august", "september", "oktoober", "november", "detsember"],
3
- monthsShort: ["jaan", "veebr", "märts", "apr", "mai", "juuni", "juuli", "aug", "sept", "okt", "nov", "dets"],
4
- weekdaysFull: ["pühapäev", "esmaspäev", "teisipäev", "kolmapäev", "neljapäev", "reede", "laupäev"],
5
- weekdaysShort: ["püh", "esm", "tei", "kol", "nel", "ree", "lau"],
6
- today: "täna",
7
- clear: "kustutama",
8
- firstDay: 1,
9
- format: "d. mmmm yyyy. a",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Estonian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni', 'juuli', 'august', 'september', 'oktoober', 'november', 'detsember' ],
5
+ monthsShort: [ 'jaan', 'veebr', 'märts', 'apr', 'mai', 'juuni', 'juuli', 'aug', 'sept', 'okt', 'nov', 'dets' ],
6
+ weekdaysFull: [ 'pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev', 'neljapäev', 'reede', 'laupäev' ],
7
+ weekdaysShort: [ 'püh', 'esm', 'tei', 'kol', 'nel', 'ree', 'lau' ],
8
+ today: 'täna',
9
+ clear: 'kustuta',
10
+ firstDay: 1,
11
+ format: 'd. mmmm yyyy. a',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'kustuta'
17
+ });
js/pickadate/translations/eu_ES.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["urtarrila", "otsaila", "martxoa", "apirila", "maiatza", "ekaina", "uztaila", "abuztua", "iraila", "urria", "azaroa", "abendua"],
3
- monthsShort: ["urt", "ots", "mar", "api", "mai", "eka", "uzt", "abu", "ira", "urr", "aza", "abe"],
4
- weekdaysFull: ["igandea", "astelehena", "asteartea", "asteazkena", "osteguna", "ostirala", "larunbata"],
5
- weekdaysShort: ["ig.", "al.", "ar.", "az.", "og.", "or.", "lr."],
6
- today: "gaur",
7
- clear: "garbitu",
8
- firstDay: 1,
9
- format: "dddd, yyyy(e)ko mmmmren da",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Basque
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'urtarrila', 'otsaila', 'martxoa', 'apirila', 'maiatza', 'ekaina', 'uztaila', 'abuztua', 'iraila', 'urria', 'azaroa', 'abendua' ],
5
+ monthsShort: [ 'urt', 'ots', 'mar', 'api', 'mai', 'eka', 'uzt', 'abu', 'ira', 'urr', 'aza', 'abe' ],
6
+ weekdaysFull: [ 'igandea', 'astelehena', 'asteartea', 'asteazkena', 'osteguna', 'ostirala', 'larunbata' ],
7
+ weekdaysShort: [ 'ig.', 'al.', 'ar.', 'az.', 'og.', 'or.', 'lr.' ],
8
+ today: 'gaur',
9
+ clear: 'garbitu',
10
+ firstDay: 1,
11
+ format: 'dddd, yyyy(e)ko mmmmren da',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'garbitu'
17
+ });
js/pickadate/translations/fa_IR.js ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Farsi
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
5
+ monthsShort: [ 'ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر' ],
6
+ weekdaysFull: [ 'یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه' ],
7
+ weekdaysShort: [ 'یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه' ],
8
+ today: 'امروز',
9
+ clear: 'پاک کردن',
10
+ close: 'بستن',
11
+ format: 'yyyy mmmm dd',
12
+ formatSubmit: 'yyyy/mm/dd',
13
+ labelMonthNext: 'ماه بعدی',
14
+ labelMonthPrev: 'ماه قبلی'
15
+ });
16
+
17
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
18
+ clear: 'پاک کردن'
19
+ });
js/pickadate/translations/fi_FI.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"],
3
- monthsShort: ["tammi", "helmi", "maalis", "huhti", "touko", "kesä", "heinä", "elo", "syys", "loka", "marras", "joulu"],
4
- weekdaysFull: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"],
5
- weekdaysShort: ["su", "ma", "ti", "ke", "to", "pe", "la"],
6
- today: "tänään",
7
- clear: "tyhjennä",
8
- firstDay: 1,
9
- format: "d.m.yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Finnish
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu' ],
5
+ monthsShort: [ 'tammi', 'helmi', 'maalis', 'huhti', 'touko', 'kesä', 'heinä', 'elo', 'syys', 'loka', 'marras', 'joulu' ],
6
+ weekdaysFull: [ 'sunnuntai', 'maanantai', 'tiistai', 'keskiviikko', 'torstai', 'perjantai', 'lauantai' ],
7
+ weekdaysShort: [ 'su', 'ma', 'ti', 'ke', 'to', 'pe', 'la' ],
8
+ today: 'tänään',
9
+ clear: 'tyhjennä',
10
+ firstDay: 1,
11
+ format: 'd.m.yyyy',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'tyhjennä'
17
+ });
js/pickadate/translations/fr_FR.js CHANGED
@@ -1,11 +1,23 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
3
- monthsShort: ["Jan", "Fev", "Mar", "Avr", "Mai", "Juin", "Juil", "Aou", "Sep", "Oct", "Nov", "Dec"],
4
- weekdaysFull: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
5
- weekdaysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"],
6
- today: "Aujourd'hui",
7
- clear: "Effacer",
8
- firstDay: 1,
9
- format: "dd mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // French
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre' ],
5
+ monthsShort: [ 'Jan', 'Fev', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Aou', 'Sep', 'Oct', 'Nov', 'Dec' ],
6
+ weekdaysFull: [ 'Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi' ],
7
+ weekdaysShort: [ 'Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam' ],
8
+ today: 'Aujourd\'hui',
9
+ clear: 'Effacer',
10
+ close: 'Fermer',
11
+ firstDay: 1,
12
+ format: 'dd mmmm yyyy',
13
+ formatSubmit: 'yyyy/mm/dd',
14
+ labelMonthNext:"Mois suivant",
15
+ labelMonthPrev:"Mois précédent",
16
+ labelMonthSelect:"Sélectionner un mois",
17
+ labelYearSelect:"Sélectionner une année"
18
+ });
19
+
20
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
21
+ clear: 'Effacer',
22
+ format: 'H:i'
23
+ });
js/pickadate/translations/ge_GEO.js ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Georgian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი', 'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი' ],
5
+ monthsShort: [ 'იან', 'თებ', 'მარტ', 'აპრ', 'მაი', 'ივნ', 'ივლ', 'აგვ', 'სექტ', 'ოქტ', 'ნოემ', 'დეკ' ],
6
+ weekdaysFull: [ 'კვირა', 'ორშაბათი', 'სამშაბათი', 'ოთხშაბათი', 'ხუშაბათი', 'პარასკევი', 'შაბათი' ],
7
+ weekdaysShort: [ 'კვ', 'ორ', 'სამ', 'ოთხ', 'ხუთ', 'პარ', 'შაბ' ],
8
+ today: 'დღეს',
9
+ clear: 'გასუფთავება',
10
+ firstDay: 1,
11
+ format: 'd mmmm yyyy',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'გასუფთავება'
17
+ });
js/pickadate/translations/gl_ES.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["Xaneiro", "Febreiro", "Marzo", "Abril", "Maio", "Xuño", "Xullo", "Agosto", "Setembro", "Outubro", "Novembro", "Decembro"],
3
- monthsShort: ["xan", "feb", "mar", "abr", "mai", "xun", "xul", "ago", "sep", "out", "nov", "dec"],
4
- weekdaysFull: ["domingo", "luns", "martes", "mércores", "xoves", "venres", "sábado"],
5
- weekdaysShort: ["dom", "lun", "mar", "mér", "xov", "ven", "sab"],
6
- today: "hoxe",
7
- clear: "borrar",
8
- firstDay: 1,
9
- format: "dddd d !de mmmm !de yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Galician
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Xaneiro', 'Febreiro', 'Marzo', 'Abril', 'Maio', 'Xuño', 'Xullo', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Decembro' ],
5
+ monthsShort: [ 'xan', 'feb', 'mar', 'abr', 'mai', 'xun', 'xul', 'ago', 'sep', 'out', 'nov', 'dec' ],
6
+ weekdaysFull: [ 'domingo', 'luns', 'martes', 'mércores', 'xoves', 'venres', 'sábado' ],
7
+ weekdaysShort: [ 'dom', 'lun', 'mar', 'mér', 'xov', 'ven', 'sab' ],
8
+ today: 'hoxe',
9
+ clear: 'borrar',
10
+ firstDay: 1,
11
+ format: 'dddd d !de mmmm !de yyyy',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'borrar'
17
+ });
js/pickadate/translations/he_IL.js CHANGED
@@ -1,10 +1,16 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"],
3
- monthsShort: ["ינו", "פבר", "מרץ", "אפר", "מאי", "יונ", "יול", "אוג", "ספט", "אוק", "נוב", "דצמ"],
4
- weekdaysFull: ["יום ראשון", "יום שני", "יום שלישי", "יום רביעי", "יום חמישי", "יום ששי", "יום שבת"],
5
- weekdaysShort: ["א", "ב", "ג", "ד", "ה", "ו", "ש"],
6
- today: "היום",
7
- clear: "למחוק",
8
- format: "yyyy mmmmב d dddd",
9
- formatSubmit: "yyyy/mm/dd"
10
- });
 
 
 
 
 
 
1
+ // Hebrew
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר' ],
5
+ monthsShort: [ 'ינו', 'פבר', 'מרץ', 'אפר', 'מאי', 'יונ', 'יול', 'אוג', 'ספט', 'אוק', 'נוב', 'דצמ' ],
6
+ weekdaysFull: [ 'יום ראשון', 'יום שני', 'יום שלישי', 'יום רביעי', 'יום חמישי', 'יום ששי', 'יום שבת' ],
7
+ weekdaysShort: [ 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ש' ],
8
+ today: 'היום',
9
+ clear: 'למחוק',
10
+ format: 'yyyy mmmmב d dddd',
11
+ formatSubmit: 'yyyy/mm/dd'
12
+ });
13
+
14
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
15
+ clear: 'למחוק'
16
+ });
js/pickadate/translations/hi_IN.js ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
2
+ monthsFull: [ 'जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर' ],
3
+ monthsShort: [ 'जन', 'फर', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जु', 'अग', 'सित', 'अक्टू', 'नव', 'दिस' ],
4
+ weekdaysFull: [ 'रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरुवार', 'शुक्रवार', 'शनिवार' ],
5
+ weekdaysShort: [ 'रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र','शनि' ],
6
+ today: 'आज की तारीख चयन करें',
7
+ clear: 'चुनी हुई तारीख को मिटाएँ',
8
+ close: 'विंडो बंद करे',
9
+ firstDay: 1,
10
+ format: 'dd/mm/yyyy',
11
+ formatSubmit: 'yyyy/mm/dd',
12
+ labelMonthNext: 'अगले माह का चयन करें',
13
+ labelMonthPrev: 'पिछले माह का चयन करें',
14
+ labelMonthSelect: 'किसि एक महीने का चयन करें',
15
+ labelYearSelect: 'किसि एक वर्ष का चयन करें'
16
+ });
17
+
18
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
19
+ clear: 'चुनी हुई तारीख को मिटाएँ'
20
+ });
js/pickadate/translations/hr_HR.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["sijećanj", "veljača", "ožujak", "travanj", "svibanj", "lipanj", "srpanj", "kolovoz", "rujan", "listopad", "studeni", "prosinac"],
3
- monthsShort: ["sij", "velj", "ožu", "tra", "svi", "lip", "srp", "kol", "ruj", "lis", "stu", "pro"],
4
- weekdaysFull: ["nedjelja", "ponedjeljak", "utorak", "srijeda", "četvrtak", "petak", "subota"],
5
- weekdaysShort: ["ned", "pon", "uto", "sri", "čet", "pet", "sub"],
6
- today: "danas",
7
- clear: "izbrisati",
8
- firstDay: 1,
9
- format: "d. mmmm yyyy.",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Croatian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj', 'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac' ],
5
+ monthsShort: [ 'sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp', 'kol', 'ruj', 'lis', 'stu', 'pro' ],
6
+ weekdaysFull: [ 'nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota' ],
7
+ weekdaysShort: [ 'ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub' ],
8
+ today: 'Danas',
9
+ clear: 'Izbriši',
10
+ close: 'Zatvori',
11
+ firstDay: 1,
12
+ format: 'd. mmmm yyyy.',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'Izbriši'
18
+ });
js/pickadate/translations/hu_HU.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["január", "február", "március", "aprilis", "május", "június", "július", "augusztus", "szeptember", "október", "november", "december"],
3
- monthsShort: ["jan", "febr", "márc", "apr", "máj", "jún", "júl", "aug", "szept", "okt", "nov", "dec"],
4
- weekdaysFull: ["vasámap", "hétfö", "kedd", "szerda", "csütörtök", "péntek", "szombat"],
5
- weekdaysShort: ["V", "H", "K", "SZ", "CS", "P", "SZ"],
6
- today: "ma",
7
- clear: "töröl",
8
- firstDay: 1,
9
- format: "yyyy. mmmm dd.",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Hungarian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'január', 'február', 'március', 'április', 'május', 'június', 'július', 'augusztus', 'szeptember', 'október', 'november', 'december' ],
5
+ monthsShort: [ 'jan', 'febr', 'márc', 'ápr', 'máj', 'jún', 'júl', 'aug', 'szept', 'okt', 'nov', 'dec' ],
6
+ weekdaysFull: [ 'vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök', 'péntek', 'szombat' ],
7
+ weekdaysShort: [ 'V', 'H', 'K', 'Sze', 'CS', 'P', 'Szo' ],
8
+ today: 'Ma',
9
+ clear: 'Törlés',
10
+ close: 'Bezárás',
11
+ firstDay: 1,
12
+ format: 'yyyy. mmmm dd.',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'Törlés'
18
+ });
js/pickadate/translations/id_ID.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"],
3
- monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Agu", "Sep", "Okt", "Nov", "Des"],
4
- weekdaysFull: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"],
5
- weekdaysShort: ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"],
6
- today: "hari ini",
7
- clear: "menghapus",
8
- firstDay: 1,
9
- format: "d mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Indonesian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember' ],
5
+ monthsShort: [ 'Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des' ],
6
+ weekdaysFull: [ 'Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu' ],
7
+ weekdaysShort: [ 'Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab' ],
8
+ today: 'hari ini',
9
+ clear: 'menghapus',
10
+ firstDay: 1,
11
+ format: 'd mmmm yyyy',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'menghapus'
17
+ });
js/pickadate/translations/is_IS.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["janúar", "febrúar", "mars", "apríl", "maí", "júní", "júlí", "ágúst", "september", "október", "nóvember", "desember"],
3
- monthsShort: ["jan", "feb", "mar", "apr", "maí", "jún", "júl", "ágú", "sep", "okt", "nóv", "des"],
4
- weekdaysFull: ["sunnudagur", "mánudagur", "þriðjudagur", "miðvikudagur", "fimmtudagur", "föstudagur", "laugardagur"],
5
- weekdaysShort: ["sun", "mán", "þri", "mið", "fim", "fös", "lau"],
6
- today: dag",
7
- clear: "Hreinsa",
8
- firstDay: 1,
9
- format: "dd. mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Icelandic
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'janúar', 'febrúar', 'mars', 'apríl', 'maí', 'júní', 'júlí', 'ágúst', 'september', 'október', 'nóvember', 'desember' ],
5
+ monthsShort: [ 'jan', 'feb', 'mar', 'apr', 'maí', 'jún', 'júl', 'ágú', 'sep', 'okt', 'nóv', 'des' ],
6
+ weekdaysFull: [ 'sunnudagur', 'mánudagur', 'þriðjudagur', 'miðvikudagur', 'fimmtudagur', 'föstudagur', 'laugardagur' ],
7
+ weekdaysShort: [ 'sun', 'mán', 'þri', 'mið', 'fim', 'fös', 'lau' ],
8
+ today: 'Í dag',
9
+ clear: 'Hreinsa',
10
+ firstDay: 1,
11
+ format: 'dd. mmmm yyyy',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'Hreinsa'
17
+ });
js/pickadate/translations/it_IT.js CHANGED
@@ -1,11 +1,24 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"],
3
- monthsShort: ["gen", "feb", "mar", "apr", "mag", "giu", "lug", "ago", "set", "ott", "nov", "dic"],
4
- weekdaysFull: ["domenica", "lunedì", "martedì", "mercoledì", "giovedì", "venerdì", "sabato"],
5
- weekdaysShort: ["dom", "lun", "mar", "mer", "gio", "ven", "sab"],
6
- today: "oggi",
7
- clear: "cancellare",
8
- firstDay: 1,
9
- format: "dddd d mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Italian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre' ],
5
+ monthsShort: [ 'gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set', 'ott', 'nov', 'dic' ],
6
+ weekdaysFull: [ 'domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato' ],
7
+ weekdaysShort: [ 'dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab' ],
8
+ today: 'Oggi',
9
+ clear: 'Cancella',
10
+ close: 'Chiudi',
11
+ firstDay: 1,
12
+ format: 'dddd d mmmm yyyy',
13
+ formatSubmit: 'yyyy/mm/dd',
14
+ labelMonthNext: 'Mese successivo',
15
+ labelMonthPrev: 'Mese precedente',
16
+ labelMonthSelect: 'Seleziona un mese',
17
+ labelYearSelect: 'Seleziona un anno'
18
+ });
19
+
20
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
21
+ clear: 'Cancella',
22
+ format: 'HH:i',
23
+ formatSubmit: 'HH:i'
24
+ });
js/pickadate/translations/ja_JP.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
3
- monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
4
- weekdaysFull: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
5
- weekdaysShort: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
6
- today: "今日",
7
- clear: "消去",
8
- firstDay: 1,
9
- format: "yyyy mm dd",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Japanese
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ '1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月' ],
5
+ monthsShort: [ '1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月' ],
6
+ weekdaysFull: [ '日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日' ],
7
+ weekdaysShort: [ '日', '月', '火', '水', '木', '金', '土' ],
8
+ today: '今日',
9
+ clear: '消去',
10
+ close: '閉じる',
11
+ firstDay: 1,
12
+ format: 'yyyy年mm月dd日',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: '消去'
18
+ });
js/pickadate/translations/km_KH.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Khmer
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'មករា', 'កុម្ភៈ', 'មីនា', 'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា', 'កញ្ញា', 'តុលា', 'វិច្ឆិកា', 'ធ្នូ' ],
5
+ monthsShort: [ 'មក.', 'កុ.', 'មី.', 'មេ.', 'ឧស.', 'មិថុ.', 'កក្ក.', 'សី.', 'កញ.', 'តុ.', 'វិច្ឆ.', 'ធ.' ],
6
+ weekdaysFull: [ 'អាទិត្យ', 'ចន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ', 'សៅរ៍' ],
7
+ weekdaysShort: [ 'អា.', 'ច.', 'អ.', 'ព.', 'ព្រ.', 'សុ.', 'ស.' ],
8
+ today: 'ថ្ងៃនេះ',
9
+ clear: 'លុប',
10
+ close: 'បិទ',
11
+ labelMonthNext: 'ខែបន្ទាប់',
12
+ labelMonthPrev: 'ខែមុន',
13
+ labelMonthSelect: 'ជ្រើសរើសខែ',
14
+ labelYearSelect: 'ជ្រើសរើសឆ្នាំ',
15
+ firstDay: 1,
16
+ showMonthsShort: false,
17
+ showWeekdaysFull: true,
18
+ format: 'ថ្ងៃទី d ខែmmmm ឆ្នាំ yyyy',
19
+ formatSubmit: 'yyyy/mm/dd'
20
+ });
21
+
22
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
23
+ clear: 'លុប'
24
+ });
js/pickadate/translations/ko_KR.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
3
- monthsShort: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
4
- weekdaysFull: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"],
5
- weekdaysShort: ["일", "", "화", "수", "목", "금", "토"],
6
- today: "오늘",
7
- clear: "취소",
8
- firstDay: 1,
9
- format: "yyyy 년 mm 월 dd 일",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Korean
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ '1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월' ],
5
+ monthsShort: [ '1월', '2', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월' ],
6
+ weekdaysFull: [ '일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일' ],
7
+ weekdaysShort: [ '일', '월', '화', '수', '목', '금', '토' ],
8
+ today: '오늘',
9
+ clear: '취소',
10
+ firstDay: 1,
11
+ format: 'yyyy 년 mm 월 dd 일',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: '취소'
17
+ });
js/pickadate/translations/lt_LT.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Lietuviškai
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ labelMonthNext: 'Sekantis mėnuo',
5
+ labelMonthPrev: 'Ankstesnis mėnuo',
6
+ labelMonthSelect: 'Pasirinkite mėnesį',
7
+ labelYearSelect: 'Pasirinkite metus',
8
+ monthsFull: ['Sausis', 'Vasaris', 'Kovas', 'Balandis', 'Gegužė', 'Birželis', 'Liepa', 'Rugpjūtis', 'Rugsėjis', 'Spalis', 'Lapkritis', 'Gruodis'],
9
+ monthsShort: ['Sau', 'Vas', 'Kov', 'Bal', 'Geg', 'Bir', 'Lie', 'Rgp', 'Rgs', 'Spa', 'Lap', 'Grd'],
10
+ weekdaysFull: ['Sekmadienis', 'Pirmadienis', 'Antradienis', 'Trečiadienis', 'Ketvirtadienis', 'Penktadienis', 'Šeštadienis'],
11
+ weekdaysShort: ['Sk', 'Pr', 'An', 'Tr', 'Kt', 'Pn', 'Št'],
12
+ today: 'Šiandien',
13
+ clear: 'Išvalyti',
14
+ close: 'Uždaryti',
15
+ firstDay: 1,
16
+ //format: 'yyyy !m. mmmm d !d.', // need to have diffrent case of full months name
17
+ format: 'yyyy-mm-dd',
18
+ formatSubmit: 'yyyy/mm/dd'
19
+ });
20
+
21
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
22
+ clear: 'Išvalyti',
23
+ format: 'HH:i'
24
+ });
js/pickadate/translations/lv_LV.js ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Latvian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Janvāris', 'Februāris', 'Marts', 'Aprīlis', 'Maijs', 'Jūnijs', 'Jūlijs', 'Augusts', 'Septembris', 'Oktobris', 'Novembris', 'Decembris' ],
5
+ monthsShort: [ 'Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jūn', 'Jūl', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec' ],
6
+ weekdaysFull: [ 'Svētdiena', 'Pirmdiena', 'Otrdiena', 'Trešdiena', 'Ceturtdiena', 'Piektdiena', 'Sestdiena' ],
7
+ weekdaysShort: [ 'Sv', 'P', 'O', 'T', 'C', 'Pk', 'S' ],
8
+ today: 'Šodiena',
9
+ clear: 'Dzēst',
10
+ close: 'Aizvērt',
11
+ firstDay: 1,
12
+ format: 'yyyy.mm.dd. dddd',
13
+ formatSubmit: 'yyyy/mm/dd',
14
+ labelMonthNext: 'Nākamais mēnesis',
15
+ labelMonthPrev: 'Iepriekšējais mēnesis',
16
+ labelMonthSelect: 'Izvēlēties mēnesi',
17
+ labelYearSelect: 'Izvēlēties gadu'
18
+ });
19
+
20
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
21
+ clear: 'Dzēst'
22
+ });
js/pickadate/translations/nb_NO.js ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Norwegian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember' ],
5
+ monthsShort: [ 'jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des' ],
6
+ weekdaysFull: [ 'søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag' ],
7
+ weekdaysShort: [ 'søn','man','tir', 'ons', 'tor', 'fre', 'lør' ],
8
+ today: 'i dag',
9
+ clear: 'nullstill',
10
+ close: 'lukk',
11
+ firstDay: 1,
12
+ format: 'dd. mmm. yyyy',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'nullstill'
18
+ });
js/pickadate/translations/ne_NP.js ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Nepali
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'जनवरी', 'फेब्रुअरी', 'मार्च', 'अप्रिल', 'मे', 'जुन', 'जुलाई', 'अगस्त', 'सेप्टेम्बर', 'अक्टोबर', 'नोवेम्बर', 'डिसेम्बर' ],
5
+ monthsShort: [ 'जन', 'फेब्रु', 'मार्च', 'अप्रिल', 'मे', 'जुन', 'जुल', 'अग', 'सेप्टे', 'अक्टो', 'नोभे', 'डिसे' ],
6
+ weekdaysFull: [ 'सोमबार', 'मङ्लबार', 'बुधबार', 'बिहीबार', 'शुक्रबार', 'शनिबार', 'आईतबार' ],
7
+ weekdaysShort: [ 'सोम', 'मंगल्', 'बुध', 'बिही', 'शुक्र', 'शनि', 'आईत' ],
8
+ numbers: [ '०', '१', '२', '३', '४', '५', '६', '७', '८', '९' ],
9
+ today: 'आज',
10
+ clear: 'मेटाउनुहोस्',
11
+ format: 'dddd, dd mmmm, yyyy',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'मेटाउनुहोस्'
17
+ });
js/pickadate/translations/nl_NL.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
3
- monthsShort: ["jan", "feb", "maa", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
4
- weekdaysFull: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"],
5
- weekdaysShort: ["zo", "ma", "di", "wo", "do", "vr", "za"],
6
- today: "vandaag",
7
- clear: "verwijderen",
8
- firstDay: 1,
9
- format: "dddd d mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Dutch
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december' ],
5
+ monthsShort: [ 'jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec' ],
6
+ weekdaysFull: [ 'zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag' ],
7
+ weekdaysShort: [ 'zo', 'ma', 'di', 'wo', 'do', 'vr', 'za' ],
8
+ today: 'vandaag',
9
+ clear: 'wissen',
10
+ close: 'sluiten',
11
+ firstDay: 1,
12
+ format: 'dddd d mmmm yyyy',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'wissen'
18
+ });
js/pickadate/translations/pl_PL.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień"],
3
- monthsShort: ["sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "paź", "lis", "gru"],
4
- weekdaysFull: ["niedziela", "poniedziałek", "wtorek", "środa", "czwartek", "piątek", "sobota"],
5
- weekdaysShort: ["N", "Pn", "Wt", "Śr", "Cz", "Pt", "So"],
6
- today: "dzisiaj",
7
- clear: "usunąć",
8
- firstDay: 1,
9
- format: "d mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Polish
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'styczeń', 'luty', 'marzec', 'kwiecień', 'maj', 'czerwiec', 'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad', 'grudzień' ],
5
+ monthsShort: [ 'sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip', 'sie', 'wrz', 'paź', 'lis', 'gru' ],
6
+ weekdaysFull: [ 'niedziela', 'poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota' ],
7
+ weekdaysShort: [ 'niedz.', 'pn.', 'wt.', 'śr.', 'cz.', 'pt.', 'sob.' ],
8
+ today: 'Dzisiaj',
9
+ clear: 'Usuń',
10
+ close: 'Zamknij',
11
+ firstDay: 1,
12
+ format: 'd mmmm yyyy',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'usunąć'
18
+ });
js/pickadate/translations/pt_BR.js CHANGED
@@ -1,10 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["janeiro", "fevereiro", "março", "abril", "maio", "junho", "julho", "agosto", "setembro", "outubro", "novembro", "dezembro"],
3
- monthsShort: ["jan", "fev", "mar", "abr", "mai", "jun", "jul", "ago", "set", "out", "nov", "dez"],
4
- weekdaysFull: ["domingo", "segunda-feira", "terça-feira", "quarta-feira", "quinta-feira", "sexta-feira", "sábado"],
5
- weekdaysShort: ["dom", "seg", "ter", "qua", "qui", "sex", "sab"],
6
- today: "hoje",
7
- clear: "excluir",
8
- format: "dddd, d !de mmmm !de yyyy",
9
- formatSubmit: "yyyy/mm/dd"
10
- });
 
 
 
 
 
 
 
1
+ // Brazilian Portuguese
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro' ],
5
+ monthsShort: [ 'jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez' ],
6
+ weekdaysFull: [ 'domingo', 'segunda-feira', 'terça-feira', 'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado' ],
7
+ weekdaysShort: [ 'dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sab' ],
8
+ today: 'hoje',
9
+ clear: 'limpar',
10
+ close: 'fechar',
11
+ format: 'dddd, d !de mmmm !de yyyy',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'limpar'
17
+ });
js/pickadate/translations/pt_PT.js CHANGED
@@ -1,10 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["janeiro", "fevereiro", "março", "abril", "maio", "junho", "julho", "agosto", "setembro", "outubro", "novembro", "dezembro"],
3
- monthsShort: ["jan", "fev", "mar", "abr", "mai", "jun", "jul", "ago", "set", "out", "nov", "dez"],
4
- weekdaysFull: ["domingo", "segunda", "terça", "quarta", "quinta", "sexta", "sábado"],
5
- weekdaysShort: ["dom", "seg", "ter", "qua", "qui", "sex", "sab"],
6
- today: "hoje",
7
- clear: "excluir",
8
- format: "d !de mmmm !de yyyy",
9
- formatSubmit: "yyyy/mm/dd"
10
- });
 
 
 
 
 
 
 
1
+ // Portuguese
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro' ],
5
+ monthsShort: [ 'jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez' ],
6
+ weekdaysFull: [ 'Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado' ],
7
+ weekdaysShort: [ 'dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sab' ],
8
+ today: 'Hoje',
9
+ clear: 'Limpar',
10
+ close: 'Fechar',
11
+ format: 'd !de mmmm !de yyyy',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'Limpar'
17
+ });
js/pickadate/translations/ro_RO.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["ianuarie", "februarie", "martie", "aprilie", "mai", "iunie", "iulie", "august", "septembrie", "octombrie", "noiembrie", "decembrie"],
3
- monthsShort: ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"],
4
- weekdaysFull: ["duminică", "luni", "marţi", "miercuri", "joi", "vineri", "sâmbătă"],
5
- weekdaysShort: ["D", "L", "Ma", "Mi", "J", "V", "S"],
6
- today: "azi",
7
- clear: "șterge",
8
- firstDay: 1,
9
- format: "dd mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Romanian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'ianuarie', 'februarie', 'martie', 'aprilie', 'mai', 'iunie', 'iulie', 'august', 'septembrie', 'octombrie', 'noiembrie', 'decembrie' ],
5
+ monthsShort: [ 'ian', 'feb', 'mar', 'apr', 'mai', 'iun', 'iul', 'aug', 'sep', 'oct', 'noi', 'dec' ],
6
+ weekdaysFull: [ 'duminică', 'luni', 'marţi', 'miercuri', 'joi', 'vineri', 'sâmbătă' ],
7
+ weekdaysShort: [ 'D', 'L', 'Ma', 'Mi', 'J', 'V', 'S' ],
8
+ today: 'azi',
9
+ clear: 'șterge',
10
+ firstDay: 1,
11
+ format: 'dd mmmm yyyy',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'șterge'
17
+ });
js/pickadate/translations/ru_RU.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["Января", "Февраля", "Марта", "Апреля", "Мая", "Июня", "Июля", "Августа", "Сентября", "Октября", "Ноября", "Декабря"],
3
- monthsShort: ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"],
4
- weekdaysFull: ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"],
5
- weekdaysShort: ["вс", "пн", "вт", "ср", "чт", "пт", "сб"],
6
- today: "сегодня",
7
- clear: "удалить",
8
- firstDay: 1,
9
- format: "d mmmm yyyy г.",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Russian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря' ],
5
+ monthsShort: [ 'янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек' ],
6
+ weekdaysFull: [ 'воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота' ],
7
+ weekdaysShort: [ 'вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб' ],
8
+ today: 'сегодня',
9
+ clear: 'удалить',
10
+ close: 'закрыть',
11
+ firstDay: 1,
12
+ format: 'd mmmm yyyy г.',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'удалить'
18
+ });
js/pickadate/translations/sk_SK.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["január", "február", "marec", "apríl", "máj", "jún", "júl", "august", "september", "október", "november", "december"],
3
- monthsShort: ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"],
4
- weekdaysFull: ["nedeļľa", "pondelok", "utorok", "streda", "š̌švrtok", "piatok", "sobota"],
5
- weekdaysShort: ["Ne", "Po", "Ut", "St", "Št", "Pi", "So"],
6
- today: "dnes",
7
- clear: "vymazať",
8
- firstDay: 1,
9
- format: "d. mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Slovak
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'január', 'február', 'marec', 'apríl', 'máj', 'jún', 'júl', 'august', 'september', 'október', 'november', 'december' ],
5
+ monthsShort: [ 'jan', 'feb', 'mar', 'apr', 'máj', 'jún', 'júl', 'aug', 'sep', 'okt', 'nov', 'dec' ],
6
+ weekdaysFull: [ 'nedeľa', 'pondelok', 'utorok', 'streda', 'štvrtok', 'piatok', 'sobota' ],
7
+ weekdaysShort: [ 'Ne', 'Po', 'Ut', 'St', 'Št', 'Pi', 'So' ],
8
+ today: 'dnes',
9
+ clear: 'vymazať',
10
+ close: 'zavrieť',
11
+ firstDay: 1,
12
+ format: 'd. mmmm yyyy',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'vymazať'
18
+ });
js/pickadate/translations/sl_SI.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["januar", "februar", "marec", "april", "maj", "junij", "julij", "avgust", "september", "oktober", "november", "december"],
3
- monthsShort: ["jan", "feb", "mar", "apr", "maj", "jun", "jul", "avg", "sep", "okt", "nov", "dec"],
4
- weekdaysFull: ["nedelja", "ponedeljek", "torek", "sreda", "četrtek", "petek", "sobota"],
5
- weekdaysShort: ["ned", "pon", "tor", "sre", "čet", "pet", "sob"],
6
- today: "danes",
7
- clear: "izbriši",
8
- firstDay: 1,
9
- format: "d. mmmm yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Slovenian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'januar', 'februar', 'marec', 'april', 'maj', 'junij', 'julij', 'avgust', 'september', 'oktober', 'november', 'december' ],
5
+ monthsShort: [ 'jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'avg', 'sep', 'okt', 'nov', 'dec' ],
6
+ weekdaysFull: [ 'nedelja', 'ponedeljek', 'torek', 'sreda', 'četrtek', 'petek', 'sobota' ],
7
+ weekdaysShort: [ 'ned', 'pon', 'tor', 'sre', 'čet', 'pet', 'sob' ],
8
+ today: 'danes',
9
+ clear: 'izbriši',
10
+ close: 'zapri',
11
+ firstDay: 1,
12
+ format: 'd. mmmm yyyy',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'izbriši'
18
+ });
js/pickadate/translations/sr_RS_cy.js ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Serbian (Cyrillic)
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'јануар','фебруар','март','април','мај','јун','јул','август','септембар','октобар','новембар','децембар' ],
5
+ monthsShort: [ 'јан.','феб.','март','апр.','мај','јун','јул','авг.','септ.','окт.','нов.','дец.' ],
6
+ weekdaysFull: [ 'недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота' ],
7
+ weekdaysShort: [ 'нед.', 'пон.', 'ут.', 'ср.', 'чет.', 'пет.', 'суб.' ],
8
+ today: 'данас',
9
+ clear: 'избриши',
10
+ close: 'затвори',
11
+ firstDay: 1,
12
+ format: 'd. MMMM yyyy.',
13
+ formatSubmit: 'yyyy/mm/dd',
14
+ labelMonthNext:"Следећи месец",
15
+ labelMonthPrev:"Претходни месец",
16
+ labelMonthSelect:"Изаберите месец",
17
+ labelYearSelect:"Изаберите годину"
18
+ });
19
+
20
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
21
+ clear: 'избриши'
22
+ });
js/pickadate/translations/sr_RS_lt.js ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Serbian (Latin)
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'januar', 'februar', 'mart', 'april', 'maj', 'jun', 'juli', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar' ],
5
+ monthsShort: [ 'jan.', 'feb.', 'mart', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sept.', 'okt.', 'nov.', 'dec.' ],
6
+ weekdaysFull: [ 'nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota' ],
7
+ weekdaysShort: [ 'ned.', 'pon.', 'ut.', 'sr.', 'čet.', 'pet.', 'sub.' ],
8
+ today: 'danas',
9
+ clear: 'izbriši',
10
+ close: 'zatvori',
11
+ firstDay: 1,
12
+ format: 'd. MMMM yyyy.',
13
+ formatSubmit: 'yyyy/mm/dd',
14
+ labelMonthNext:"Sledeći mesec",
15
+ labelMonthPrev:"Prethodni mesec",
16
+ labelMonthSelect:"Izaberite mesec",
17
+ labelYearSelect:"Izaberite godinu"
18
+ });
19
+
20
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
21
+ clear: 'izbriši'
22
+ });
js/pickadate/translations/sv_SE.js CHANGED
@@ -1,11 +1,22 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["januari", "februari", "mars", "april", "maj", "juni", "juli", "augusti", "september", "oktober", "november", "december"],
3
- monthsShort: ["jan", "feb", "mar", "apr", "maj", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
4
- weekdaysFull: ["söndag", "måndag", "tisdag", "onsdag", "torsdag", "fredag", "lördag"],
5
- weekdaysShort: ["sön", "mån", "tis", "ons", "tor", "fre", "lör"],
6
- today: "i dag",
7
- clear: "bort",
8
- firstDay: 1,
9
- format: "d/m yyyy",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
 
 
 
 
1
+ // Swedish
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december' ],
5
+ monthsShort: [ 'jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec' ],
6
+ weekdaysFull: [ 'söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag', 'lördag' ],
7
+ weekdaysShort: [ 'sön', 'mån', 'tis', 'ons', 'tor', 'fre', 'lör' ],
8
+ today: 'Idag',
9
+ clear: 'Rensa',
10
+ close: 'Stäng',
11
+ firstDay: 1,
12
+ format: 'yyyy-mm-dd',
13
+ formatSubmit: 'yyyy/mm/dd',
14
+ labelMonthNext: 'Nästa månad',
15
+ labelMonthPrev: 'Föregående månad',
16
+ labelMonthSelect: 'Välj månad',
17
+ labelYearSelect: 'Välj år'
18
+ });
19
+
20
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
21
+ clear: 'Rensa'
22
+ });
js/pickadate/translations/th_TH.js CHANGED
@@ -1,10 +1,16 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม"],
3
- monthsShort: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."],
4
- weekdaysFull: ["อาทติย", "จันทร", "องัคาร", "พุธ", "พฤหสั บดี", "ศกุร", "เสาร"],
5
- weekdaysShort: ["อ.", "จ.", "อ.", "พ.", "พฤ.", "ศ.", "ส."],
6
- today: "วันนี้",
7
- clear: "ลบ",
8
- format: "d mmmm yyyy",
9
- formatSubmit: "yyyy/mm/dd"
10
- });
 
 
 
 
 
 
1
+ // Thai
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม' ],
5
+ monthsShort: [ 'ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.' ],
6
+ weekdaysFull: [ 'อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัสบดี', 'ศุกร์', 'เสาร์' ],
7
+ weekdaysShort: [ 'อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.' ],
8
+ today: 'วันนี้',
9
+ clear: 'ลบ',
10
+ format: 'd mmmm yyyy',
11
+ formatSubmit: 'yyyy/mm/dd'
12
+ });
13
+
14
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
15
+ clear: 'ลบ'
16
+ });
js/pickadate/translations/tr_TR.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"],
3
- monthsShort: ["Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara"],
4
- weekdaysFull: ["Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi"],
5
- weekdaysShort: ["Pzr", "Pzt", "Sal", "Çrş", "Prş", "Cum", "Cmt"],
6
- today: "bugün",
7
- clear: "sil",
8
- firstDay: 1,
9
- format: "dd mmmm yyyy dddd",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Turkish
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık' ],
5
+ monthsShort: [ 'Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara' ],
6
+ weekdaysFull: [ 'Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi' ],
7
+ weekdaysShort: [ 'Pzr', 'Pzt', 'Sal', 'Çrş', 'Prş', 'Cum', 'Cmt' ],
8
+ today: 'Bugün',
9
+ clear: 'Sil',
10
+ close: 'Kapat',
11
+ firstDay: 1,
12
+ format: 'dd mmmm yyyy dddd',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'sil'
18
+ });
js/pickadate/translations/uk_UA.js CHANGED
@@ -1,11 +1,17 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["січень", "лютий", "березень", "квітень", "травень", "червень", "липень", "серпень", "вересень", "жовтень", "листопад", "грудень"],
3
- monthsShort: ["січ", "лют", "бер", "кві", "тра", "чер", "лип", "сер", "вер", "жов", "лис", "гру"],
4
- weekdaysFull: ["неділя", "понеділок", "вівторок", "середа", "четвер", "п‘ятниця", "субота"],
5
- weekdaysShort: ["нд", "пн", "вт", "ср", "чт", "пт", "сб"],
6
- today: "сьогодні",
7
- clear: "викреслити",
8
- firstDay: 1,
9
- format: "dd mmmm yyyy p.",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
1
+ // Ukrainian
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'січень', 'лютий', 'березень', 'квітень', 'травень', 'червень', 'липень', 'серпень', 'вересень', 'жовтень', 'листопад', 'грудень' ],
5
+ monthsShort: [ 'січ', 'лют', 'бер', 'кві', 'тра', 'чер', 'лип', 'сер', 'вер', 'жов', 'лис', 'гру' ],
6
+ weekdaysFull: [ 'неділя', 'понеділок', 'вівторок', 'середа', 'четвер', 'п‘ятниця', 'субота' ],
7
+ weekdaysShort: [ 'нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб' ],
8
+ today: 'сьогодні',
9
+ clear: 'викреслити',
10
+ firstDay: 1,
11
+ format: 'dd mmmm yyyy p.',
12
+ formatSubmit: 'yyyy/mm/dd'
13
+ });
14
+
15
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
16
+ clear: 'викреслити'
17
+ });
js/pickadate/translations/vi_VN.js ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Vietnamese
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ 'Tháng Một', 'Tháng Hai', 'Tháng Ba', 'Tháng Tư', 'Tháng Năm', 'Tháng Sáu', 'Tháng Bảy', 'Tháng Tám', 'Tháng Chín', 'Tháng Mười', 'Tháng Mười Một', 'Tháng Mười Hai' ],
5
+ monthsShort: [ 'Một', 'Hai', 'Ba', 'Tư', 'Năm', 'Sáu', 'Bảy', 'Tám', 'Chín', 'Mười', 'Mười Một', 'Mười Hai' ],
6
+ weekdaysFull: [ 'Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư', 'Thứ Năm', 'Thứ Sáu', 'Thứ Bảy' ],
7
+ weekdaysShort: [ 'C.Nhật', 'T.Hai', 'T.Ba', 'T.Tư', 'T.Năm', 'T.Sáu', 'T.Bảy' ],
8
+ today: 'Hôm Nay',
9
+ clear: 'Xoá',
10
+ close: 'Đóng',
11
+ firstDay: 1,
12
+ format: 'Bạn chọn: dddd, dd mmmm, yyyy',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: 'Xoá'
18
+ });
js/pickadate/translations/zh_CN.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
3
- monthsShort: ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"],
4
- weekdaysFull: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
5
- weekdaysShort: ["日", "", "", "", "", "", ""],
6
- today: "今日",
7
- clear: "删",
8
- firstDay: 1,
9
- format: "yyyy 年 mm 月 dd 日",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Simplified Chinese
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月' ],
5
+ monthsShort: [ '', '', '', '', '', '', '七', '八', '九', '十', '十一', '十二' ],
6
+ weekdaysFull: [ '星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六' ],
7
+ weekdaysShort: [ '日', '一', '二', '三', '四', '五', '六' ],
8
+ today: '今天',
9
+ clear: '清除',
10
+ close: '关闭',
11
+ firstDay: 1,
12
+ format: 'yyyy 年 mm 月 dd 日',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: '清除'
18
+ });
js/pickadate/translations/zh_TW.js CHANGED
@@ -1,11 +1,18 @@
1
- jQuery.extend(jQuery.fn.pickadate.defaults, {
2
- monthsFull: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
3
- monthsShort: ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"],
4
- weekdaysFull: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
5
- weekdaysShort: ["日", "", "", "", "", "", ""],
6
- today: "今天",
7
- clear: "清除",
8
- firstDay: 1,
9
- format: "yyyy 年 mm 月 dd 日",
10
- formatSubmit: "yyyy/mm/dd"
11
- });
 
 
 
 
 
 
 
1
+ // Traditional Chinese
2
+
3
+ jQuery.extend( jQuery.fn.pickadate.defaults, {
4
+ monthsFull: [ '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月' ],
5
+ monthsShort: [ '', '', '', '', '', '', '七', '八', '九', '十', '十一', '十二' ],
6
+ weekdaysFull: [ '星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六' ],
7
+ weekdaysShort: [ '日', '一', '二', '三', '四', '五', '六' ],
8
+ today: '今天',
9
+ clear: '清除',
10
+ close: '關閉',
11
+ firstDay: 1,
12
+ format: 'yyyy 年 mm 月 dd 日',
13
+ formatSubmit: 'yyyy/mm/dd'
14
+ });
15
+
16
+ jQuery.extend( jQuery.fn.pickatime.defaults, {
17
+ clear: '清除'
18
+ });
my-calendar-api.php CHANGED
@@ -17,14 +17,15 @@ if ( ! defined( 'ABSPATH' ) ) {
17
  * Main API function
18
  */
19
  function my_calendar_api() {
20
- if ( isset( $_REQUEST['my-calendar-api'] ) ) {
21
  if ( 'true' === get_option( 'mc_api_enabled' ) ) {
22
  // use this filter to add custom scripting handling API keys.
23
  $api_key = apply_filters( 'mc_api_key', true );
24
  if ( $api_key ) {
25
  $format = ( isset( $_REQUEST['my-calendar-api'] ) ) ? $_REQUEST['my-calendar-api'] : 'json';
26
- $from = ( isset( $_REQUEST['from'] ) ) ? $_REQUEST['from'] : date( 'Y-m-d', current_time( 'timestamp' ) );
27
- $to = ( isset( $_REQUEST['to'] ) ) ? $_REQUEST['to'] : date( 'Y-m-d', strtotime( apply_filters( 'mc_api_auto_date', '+ 7 days' ) ) );
 
28
  // sanitization is handled elsewhere.
29
  $category = ( isset( $_REQUEST['mcat'] ) ) ? $_REQUEST['mcat'] : '';
30
  $ltype = ( isset( $_REQUEST['ltype'] ) ) ? $_REQUEST['ltype'] : '';
@@ -294,7 +295,7 @@ function mc_format_rss( $events ) {
294
  <language>' . get_bloginfo( 'language' ) . '</language>
295
  <managingEditor>' . get_bloginfo( 'admin_email' ) . ' (' . get_bloginfo( 'name' ) . ' Admin)</managingEditor>
296
  <generator>My Calendar WordPress Plugin http://www.joedolson.com/my-calendar/</generator>
297
- <lastBuildDate>' . mysql2date( 'D, d M Y H:i:s +0000', current_time( 'timestamp' ) ) . '</lastBuildDate>
298
  <atom:link href="' . htmlentities( esc_url( add_query_arg( $_GET, get_feed_link( 'my-calendar-rss' ) ) ) ) . '" rel="self" type="application/rss+xml" />' . PHP_EOL;
299
  foreach ( $events as $date ) {
300
  foreach ( array_keys( $date ) as $key ) {
@@ -378,8 +379,8 @@ function mc_ics_subscribe_outlook() {
378
  */
379
  function my_calendar_ical() {
380
  $p = ( isset( $_GET['span'] ) ) ? 'year' : false;
381
- $y = ( isset( $_GET['yr'] ) ) ? $_GET['yr'] : date( 'Y' );
382
- $m = ( isset( $_GET['month'] ) ) ? $_GET['month'] : date( 'n' );
383
  $ny = ( isset( $_GET['nyr'] ) ) ? $_GET['nyr'] : $y;
384
  $nm = ( isset( $_GET['nmonth'] ) ) ? $_GET['nmonth'] : $m;
385
  $cat = ( isset( $_GET['mcat'] ) ) ? intval( $_GET['mcat'] ) : '';
@@ -388,7 +389,7 @@ function my_calendar_ical() {
388
  $from = "$y-1-1";
389
  $to = "$y-12-31";
390
  } else {
391
- $d = date( 't', mktime( 0, 0, 0, $m, 1, $y ) );
392
  $from = "$y-$m-1";
393
  $to = "$ny-$nm-$d";
394
  }
17
  * Main API function
18
  */
19
  function my_calendar_api() {
20
+ if ( isset( $_REQUEST['my-calendar-api'] ) || isset( $_REQUEST['mc-api'] ) ) {
21
  if ( 'true' === get_option( 'mc_api_enabled' ) ) {
22
  // use this filter to add custom scripting handling API keys.
23
  $api_key = apply_filters( 'mc_api_key', true );
24
  if ( $api_key ) {
25
  $format = ( isset( $_REQUEST['my-calendar-api'] ) ) ? $_REQUEST['my-calendar-api'] : 'json';
26
+ $format = ( isset( $_REQUEST['mc-api'] ) ) ? $_REQUEST['mc-api'] : $format;
27
+ $from = ( isset( $_REQUEST['from'] ) ) ? $_REQUEST['from'] : current_time( 'Y-m-d' );
28
+ $to = ( isset( $_REQUEST['to'] ) ) ? $_REQUEST['to'] : mc_date( 'Y-m-d', strtotime( apply_filters( 'mc_api_auto_date', '+ 7 days' ) ) );
29
  // sanitization is handled elsewhere.
30
  $category = ( isset( $_REQUEST['mcat'] ) ) ? $_REQUEST['mcat'] : '';
31
  $ltype = ( isset( $_REQUEST['ltype'] ) ) ? $_REQUEST['ltype'] : '';
295
  <language>' . get_bloginfo( 'language' ) . '</language>
296
  <managingEditor>' . get_bloginfo( 'admin_email' ) . ' (' . get_bloginfo( 'name' ) . ' Admin)</managingEditor>
297
  <generator>My Calendar WordPress Plugin http://www.joedolson.com/my-calendar/</generator>
298
+ <lastBuildDate>' . mysql2date( 'D, d M Y H:i:s +0000', time() ) . '</lastBuildDate>
299
  <atom:link href="' . htmlentities( esc_url( add_query_arg( $_GET, get_feed_link( 'my-calendar-rss' ) ) ) ) . '" rel="self" type="application/rss+xml" />' . PHP_EOL;
300
  foreach ( $events as $date ) {
301
  foreach ( array_keys( $date ) as $key ) {
379
  */
380
  function my_calendar_ical() {
381
  $p = ( isset( $_GET['span'] ) ) ? 'year' : false;
382
+ $y = ( isset( $_GET['yr'] ) ) ? $_GET['yr'] : mc_date( 'Y' );
383
+ $m = ( isset( $_GET['month'] ) ) ? $_GET['month'] : mc_date( 'n' );
384
  $ny = ( isset( $_GET['nyr'] ) ) ? $_GET['nyr'] : $y;
385
  $nm = ( isset( $_GET['nmonth'] ) ) ? $_GET['nmonth'] : $m;
386
  $cat = ( isset( $_GET['mcat'] ) ) ? intval( $_GET['mcat'] ) : '';
389
  $from = "$y-1-1";
390
  $to = "$y-12-31";
391
  } else {
392
+ $d = mc_date( 't', mktime( 0, 0, 0, $m, 1, $y ), false );
393
  $from = "$y-$m-1";
394
  $to = "$ny-$nm-$d";
395
  }
my-calendar-categories.php CHANGED
@@ -44,13 +44,13 @@ function mc_directory_list( $directory ) {
44
  $results = array();
45
  $handler = opendir( $directory );
46
  // keep going until all files in directory have been read.
47
- while ( $file = readdir( $handler ) ) {
48
  // if $file isn't this directory or its parent add it to the results array.
49
  if ( filesize( $directory . '/' . $file ) > 11 ) {
50
- if ( '.' != $file && '..' != $file && ! is_dir( $directory . '/' . $file ) && (
51
- exif_imagetype( $directory . '/' . $file ) == IMAGETYPE_GIF ||
52
- exif_imagetype( $directory . '/' . $file ) == IMAGETYPE_PNG ||
53
- exif_imagetype( $directory . '/' . $file ) == IMAGETYPE_JPEG )
54
  ) {
55
  $results[] = $file;
56
  }
@@ -72,7 +72,7 @@ function mc_private_categories() {
72
  if ( ! is_user_logged_in() ) {
73
  $categories = mc_get_private_categories();
74
  $cats = implode( ',', $categories );
75
- if ( '' != $cats ) {
76
  $cats = " AND c.category_id NOT IN ($cats)";
77
  }
78
  }
@@ -174,7 +174,7 @@ function my_calendar_manage_categories() {
174
  } else {
175
  $cal_results = false;
176
  }
177
- if ( get_option( 'mc_default_category' ) == $cat_id ) {
178
  update_option( 'mc_default_category', 1 );
179
  }
180
  if ( $results && ( $cal_results || $rel_results ) ) {
@@ -193,7 +193,7 @@ function my_calendar_manage_categories() {
193
  update_option( 'mc_default_category', (int) $_POST['category_id'] );
194
  $append .= __( 'Default category changed.', 'my-calendar' );
195
  } else {
196
- if ( get_option( 'mc_default_category' ) == (int) $_POST['category_id'] ) {
197
  delete_option( 'mc_default_category' );
198
  }
199
  }
@@ -201,7 +201,7 @@ function my_calendar_manage_categories() {
201
  update_option( 'mc_skip_holidays_category', (int) $_POST['category_id'] );
202
  $append .= __( 'Holiday category changed.', 'my-calendar' );
203
  } else {
204
- if ( get_option( 'mc_skip_holidays_category' ) == (int) $_POST['category_id'] ) {
205
  delete_option( 'mc_skip_holidays_category' );
206
  }
207
  }
@@ -222,7 +222,7 @@ function my_calendar_manage_categories() {
222
  mc_edit_category_form( 'edit', $cur_cat );
223
  }
224
 
225
- if ( isset( $_GET['mode'] ) && 'edit' != $_GET['mode'] || isset( $_POST['mode'] ) && 'edit' != $_POST['mode'] || ! isset( $_GET['mode'] ) && ! isset( $_POST['mode'] ) ) {
226
  mc_edit_category_form( 'add' );
227
  }
228
  ?>
@@ -291,7 +291,7 @@ function mc_create_category( $category ) {
291
  'category_name' => $category['category_name'],
292
  'category_color' => $category['category_color'],
293
  'category_icon' => $category['category_icon'],
294
- 'category_private' => ( ( isset( $category['category_private'] ) && ( 'on' === $category['category_private'] || 1 == $category['category_private'] ) ) ? 1 : 0 ),
295
  'category_term' => $term,
296
  );
297
 
@@ -315,9 +315,12 @@ function mc_edit_category_form( $view = 'edit', $cat_id = '' ) {
315
  $dir = plugin_dir_path( __FILE__ );
316
  $url = plugin_dir_url( __FILE__ );
317
  $cur_cat = false;
318
- if ( '' != $cat_id ) {
319
  $cat_id = (int) $cat_id;
320
  $cur_cat = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM ' . my_calendar_categories_table() . ' WHERE category_id=%d', $cat_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
 
 
 
321
  }
322
  if ( mc_is_custom_icon() ) {
323
  $directory = str_replace( '/my-calendar', '', $dir ) . '/my-calendar-custom/';
@@ -384,7 +387,7 @@ function mc_edit_category_form( $view = 'edit', $cat_id = '' ) {
384
  <label for="cat_name"><?php _e( 'Category Name', 'my-calendar' ); ?></label>
385
  <input type="text" id="cat_name" name="category_name" class="input" size="30" value="<?php echo esc_attr( $cat_name ); ?>"/>
386
  <label for="cat_color"><?php _e( 'Color', 'my-calendar' ); ?></label>
387
- <input type="text" id="cat_color" name="category_color" class="mc-color-input" size="10" maxlength="7" value="<?php echo ( '#' != $color ) ? esc_attr( $color ) : ''; ?>"/>
388
  </li>
389
  <?php
390
  if ( 'true' === get_option( 'mc_hide_icons' ) ) {
@@ -397,7 +400,7 @@ function mc_edit_category_form( $view = 'edit', $cat_id = '' ) {
397
  <option value=''><?php _e( 'None', 'my-calendar' ); ?></option>
398
  <?php
399
  foreach ( $iconlist as $value ) {
400
- $selected = ( ( ! empty( $cur_cat ) && is_object( $cur_cat ) ) && $cur_cat->category_icon == $value ) ? ' selected="selected"' : '';
401
  echo "<option value='" . esc_attr( $value ) . "'$selected style='background: url(" . esc_url( str_replace( 'my-calendar/', '', $url ) . "$path/$value" ) . ") left 50% no-repeat;'>$value</option>";
402
  }
403
  ?>
@@ -411,7 +414,7 @@ function mc_edit_category_form( $view = 'edit', $cat_id = '' ) {
411
  if ( 'add' === $view ) {
412
  $private_checked = '';
413
  } else {
414
- if ( ! empty( $cur_cat ) && is_object( $cur_cat ) && 1 == $cur_cat->category_private ) {
415
  $private_checked = ' checked="checked"';
416
  } else {
417
  $private_checked = '';
@@ -552,11 +555,11 @@ function mc_get_category_detail( $cat_id, $field = 'category_name' ) {
552
  $category = $mcdb->get_row( $mcdb->prepare( 'SELECT * FROM ' . my_calendar_categories_table() . ' WHERE category_id=%d', $cat_id ) );
553
 
554
  if ( $category ) {
555
- if ( false == $field ) {
556
  return $category;
557
  }
558
 
559
- return $category->$field;
560
  }
561
  }
562
 
@@ -596,7 +599,7 @@ function mc_manage_categories() {
596
  ?>
597
  </h1>
598
  <?php
599
- $co = ( ! isset( $_GET['co'] ) ) ? 1 : (int) $_GET['co'];
600
  switch ( $co ) {
601
  case 1:
602
  $cat_order = 'category_id';
@@ -616,16 +619,16 @@ function mc_manage_categories() {
616
  <tr>
617
  <th scope="col">
618
  <?php
619
- echo ( 2 == $co ) ? '<a href="' . admin_url( 'admin.php?page=my-calendar-categories&amp;co=1' ) . '">' : '';
620
  _e( 'ID', 'my-calendar' );
621
- echo ( 2 == $co ) ? '</a>' : '';
622
  ?>
623
  </th>
624
  <th scope="col">
625
  <?php
626
- echo ( 1 == $co ) ? '<a href="' . admin_url( 'admin.php?page=my-calendar-categories&amp;co=2' ) . '">' : '';
627
  _e( 'Category Name', 'my-calendar' );
628
- echo ( 1 == $co ) ? '</a>' : '';
629
  ?>
630
  </th>
631
  <th scope="col"><?php _e( 'Color/Icon', 'my-calendar' ); ?></th>
@@ -638,7 +641,7 @@ function mc_manage_categories() {
638
  $class = '';
639
  foreach ( $categories as $cat ) {
640
  $class = ( 'alternate' === $class ) ? '' : 'alternate';
641
- if ( '' != $cat->category_icon && 'true' != get_option( 'mc_hide_icons' ) ) {
642
  $icon_src = ( mc_file_exists( $cat->category_icon ) ) ? mc_get_file( $cat->category_icon, 'url' ) : plugins_url( 'my-calendar/images/icons/' . $cat->category_icon );
643
  } else {
644
  $icon_src = false;
@@ -652,16 +655,16 @@ function mc_manage_categories() {
652
  <td>
653
  <?php
654
  echo $cat_name;
655
- if ( get_option( 'mc_default_category' ) == $cat->category_id ) {
656
  echo ' <strong>' . __( '(Default)' ) . '</strong>';
657
  }
658
- if ( get_option( 'mc_skip_holidays_category' ) == $cat->category_id ) {
659
  echo ' <strong>' . __( '(Holiday)' ) . '</strong>';
660
  }
661
  ?>
662
  </td>
663
- <td style="background-color:<?php echo $background; ?>;color: <?php echo $foreground; ?>"><?php echo ( $icon_src ) ? "<img src='$icon_src' alt='' />" : ''; ?> <?php echo ( '#' != $background ) ? $background : ''; ?></td>
664
- <td><?php echo ( 1 == $cat->category_private ) ? __( 'Yes', 'my-calendar' ) : __( 'No', 'my-calendar' ); ?></td>
665
  <td>
666
  <a href="<?php echo admin_url( "admin.php?page=my-calendar-categories&amp;mode=edit&amp;category_id=$cat->category_id" ); ?>"
667
  class='edit'>
@@ -672,7 +675,7 @@ function mc_manage_categories() {
672
  </a>
673
  </td>
674
  <?php
675
- if ( 1 == $cat->category_id ) {
676
  echo '<td>' . __( 'N/A', 'my-calendar' ) . '</td>';
677
  } else {
678
  ?>
@@ -711,7 +714,7 @@ function mc_profile() {
711
 
712
  if ( user_can( $user_edit, 'mc_manage_events' ) && current_user_can( 'manage_options' ) ) {
713
  $permissions = get_user_meta( $user_edit, 'mc_user_permissions', true );
714
- $selected = ( empty( $permissions ) || in_array( 'all', $permissions ) || user_can( $user_edit, 'manage_options' ) ) ? ' checked="checked"' : '';
715
  ?>
716
  <h3><?php _e( 'My Calendar Editor Permissions', 'my-calendar' ); ?></h3>
717
  <table class="form-table">
@@ -796,7 +799,7 @@ function mc_category_select( $data = false, $option = true, $multiple = false, $
796
  foreach ( $cats as $cat ) {
797
  $selected = '';
798
  // if category is private, don't show if user is not logged in.
799
- if ( '1' == $cat->category_private && ! is_user_logged_in() ) {
800
  continue;
801
  }
802
  if ( ! empty( $data ) ) {
@@ -812,18 +815,18 @@ function mc_category_select( $data = false, $option = true, $multiple = false, $
812
  }
813
  }
814
  if ( $multiple ) {
815
- if ( is_array( $category ) && in_array( $cat->category_id, $category ) ) {
816
  $selected = ' checked="checked"';
817
- } else if ( $category == $cat->category_id ) {
818
  $selected = ' checked="checked"';
819
  }
820
  } else {
821
- if ( $category == $cat->category_id ) {
822
  $selected = ' selected="selected"';
823
  }
824
  }
825
  } else {
826
- if ( get_option( 'mc_default_category' ) == $cat->category_id ) {
827
  $selected = ' checked="checked"';
828
  }
829
  }
@@ -834,7 +837,7 @@ function mc_category_select( $data = false, $option = true, $multiple = false, $
834
  } else {
835
  $c = '<option value="' . $cat->category_id . '" ' . $selected . '>' . $category_name . '</option>';
836
  }
837
- if ( get_option( 'mc_default_category' ) != $cat->category_id ) {
838
  $list .= $c;
839
  } else {
840
  $default = $c;
44
  $results = array();
45
  $handler = opendir( $directory );
46
  // keep going until all files in directory have been read.
47
+ while ( false !== ( $file = readdir( $handler ) ) ) { // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
48
  // if $file isn't this directory or its parent add it to the results array.
49
  if ( filesize( $directory . '/' . $file ) > 11 ) {
50
+ if ( '.' !== $file && '..' !== $file && ! is_dir( $directory . '/' . $file ) && (
51
+ exif_imagetype( $directory . '/' . $file ) === IMAGETYPE_GIF ||
52
+ exif_imagetype( $directory . '/' . $file ) === IMAGETYPE_PNG ||
53
+ exif_imagetype( $directory . '/' . $file ) === IMAGETYPE_JPEG )
54
  ) {
55
  $results[] = $file;
56
  }
72
  if ( ! is_user_logged_in() ) {
73
  $categories = mc_get_private_categories();
74
  $cats = implode( ',', $categories );
75
+ if ( '' !== $cats ) {
76
  $cats = " AND c.category_id NOT IN ($cats)";
77
  }
78
  }
174
  } else {
175
  $cal_results = false;
176
  }
177
+ if ( get_option( 'mc_default_category' ) === (string) $cat_id ) {
178
  update_option( 'mc_default_category', 1 );
179
  }
180
  if ( $results && ( $cal_results || $rel_results ) ) {
193
  update_option( 'mc_default_category', (int) $_POST['category_id'] );
194
  $append .= __( 'Default category changed.', 'my-calendar' );
195
  } else {
196
+ if ( get_option( 'mc_default_category' ) === (string) $_POST['category_id'] ) {
197
  delete_option( 'mc_default_category' );
198
  }
199
  }
201
  update_option( 'mc_skip_holidays_category', (int) $_POST['category_id'] );
202
  $append .= __( 'Holiday category changed.', 'my-calendar' );
203
  } else {
204
+ if ( get_option( 'mc_skip_holidays_category' ) === (string) $_POST['category_id'] ) {
205
  delete_option( 'mc_skip_holidays_category' );
206
  }
207
  }
222
  mc_edit_category_form( 'edit', $cur_cat );
223
  }
224
 
225
+ if ( isset( $_GET['mode'] ) && 'edit' !== $_GET['mode'] || isset( $_POST['mode'] ) && 'edit' !== $_POST['mode'] || ! isset( $_GET['mode'] ) && ! isset( $_POST['mode'] ) ) {
226
  mc_edit_category_form( 'add' );
227
  }
228
  ?>
291
  'category_name' => $category['category_name'],
292
  'category_color' => $category['category_color'],
293
  'category_icon' => $category['category_icon'],
294
+ 'category_private' => ( ( isset( $category['category_private'] ) && ( 'on' === $category['category_private'] || '1' === (string) $category['category_private'] ) ) ? 1 : 0 ),
295
  'category_term' => $term,
296
  );
297
 
315
  $dir = plugin_dir_path( __FILE__ );
316
  $url = plugin_dir_url( __FILE__ );
317
  $cur_cat = false;
318
+ if ( $cat_id ) {
319
  $cat_id = (int) $cat_id;
320
  $cur_cat = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM ' . my_calendar_categories_table() . ' WHERE category_id=%d', $cat_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
321
+ } else {
322
+ // If no category ID, change view.
323
+ $view = 'add';
324
  }
325
  if ( mc_is_custom_icon() ) {
326
  $directory = str_replace( '/my-calendar', '', $dir ) . '/my-calendar-custom/';
387
  <label for="cat_name"><?php _e( 'Category Name', 'my-calendar' ); ?></label>
388
  <input type="text" id="cat_name" name="category_name" class="input" size="30" value="<?php echo esc_attr( $cat_name ); ?>"/>
389
  <label for="cat_color"><?php _e( 'Color', 'my-calendar' ); ?></label>
390
+ <input type="text" id="cat_color" name="category_color" class="mc-color-input" size="10" maxlength="7" value="<?php echo ( '#' !== $color ) ? esc_attr( $color ) : ''; ?>"/>
391
  </li>
392
  <?php
393
  if ( 'true' === get_option( 'mc_hide_icons' ) ) {
400
  <option value=''><?php _e( 'None', 'my-calendar' ); ?></option>
401
  <?php
402
  foreach ( $iconlist as $value ) {
403
+ $selected = ( ( ! empty( $cur_cat ) && is_object( $cur_cat ) ) && $cur_cat->category_icon === $value ) ? ' selected="selected"' : '';
404
  echo "<option value='" . esc_attr( $value ) . "'$selected style='background: url(" . esc_url( str_replace( 'my-calendar/', '', $url ) . "$path/$value" ) . ") left 50% no-repeat;'>$value</option>";
405
  }
406
  ?>
414
  if ( 'add' === $view ) {
415
  $private_checked = '';
416
  } else {
417
+ if ( ! empty( $cur_cat ) && is_object( $cur_cat ) && '1' === (string) $cur_cat->category_private ) {
418
  $private_checked = ' checked="checked"';
419
  } else {
420
  $private_checked = '';
555
  $category = $mcdb->get_row( $mcdb->prepare( 'SELECT * FROM ' . my_calendar_categories_table() . ' WHERE category_id=%d', $cat_id ) );
556
 
557
  if ( $category ) {
558
+ if ( ! $field ) {
559
  return $category;
560
  }
561
 
562
+ return (string) $category->$field;
563
  }
564
  }
565
 
599
  ?>
600
  </h1>
601
  <?php
602
+ $co = ( ! isset( $_GET['co'] ) ) ? '1' : (int) $_GET['co'];
603
  switch ( $co ) {
604
  case 1:
605
  $cat_order = 'category_id';
619
  <tr>
620
  <th scope="col">
621
  <?php
622
+ echo ( '2' === $co ) ? '<a href="' . admin_url( 'admin.php?page=my-calendar-categories&amp;co=1' ) . '">' : '';
623
  _e( 'ID', 'my-calendar' );
624
+ echo ( '2' === $co ) ? '</a>' : '';
625
  ?>
626
  </th>
627
  <th scope="col">
628
  <?php
629
+ echo ( '1' === $co ) ? '<a href="' . admin_url( 'admin.php?page=my-calendar-categories&amp;co=2' ) . '">' : '';
630
  _e( 'Category Name', 'my-calendar' );
631
+ echo ( '1' === $co ) ? '</a>' : '';
632
  ?>
633
  </th>
634
  <th scope="col"><?php _e( 'Color/Icon', 'my-calendar' ); ?></th>
641
  $class = '';
642
  foreach ( $categories as $cat ) {
643
  $class = ( 'alternate' === $class ) ? '' : 'alternate';
644
+ if ( ! $cat->category_icon && 'true' !== get_option( 'mc_hide_icons' ) ) {
645
  $icon_src = ( mc_file_exists( $cat->category_icon ) ) ? mc_get_file( $cat->category_icon, 'url' ) : plugins_url( 'my-calendar/images/icons/' . $cat->category_icon );
646
  } else {
647
  $icon_src = false;
655
  <td>
656
  <?php
657
  echo $cat_name;
658
+ if ( get_option( 'mc_default_category' ) === (string) $cat->category_id ) {
659
  echo ' <strong>' . __( '(Default)' ) . '</strong>';
660
  }
661
+ if ( get_option( 'mc_skip_holidays_category' ) === (string) $cat->category_id ) {
662
  echo ' <strong>' . __( '(Holiday)' ) . '</strong>';
663
  }
664
  ?>
665
  </td>
666
+ <td style="background-color:<?php echo $background; ?>;color: <?php echo $foreground; ?>"><?php echo ( $icon_src ) ? "<img src='$icon_src' alt='' />" : ''; ?> <?php echo ( '#' !== $background ) ? $background : ''; ?></td>
667
+ <td><?php echo ( '1' === (string) $cat->category_private ) ? __( 'Yes', 'my-calendar' ) : __( 'No', 'my-calendar' ); ?></td>
668
  <td>
669
  <a href="<?php echo admin_url( "admin.php?page=my-calendar-categories&amp;mode=edit&amp;category_id=$cat->category_id" ); ?>"
670
  class='edit'>
675
  </a>
676
  </td>
677
  <?php
678
+ if ( '1' === (string) $cat->category_id ) {
679
  echo '<td>' . __( 'N/A', 'my-calendar' ) . '</td>';
680
  } else {
681
  ?>
714
 
715
  if ( user_can( $user_edit, 'mc_manage_events' ) && current_user_can( 'manage_options' ) ) {
716
  $permissions = get_user_meta( $user_edit, 'mc_user_permissions', true );
717
+ $selected = ( empty( $permissions ) || in_array( 'all', $permissions, true ) || user_can( $user_edit, 'manage_options' ) ) ? ' checked="checked"' : '';
718
  ?>
719
  <h3><?php _e( 'My Calendar Editor Permissions', 'my-calendar' ); ?></h3>
720
  <table class="form-table">
799
  foreach ( $cats as $cat ) {
800
  $selected = '';
801
  // if category is private, don't show if user is not logged in.
802
+ if ( '1' === (string) $cat->category_private && ! is_user_logged_in() ) {
803
  continue;
804
  }
805
  if ( ! empty( $data ) ) {
815
  }
816
  }
817
  if ( $multiple ) {
818
+ if ( is_array( $category ) && in_array( $cat->category_id, $category, true ) ) {
819
  $selected = ' checked="checked"';
820
+ } elseif ( (int) $category === (int) $cat->category_id ) {
821
  $selected = ' checked="checked"';
822
  }
823
  } else {
824
+ if ( (int) $category === (int) $cat->category_id ) {
825
  $selected = ' selected="selected"';
826
  }
827
  }
828
  } else {
829
+ if ( get_option( 'mc_default_category' ) === (string) $cat->category_id ) {
830
  $selected = ' checked="checked"';
831
  }
832
  }
837
  } else {
838
  $c = '<option value="' . $cat->category_id . '" ' . $selected . '>' . $category_name . '</option>';
839
  }
840
+ if ( get_option( 'mc_default_category' ) !== (string) $cat->category_id ) {
841
  $list .= $c;
842
  } else {
843
  $default = $c;
my-calendar-core.php CHANGED
@@ -16,7 +16,7 @@ if ( ! defined( 'ABSPATH' ) ) {
16
  /**
17
  * Add feeds to WordPress feed handler.
18
  */
19
- function my_calendar_add_feed() {
20
  add_feed( 'my-calendar-rss', 'my_calendar_rss' );
21
  add_feed( 'my-calendar-ics', 'my_calendar_ical' );
22
  add_feed( 'my-calendar-google', 'mc_ics_subscribe_google' );
@@ -153,8 +153,8 @@ function mc_register_styles() {
153
  $js_array = ( '' !== trim( get_option( 'mc_show_js', '' ) ) ) ? explode( ',', get_option( 'mc_show_js' ) ) : array();
154
  $css_array = ( '' !== trim( get_option( 'mc_show_css', '' ) ) ) ? explode( ',', get_option( 'mc_show_css' ) ) : array();
155
  $use_default = ( $default && ! $id ) ? true : false;
156
- $js_usage = ( ( empty( $js_array ) ) || ( $id && in_array( $id, $js_array ) ) ) ? true : false;
157
- $css_usage = ( ( empty( $css_array ) ) || ( $id && in_array( $id, $css_array ) ) ) ? true : false;
158
 
159
  // check whether any scripts are actually enabled.
160
  if ( get_option( 'mc_calendar_javascript' ) !== '1' || get_option( 'mc_list_javascript' ) !== '1' || get_option( 'mc_mini_javascript' ) !== '1' || get_option( 'mc_ajax_javascript' ) !== '1' ) {
@@ -192,47 +192,20 @@ function mc_register_styles() {
192
  /**
193
  * Publically written head styles & scripts
194
  */
195
- function my_calendar_head() {
196
- global $wpdb, $wp_query;
197
- $mcdb = $wpdb;
198
- if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
199
- $mcdb = mc_remote_db();
200
- }
201
  $array = array();
202
 
203
  if ( get_option( 'mc_use_styles' ) !== 'true' ) {
204
- $this_post = $wp_query->get_queried_object();
205
- $id = (string) ( is_object( $this_post ) && isset( $this_post->ID ) ) ? $this_post->ID : false;
206
- $array = ( '' !== get_option( 'mc_show_css', '' ) ) ? explode( ',', get_option( 'mc_show_css' ) ) : $array;
 
207
  if ( ( is_array( $array ) && ! empty( $array ) ) || in_array( $id, $array, true ) || get_option( 'mc_show_css', '' ) === '' ) {
208
  // generate category colors.
209
- $category_styles = '';
210
- $inv = '';
211
- $type = '';
212
- $alt = '';
213
- $categories = $mcdb->get_results( 'SELECT * FROM ' . my_calendar_categories_table( get_current_blog_id() ) . ' ORDER BY category_id ASC' );
214
- foreach ( $categories as $category ) {
215
- $class = mc_category_class( $category, 'mc_' );
216
- $hex = ( strpos( $category->category_color, '#' ) !== 0 ) ? '#' : '';
217
- $color = $hex . $category->category_color;
218
- if ( '#' !== $color ) {
219
- $hcolor = mc_shift_color( $category->category_color );
220
- if ( 'font' === get_option( 'mc_apply_color' ) ) {
221
- $type = 'color';
222
- $alt = 'background';
223
- } elseif ( 'background' === get_option( 'mc_apply_color' ) ) {
224
- $type = 'background';
225
- $alt = 'color';
226
- }
227
- $inverse = mc_inverse_color( $color );
228
- $inv = "$alt: $inverse;";
229
- if ( 'font' === get_option( 'mc_apply_color' ) || 'background' === get_option( 'mc_apply_color' ) ) {
230
- // always an anchor as of 1.11.0, apply also to title.
231
- $category_styles .= "\n.mc-main .$class .event-title, .mc-main .$class .event-title a { $type: $color; $inv }";
232
- $category_styles .= "\n.mc-main .$class .event-title a:hover, .mc-main .$class .event-title a:focus { $type: $hcolor;}";
233
- }
234
- }
235
- }
236
 
237
  $styles = (array) get_option( 'mc_style_vars' );
238
  $style_vars = '';
@@ -242,17 +215,14 @@ function my_calendar_head() {
242
  }
243
  }
244
  if ( '' !== $style_vars ) {
245
- $style_vars = '.mc-main {' . $style_vars . '}';
246
  }
247
 
248
  $all_styles = "
249
  <style type=\"text/css\">
250
  <!--
251
- /* Styles by My Calendar - Joseph C Dolson http://www.joedolson.com/ */
252
  $category_styles
253
- .mc-event-visible {
254
- display: block!important;
255
- }
256
  $style_vars
257
  -->
258
  </style>";
@@ -261,6 +231,54 @@ $style_vars
261
  }
262
  }
263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  /**
265
  * Deal with events posted by a user when that user is deleted
266
  *
@@ -295,7 +313,7 @@ function mc_admin_body_class( $classes ) {
295
  /**
296
  * Write custom JS in admin head.
297
  */
298
- function my_calendar_write_js() {
299
  if ( isset( $_GET['page'] ) && ( 'my-calendar' === $_GET['page'] || 'my-calendar-locations' === $_GET['page'] ) ) {
300
  ?>
301
  <script>
@@ -448,16 +466,16 @@ function mc_footer_js() {
448
  /**
449
  * Add stylesheets to My Calendar admin screens
450
  */
451
- function my_calendar_add_styles() {
452
  global $current_screen;
453
  $id = $current_screen->id;
454
  if ( false !== strpos( $id, 'my-calendar' ) ) {
455
  wp_enqueue_style( 'mc-styles', plugins_url( 'css/mc-styles.css', __FILE__ ) );
456
 
457
  if ( 'toplevel_page_my-calendar' === $id ) {
458
- wp_enqueue_style( 'mc-pickadate-default', plugins_url( 'js/pickadate/themes/default.css', __FILE__ ) );
459
- wp_enqueue_style( 'mc-pickadate-date', plugins_url( 'js/pickadate/themes/default.date.css', __FILE__ ) );
460
- wp_enqueue_style( 'mc-pickadate-time', plugins_url( 'js/pickadate/themes/default.time.css', __FILE__ ) );
461
  }
462
  }
463
  }
@@ -656,7 +674,7 @@ function my_calendar_check() {
656
  } else {
657
  // For each release requiring an upgrade path, add a version compare.
658
  // Loop will run every relevant upgrade cycle.
659
- $valid_upgrades = array( '2.2.10', '2.3.0', '2.3.11', '2.3.15', '2.4.4', '3.0.0', '3.1.13' );
660
  foreach ( $valid_upgrades as $upgrade ) {
661
  if ( version_compare( $current_version, $upgrade, '<' ) ) {
662
  $upgrade_path[] = $upgrade;
@@ -758,41 +776,35 @@ function mc_do_upgrades( $upgrade_path ) {
758
  update_option( 'mc_input_options', $mc_input_options );
759
  mc_transition_db();
760
  break;
761
- case '2.2.10': // 10/29/13 (2.2.13).
762
- delete_option( 'mc_show_print' );
763
- delete_option( 'mc_show_ical' );
764
- delete_option( 'mc_show_rss' );
765
- delete_option( 'mc_draggable' );
766
- delete_option( 'mc_caching_enabled' ); // remove caching support via options. Filter only.
767
- break;
768
  default:
769
  break;
770
  }
771
  }
772
  }
773
 
774
- add_action( 'admin_bar_menu', 'my_calendar_admin_bar', 200 );
775
  /**
776
  * Set up adminbar links
777
  */
778
- function my_calendar_admin_bar() {
779
  global $wp_admin_bar;
780
- if ( current_user_can( 'mc_add_events' ) && 'true' !== get_option( 'mc_remote' ) ) {
781
- $url = apply_filters( 'mc_add_events_url', admin_url( 'admin.php?page=my-calendar' ) );
782
- $args = array(
783
- 'id' => 'mc-add-event',
784
- 'title' => __( 'Add Event', 'my-calendar' ),
785
- 'href' => $url,
786
- );
787
- $wp_admin_bar->add_node( $args );
788
- }
789
  if ( mc_get_uri( 'boolean' ) ) {
790
- $url = esc_url( apply_filters( 'mc_adminbar_uri', mc_get_uri() ) );
791
- $args = array(
792
- 'id' => 'mc-my-calendar',
793
- 'title' => __( 'View Calendar', 'my-calendar' ),
794
- 'href' => $url,
795
- );
 
 
 
 
 
 
 
 
 
796
  $wp_admin_bar->add_node( $args );
797
  } else {
798
  $url = admin_url( 'admin.php?page=my-calendar-config#my-calendar-manage' );
@@ -803,13 +815,25 @@ function my_calendar_admin_bar() {
803
  );
804
  $wp_admin_bar->add_node( $args );
805
  }
 
 
 
 
 
 
 
 
 
 
 
 
806
  if ( current_user_can( 'mc_manage_events' ) && current_user_can( 'mc_add_events' ) ) {
807
  $url = admin_url( 'admin.php?page=my-calendar-manage' );
808
  $args = array(
809
  'id' => 'mc-manage-events',
810
  'title' => __( 'Events', 'my-calendar' ),
811
  'href' => $url,
812
- 'parent' => 'mc-add-event',
813
  );
814
  $wp_admin_bar->add_node( $args );
815
  }
@@ -819,7 +843,7 @@ function my_calendar_admin_bar() {
819
  'id' => 'mc-manage-categories',
820
  'title' => __( 'Categories', 'my-calendar' ),
821
  'href' => $url,
822
- 'parent' => 'mc-add-event',
823
  );
824
  $wp_admin_bar->add_node( $args );
825
  }
@@ -829,7 +853,7 @@ function my_calendar_admin_bar() {
829
  'id' => 'mc-manage-locations',
830
  'title' => __( 'Locations', 'my-calendar' ),
831
  'href' => $url,
832
- 'parent' => 'mc-add-event',
833
  );
834
  $wp_admin_bar->add_node( $args );
835
  }
@@ -839,7 +863,7 @@ function my_calendar_admin_bar() {
839
  'id' => 'mc-submit-events',
840
  'title' => __( 'Public Submissions', 'my-calendar' ),
841
  'href' => $url,
842
- 'parent' => 'mc-add-event',
843
  );
844
  $wp_admin_bar->add_node( $args );
845
  }
@@ -1091,6 +1115,23 @@ function mc_scripts() {
1091
  }
1092
 
1093
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1094
  add_action( 'wp_ajax_mc_post_lookup', 'mc_post_lookup' );
1095
  /**
1096
  * Add post lookup for assigning My Calendar main page
@@ -1220,8 +1261,8 @@ function mc_ajax_add_date() {
1220
  $format = array( '%d', '%s', '%s', '%d' );
1221
  $data = array(
1222
  'occur_event_id' => $event_id,
1223
- 'occur_begin' => date( 'Y-m-d H:i:s', $begin ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
1224
- 'occur_end' => date( 'Y-m-d H:i:s', $end ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
1225
  'occur_group_id' => $group_id,
1226
  );
1227
  $result = $wpdb->insert( my_calendar_event_table(), $data, $format );
@@ -1509,6 +1550,8 @@ function mc_register_actions() {
1509
  // Filters.
1510
  add_filter( 'post_updated_messages', 'mc_posttypes_messages' );
1511
  add_filter( 'tmp_grunion_allow_editor_view', '__return_false' );
 
 
1512
 
1513
  // Actions.
1514
  add_action( 'init', 'mc_taxonomies', 0 );
@@ -1527,6 +1570,59 @@ function mc_load_permalinks() {
1527
  add_settings_field( 'mc_cpt_base', __( 'My Calendar Events base' ), 'mc_field_callback', 'permalink', 'optional', $opts );
1528
  }
1529
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1530
  /**
1531
  * Custom field callback for permalinks settings
1532
  */
@@ -1783,7 +1879,7 @@ function my_calendar_privacy_export( $email_address, $page = 1 ) {
1783
  }
1784
 
1785
  // Need to get all events with this email address as host, author, or meta data.
1786
- $posts = $wpdb->get_results( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_submitter_details' AND 'meta_value' LIKE %s", '%' . $wpdb->esc_like( $email_address ) . '%s' ) );
1787
  foreach ( $posts as $post ) {
1788
  $events[] = get_post_meta( $post, '_mc_event_id', true );
1789
  }
@@ -1880,7 +1976,7 @@ function my_calendar_privacy_eraser( $email_address, $page = 1 ) {
1880
  }
1881
 
1882
  // Need to get all events with this email address as host, author, or meta data.
1883
- $posts = $wpdb->get_results( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_submitter_details' AND 'meta_value' LIKE %s", '%' . $wpdb->esc_like( $email_address ) . '%s' ) );
1884
  foreach ( $posts as $post ) {
1885
  $deletions[] = get_post_meta( $post, '_mc_event_id', true );
1886
  }
16
  /**
17
  * Add feeds to WordPress feed handler.
18
  */
19
+ function mc_add_feed() {
20
  add_feed( 'my-calendar-rss', 'my_calendar_rss' );
21
  add_feed( 'my-calendar-ics', 'my_calendar_ical' );
22
  add_feed( 'my-calendar-google', 'mc_ics_subscribe_google' );
153
  $js_array = ( '' !== trim( get_option( 'mc_show_js', '' ) ) ) ? explode( ',', get_option( 'mc_show_js' ) ) : array();
154
  $css_array = ( '' !== trim( get_option( 'mc_show_css', '' ) ) ) ? explode( ',', get_option( 'mc_show_css' ) ) : array();
155
  $use_default = ( $default && ! $id ) ? true : false;
156
+ $js_usage = ( ( empty( $js_array ) ) || ( $id && in_array( (string) $id, $js_array, true ) ) ) ? true : false;
157
+ $css_usage = ( ( empty( $css_array ) ) || ( $id && in_array( (string) $id, $css_array, true ) ) ) ? true : false;
158
 
159
  // check whether any scripts are actually enabled.
160
  if ( get_option( 'mc_calendar_javascript' ) !== '1' || get_option( 'mc_list_javascript' ) !== '1' || get_option( 'mc_mini_javascript' ) !== '1' || get_option( 'mc_ajax_javascript' ) !== '1' ) {
192
  /**
193
  * Publically written head styles & scripts
194
  */
195
+ function mc_head() {
196
+ global $wp_query;
 
 
 
 
197
  $array = array();
198
 
199
  if ( get_option( 'mc_use_styles' ) !== 'true' ) {
200
+ $this_post = $wp_query->get_queried_object();
201
+ $id = (string) ( is_object( $this_post ) && isset( $this_post->ID ) ) ? $this_post->ID : false;
202
+ $array = ( '' !== get_option( 'mc_show_css', '' ) ) ? explode( ',', get_option( 'mc_show_css' ) ) : $array;
203
+ $category_vars = '';
204
  if ( ( is_array( $array ) && ! empty( $array ) ) || in_array( $id, $array, true ) || get_option( 'mc_show_css', '' ) === '' ) {
205
  // generate category colors.
206
+ $category_css = mc_generate_category_styles();
207
+ $category_styles = $category_css['styles'];
208
+ $category_vars = $category_css['vars'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
210
  $styles = (array) get_option( 'mc_style_vars' );
211
  $style_vars = '';
215
  }
216
  }
217
  if ( '' !== $style_vars ) {
218
+ $style_vars = '.mc-main {' . $style_vars . $category_vars . '}';
219
  }
220
 
221
  $all_styles = "
222
  <style type=\"text/css\">
223
  <!--
224
+ /* Styles by My Calendar - Joseph C Dolson https://www.joedolson.com/ */
225
  $category_styles
 
 
 
226
  $style_vars
227
  -->
228
  </style>";
231
  }
232
  }
233
 
234
+ /**
235
+ * Generate category styles for use by My Calendar core.
236
+ *
237
+ * @return array Variable styles & category styles.
238
+ */
239
+ function mc_generate_category_styles() {
240
+ global $wpdb;
241
+ $mcdb = $wpdb;
242
+ if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
243
+ $mcdb = mc_remote_db();
244
+ }
245
+ $category_styles = '';
246
+ $category_vars = '';
247
+ $inv = '';
248
+ $type = '';
249
+ $alt = '';
250
+ $categories = $mcdb->get_results( 'SELECT * FROM ' . my_calendar_categories_table( get_current_blog_id() ) . ' ORDER BY category_id ASC' );
251
+ foreach ( $categories as $category ) {
252
+ $class = mc_category_class( $category, 'mc_' );
253
+ $hex = ( strpos( $category->category_color, '#' ) !== 0 ) ? '#' : '';
254
+ $color = $hex . $category->category_color;
255
+ if ( '#' !== $color ) {
256
+ $hcolor = mc_shift_color( $category->category_color );
257
+ if ( 'font' === get_option( 'mc_apply_color' ) ) {
258
+ $type = 'color';
259
+ $alt = 'background';
260
+ } elseif ( 'background' === get_option( 'mc_apply_color' ) ) {
261
+ $type = 'background';
262
+ $alt = 'color';
263
+ }
264
+ $inverse = mc_inverse_color( $color );
265
+ $inv = "$alt: $inverse;";
266
+ if ( 'font' === get_option( 'mc_apply_color' ) || 'background' === get_option( 'mc_apply_color' ) ) {
267
+ // always an anchor as of 1.11.0, apply also to title.
268
+ $category_styles .= "\n.mc-main .$class .event-title, .mc-main .$class .event-title a { $type: $color; $inv }";
269
+ $category_styles .= "\n.mc-main .$class .event-title a:hover, .mc-main .$class .event-title a:focus { $type: $hcolor;}";
270
+ }
271
+ // Variables aren't dependent on options.
272
+ $category_vars .= '--category-' . $class . ': ' . $color . '; ';
273
+ }
274
+ }
275
+
276
+ return array(
277
+ 'styles' => $category_styles,
278
+ 'vars' => $category_vars,
279
+ );
280
+ }
281
+
282
  /**
283
  * Deal with events posted by a user when that user is deleted
284
  *
313
  /**
314
  * Write custom JS in admin head.
315
  */
316
+ function mc_write_js() {
317
  if ( isset( $_GET['page'] ) && ( 'my-calendar' === $_GET['page'] || 'my-calendar-locations' === $_GET['page'] ) ) {
318
  ?>
319
  <script>
466
  /**
467
  * Add stylesheets to My Calendar admin screens
468
  */
469
+ function mc_add_styles() {
470
  global $current_screen;
471
  $id = $current_screen->id;
472
  if ( false !== strpos( $id, 'my-calendar' ) ) {
473
  wp_enqueue_style( 'mc-styles', plugins_url( 'css/mc-styles.css', __FILE__ ) );
474
 
475
  if ( 'toplevel_page_my-calendar' === $id ) {
476
+ wp_enqueue_style( 'mc-pickadate-default', plugins_url( 'js/pickadate/themes/classic.css', __FILE__ ) );
477
+ wp_enqueue_style( 'mc-pickadate-date', plugins_url( 'js/pickadate/themes/classic.date.css', __FILE__ ) );
478
+ wp_enqueue_style( 'mc-pickadate-time', plugins_url( 'js/pickadate/themes/classic.time.css', __FILE__ ) );
479
  }
480
  }
481
  }
674
  } else {
675
  // For each release requiring an upgrade path, add a version compare.
676
  // Loop will run every relevant upgrade cycle.
677
+ $valid_upgrades = array( '2.3.0', '2.3.11', '2.3.15', '2.4.4', '3.0.0', '3.1.13' );
678
  foreach ( $valid_upgrades as $upgrade ) {
679
  if ( version_compare( $current_version, $upgrade, '<' ) ) {
680
  $upgrade_path[] = $upgrade;
776
  update_option( 'mc_input_options', $mc_input_options );
777
  mc_transition_db();
778
  break;
 
 
 
 
 
 
 
779
  default:
780
  break;
781
  }
782
  }
783
  }
784
 
785
+ add_action( 'admin_bar_menu', 'mc_admin_bar', 200 );
786
  /**
787
  * Set up adminbar links
788
  */
789
+ function mc_admin_bar() {
790
  global $wp_admin_bar;
791
+ $mc_id = get_option( 'mc_uri_id' );
 
 
 
 
 
 
 
 
792
  if ( mc_get_uri( 'boolean' ) ) {
793
+ if ( is_page( $mc_id ) ) {
794
+ $url = apply_filters( 'mc_add_events_url', admin_url( 'admin.php?page=my-calendar' ) );
795
+ $args = array(
796
+ 'id' => 'mc-my-calendar',
797
+ 'title' => __( 'Add Event', 'my-calendar' ),
798
+ 'href' => $url,
799
+ );
800
+ } else {
801
+ $url = esc_url( apply_filters( 'mc_adminbar_uri', mc_get_uri() ) );
802
+ $args = array(
803
+ 'id' => 'mc-my-calendar',
804
+ 'title' => __( 'My Calendar', 'my-calendar' ),
805
+ 'href' => $url,
806
+ );
807
+ }
808
  $wp_admin_bar->add_node( $args );
809
  } else {
810
  $url = admin_url( 'admin.php?page=my-calendar-config#my-calendar-manage' );
815
  );
816
  $wp_admin_bar->add_node( $args );
817
  }
818
+ if ( current_user_can( 'mc_add_events' ) && 'true' !== get_option( 'mc_remote' ) ) {
819
+ if ( ! is_page( $mc_id ) ) {
820
+ $url = apply_filters( 'mc_add_events_url', admin_url( 'admin.php?page=my-calendar' ) );
821
+ $args = array(
822
+ 'id' => 'mc-add-event',
823
+ 'title' => __( 'Add Event', 'my-calendar' ),
824
+ 'href' => $url,
825
+ 'parent' => 'mc-my-calendar',
826
+ );
827
+ $wp_admin_bar->add_node( $args );
828
+ }
829
+ }
830
  if ( current_user_can( 'mc_manage_events' ) && current_user_can( 'mc_add_events' ) ) {
831
  $url = admin_url( 'admin.php?page=my-calendar-manage' );
832
  $args = array(
833
  'id' => 'mc-manage-events',
834
  'title' => __( 'Events', 'my-calendar' ),
835
  'href' => $url,
836
+ 'parent' => 'mc-my-calendar',
837
  );
838
  $wp_admin_bar->add_node( $args );
839
  }
843
  'id' => 'mc-manage-categories',
844
  'title' => __( 'Categories', 'my-calendar' ),
845
  'href' => $url,
846
+ 'parent' => 'mc-my-calendar',
847
  );
848
  $wp_admin_bar->add_node( $args );
849
  }
853
  'id' => 'mc-manage-locations',
854
  'title' => __( 'Locations', 'my-calendar' ),
855
  'href' => $url,
856
+ 'parent' => 'mc-my-calendar',
857
  );
858
  $wp_admin_bar->add_node( $args );
859
  }
863
  'id' => 'mc-submit-events',
864
  'title' => __( 'Public Submissions', 'my-calendar' ),
865
  'href' => $url,
866
+ 'parent' => 'mc-my-calendar',
867
  );
868
  $wp_admin_bar->add_node( $args );
869
  }
1115
  }
1116
 
1117
 
1118
+ add_filter( 'mc_time_format', 'mc_time_format', 10, 1 );
1119
+ /**
1120
+ * Default time format is 'h:i A' (standard US time format).
1121
+ * Pass a string using pickadate.time rules: http://amsul.ca/pickadate.js/time/#formatting-rules.
1122
+ *
1123
+ * @param string $format Default time format string.
1124
+ *
1125
+ * @return string new format.
1126
+ */
1127
+ function mc_time_format( $format ) {
1128
+ if ( 'G:i' === get_option( 'mc_time_format' ) || 'H:i' === get_option( 'mc_time_format' ) || 'G:i' === get_option( 'time_format' ) || 'H:i' === get_option( 'time_format' ) ) {
1129
+ return 'H:i'; // European 24-hour format.
1130
+ }
1131
+
1132
+ return $format;
1133
+ }
1134
+
1135
  add_action( 'wp_ajax_mc_post_lookup', 'mc_post_lookup' );
1136
  /**
1137
  * Add post lookup for assigning My Calendar main page
1261
  $format = array( '%d', '%s', '%s', '%d' );
1262
  $data = array(
1263
  'occur_event_id' => $event_id,
1264
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', $begin, false ),
1265
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', $end, false ),
1266
  'occur_group_id' => $group_id,
1267
  );
1268
  $result = $wpdb->insert( my_calendar_event_table(), $data, $format );
1550
  // Filters.
1551
  add_filter( 'post_updated_messages', 'mc_posttypes_messages' );
1552
  add_filter( 'tmp_grunion_allow_editor_view', '__return_false' );
1553
+ add_filter( 'next_post_link', 'mc_next_post_link', 10, 5 );
1554
+ add_filter( 'previous_post_link', 'mc_previous_post_link', 10, 5 );
1555
 
1556
  // Actions.
1557
  add_action( 'init', 'mc_taxonomies', 0 );
1570
  add_settings_field( 'mc_cpt_base', __( 'My Calendar Events base' ), 'mc_field_callback', 'permalink', 'optional', $opts );
1571
  }
1572
 
1573
+ /**
1574
+ * Change out previous post link for previous event.
1575
+ *
1576
+ * @param string $output Original link.
1577
+ * @param string $format Link anchor format.
1578
+ * @param string $link Link permalink format.
1579
+ * @param WP_Post $post The adjacent post.
1580
+ * @param string $adj next or previous.
1581
+ *
1582
+ * @return string
1583
+ */
1584
+ function mc_previous_post_link( $output, $format, $link, $post, $adj ) {
1585
+ $output = '';
1586
+ if ( is_singular( 'mc-events' ) && isset( $_GET['mc_id'] ) ) {
1587
+ $mc_id = (int) $_GET['mc_id'];
1588
+ $event = mc_adjacent_event( $mc_id, 'previous' );
1589
+ $title = $event['title'];
1590
+ $link = $event['details_link'];
1591
+ $date = ' <span class="mc-event-date">' . $event['date'] . '</span>';
1592
+
1593
+ $output = str_replace( '%link', '<a href="' . $link . '" rel="next" class="mc-adjacent">' . $title . $date . '</a>', $format );
1594
+ }
1595
+
1596
+ return $output;
1597
+ }
1598
+
1599
+ /**
1600
+ * Change out previous post link for previous event.
1601
+ *
1602
+ * @param string $output Original link.
1603
+ * @param string $format Link anchor format.
1604
+ * @param string $link Link permalink format.
1605
+ * @param WP_Post $post The adjacent post.
1606
+ * @param string $adj next or previous.
1607
+ *
1608
+ * @return string
1609
+ */
1610
+ function mc_next_post_link( $output, $format, $link, $post, $adj ) {
1611
+ $output = '';
1612
+ if ( is_singular( 'mc-events' ) && isset( $_GET['mc_id'] ) ) {
1613
+ $mc_id = (int) $_GET['mc_id'];
1614
+ $event = mc_adjacent_event( $mc_id, 'next' );
1615
+ $title = apply_filters( 'the_title', $event['title'], $event['post'] );
1616
+ $link = $event['details_link'];
1617
+ $date = ' <span class="mc-event-date">' . $event['date'] . '</span>';
1618
+
1619
+ $output = str_replace( '%link', '<a href="' . $link . '" rel="next" class="mc-adjacent">' . $title . $date . '</a>', $format );
1620
+ }
1621
+
1622
+ return $output;
1623
+ }
1624
+
1625
+
1626
  /**
1627
  * Custom field callback for permalinks settings
1628
  */
1879
  }
1880
 
1881
  // Need to get all events with this email address as host, author, or meta data.
1882
+ $posts = $wpdb->get_results( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_submitter_details' AND 'meta_value' LIKE %s", '%' . esc_sql( $email_address ) . '%s' ) );
1883
  foreach ( $posts as $post ) {
1884
  $events[] = get_post_meta( $post, '_mc_event_id', true );
1885
  }
1976
  }
1977
 
1978
  // Need to get all events with this email address as host, author, or meta data.
1979
+ $posts = $wpdb->get_results( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_submitter_details' AND 'meta_value' LIKE %s", '%' . esc_sql( $email_address ) . '%s' ) );
1980
  foreach ( $posts as $post ) {
1981
  $deletions[] = get_post_meta( $post, '_mc_event_id', true );
1982
  }
my-calendar-event-manager.php CHANGED
@@ -27,7 +27,7 @@ function mc_event_post( $action, $data, $event_id ) {
27
  if ( 'add' === $action || 'copy' === $action ) {
28
  $post_id = mc_create_event_post( $data, $event_id );
29
  } elseif ( 'edit' === $action ) {
30
- if ( isset( $_POST['event_post'] ) && ( 0 == $_POST['event_post'] || '' == $_POST['event_post'] ) ) {
31
  $post_id = mc_create_event_post( $data, $event_id );
32
  } else {
33
  $post_id = ( isset( $_POST['event_post'] ) ) ? absint( $_POST['event_post'] ) : false;
@@ -50,8 +50,8 @@ function mc_event_post( $action, $data, $event_id ) {
50
  }
51
  }
52
  // if any selected category is private, make private.
53
- if ( 'private' != $privacy ) {
54
- $privacy = ( 1 == mc_get_category_detail( $category, 'category_private' ) ) ? 'private' : 'publish';
55
  }
56
  $terms[] = (int) $term;
57
  }
@@ -79,7 +79,7 @@ function mc_event_post( $action, $data, $event_id ) {
79
  }
80
  $post_id = wp_update_post( $my_post );
81
  wp_set_object_terms( $post_id, $terms, 'mc-event-category' );
82
- if ( '' == $data['event_image'] ) {
83
  delete_post_thumbnail( $post_id );
84
  } else {
85
  // check POST data.
@@ -114,7 +114,7 @@ function mc_add_post_meta_data( $post_id, $post, $data, $event_id ) {
114
  $description = isset( $data['event_desc'] ) ? $data['event_desc'] : '';
115
  $image = isset( $data['event_image'] ) ? esc_url_raw( $data['event_image'] ) : '';
116
  $guid = get_post_meta( $post_id, '_mc_guid', true );
117
- if ( '' == $guid ) {
118
  $guid = md5( $post_id . $event_id . $data['event_title'] );
119
  update_post_meta( $post_id, '_mc_guid', $guid );
120
  }
@@ -153,8 +153,8 @@ function mc_create_event_post( $data, $event_id ) {
153
  foreach ( $categories as $category ) {
154
  $term = mc_get_category_detail( $category, 'category_term' );
155
  // if any selected category is private, make private.
156
- if ( 'private' != $privacy ) {
157
- $privacy = ( 1 == mc_get_category_detail( $category, 'category_private' ) ) ? 'private' : 'publish';
158
  }
159
  $terms[] = (int) $term;
160
  }
@@ -174,7 +174,7 @@ function mc_create_event_post( $data, $event_id ) {
174
  'post_status' => $post_status,
175
  'post_author' => $auth,
176
  'post_name' => sanitize_title( $title ),
177
- 'post_date' => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
178
  'post_type' => $type,
179
  'post_excerpt' => $excerpt,
180
  );
@@ -268,7 +268,7 @@ function mc_bulk_action( $action ) {
268
  foreach ( $events as $value ) {
269
  $value = (int) $value;
270
  $total = count( $events );
271
- if ( 'delete' == $action ) {
272
  $result = $wpdb->get_results( $wpdb->prepare( 'SELECT event_author FROM ' . my_calendar_table() . ' WHERE event_id = %d', $value ), ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
273
  if ( mc_can_edit_event( $value ) ) {
274
  $occurrences = 'DELETE FROM ' . my_calendar_event_table() . ' WHERE occur_event_id = %d';
@@ -278,7 +278,7 @@ function mc_bulk_action( $action ) {
278
  $i ++;
279
  }
280
  }
281
- if ( 'delete' != $action && current_user_can( 'mc_approve_events' ) ) {
282
  $ids[] = (int) $value;
283
  $prepare[] = '%d';
284
  $i ++;
@@ -304,7 +304,6 @@ function mc_bulk_action( $action ) {
304
  break;
305
  case 'unspam':
306
  $sql = 'UPDATE ' . my_calendar_table() . ' SET event_flagged = 0 WHERE event_id IN (' . $prepared . ')';
307
- // send ham report to Akismet.
308
  // send notifications.
309
  foreach ( $ids as $id ) {
310
  $post_ID = mc_get_event_post( $id );
@@ -397,7 +396,7 @@ function mc_bulk_message( $results, $action ) {
397
  * @return string
398
  */
399
  function mc_show_error( $message, $echo = true ) {
400
- if ( trim( $message ) == '' ) {
401
  return '';
402
  }
403
  $message = strip_tags( $message, mc_admin_strip_tags() );
@@ -419,7 +418,7 @@ function mc_show_error( $message, $echo = true ) {
419
  * @return string
420
  */
421
  function mc_show_notice( $message, $echo = true ) {
422
- if ( trim( $message ) == '' ) {
423
  return '';
424
  }
425
  $message = strip_tags( $message, mc_admin_strip_tags() );
@@ -444,7 +443,7 @@ function my_calendar_manage() {
444
  if ( isset( $_GET['date'] ) ) {
445
  $event_instance = (int) $_GET['date'];
446
  $inst = $wpdb->get_var( $wpdb->prepare( 'SELECT occur_begin FROM ' . my_calendar_event_table() . ' WHERE occur_id=%d', $event_instance ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
447
- $instance_date = '(' . date( 'Y-m-d', mc_strtotime( $inst ) ) . ')';
448
  } else {
449
  $instance_date = '';
450
  } ?>
@@ -615,8 +614,8 @@ function my_calendar_edit() {
615
  <div class="wrap my-calendar-admin">
616
  <?php
617
  my_calendar_check_db();
618
- if ( 2 == get_site_option( 'mc_multisite' ) ) {
619
- if ( 0 == get_option( 'mc_current_table' ) ) {
620
  $message = __( 'Currently editing your local calendar', 'my-calendar' );
621
  } else {
622
  $message = __( 'Currently editing your central calendar', 'my-calendar' );
@@ -691,11 +690,11 @@ function my_calendar_save( $action, $output, $event_id = false ) {
691
  $event = mc_get_first_event( $event_id );
692
  my_calendar_send_email( $event );
693
  }
694
- if ( 0 == $add['event_approved'] ) {
695
  $message = mc_show_notice( __( 'Event draft saved.', 'my-calendar' ), false );
696
  } else {
697
  // jd_doTwitterAPIPost was changed to wpt_post_to_twitter on 1.19.2017.
698
- if ( function_exists( 'wpt_post_to_twitter' ) && isset( $_POST['mc_twitter'] ) && '' != trim( $_POST['mc_twitter'] ) ) {
699
  wpt_post_to_twitter( stripslashes( $_POST['mc_twitter'] ) );
700
  }
701
  if ( mc_get_uri( 'boolean' ) ) {
@@ -705,7 +704,7 @@ function my_calendar_save( $action, $output, $event_id = false ) {
705
  } else {
706
  $event_link = false;
707
  }
708
- if ( '' != $event_error ) {
709
  $message = $event_error;
710
  } else {
711
  $message = __( 'Event added. It will now show on the calendar.', 'my-calendar' );
@@ -719,7 +718,7 @@ function my_calendar_save( $action, $output, $event_id = false ) {
719
  }
720
  }
721
 
722
- if ( 'edit' === $action && true == $proceed ) {
723
  $result = true;
724
  // Translators: URL to view calendar.
725
  $url = sprintf( __( 'View <a href="%s">your calendar</a>.', 'my-calendar' ), mc_get_uri() );
@@ -730,13 +729,13 @@ function my_calendar_save( $action, $output, $event_id = false ) {
730
  mc_update_category_relationships( $cats, $event_id );
731
 
732
  $update = apply_filters( 'mc_before_save_update', $update, $event_id );
733
- $endtime = date( 'H:i:00', mc_strtotime( $update['event_endtime'] ) );
734
  $prev_eb = ( isset( $_POST['prev_event_begin'] ) ) ? $_POST['prev_event_begin'] : '';
735
  $prev_et = ( isset( $_POST['prev_event_time'] ) ) ? $_POST['prev_event_time'] : '';
736
  $prev_ee = ( isset( $_POST['prev_event_end'] ) ) ? $_POST['prev_event_end'] : '';
737
  $prev_eet = ( isset( $_POST['prev_event_endtime'] ) ) ? $_POST['prev_event_endtime'] : '';
738
- $update_time = date( 'H:i:00', mc_strtotime( $update['event_time'] ) );
739
- $date_changed = ( $update['event_begin'] != $prev_eb || $update_time != $prev_et || $update['event_end'] != $prev_ee || ( $endtime != $prev_eet && ( '' != $prev_eet && '23:59:59' != $endtime ) ) ) ? true : false;
740
  if ( isset( $_POST['event_instance'] ) ) {
741
  // compares the information sent to the information saved for a given event.
742
  $is_changed = mc_compare( $update, $event_id );
@@ -746,7 +745,7 @@ function my_calendar_save( $action, $output, $event_id = false ) {
746
  // if group ID == 0, need to add group ID to both records.
747
  // if a single instance is edited, it should not inherit recurring settings from parent.
748
  $update['event_recur'] = 'S1';
749
- if ( 0 == $update['event_group_id'] ) {
750
  $update['event_group_id'] = $event_id;
751
  mc_update_data( $event_id, 'event_group_id', $event_id );
752
  }
@@ -761,7 +760,7 @@ function my_calendar_save( $action, $output, $event_id = false ) {
761
  mc_update_category_relationships( $cats, $new_event );
762
  $result = mc_update_instance( $event_instance, $new_event, $update );
763
  } else {
764
- if ( $update['event_begin'][0] == $_POST['prev_event_begin'] && $update['event_end'][0] == $_POST['prev_event_end'] ) {
765
  // There were no changes at all.
766
  } else {
767
  // Only dates were changed.
@@ -780,7 +779,7 @@ function my_calendar_save( $action, $output, $event_id = false ) {
780
  '%d'
781
  );
782
  if ( isset( $_POST['prev_event_repeats'] ) && isset( $_POST['prev_event_recur'] ) ) {
783
- $recur_changed = ( $update['event_repeats'] != $_POST['prev_event_repeats'] || $update['event_recur'] != $_POST['prev_event_recur'] ) ? true : false;
784
  } else {
785
  $recur_changed = false;
786
  }
@@ -803,12 +802,12 @@ function my_calendar_save( $action, $output, $event_id = false ) {
803
  // do an action using the $action and processed event data.
804
  $event_approved = ( current_user_can( 'mc_approve_events' ) ) ? 1 : 0;
805
  // check for event_approved provides support for older versions of My Calendar Pro.
806
- if ( isset( $post['event_approved'] ) && $post['event_approved'] != $event_approved ) {
807
  $event_approved = absint( $post['event_approved'] );
808
  }
809
  if ( isset( $_POST['prev_event_status'] ) ) {
810
  // Don't execute transition actions if prev status not known.
811
- do_action( 'mc_transition_event', (int) $_POST['prev_event_status'], $event_approved );
812
  }
813
  $message = mc_show_notice( __( 'Event updated successfully', 'my-calendar' ) . ". $url", false );
814
  }
@@ -858,7 +857,7 @@ function mc_set_category_relationships( $cats, $event_id ) {
858
  function mc_update_category_relationships( $cats, $event_id ) {
859
  global $wpdb;
860
  $old_cats = mc_get_categories( $event_id, 'testing' );
861
- if ( $old_cats == $cats ) {
862
  return;
863
  }
864
  $wpdb->delete( my_calendar_category_relationships_table(), array( 'event_id' => $event_id ), '%d' );
@@ -892,7 +891,7 @@ function mc_error_check( $event_id ) {
892
  'event_id' => $event_id,
893
  );
894
  $edit_link = ' <a href="' . esc_url( add_query_arg( $args, admin_url( 'admin.php?page=my-calendar' ) ) ) . '">' . __( 'Edit Event', 'my-calendar' ) . '</a>';
895
- $test = ( '' != $test ) ? str_replace( '</p></div>', "$edit_link</p></div>", $test ) : $test;
896
 
897
  return $test;
898
  }
@@ -992,8 +991,8 @@ function mc_edit_event_form( $mode = 'add', $event_id = false ) {
992
 
993
  apply_filters( 'mc_event_notices', '', $data, $event_id );
994
 
995
- if ( is_object( $data ) && 1 != $data->event_approved && 'edit' === $mode ) {
996
- if ( 0 == $data->event_approved ) {
997
  mc_show_error( __( '<strong>Draft</strong>: Publish this event to show it on the calendar.', 'my-calendar' ) );
998
  } else {
999
  mc_show_error( __( '<strong>Trash</strong>: Remove from the trash to show this event on the calendar.', 'my-calendar' ) );
@@ -1029,8 +1028,25 @@ function mc_get_instance_data( $instance_id ) {
1029
  * @return string.
1030
  */
1031
  function mc_show_edit_block( $field ) {
1032
- $admin = ( 'true' == get_option( 'mc_input_options_administrators' ) && current_user_can( 'manage_options' ) ) ? true : false;
1033
- $input = get_option( 'mc_input_options' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1034
  $user = get_current_user_id();
1035
  $screen = get_current_screen();
1036
  $option = $screen->get_option( 'mc_show_on_page', 'option' );
@@ -1049,7 +1065,7 @@ function mc_show_edit_block( $field ) {
1049
  return false;
1050
  }
1051
  } else {
1052
- if ( 'off' === $input[ $field ] || '' == $input[ $field ] ) {
1053
  return false;
1054
  } elseif ( 'off' === $show[ $field ] ) {
1055
  return false;
@@ -1150,7 +1166,7 @@ function mc_show_block( $field, $has_data, $data, $echo = true, $default = '' )
1150
  $image = ( has_post_thumbnail( $data->event_post ) ) ? get_the_post_thumbnail_url( $data->event_post ) : $data->event_image;
1151
  $image_id = ( has_post_thumbnail( $data->event_post ) ) ? get_post_thumbnail_id( $data->event_post ) : '';
1152
  } else {
1153
- $image = ( $has_data && '' != $data->event_image ) ? $data->event_image : '';
1154
  $image_id = '';
1155
  }
1156
  if ( $show_block ) {
@@ -1158,7 +1174,7 @@ function mc_show_block( $field, $has_data, $data, $echo = true, $default = '' )
1158
  <div class="mc-image-upload field-holder">
1159
  <input type="hidden" name="event_image_id" value="' . esc_attr( $image_id ) . '" class="textfield" id="e_image_id" />
1160
  <label for="e_image">' . __( 'Add an image:', 'my-calendar' ) . '</label><br /><input type="text" name="event_image" id="e_image" size="60" value="' . esc_attr( $image ) . '" placeholder="http://yourdomain.com/image.jpg" /> <button type="button" class="button textfield-field">' . __( 'Upload', 'my-calendar' ) . '</button>';
1161
- if ( '' != $image ) {
1162
  $image = ( has_post_thumbnail( $data->event_post ) ) ? get_the_post_thumbnail_url( $data->event_post ) : $data->event_image;
1163
  $return .= '<div class="event_image"><img src="' . esc_attr( $image ) . '" alt="" /></div>';
1164
  } else {
@@ -1199,9 +1215,9 @@ function mc_show_block( $field, $has_data, $data, $echo = true, $default = '' )
1199
  case 'event_link':
1200
  if ( $show_block ) {
1201
  $value = ( $has_data ) ? esc_url( $data->event_link ) : '';
1202
- if ( $has_data && '1' == $data->event_link_expires ) {
1203
  $checked = ' checked="checked"';
1204
- } elseif ( $has_data && '0' == $data->event_link_expires ) {
1205
  $checked = '';
1206
  } elseif ( 'true' === get_option( 'mc_event_link_expires' ) ) {
1207
  $checked = ' checked="checked"';
@@ -1218,7 +1234,7 @@ function mc_show_block( $field, $has_data, $data, $echo = true, $default = '' )
1218
  $recurs = str_split( $event_recur, 1 );
1219
  $recur = $recurs[0];
1220
  $every = ( isset( $recurs[1] ) ) ? str_replace( $recurs[0], '', $event_recur ) : 1;
1221
- if ( 1 == $every && 'B' === $recur ) {
1222
  $every = 2;
1223
  }
1224
  $prev = '<input type="hidden" name="prev_event_repeats" value="' . $data->event_repeats . '" /><input type="hidden" name="prev_event_recur" value="' . $data->event_recur . '" />';
@@ -1227,7 +1243,7 @@ function mc_show_block( $field, $has_data, $data, $echo = true, $default = '' )
1227
  $every = 1;
1228
  $prev = '';
1229
  }
1230
- if ( is_object( $data ) && null != $data->event_repeats ) {
1231
  $repeats = $data->event_repeats;
1232
  } else {
1233
  $repeats = 0;
@@ -1253,7 +1269,7 @@ function mc_show_block( $field, $has_data, $data, $echo = true, $default = '' )
1253
  </div>
1254
  ' . $post;
1255
  } else {
1256
- if ( '' == $every && '' == $repeats ) {
1257
  $every = 'S';
1258
  $repeats = '0';
1259
  }
@@ -1304,7 +1320,7 @@ function mc_show_block( $field, $has_data, $data, $echo = true, $default = '' )
1304
  return;
1305
  }
1306
  $return = apply_filters( 'mc_show_block', $return, $data, $field, $has_data );
1307
- if ( true == $echo ) {
1308
  echo $return;
1309
  } else {
1310
  return $return;
@@ -1325,7 +1341,7 @@ function mc_test_occurrence_overlap( $data, $return = false ) {
1325
  // If this event is single, skip query.
1326
  $single_recur = ( 'S' === $data->event_recur || 'S1' === $data->event_recur ) ? true : false;
1327
  // If event starts and ends on same day, skip query.
1328
- $start_end = ( $data->event_begin == $data->event_end ) ? true : false;
1329
  // Only run test when an event is set up to recur & starts/ends on different days.
1330
  if ( ! $single_recur && ! $start_end ) {
1331
  $check = mc_increment_event( $data->event_id, array(), 'test' );
@@ -1387,8 +1403,8 @@ function mc_form_fields( $data, $mode, $event_id ) {
1387
  }
1388
  echo apply_filters( 'mc_before_event_form', '', $event_id );
1389
  $action = add_query_arg( $query_args, admin_url( 'admin.php?page=my-calendar' ) );
1390
- $group_id = ( ! empty( $data->event_group_id ) && 'copy' != $mode ) ? $data->event_group_id : mc_group_id();
1391
- $event_author = ( 'edit' != $mode ) ? $user_ID : $data->event_author;
1392
  ?>
1393
  <form id="my-calendar" method="post" action="<?php echo $action; ?>">
1394
  <div>
@@ -1442,7 +1458,7 @@ function mc_form_fields( $data, $mode, $event_id ) {
1442
  ?>
1443
  </div>
1444
  <?php
1445
- if ( ! empty( $_GET['date'] ) && 'S' != $data->event_recur ) {
1446
  $event = mc_get_event( $instance );
1447
  $date = date_i18n( mc_date_format(), mc_strtotime( $event->occur_begin ) );
1448
  // Translators: Date of a specific event occurrence.
@@ -1459,10 +1475,10 @@ function mc_form_fields( $data, $mode, $event_id ) {
1459
  <input type="text" id="e_title" name="event_title" size="50" maxlength="255" value="<?php echo ( $has_data ) ? apply_filters( 'mc_manage_event_title', stripslashes( esc_attr( $data->event_title ) ), $data ) : ''; ?>" />
1460
  </p>
1461
  <?php
1462
- if ( is_object( $data ) && 1 == $data->event_flagged ) {
1463
- if ( '0' == $data->event_flagged ) {
1464
  $flagged = ' checked="checked"';
1465
- } elseif ( '1' == $data->event_flagged ) {
1466
  $flagged = '';
1467
  }
1468
  ?>
@@ -1477,7 +1493,7 @@ function mc_form_fields( $data, $mode, $event_id ) {
1477
  apply_filters( 'mc_insert_custom_fields', '', $has_data, $data );
1478
 
1479
  if ( function_exists( 'wpt_post_to_twitter' ) && current_user_can( 'wpt_can_tweet' ) ) {
1480
- if ( ! ( 'edit' === $mode && 1 == $data->event_approved ) ) {
1481
  $mc_allowed = absint( ( get_option( 'wpt_tweet_length' ) ) ? get_option( 'wpt_tweet_length' ) : 140 );
1482
  ?>
1483
  <p class='mc-twitter'>
@@ -1517,11 +1533,11 @@ function mc_form_fields( $data, $mode, $event_id ) {
1517
  <?php echo apply_filters( 'mc_datetime_inputs', '', $has_data, $data, 'admin' ); ?>
1518
  </div>
1519
  <?php
1520
- if ( 'edit' != $mode ) {
1521
  $span_checked = '';
1522
- if ( $has_data && '1' == $data->event_span ) {
1523
  $span_checked = ' checked="checked"';
1524
- } elseif ( $has_data && '0' == $data->event_span ) {
1525
  $span_checked = '';
1526
  }
1527
  ?>
@@ -1541,7 +1557,7 @@ function mc_form_fields( $data, $mode, $event_id ) {
1541
  ?>
1542
  <div id='mc-accordion'>
1543
  <?php
1544
- if ( 'S' != $data->event_recur ) {
1545
  ?>
1546
  <h4><span class='dashicons' aria-hidden='true'> </span><button type="button" class="button-link"><?php _e( 'Scheduled dates for this event', 'my-calendar' ); ?></button></h4>
1547
  <div>
@@ -1561,13 +1577,13 @@ function mc_form_fields( $data, $mode, $event_id ) {
1561
  </ul>
1562
  <p><button type='button' class='add-occurrence' aria-expanded="false"><span class='dashicons' aria-hidden='true'> </span><?php _e( 'Add another date', 'my-calendar' ); ?></button></p>
1563
  <div class='mc_add_new'>
1564
- <?php echo mc_recur_datetime_input(); ?>
1565
  <button type='button' class='save-occurrence'><?php _e( 'Add Date', 'my-calendar' ); ?></button>
1566
  </div>
1567
  </div>
1568
  <?php
1569
  }
1570
- if ( 0 != $data->event_group_id ) {
1571
  $edit_group_url = admin_url( 'admin.php?page=my-calendar-groups&mode=edit&event_id=' . $data->event_id . '&group_id=' . $data->event_group_id );
1572
  ?>
1573
  <h4><span class='dashicons' aria-hidden='true'> </span><button type="button" class="button-link"><?php _e( 'Related Events:', 'my-calendar' ); ?></button> (<a href='<?php echo $edit_group_url; ?>'><?php _e( 'Edit group', 'my-calendar' ); ?></a>)
@@ -1606,7 +1622,7 @@ function mc_form_fields( $data, $mode, $event_id ) {
1606
  </div>
1607
  <?php
1608
  $custom_fields = apply_filters( 'mc_event_details', '', $has_data, $data, 'admin' );
1609
- if ( '' != $custom_fields ) {
1610
  ?>
1611
  <div class="ui-sortable meta-box-sortables">
1612
  <div class="postbox">
@@ -1652,7 +1668,7 @@ function mc_form_fields( $data, $mode, $event_id ) {
1652
  } else {
1653
  $event_location = false;
1654
  }
1655
- if ( $loc->location_id == $event_location ) {
1656
  // Translators: label for current location.
1657
  $current_location = "<span id='mc-current-location'>" . sprintf( __( 'Current location: %s', 'my-calendar' ), $loc_name ) . '</span>';
1658
  $current_location .= "<input type='hidden' name='preset_location' value='$event_location' />";
@@ -1692,8 +1708,8 @@ function mc_form_fields( $data, $mode, $event_id ) {
1692
  $hol_checked = ( 'true' === get_option( 'mc_skip_holidays' ) ) ? ' checked="checked"' : '';
1693
  $fifth_checked = ( 'true' === get_option( 'mc_no_fifth_week' ) ) ? ' checked="checked"' : '';
1694
  if ( $has_data ) {
1695
- $hol_checked = ( '1' == $data->event_holiday ) ? ' checked="checked"' : '';
1696
- $fifth_checked = ( '1' == $data->event_fifth_week ) ? ' checked="checked"' : '';
1697
  }
1698
  ?>
1699
  <div class="ui-sortable meta-box-sortables">
@@ -1718,8 +1734,8 @@ function mc_form_fields( $data, $mode, $event_id ) {
1718
  <?php
1719
  } else {
1720
  if ( $has_data ) {
1721
- $event_holiday = ( '1' == $data->event_holiday ) ? 'true' : 'false';
1722
- $event_fifth = ( '1' == $data->event_fifth_week ) ? 'true' : 'false';
1723
  } else {
1724
  $event_holiday = get_option( 'mc_skip_holidays' );
1725
  $event_fifth = get_option( 'mc_no_fifth_week' );
@@ -1757,6 +1773,10 @@ function mc_form_fields( $data, $mode, $event_id ) {
1757
  */
1758
  function mc_get_users( $group = 'authors' ) {
1759
  global $blog_id;
 
 
 
 
1760
  $count = count_users( 'time' );
1761
  $args = array(
1762
  'blog_id' => $blog_id,
@@ -1782,12 +1802,12 @@ function mc_selected_users( $selected = '', $group = 'authors' ) {
1782
  $users = mc_get_users( $group );
1783
  $options = '';
1784
  foreach ( $users as $u ) {
1785
- if ( in_array( $u->ID, $selected ) ) {
1786
  $checked = ' selected="selected"';
1787
  } else {
1788
  $checked = '';
1789
  }
1790
- $display_name = ( '' == $u->display_name ) ? $u->user_nicename : $u->display_name;
1791
  $options .= '<option value="' . $u->ID . '"' . $checked . ">$display_name</option>\n";
1792
  }
1793
 
@@ -1849,7 +1869,7 @@ function mc_event_accessibility( $form, $data, $label ) {
1849
  $label = $a;
1850
  $checked = '';
1851
  if ( is_array( $events_access ) ) {
1852
- $checked = ( in_array( $k, $events_access ) || in_array( $a, $events_access ) ) ? ' checked="checked"' : '';
1853
  }
1854
  $item = sprintf( '<li><input type="checkbox" id="%1$s" name="events_access[]" value="%4$s" class="checkbox" %2$s /> <label for="%1$s">%3$s</label></li>', esc_attr( $id ), $checked, esc_html( $label ), esc_attr( $a ) );
1855
  $form .= $item;
@@ -1885,7 +1905,7 @@ function mc_list_events() {
1885
  $sortdir = 'default';
1886
  }
1887
 
1888
- $default_direction = ( '' == get_option( 'mc_default_direction' ) ) ? 'ASC' : get_option( 'mc_default_direction' );
1889
  $sortbydirection = ( 'default' === $sortdir ) ? $default_direction : $sortdir;
1890
 
1891
  $sortby = ( isset( $_GET['sort'] ) ) ? $_GET['sort'] : get_option( 'mc_default_sort' );
@@ -1970,12 +1990,12 @@ function mc_list_events() {
1970
  if ( 'event_label' === $restrict ) {
1971
  $filter = "'$filter'";
1972
  }
1973
- if ( '' == $limit && '' != $filter ) {
1974
  $limit = "WHERE $restrict = $filter";
1975
- } elseif ( '' != $limit && '' != $filter ) {
1976
  $limit .= "AND $restrict = $filter";
1977
  }
1978
- if ( '' == $filter || ! $allow_filters ) {
1979
  $filtered = '';
1980
  } else {
1981
  $filtered = "<span class='dashicons dashicons-no' aria-hidden='true'></span><a href='" . admin_url( 'admin.php?page=my-calendar-manage' ) . "'>" . __( 'Clear filters', 'my-calendar' ) . '</a>';
@@ -1989,18 +2009,18 @@ function mc_list_events() {
1989
  $items_per_page = $screen->get_option( 'per_page', 'default' );
1990
  }
1991
  // Default limits.
1992
- if ( '' == $limit ) {
1993
- $limit .= ( 'event_flagged' != $restrict ) ? ' WHERE event_flagged = 0' : '';
1994
  } else {
1995
- $limit .= ( 'event_flagged' != $restrict ) ? ' AND event_flagged = 0' : '';
1996
  }
1997
  if ( isset( $_POST['mcs'] ) ) {
1998
  $query = $_POST['mcs'];
1999
  $limit .= mc_prepare_search_query( $query );
2000
  }
2001
  $query_limit = ( ( $current - 1 ) * $items_per_page );
2002
- $limit .= ( 'archived' != $restrict ) ? ' AND event_status = 1' : ' AND event_status = 0';
2003
- if ( 'event_category' != $sortbyvalue ) {
2004
  $events = $wpdb->get_results( $wpdb->prepare( 'SELECT SQL_CALC_FOUND_ROWS event_id FROM ' . my_calendar_table() . " $limit ORDER BY $sortbyvalue $sortbydirection " . 'LIMIT %d, %d', $query_limit, $items_per_page ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
2005
  } else {
2006
  $limit = str_replace( array( 'WHERE ' ), '', $limit );
@@ -2081,7 +2101,7 @@ function mc_list_events() {
2081
  </div>
2082
  <div>
2083
  <label for="mc_search" class='screen-reader-text'><?php _e( 'Search', 'my-calendar' ); ?></label>
2084
- <input type='text' role='search' name='mcs' id='mc_search' value=' <?php echo esc_attr( $search_text ); ?>' />
2085
  <input type='submit' value='<?php _e( 'Search Events', 'my-calendar' ); ?>' class='button-secondary'/>
2086
  </div>
2087
  </form>
@@ -2130,22 +2150,22 @@ function mc_list_events() {
2130
  <tr>
2131
  <th scope="col" style="width: 50px;"><input type='checkbox' class='selectall' id='mass_edit'/>
2132
  <label for='mass_edit' class="screen-reader-text"><?php _e( 'Check/Uncheck all', 'my-calendar' ); ?></label>
2133
- <a class="<?php echo ( 1 == $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=1$sorting" ); ?>"><?php _e( 'ID', 'my-calendar' ); ?></a>
2134
  </th>
2135
  <th scope="col">
2136
- <a class="<?php echo ( 2 == $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=2$sorting" ); ?>"><?php _e( 'Title', 'my-calendar' ); ?></a>
2137
  </th>
2138
  <th scope="col">
2139
- <a class="<?php echo ( 7 == $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=7$sorting" ); ?>"><?php _e( 'Location', 'my-calendar' ); ?></a>
2140
  </th>
2141
  <th scope="col">
2142
- <a class="<?php echo ( 4 == $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=4$sorting" ); ?>"><?php _e( 'Date/Time', 'my-calendar' ); ?></a>
2143
  </th>
2144
  <th scope="col">
2145
- <a class="<?php echo ( 5 == $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=5$sorting" ); ?>"><?php _e( 'Author', 'my-calendar' ); ?></a>
2146
  </th>
2147
  <th scope="col">
2148
- <a class="<?php echo ( 6 == $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=6$sorting" ); ?>"><?php _e( 'Category', 'my-calendar' ); ?></a>
2149
  </th>
2150
  </tr>
2151
  </thead>
@@ -2160,11 +2180,11 @@ function mc_list_events() {
2160
  continue;
2161
  }
2162
  $class = ( 'alternate' === $class ) ? 'even' : 'alternate';
2163
- $pending = ( 0 == $event->event_approved ) ? 'pending' : '';
2164
- $trashed = ( 2 == $event->event_approved ) ? 'trashed' : '';
2165
- $author = ( 0 != $event->event_author ) ? get_userdata( $event->event_author ) : 'Public Submitter';
2166
 
2167
- if ( 1 == $event->event_flagged && ( isset( $_GET['restrict'] ) && 'flagged' === $_GET['restrict'] ) ) {
2168
  $spam = 'spam';
2169
  $pending = '';
2170
  $spam_label = '<strong>' . __( 'Possible spam', 'my-calendar' ) . ':</strong> ';
@@ -2173,10 +2193,10 @@ function mc_list_events() {
2173
  $spam_label = '';
2174
  }
2175
 
2176
- $trash = ( '' != $trashed ) ? ' - ' . __( 'Trash', 'my-calendar' ) : '';
2177
- $draft = ( '' != $pending ) ? ' - ' . __( 'Draft', 'my-calendar' ) : $trash;
2178
  $check = mc_test_occurrence_overlap( $event, true );
2179
- $problem = ( '' != $check ) ? 'problem' : '';
2180
  $edit_url = admin_url( "admin.php?page=my-calendar&amp;mode=edit&amp;event_id=$event->event_id" );
2181
  $copy_url = admin_url( "admin.php?page=my-calendar&amp;mode=copy&amp;event_id=$event->event_id" );
2182
  $view_url = mc_get_details_link( $event );
@@ -2187,7 +2207,7 @@ function mc_list_events() {
2187
  ?>
2188
  <tr class="<?php echo "$class $spam $pending $trashed $problem"; ?>">
2189
  <th scope="row">
2190
- <input type="checkbox" value="<?php echo $event->event_id; ?>" name="mass_edit[]" id="mc<?php echo $event->event_id; ?>" <?php echo ( 1 == $event->event_flagged ) ? 'checked="checked"' : ''; ?> />
2191
  <label for="mc<?php echo $event->event_id; ?>">
2192
  <?php
2193
  // Translators: Event ID.
@@ -2207,7 +2227,7 @@ function mc_list_events() {
2207
  echo strip_tags( stripslashes( $event->event_title ) );
2208
  if ( $can_edit ) {
2209
  echo '</a>';
2210
- if ( '' != $check ) {
2211
  // Translators: URL to edit event.
2212
  echo '<br /><strong class="error">' . sprintf( __( 'There is a problem with this event. <a href="%s">Edit</a>', 'my-calendar' ), $edit_url ) . '</strong>';
2213
  }
@@ -2248,7 +2268,7 @@ function mc_list_events() {
2248
  |
2249
  <?php
2250
  if ( current_user_can( 'mc_approve_events' ) && $can_edit ) {
2251
- if ( 1 == $event->event_approved ) {
2252
  $mo = 'reject';
2253
  $te = __( 'Trash', 'my-calendar' );
2254
  } else {
@@ -2275,7 +2295,7 @@ function mc_list_events() {
2275
  </td>
2276
  <td>
2277
  <?php
2278
- if ( '' != $event->event_label ) {
2279
  $elabel = urlencode( $event->event_label );
2280
  ?>
2281
  <a class='mc_filter' href='<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;filter=$elabel&amp;restrict=where" ); ?>' title="<?php _e( 'Filter by location', 'my-calendar' ); ?>"><span class="screen-reader-text"><?php _e( 'Show only: ', 'my-calendar' ); ?></span><?php echo strip_tags( stripslashes( $event->event_label ) ); ?></a>
@@ -2285,7 +2305,7 @@ function mc_list_events() {
2285
  </td>
2286
  <td>
2287
  <?php
2288
- if ( '23:59:59' != $event->event_endtime ) {
2289
  $event_time = date_i18n( get_option( 'mc_time_format' ), mc_strtotime( $event->event_time ) );
2290
  } else {
2291
  $event_time = mc_notime_label( $event );
@@ -2326,12 +2346,12 @@ function mc_list_events() {
2326
  $string = '';
2327
  if ( is_array( $categories ) ) {
2328
  foreach ( $categories as $category ) {
2329
- if ( $category != $event->event_category ) {
2330
  $cats[] = mc_get_category_detail( $category, 'category_name' );
2331
  }
2332
  $string = implode( ', ', $cats );
2333
  }
2334
- echo ( '' != $string ) ? '(' . $string . ')' : '';
2335
  }
2336
  ?>
2337
  </td>
@@ -2538,15 +2558,15 @@ function mc_check_data( $action, $post, $i ) {
2538
  // ...AND there's no reason to allow it, since weekday events will NEVER happen on the weekend.
2539
  $begin = trim( $post['event_begin'][ $i ] );
2540
  $end = ( ! empty( $post['event_end'] ) ) ? trim( $post['event_end'][ $i ] ) : $post['event_begin'][ $i ];
2541
- if ( 'E' === $recur && 0 == ( date( 'w', mc_strtotime( $begin ) ) || 6 == date( 'w', mc_strtotime( $begin ) ) ) ) {
2542
- if ( 0 == date( 'w', mc_strtotime( $begin ) ) ) {
2543
  $newbegin = my_calendar_add_date( $begin, 1 );
2544
  if ( ! empty( $post['event_end'][ $i ] ) ) {
2545
  $newend = my_calendar_add_date( $end, 1 );
2546
  } else {
2547
  $newend = $newbegin;
2548
  }
2549
- } elseif ( 6 == date( 'w', mc_strtotime( $begin ) ) ) {
2550
  $newbegin = my_calendar_add_date( $begin, 2 );
2551
  if ( ! empty( $post['event_end'][ $i ] ) ) {
2552
  $newend = my_calendar_add_date( $end, 2 );
@@ -2561,24 +2581,24 @@ function mc_check_data( $action, $post, $i ) {
2561
  $end = ! empty( $post['event_end'][ $i ] ) ? trim( $post['event_end'][ $i ] ) : $begin;
2562
  }
2563
 
2564
- $begin = date( 'Y-m-d', mc_strtotime( $begin ) );// regardless of entry format, convert.
2565
  $time = ! empty( $post['event_time'][ $i ] ) ? trim( $post['event_time'][ $i ] ) : '';
2566
- if ( '' != $time ) {
2567
  $default_modifier = apply_filters( 'mc_default_event_length', '1 hour' );
2568
- $endtime = ! empty( $post['event_endtime'][ $i ] ) ? trim( $post['event_endtime'][ $i ] ) : date( 'H:i:s', mc_strtotime( $time . ' +' . $default_modifier ) );
2569
- if ( empty( $post['event_endtime'][ $i ] ) && date( 'H', mc_strtotime( $endtime ) ) == '00' ) {
2570
  // If one hour pushes event into next day, reset to 11:59pm.
2571
  $endtime = '23:59:00';
2572
  }
2573
  } else {
2574
  $endtime = ! empty( $post['event_endtime'][ $i ] ) ? trim( $post['event_endtime'][ $i ] ) : '';
2575
  }
2576
- $time = ( '' == $time || '00:00:00' === $time ) ? '00:00:00' : $time; // Set at midnight if not provided.
2577
- $endtime = ( '' == $endtime && '00:00:00' === $time ) ? '23:59:59' : $endtime; // Set at end of night if np.
2578
 
2579
  // Prevent setting enddate to incorrect value on copy.
2580
  if ( mc_strtotime( $end ) < mc_strtotime( $begin ) && 'copy' === $action ) {
2581
- $end = date( 'Y-m-d', ( mc_strtotime( $begin ) + ( mc_strtotime( $post['prev_event_end'] ) - mc_strtotime( $post['prev_event_begin'] ) ) ) );
2582
  }
2583
  if ( isset( $post['event_allday'] ) && 0 !== (int) $post['event_allday'] ) {
2584
  $time = '00:00:00';
@@ -2586,9 +2606,9 @@ function mc_check_data( $action, $post, $i ) {
2586
  }
2587
 
2588
  // Verify formats.
2589
- $time = date( 'H:i:s', mc_strtotime( $time ) );
2590
- $endtime = date( 'H:i:s', mc_strtotime( $endtime ) );
2591
- $end = date( 'Y-m-d', mc_strtotime( $end ) ); // regardless of entry format, convert.
2592
  $repeats = ( isset( $post['event_repeats'] ) ) ? trim( $post['event_repeats'] ) : 0;
2593
  $host = ! empty( $post['event_host'] ) ? $post['event_host'] : $user->ID;
2594
  $primary = false;
@@ -2601,7 +2621,7 @@ function mc_check_data( $action, $post, $i ) {
2601
  foreach ( $cats as $cat ) {
2602
  $private = mc_get_category_detail( $cat, 'category_private' );
2603
  // If a selected category is private, set that category as primary instead.
2604
- if ( 1 == $private ) {
2605
  $primary = $cat;
2606
  }
2607
  }
@@ -2616,7 +2636,7 @@ function mc_check_data( $action, $post, $i ) {
2616
  $expires = ! empty( $post['event_link_expires'] ) ? $post['event_link_expires'] : '0';
2617
  $approved = ( current_user_can( 'mc_approve_events' ) ) ? 1 : 0;
2618
  // Check for event_approved provides support for older versions of My Calendar Pro.
2619
- if ( isset( $post['event_approved'] ) && $post['event_approved'] != $approved ) {
2620
  $approved = absint( $post['event_approved'] );
2621
  }
2622
 
@@ -2628,11 +2648,11 @@ function mc_check_data( $action, $post, $i ) {
2628
  $event_holiday = ! empty( $post['event_holiday'] ) ? 1 : 0;
2629
  $group_id = (int) $post['event_group_id'];
2630
  $event_group_id = ( ( is_array( $post['event_begin'] ) && count( $post['event_begin'] ) > 1 ) || mc_event_is_grouped( $group_id ) ) ? $group_id : 0;
2631
- $event_span = ( ! empty( $post['event_span'] ) && 0 != $event_group_id ) ? 1 : 0;
2632
  $event_hide_end = ( ! empty( $post['event_hide_end'] ) ) ? (int) $post['event_hide_end'] : 0;
2633
- $event_hide_end = ( '' == $time || '23:59:59' === $time ) ? 1 : $event_hide_end; // Hide end time on all day events.
2634
  // Set location.
2635
- if ( 'none' != $location_preset && is_numeric( $location_preset ) ) {
2636
  $location = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM ' . my_calendar_locations_table() . ' WHERE location_id = %d', $location_preset ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2637
  $event_label = $location->location_label;
2638
  $event_street = $location->location_street;
@@ -2666,7 +2686,7 @@ function mc_check_data( $action, $post, $i ) {
2666
  $event_phone2 = ! empty( $post['event_phone2'] ) ? $post['event_phone2'] : '';
2667
  $event_access = ! empty( $post['event_access'] ) ? $post['event_access'] : '';
2668
  $event_access = ! empty( $post['event_access_hidden'] ) ? unserialize( $post['event_access_hidden'] ) : $event_access;
2669
- if ( isset( $post['mc_copy_location'] ) && 'on' === $post['mc_copy_location'] && 0 == $i ) {
2670
  // Only the first event, if adding multiples.
2671
  $add_loc = array(
2672
  'location_label' => $event_label,
@@ -2702,7 +2722,7 @@ function mc_check_data( $action, $post, $i ) {
2702
  }
2703
 
2704
  // Check for a valid or empty time.
2705
- $time = ( '' == $time ) ? '23:59:59' : date( 'H:i:00', mc_strtotime( $time ) );
2706
  $time_format_one = '/^([0-1][0-9]):([0-5][0-9]):([0-5][0-9])$/';
2707
  $time_format_two = '/^([2][0-3]):([0-5][0-9]):([0-5][0-9])$/';
2708
  if ( preg_match( $time_format_one, $time ) || preg_match( $time_format_two, $time ) ) {
@@ -2710,12 +2730,12 @@ function mc_check_data( $action, $post, $i ) {
2710
  $errors .= mc_show_error( __( 'The time field must either be blank or be entered in the format hh:mm am/pm', 'my-calendar' ), false );
2711
  }
2712
  // Check for a valid or empty end time.
2713
- if ( preg_match( $time_format_one, $endtime ) || preg_match( $time_format_two, $endtime ) || '' == $endtime ) {
2714
  } else {
2715
  $errors .= mc_show_error( __( 'The end time field must either be blank or be entered in the format hh:mm am/pm', 'my-calendar' ), false );
2716
  }
2717
  // Check for valid URL (blank or starting with http://).
2718
- if ( ! ( '' == $event_link || preg_match( '/^(http)(s?)(:)\/\//', $event_link ) ) ) {
2719
  $event_link = 'http://' . $event_link;
2720
  }
2721
  }
@@ -2726,7 +2746,7 @@ function mc_check_data( $action, $post, $i ) {
2726
  }
2727
  // Run checks on recurrence profile.
2728
  $valid_recur = array( 'W', 'B', 'M', 'U', 'Y', 'D', 'E' );
2729
- if ( ( 0 == $repeats && 'S' === $recur ) || ( ( $repeats >= 0 ) && in_array( $recur, $valid_recur ) ) ) {
2730
  $recur = $recur . $every;
2731
  } else {
2732
  // if it's not valid, assign a default value.
@@ -2744,18 +2764,17 @@ function mc_check_data( $action, $post, $i ) {
2744
  $errors .= mc_show_error( sprintf( __( 'That event conflicts with a <a href="%s">previously scheduled event</a>.', 'my-calendar' ), $conflict ), false );
2745
  }
2746
  }
2747
- $spam_content = ( '' != $desc ) ? $desc : $short;
2748
  $spam = mc_spam( $event_link, $spam_content, $post );
2749
  // Likelihood that event will be flagged as spam, have a zero start time and be legit is minimal. Just kill it.
2750
- if ( 1 == $spam && '1970-01-01' === $begin ) {
2751
  die;
2752
  }
2753
 
2754
  $current_user = wp_get_current_user();
2755
- $event_author = ( $event_author == $current_user->ID || current_user_can( 'mc_manage_events' ) ) ? $event_author : $current_user->ID;
2756
  $primary = ( ! $primary ) ? 1 : $primary;
2757
  $cats = ( isset( $cats ) && is_array( $cats ) ) ? $cats : array( 1 );
2758
-
2759
  $submit = array(
2760
  // Begin strings.
2761
  'event_begin' => $begin,
@@ -2802,9 +2821,9 @@ function mc_check_data( $action, $post, $i ) {
2802
  // Array: removed before DB insertion.
2803
  'event_categories' => $cats,
2804
  );
2805
- $errors = apply_filters( 'mc_fields_required', '', $submit );
2806
 
2807
- if ( '' == $errors ) {
2808
  $ok = true;
2809
 
2810
  $submit = array_map( 'mc_kses_post', $submit );
@@ -2877,7 +2896,7 @@ function mc_check_data( $action, $post, $i ) {
2877
  */
2878
  function mcs_check_conflicts( $begin, $time, $end, $endtime, $event_label ) {
2879
  global $wpdb;
2880
- $select_location = ( '' != $event_label ) ? "event_label = '" . esc_sql( $event_label ) . "' AND" : '';
2881
  $begin_time = $begin . ' ' . $time;
2882
  $end_time = $end . ' ' . $endtime;
2883
  // Need two queries; one to find outer events, one to find inner events.
@@ -2924,14 +2943,14 @@ function mc_compare( $update, $id ) {
2924
 
2925
  foreach ( $update as $k => $v ) {
2926
  // Event_recur and event_repeats always set to single and 0; event_begin and event_end need to be checked elsewhere.
2927
- if ( 'event_recur' != $k && 'event_repeats' != $k && 'event_begin' != $k && 'event_end' != $k ) {
2928
  $update_string .= trim( $v );
2929
  $event_string .= trim( $event->$k );
2930
  }
2931
  }
2932
  $update_hash = md5( $update_string );
2933
  $event_hash = md5( $event_string );
2934
- if ( $update_hash == $event_hash ) {
2935
  return false;
2936
  } else {
2937
  return true;
@@ -3026,7 +3045,7 @@ function mc_instance_list( $args ) {
3026
 
3027
  global $wpdb;
3028
  $output = '';
3029
- if ( true == $instance ) {
3030
  $sql = 'SELECT * FROM ' . my_calendar_event_table() . ' WHERE occur_id=%d ORDER BY occur_begin ASC';
3031
  } else {
3032
  $sql = 'SELECT * FROM ' . my_calendar_event_table() . ' WHERE occur_event_id=%d ORDER BY occur_begin ASC';
@@ -3038,8 +3057,8 @@ function mc_instance_list( $args ) {
3038
  $event_id = $result->occur_id;
3039
  $event = mc_get_event( $event_id );
3040
  $array = mc_create_tags( $event );
3041
- if ( in_array( $template, array( 'details', 'grid', 'list', 'mini' ) ) || mc_key_exists( $template ) ) {
3042
- if ( 1 == get_option( 'mc_use_' . $template . '_template' ) ) {
3043
  $template = mc_get_template( $template );
3044
  } elseif ( mc_key_exists( $template ) ) {
3045
  $template = mc_get_custom_template( $template );
@@ -3047,12 +3066,12 @@ function mc_instance_list( $args ) {
3047
  $details = my_calendar_draw_event( $event, 'single', $event->event_begin, $event->event_time, '' );
3048
  }
3049
  }
3050
- $item = ( '' != $list ) ? mc_draw_template( $array, $list ) : '';
3051
- if ( '' == $details ) {
3052
- $details = ( '' != $template ) ? mc_draw_template( $array, $template ) : '';
3053
  }
3054
  $output .= $item;
3055
- if ( '' == $list ) {
3056
  break;
3057
  }
3058
  }
@@ -3079,8 +3098,8 @@ function mc_admin_instances( $id, $occur = false ) {
3079
  $deleted = get_post_meta( $event_post, '_mc_deleted_instances', true );
3080
  if ( is_array( $results ) && is_admin() ) {
3081
  foreach ( $results as $result ) {
3082
- $begin = "<span id='occur_date_$result->occur_id'>" . date_i18n( mc_date_format(), mc_strtotime( $result->occur_begin ) ) . ', ' . date( get_option( 'mc_time_format' ), mc_strtotime( $result->occur_begin ) ) . '</span>';
3083
- if ( $result->occur_id == $occur ) {
3084
  $control = '';
3085
  $edit = '<em>' . __( 'Editing Now', 'my-calendar' ) . '</em>';
3086
  } else {
@@ -3103,7 +3122,7 @@ function mc_admin_instances( $id, $occur = false ) {
3103
  */
3104
  function mc_event_is_grouped( $group_id ) {
3105
  global $wpdb;
3106
- if ( 0 == $group_id ) {
3107
  return false;
3108
  } else {
3109
  $value = $wpdb->get_var( $wpdb->prepare( 'SELECT count( event_group_id ) FROM ' . my_calendar_table() . ' WHERE event_group_id = %d', $group_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
@@ -3147,40 +3166,40 @@ function mc_standard_datetime_input( $form, $has_data, $data, $instance, $contex
3147
 
3148
  if ( isset( $_GET['date'] ) ) {
3149
  $event = mc_get_event( (int) $_GET['date'] );
3150
- $event_begin = date( 'Y-m-d', mc_strtotime( $event->occur_begin ) );
3151
- $event_end = date( 'Y-m-d', mc_strtotime( $event->occur_end ) );
3152
  }
3153
  // Set event end to empty if matches begin. Makes input and changes easier.
3154
- if ( $event_begin == $event_end ) {
3155
  $event_end = '';
3156
  }
3157
- $starttime = ( mc_is_all_day( $data ) ) ? '' : date( apply_filters( 'mc_time_format', 'h:i A' ), mc_strtotime( $data->event_time ) );
3158
- $endtime = ( mc_is_all_day( $data ) ) ? '' : date( apply_filters( 'mc_time_format', 'h:i A' ), mc_strtotime( $data->event_endtime ) );
3159
  } else {
3160
- $event_begin = date( 'Y-m-d' );
3161
  $event_end = '';
3162
  $starttime = '';
3163
  $endtime = '';
3164
  }
3165
 
3166
  $allday = ( $has_data && ( mc_is_all_day( $data ) ) ) ? ' checked="checked"' : '';
3167
- $hide = ( $has_data && '1' == $data->event_hide_end ) ? ' checked="checked"' : '';
3168
  $allday_label = ( $has_data ) ? mc_notime_label( $data ) : get_option( 'mc_notime_text' );
3169
 
3170
- $form .= '<p>
3171
- <label for="mc_event_date" id="eblabel">' . __( 'Date (YYYY-MM-DD)', 'my-calendar' ) . '</label> <input type="text" id="mc_event_date" class="mc-datepicker" name="event_begin[]" size="10" value="" data-value="' . esc_attr( $event_begin ) . '" />
3172
  <label for="mc_event_time">' . __( 'From', 'my-calendar' ) . '</label>
3173
- <input type="text" id="mc_event_time" class="mc-timepicker" name="event_time[]" size="8" value="' . esc_attr( $starttime ) . '" />
3174
  <label for="mc_event_endtime">' . __( 'To', 'my-calendar' ) . '</label>
3175
- <input type="text" id="mc_event_endtime" class="mc-timepicker" name="event_endtime[]" size="8" value="' . esc_attr( $endtime ) . '" />
3176
- </p>
3177
  <ul>
3178
  <li><input type="checkbox" value="1" id="e_allday" name="event_allday"' . $allday . ' /> <label for="e_allday">' . __( 'All day event', 'my-calendar' ) . '</label> <span class="event_time_label"><label for="e_time_label">' . __( 'Time label:', 'my-calendar' ) . '</label> <input type="text" name="event_time_label" id="e_time_label" value="' . esc_attr( $allday_label ) . '" /> </li>
3179
  <li><input type="checkbox" value="1" id="e_hide_end" name="event_hide_end"' . $hide . ' /> <label for="e_hide_end">' . __( 'Hide end time', 'my-calendar' ) . '</label></li>
3180
  </ul>
3181
- <p>
3182
- <label for="mc_event_enddate" id="eelabel"><em>' . __( 'End Date (YYYY-MM-DD, optional)', 'my-calendar' ) . '</em></label> <input type="text" name="event_end[]" id="mc_event_enddate" class="mc-datepicker" size="10" value="" data-value="' . esc_attr( $event_end ) . '" />
3183
- </p>';
3184
 
3185
  return $form;
3186
  }
@@ -3188,13 +3207,15 @@ function mc_standard_datetime_input( $form, $has_data, $data, $instance, $contex
3188
  /**
3189
  * Date time inputs to add a single instance to recurring event info
3190
  *
 
 
3191
  * @return string form HTML
3192
  */
3193
- function mc_recur_datetime_input() {
3194
- $event_begin = date( 'Y-m-d' );
3195
- $event_end = '';
3196
- $starttime = '';
3197
- $endtime = '';
3198
 
3199
  $form = '<p>
3200
  <label for="r_begin">' . __( 'Date (YYYY-MM-DD)', 'my-calendar' ) . '</label> <input type="text" id="r_begin" class="mc-datepicker" name="recur_begin[]" size="10" value="" data-value="' . esc_attr( $event_begin ) . '" />
@@ -3248,7 +3269,7 @@ add_action( 'save_post', 'mc_post_update_event' );
3248
  * @param int $id Post ID.
3249
  */
3250
  function mc_post_update_event( $id ) {
3251
- if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE || wp_is_post_revision( $id ) || ! ( get_post_type( $id ) == 'mc-events' ) ) {
3252
  return $id;
3253
  }
3254
  $post = get_post( $id );
@@ -3376,9 +3397,9 @@ function mc_controls( $mode, $has_data, $event, $position = 'header' ) {
3376
  if ( 'edit' === $mode ) {
3377
  $controls['prev_status'] = "<input type='hidden' name='prev_event_status' value='" . absint( $event->event_approved ) . "' />";
3378
  if ( current_user_can( 'mc_approve_events' ) || current_user_can( 'mc_publish_events' ) ) { // Added by Roland P.
3379
- if ( $has_data && '1' == $event->event_approved ) {
3380
  $checked = ' checked="checked"';
3381
- } elseif ( $has_data && 0 == $event->event_approved ) {
3382
  $checked = '';
3383
  }
3384
  $status_control = "
@@ -3409,7 +3430,7 @@ function mc_controls( $mode, $has_data, $event, $position = 'header' ) {
3409
 
3410
  $controls_output = '';
3411
  foreach ( $controls as $key => $control ) {
3412
- if ( 'prev_status' != $key ) {
3413
  $control = '<li>' . $control . '</li>';
3414
  }
3415
 
@@ -3439,7 +3460,7 @@ function mc_related_events( $id ) {
3439
  $event = $result->occur_event_id;
3440
  $current = '<a href="' . admin_url( 'admin.php?page=my-calendar' ) . '&amp;mode=edit&amp;event_id=' . $event . '">';
3441
  $end = '</a>';
3442
- $begin = date_i18n( mc_date_format(), strtotime( $result->occur_begin ) ) . ', ' . date( get_option( 'mc_time_format' ), strtotime( $result->occur_begin ) );
3443
  $template = $current . $begin . $end;
3444
  $output .= "<li>$template</li>";
3445
  }
@@ -3462,7 +3483,7 @@ function mc_can_edit_category( $category, $user ) {
3462
  $permissions = get_user_meta( $user, 'mc_user_permissions', true );
3463
  $permissions = apply_filters( 'mc_user_permissions', $permissions, $category, $user );
3464
 
3465
- if ( ( ! $permissions || empty( $permissions ) ) || in_array( 'all', $permissions ) || in_array( $category, $permissions ) || current_user_can( 'manage_options' ) ) {
3466
  return true;
3467
  }
3468
 
@@ -3518,7 +3539,7 @@ function mc_can_edit_event( $event = false ) {
3518
  }
3519
  $return = false;
3520
 
3521
- if ( ( current_user_can( 'mc_manage_events' ) && $has_permissions ) || ( $user == $event_author ) ) {
3522
  $return = true;
3523
  }
3524
 
@@ -3541,33 +3562,33 @@ function mc_recur_string( $event ) {
3541
  switch ( $recur ) {
3542
  case 'D':
3543
  // Translators: number of days between repetitions.
3544
- $string = ( 1 == $every ) ? __( 'Daily', 'my-calendar' ) : sprintf( __( 'Every %d days', 'my-calendar' ), $every );
3545
  break;
3546
  case 'E':
3547
  // Translators: number of days between repetitions.
3548
- $string = ( 1 == $every ) ? __( 'Weekdays', 'my-calendar' ) : sprintf( __( 'Every %d weekdays', 'my-calendar' ), $every );
3549
  break;
3550
  case 'W':
3551
  // Translators: number of weeks between repetitions.
3552
- $string = ( 1 == $every ) ? __( 'Weekly', 'my-calendar' ) : sprintf( __( 'Every %d weeks', 'my-calendar' ), $every );
3553
  break;
3554
  case 'B':
3555
  $string = __( 'Bi-Weekly', 'my-calendar' );
3556
  break;
3557
  case 'M':
3558
  // Translators: number of months between repetitions.
3559
- $string = ( 1 == $every ) ? __( 'Monthly (by date)', 'my-calendar' ) : sprintf( __( 'Every %d months (by date)', 'my-calendar' ), $every );
3560
  break;
3561
  case 'U':
3562
  $string = __( 'Monthly (by day)', 'my-calendar' );
3563
  break;
3564
  case 'Y':
3565
  // Translators: number of years between repetitions.
3566
- $string = ( 1 == $every ) ? __( 'Yearly', 'my-calendar' ) : sprintf( __( 'Every %d years', 'my-calendar' ), $every );
3567
  break;
3568
  }
3569
  $eternity = _mc_increment_values( $recur );
3570
- if ( $event->event_repeats > 0 && 'S' != $recur ) {
3571
  // Translators: number of repeats.
3572
  $string .= ' ' . sprintf( __( '&ndash; %d Times', 'my-calendar' ), $event->event_repeats );
3573
  } elseif ( $eternity ) {
@@ -3590,7 +3611,7 @@ function mc_recur_options( $value ) {
3590
  $s = ( 'S' === $value ) ? ' selected="selected"' : '';
3591
  $d = ( 'D' === $value ) ? ' selected="selected"' : '';
3592
  $e = ( 'E' === $value ) ? ' selected="selected"' : '';
3593
- $w = ( 'W' === $value || 'B' == $value ) ? ' selected="selected"' : '';
3594
  $m = ( 'M' === $value ) ? ' selected="selected"' : '';
3595
  $u = ( 'U' === $value ) ? ' selected="selected"' : '';
3596
  $y = ( 'Y' === $value ) ? ' selected="selected"' : '';
@@ -3655,7 +3676,7 @@ function mc_get_instances( $id ) {
3655
  $return = array();
3656
 
3657
  foreach ( $results as $result ) {
3658
- $key = sanitize_key( date( 'Y-m-d', strtotime( $result->occur_begin ) ) );
3659
  $return[ $key ] = $result->occur_id;
3660
  }
3661
 
@@ -3686,9 +3707,9 @@ add_filter( 'mc_instance_data', 'mc_reuse_id', 10, 3 );
3686
  * @return array new data to insert
3687
  */
3688
  function mc_reuse_id( $data, $begin, $instances ) {
3689
- $begin = sanitize_key( date( 'Y-m-d', $begin ) );
3690
  $keys = array_keys( $instances );
3691
- if ( ! empty( $instances ) && in_array( $begin, $keys ) ) {
3692
  $restore_id = $instances[ $begin ];
3693
  $data['occur_id'] = $restore_id;
3694
  }
@@ -3707,9 +3728,9 @@ add_filter( 'mc_instance_format', 'mc_reuse_id_format', 10, 3 );
3707
  * @return array new formats for data
3708
  */
3709
  function mc_reuse_id_format( $format, $begin, $instances ) {
3710
- $begin = sanitize_key( date( 'Y-m-d', $begin ) );
3711
  $keys = array_keys( $instances );
3712
- if ( ! empty( $instances ) && in_array( $begin, $keys ) ) {
3713
  $format = array( '%d', '%s', '%s', '%d', '%d' );
3714
  }
3715
 
@@ -3749,11 +3770,11 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3749
  $recur = $recurs[0];
3750
  // Can't use 2nd value directly if it's two digits.
3751
  $every = ( isset( $recurs[1] ) ) ? str_replace( $recurs[0], '', $event->event_recur ) : 1;
3752
- if ( 'S' != $recur ) {
3753
  // If this event had a rep of 0, translate that.
3754
- $event_repetition = ( 0 != $event->event_repeats ) ? $event->event_repeats : _mc_increment_values( $recur );
3755
  $numforward = (int) $event_repetition;
3756
- if ( 'S' != $recur ) {
3757
  switch ( $recur ) {
3758
  case 'D':
3759
  for ( $i = 0; $i <= $numforward; $i ++ ) {
@@ -3762,8 +3783,8 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3762
 
3763
  $data = array(
3764
  'occur_event_id' => $id,
3765
- 'occur_begin' => date( 'Y-m-d H:i:s', $begin ),
3766
- 'occur_end' => date( 'Y-m-d H:i:s', $end ),
3767
  'occur_group_id' => $group_id,
3768
  );
3769
  if ( 'test' === $test && $i > 0 ) {
@@ -3789,11 +3810,11 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3789
  for ( $i = 0; $i <= $numforward; $i ++ ) {
3790
  $begin = my_calendar_add_date( $orig_begin, $i * $every, 0, 0 );
3791
  $end = my_calendar_add_date( $orig_end, $i * $every, 0, 0 );
3792
- if ( 0 != ( date( 'w', $begin ) && 6 != date( 'w', $begin ) ) ) {
3793
  $data = array(
3794
  'occur_event_id' => $id,
3795
- 'occur_begin' => date( 'Y-m-d H:i:s', $begin ),
3796
- 'occur_end' => date( 'Y-m-d H:i:s', $end ),
3797
  'occur_group_id' => $group_id,
3798
  );
3799
  if ( 'test' === $test && $i > 0 ) {
@@ -3819,8 +3840,8 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3819
  $end = strtotime( $orig_end . ' ' . ( $every * $i ) . ' weekdays' );
3820
  $data = array(
3821
  'occur_event_id' => $id,
3822
- 'occur_begin' => date( 'Y-m-d H:i:s', $begin ),
3823
- 'occur_end' => date( 'Y-m-d H:i:s', $end ),
3824
  'occur_group_id' => $group_id,
3825
  );
3826
  if ( 'test' === $test && $i > 0 ) {
@@ -3844,8 +3865,8 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3844
  $end = my_calendar_add_date( $orig_end, ( $i * 7 ) * $every, 0, 0 );
3845
  $data = array(
3846
  'occur_event_id' => $id,
3847
- 'occur_begin' => date( 'Y-m-d H:i:s', $begin ),
3848
- 'occur_end' => date( 'Y-m-d H:i:s', $end ),
3849
  'occur_group_id' => $group_id,
3850
  );
3851
  if ( 'test' === $test && $i > 0 ) {
@@ -3868,8 +3889,8 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3868
  $end = my_calendar_add_date( $orig_end, ( $i * 14 ), 0, 0 );
3869
  $data = array(
3870
  'occur_event_id' => $id,
3871
- 'occur_begin' => date( 'Y-m-d H:i:s', $begin ),
3872
- 'occur_end' => date( 'Y-m-d H:i:s', $end ),
3873
  'occur_group_id' => $group_id,
3874
  );
3875
  if ( 'test' === $test && $i > 0 ) {
@@ -3892,8 +3913,8 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3892
  $end = my_calendar_add_date( $orig_end, 0, $i * $every, 0 );
3893
  $data = array(
3894
  'occur_event_id' => $id,
3895
- 'occur_begin' => date( 'Y-m-d H:i:s', $begin ),
3896
- 'occur_end' => date( 'Y-m-d H:i:s', $end ),
3897
  'occur_group_id' => $group_id,
3898
  );
3899
  if ( 'test' === $test && $i > 0 ) {
@@ -3912,14 +3933,14 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3912
  break;
3913
  case 'U':
3914
  // Important to keep track of which date variables are strings and which are timestamps.
3915
- $week_of_event = week_of_month( date( 'd', strtotime( $event->event_begin ) ) );
3916
  $newbegin = my_calendar_add_date( $orig_begin, 28, 0, 0 );
3917
  $newend = my_calendar_add_date( $orig_end, 28, 0, 0 );
3918
  $fifth_week = $event->event_fifth_week;
3919
  $data = array(
3920
  'occur_event_id' => $id,
3921
- 'occur_begin' => date( 'Y-m-d H:i:s', strtotime( $orig_begin ) ),
3922
- 'occur_end' => date( 'Y-m-d H:i:s', strtotime( $orig_end ) ),
3923
  'occur_group_id' => $group_id,
3924
  );
3925
 
@@ -3933,26 +3954,26 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3933
  }
3934
  $numforward = ( $numforward - 1 );
3935
  for ( $i = 0; $i <= $numforward; $i ++ ) {
3936
- $next_week_diff = ( date( 'm', $newbegin ) == date( 'm', my_calendar_add_date( date( 'Y-m-d', $newbegin ), 7, 0, 0 ) ) ) ? false : true;
3937
- $move_event = ( ( 1 == $fifth_week ) && ( ( week_of_month( date( 'd', $newbegin ) ) + 1 ) == $week_of_event ) && true == $next_week_diff ) ? true : false;
3938
- if ( week_of_month( date( 'd', $newbegin ) ) == $week_of_event || true == $move_event ) {
3939
  } else {
3940
- $newbegin = my_calendar_add_date( date( 'Y-m-d H:i:s', $newbegin ), 7, 0, 0 );
3941
- $newend = my_calendar_add_date( date( 'Y-m-d H:i:s', $newend ), 7, 0, 0 );
3942
- $move_event = ( 1 == $fifth_week && week_of_month( date( 'd', $newbegin ) ) + 1 == $week_of_event ) ? true : false;
3943
- if ( week_of_month( date( 'd', $newbegin ) ) == $week_of_event || true == $move_event ) {
3944
  } else {
3945
- $newbegin = my_calendar_add_date( date( 'Y-m-d H:i:s', $newbegin ), 14, 0, 0 );
3946
- $newend = my_calendar_add_date( date( 'Y-m-d H:i:s', $newend ), 14, 0, 0 );
3947
  }
3948
  }
3949
  $data = array(
3950
  'occur_event_id' => $id,
3951
- 'occur_begin' => date( 'Y-m-d H:i:s', $newbegin ),
3952
- 'occur_end' => date( 'Y-m-d H:i:s', $newend ),
3953
  'occur_group_id' => $group_id,
3954
  );
3955
- if ( 'test' == $test && $i > 0 ) {
3956
  return $data;
3957
  }
3958
  $return[] = $data;
@@ -3964,8 +3985,8 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3964
  $wpdb->insert( my_calendar_event_table(), $data, $format );
3965
  }
3966
  }
3967
- $newbegin = my_calendar_add_date( date( 'Y-m-d H:i:s', $newbegin ), 28, 0, 0 );
3968
- $newend = my_calendar_add_date( date( 'Y-m-d H:i:s', $newend ), 28, 0, 0 );
3969
  }
3970
  break;
3971
  case 'Y':
@@ -3974,8 +3995,8 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3974
  $end = my_calendar_add_date( $orig_end, 0, 0, $i * $every );
3975
  $data = array(
3976
  'occur_event_id' => $id,
3977
- 'occur_begin' => date( 'Y-m-d H:i:s', $begin ),
3978
- 'occur_end' => date( 'Y-m-d H:i:s', $end ),
3979
  'occur_group_id' => $group_id,
3980
  );
3981
  if ( 'test' === $test && $i > 0 ) {
@@ -3999,8 +4020,8 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
3999
  $end = strtotime( $orig_end );
4000
  $data = array(
4001
  'occur_event_id' => $id,
4002
- 'occur_begin' => date( 'Y-m-d H:i:s', $begin ),
4003
- 'occur_end' => date( 'Y-m-d H:i:s', $end ),
4004
  'occur_group_id' => $group_id,
4005
  );
4006
  if ( ! $test ) {
@@ -4013,7 +4034,7 @@ function mc_increment_event( $id, $post = array(), $test = false, $instances = a
4013
  }
4014
  }
4015
 
4016
- if ( true == $test ) {
4017
  return $return;
4018
  }
4019
 
27
  if ( 'add' === $action || 'copy' === $action ) {
28
  $post_id = mc_create_event_post( $data, $event_id );
29
  } elseif ( 'edit' === $action ) {
30
+ if ( isset( $_POST['event_post'] ) && ( 0 === (int) $_POST['event_post'] || '' === $_POST['event_post'] ) ) {
31
  $post_id = mc_create_event_post( $data, $event_id );
32
  } else {
33
  $post_id = ( isset( $_POST['event_post'] ) ) ? absint( $_POST['event_post'] ) : false;
50
  }
51
  }
52
  // if any selected category is private, make private.
53
+ if ( 'private' !== $privacy ) {
54
+ $privacy = ( '1' === mc_get_category_detail( $category, 'category_private' ) ) ? 'private' : 'publish';
55
  }
56
  $terms[] = (int) $term;
57
  }
79
  }
80
  $post_id = wp_update_post( $my_post );
81
  wp_set_object_terms( $post_id, $terms, 'mc-event-category' );
82
+ if ( '' === $data['event_image'] ) {
83
  delete_post_thumbnail( $post_id );
84
  } else {
85
  // check POST data.
114
  $description = isset( $data['event_desc'] ) ? $data['event_desc'] : '';
115
  $image = isset( $data['event_image'] ) ? esc_url_raw( $data['event_image'] ) : '';
116
  $guid = get_post_meta( $post_id, '_mc_guid', true );
117
+ if ( '' === $guid ) {
118
  $guid = md5( $post_id . $event_id . $data['event_title'] );
119
  update_post_meta( $post_id, '_mc_guid', $guid );
120
  }
153
  foreach ( $categories as $category ) {
154
  $term = mc_get_category_detail( $category, 'category_term' );
155
  // if any selected category is private, make private.
156
+ if ( 'private' !== $privacy ) {
157
+ $privacy = ( '1' === mc_get_category_detail( $category, 'category_private' ) ) ? 'private' : 'publish';
158
  }
159
  $terms[] = (int) $term;
160
  }
174
  'post_status' => $post_status,
175
  'post_author' => $auth,
176
  'post_name' => sanitize_title( $title ),
177
+ 'post_date' => current_time( 'Y-m-d H:i:s' ),
178
  'post_type' => $type,
179
  'post_excerpt' => $excerpt,
180
  );
268
  foreach ( $events as $value ) {
269
  $value = (int) $value;
270
  $total = count( $events );
271
+ if ( 'delete' === $action ) {
272
  $result = $wpdb->get_results( $wpdb->prepare( 'SELECT event_author FROM ' . my_calendar_table() . ' WHERE event_id = %d', $value ), ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
273
  if ( mc_can_edit_event( $value ) ) {
274
  $occurrences = 'DELETE FROM ' . my_calendar_event_table() . ' WHERE occur_event_id = %d';
278
  $i ++;
279
  }
280
  }
281
+ if ( 'delete' !== $action && current_user_can( 'mc_approve_events' ) ) {
282
  $ids[] = (int) $value;
283
  $prepare[] = '%d';
284
  $i ++;
304
  break;
305
  case 'unspam':
306
  $sql = 'UPDATE ' . my_calendar_table() . ' SET event_flagged = 0 WHERE event_id IN (' . $prepared . ')';
 
307
  // send notifications.
308
  foreach ( $ids as $id ) {
309
  $post_ID = mc_get_event_post( $id );
396
  * @return string
397
  */
398
  function mc_show_error( $message, $echo = true ) {
399
+ if ( trim( $message ) === '' ) {
400
  return '';
401
  }
402
  $message = strip_tags( $message, mc_admin_strip_tags() );
418
  * @return string
419
  */
420
  function mc_show_notice( $message, $echo = true ) {
421
+ if ( trim( $message ) === '' ) {
422
  return '';
423
  }
424
  $message = strip_tags( $message, mc_admin_strip_tags() );
443
  if ( isset( $_GET['date'] ) ) {
444
  $event_instance = (int) $_GET['date'];
445
  $inst = $wpdb->get_var( $wpdb->prepare( 'SELECT occur_begin FROM ' . my_calendar_event_table() . ' WHERE occur_id=%d', $event_instance ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
446
+ $instance_date = '(' . mc_date( 'Y-m-d', mc_strtotime( $inst ), false ) . ')';
447
  } else {
448
  $instance_date = '';
449
  } ?>
614
  <div class="wrap my-calendar-admin">
615
  <?php
616
  my_calendar_check_db();
617
+ if ( '2' === get_site_option( 'mc_multisite' ) ) {
618
+ if ( '0' === get_option( 'mc_current_table' ) ) {
619
  $message = __( 'Currently editing your local calendar', 'my-calendar' );
620
  } else {
621
  $message = __( 'Currently editing your central calendar', 'my-calendar' );
690
  $event = mc_get_first_event( $event_id );
691
  my_calendar_send_email( $event );
692
  }
693
+ if ( '0' === (string) $add['event_approved'] ) {
694
  $message = mc_show_notice( __( 'Event draft saved.', 'my-calendar' ), false );
695
  } else {
696
  // jd_doTwitterAPIPost was changed to wpt_post_to_twitter on 1.19.2017.
697
+ if ( function_exists( 'wpt_post_to_twitter' ) && isset( $_POST['mc_twitter'] ) && '' !== trim( $_POST['mc_twitter'] ) ) {
698
  wpt_post_to_twitter( stripslashes( $_POST['mc_twitter'] ) );
699
  }
700
  if ( mc_get_uri( 'boolean' ) ) {
704
  } else {
705
  $event_link = false;
706
  }
707
+ if ( '' !== trim( $event_error ) ) {
708
  $message = $event_error;
709
  } else {
710
  $message = __( 'Event added. It will now show on the calendar.', 'my-calendar' );
718
  }
719
  }
720
 
721
+ if ( 'edit' === $action && true === $proceed ) {
722
  $result = true;
723
  // Translators: URL to view calendar.
724
  $url = sprintf( __( 'View <a href="%s">your calendar</a>.', 'my-calendar' ), mc_get_uri() );
729
  mc_update_category_relationships( $cats, $event_id );
730
 
731
  $update = apply_filters( 'mc_before_save_update', $update, $event_id );
732
+ $endtime = mc_date( 'H:i:00', mc_strtotime( $update['event_endtime'] ), false );
733
  $prev_eb = ( isset( $_POST['prev_event_begin'] ) ) ? $_POST['prev_event_begin'] : '';
734
  $prev_et = ( isset( $_POST['prev_event_time'] ) ) ? $_POST['prev_event_time'] : '';
735
  $prev_ee = ( isset( $_POST['prev_event_end'] ) ) ? $_POST['prev_event_end'] : '';
736
  $prev_eet = ( isset( $_POST['prev_event_endtime'] ) ) ? $_POST['prev_event_endtime'] : '';
737
+ $update_time = mc_date( 'H:i:00', mc_strtotime( $update['event_time'] ), false );
738
+ $date_changed = ( $update['event_begin'] !== $prev_eb || $update_time !== $prev_et || $update['event_end'] !== $prev_ee || ( $endtime !== $prev_eet && ( '' !== $prev_eet && '23:59:59' !== $endtime ) ) ) ? true : false;
739
  if ( isset( $_POST['event_instance'] ) ) {
740
  // compares the information sent to the information saved for a given event.
741
  $is_changed = mc_compare( $update, $event_id );
745
  // if group ID == 0, need to add group ID to both records.
746
  // if a single instance is edited, it should not inherit recurring settings from parent.
747
  $update['event_recur'] = 'S1';
748
+ if ( 0 === (int) $update['event_group_id'] ) {
749
  $update['event_group_id'] = $event_id;
750
  mc_update_data( $event_id, 'event_group_id', $event_id );
751
  }
760
  mc_update_category_relationships( $cats, $new_event );
761
  $result = mc_update_instance( $event_instance, $new_event, $update );
762
  } else {
763
+ if ( $update['event_begin'][0] === $_POST['prev_event_begin'] && $update['event_end'][0] === $_POST['prev_event_end'] ) {
764
  // There were no changes at all.
765
  } else {
766
  // Only dates were changed.
779
  '%d'
780
  );
781
  if ( isset( $_POST['prev_event_repeats'] ) && isset( $_POST['prev_event_recur'] ) ) {
782
+ $recur_changed = ( $update['event_repeats'] !== $_POST['prev_event_repeats'] || $update['event_recur'] !== $_POST['prev_event_recur'] ) ? true : false;
783
  } else {
784
  $recur_changed = false;
785
  }
802
  // do an action using the $action and processed event data.
803
  $event_approved = ( current_user_can( 'mc_approve_events' ) ) ? 1 : 0;
804
  // check for event_approved provides support for older versions of My Calendar Pro.
805
+ if ( isset( $post['event_approved'] ) && $post['event_approved'] !== $event_approved ) {
806
  $event_approved = absint( $post['event_approved'] );
807
  }
808
  if ( isset( $_POST['prev_event_status'] ) ) {
809
  // Don't execute transition actions if prev status not known.
810
+ do_action( 'mc_transition_event', (int) $_POST['prev_event_status'], $event_approved, $action, $data, $event_id );
811
  }
812
  $message = mc_show_notice( __( 'Event updated successfully', 'my-calendar' ) . ". $url", false );
813
  }
857
  function mc_update_category_relationships( $cats, $event_id ) {
858
  global $wpdb;
859
  $old_cats = mc_get_categories( $event_id, 'testing' );
860
+ if ( $old_cats === $cats ) {
861
  return;
862
  }
863
  $wpdb->delete( my_calendar_category_relationships_table(), array( 'event_id' => $event_id ), '%d' );
891
  'event_id' => $event_id,
892
  );
893
  $edit_link = ' <a href="' . esc_url( add_query_arg( $args, admin_url( 'admin.php?page=my-calendar' ) ) ) . '">' . __( 'Edit Event', 'my-calendar' ) . '</a>';
894
+ $test = ( '' !== $test ) ? str_replace( '</p></div>', "$edit_link</p></div>", $test ) : $test;
895
 
896
  return $test;
897
  }
991
 
992
  apply_filters( 'mc_event_notices', '', $data, $event_id );
993
 
994
+ if ( is_object( $data ) && 1 !== (int) $data->event_approved && 'edit' === $mode ) {
995
+ if ( 0 === (int) $data->event_approved ) {
996
  mc_show_error( __( '<strong>Draft</strong>: Publish this event to show it on the calendar.', 'my-calendar' ) );
997
  } else {
998
  mc_show_error( __( '<strong>Trash</strong>: Remove from the trash to show this event on the calendar.', 'my-calendar' ) );
1028
  * @return string.
1029
  */
1030
  function mc_show_edit_block( $field ) {
1031
+ $admin = ( 'true' === get_option( 'mc_input_options_administrators' ) && current_user_can( 'manage_options' ) ) ? true : false;
1032
+ $input = get_option( 'mc_input_options' );
1033
+ // Array of all options in off position.
1034
+ $defaults = array(
1035
+ 'event_location_dropdown' => 'on',
1036
+ 'event_short' => 'on',
1037
+ 'event_desc' => 'on',
1038
+ 'event_category' => 'on',
1039
+ 'event_image' => 'on',
1040
+ 'event_link' => 'on',
1041
+ 'event_recurs' => 'on',
1042
+ 'event_open' => 'on',
1043
+ 'event_location' => 'off',
1044
+ 'event_specials' => 'on',
1045
+ 'event_access' => 'on',
1046
+ 'event_host' => 'on',
1047
+ );
1048
+
1049
+ $input = array_merge( $defaults, $input );
1050
  $user = get_current_user_id();
1051
  $screen = get_current_screen();
1052
  $option = $screen->get_option( 'mc_show_on_page', 'option' );
1065
  return false;
1066
  }
1067
  } else {
1068
+ if ( 'off' === $input[ $field ] || '' === $input[ $field ] ) {
1069
  return false;
1070
  } elseif ( 'off' === $show[ $field ] ) {
1071
  return false;
1166
  $image = ( has_post_thumbnail( $data->event_post ) ) ? get_the_post_thumbnail_url( $data->event_post ) : $data->event_image;
1167
  $image_id = ( has_post_thumbnail( $data->event_post ) ) ? get_post_thumbnail_id( $data->event_post ) : '';
1168
  } else {
1169
+ $image = ( $has_data && '' !== $data->event_image ) ? $data->event_image : '';
1170
  $image_id = '';
1171
  }
1172
  if ( $show_block ) {
1174
  <div class="mc-image-upload field-holder">
1175
  <input type="hidden" name="event_image_id" value="' . esc_attr( $image_id ) . '" class="textfield" id="e_image_id" />
1176
  <label for="e_image">' . __( 'Add an image:', 'my-calendar' ) . '</label><br /><input type="text" name="event_image" id="e_image" size="60" value="' . esc_attr( $image ) . '" placeholder="http://yourdomain.com/image.jpg" /> <button type="button" class="button textfield-field">' . __( 'Upload', 'my-calendar' ) . '</button>';
1177
+ if ( '' !== $image ) {
1178
  $image = ( has_post_thumbnail( $data->event_post ) ) ? get_the_post_thumbnail_url( $data->event_post ) : $data->event_image;
1179
  $return .= '<div class="event_image"><img src="' . esc_attr( $image ) . '" alt="" /></div>';
1180
  } else {
1215
  case 'event_link':
1216
  if ( $show_block ) {
1217
  $value = ( $has_data ) ? esc_url( $data->event_link ) : '';
1218
+ if ( $has_data && '1' === $data->event_link_expires ) {
1219
  $checked = ' checked="checked"';
1220
+ } elseif ( $has_data && '0' === $data->event_link_expires ) {
1221
  $checked = '';
1222
  } elseif ( 'true' === get_option( 'mc_event_link_expires' ) ) {
1223
  $checked = ' checked="checked"';
1234
  $recurs = str_split( $event_recur, 1 );
1235
  $recur = $recurs[0];
1236
  $every = ( isset( $recurs[1] ) ) ? str_replace( $recurs[0], '', $event_recur ) : 1;
1237
+ if ( 1 === (int) $every && 'B' === $recur ) {
1238
  $every = 2;
1239
  }
1240
  $prev = '<input type="hidden" name="prev_event_repeats" value="' . $data->event_repeats . '" /><input type="hidden" name="prev_event_recur" value="' . $data->event_recur . '" />';
1243
  $every = 1;
1244
  $prev = '';
1245
  }
1246
+ if ( is_object( $data ) && null !== $data->event_repeats ) {
1247
  $repeats = $data->event_repeats;
1248
  } else {
1249
  $repeats = 0;
1269
  </div>
1270
  ' . $post;
1271
  } else {
1272
+ if ( '' === $every && '' === $repeats ) {
1273
  $every = 'S';
1274
  $repeats = '0';
1275
  }
1320
  return;
1321
  }
1322
  $return = apply_filters( 'mc_show_block', $return, $data, $field, $has_data );
1323
+ if ( true === $echo ) {
1324
  echo $return;
1325
  } else {
1326
  return $return;
1341
  // If this event is single, skip query.
1342
  $single_recur = ( 'S' === $data->event_recur || 'S1' === $data->event_recur ) ? true : false;
1343
  // If event starts and ends on same day, skip query.
1344
+ $start_end = ( $data->event_begin === $data->event_end ) ? true : false;
1345
  // Only run test when an event is set up to recur & starts/ends on different days.
1346
  if ( ! $single_recur && ! $start_end ) {
1347
  $check = mc_increment_event( $data->event_id, array(), 'test' );
1403
  }
1404
  echo apply_filters( 'mc_before_event_form', '', $event_id );
1405
  $action = add_query_arg( $query_args, admin_url( 'admin.php?page=my-calendar' ) );
1406
+ $group_id = ( ! empty( $data->event_group_id ) && 'copy' !== $mode ) ? $data->event_group_id : mc_group_id();
1407
+ $event_author = ( 'edit' !== $mode ) ? $user_ID : $data->event_author;
1408
  ?>
1409
  <form id="my-calendar" method="post" action="<?php echo $action; ?>">
1410
  <div>
1458
  ?>
1459
  </div>
1460
  <?php
1461
+ if ( ! empty( $_GET['date'] ) && 'S' !== $data->event_recur ) {
1462
  $event = mc_get_event( $instance );
1463
  $date = date_i18n( mc_date_format(), mc_strtotime( $event->occur_begin ) );
1464
  // Translators: Date of a specific event occurrence.
1475
  <input type="text" id="e_title" name="event_title" size="50" maxlength="255" value="<?php echo ( $has_data ) ? apply_filters( 'mc_manage_event_title', stripslashes( esc_attr( $data->event_title ) ), $data ) : ''; ?>" />
1476
  </p>
1477
  <?php
1478
+ if ( is_object( $data ) && 1 === (int) $data->event_flagged ) {
1479
+ if ( '0' === $data->event_flagged ) {
1480
  $flagged = ' checked="checked"';
1481
+ } elseif ( '1' === $data->event_flagged ) {
1482
  $flagged = '';
1483
  }
1484
  ?>
1493
  apply_filters( 'mc_insert_custom_fields', '', $has_data, $data );
1494
 
1495
  if ( function_exists( 'wpt_post_to_twitter' ) && current_user_can( 'wpt_can_tweet' ) ) {
1496
+ if ( ! ( 'edit' === $mode && 1 === (int) $data->event_approved ) ) {
1497
  $mc_allowed = absint( ( get_option( 'wpt_tweet_length' ) ) ? get_option( 'wpt_tweet_length' ) : 140 );
1498
  ?>
1499
  <p class='mc-twitter'>
1533
  <?php echo apply_filters( 'mc_datetime_inputs', '', $has_data, $data, 'admin' ); ?>
1534
  </div>
1535
  <?php
1536
+ if ( 'edit' !== $mode ) {
1537
  $span_checked = '';
1538
+ if ( $has_data && '1' === $data->event_span ) {
1539
  $span_checked = ' checked="checked"';
1540
+ } elseif ( $has_data && '0' === $data->event_span ) {
1541
  $span_checked = '';
1542
  }
1543
  ?>
1557
  ?>
1558
  <div id='mc-accordion'>
1559
  <?php
1560
+ if ( 'S' !== $data->event_recur ) {
1561
  ?>
1562
  <h4><span class='dashicons' aria-hidden='true'> </span><button type="button" class="button-link"><?php _e( 'Scheduled dates for this event', 'my-calendar' ); ?></button></h4>
1563
  <div>
1577
  </ul>
1578
  <p><button type='button' class='add-occurrence' aria-expanded="false"><span class='dashicons' aria-hidden='true'> </span><?php _e( 'Add another date', 'my-calendar' ); ?></button></p>
1579
  <div class='mc_add_new'>
1580
+ <?php echo mc_recur_datetime_input( $data ); ?>
1581
  <button type='button' class='save-occurrence'><?php _e( 'Add Date', 'my-calendar' ); ?></button>
1582
  </div>
1583
  </div>
1584
  <?php
1585
  }
1586
+ if ( 0 !== (int) $data->event_group_id ) {
1587
  $edit_group_url = admin_url( 'admin.php?page=my-calendar-groups&mode=edit&event_id=' . $data->event_id . '&group_id=' . $data->event_group_id );
1588
  ?>
1589
  <h4><span class='dashicons' aria-hidden='true'> </span><button type="button" class="button-link"><?php _e( 'Related Events:', 'my-calendar' ); ?></button> (<a href='<?php echo $edit_group_url; ?>'><?php _e( 'Edit group', 'my-calendar' ); ?></a>)
1622
  </div>
1623
  <?php
1624
  $custom_fields = apply_filters( 'mc_event_details', '', $has_data, $data, 'admin' );
1625
+ if ( '' !== $custom_fields ) {
1626
  ?>
1627
  <div class="ui-sortable meta-box-sortables">
1628
  <div class="postbox">
1668
  } else {
1669
  $event_location = false;
1670
  }
1671
+ if ( (int) $loc->location_id === (int) $event_location ) {
1672
  // Translators: label for current location.
1673
  $current_location = "<span id='mc-current-location'>" . sprintf( __( 'Current location: %s', 'my-calendar' ), $loc_name ) . '</span>';
1674
  $current_location .= "<input type='hidden' name='preset_location' value='$event_location' />";
1708
  $hol_checked = ( 'true' === get_option( 'mc_skip_holidays' ) ) ? ' checked="checked"' : '';
1709
  $fifth_checked = ( 'true' === get_option( 'mc_no_fifth_week' ) ) ? ' checked="checked"' : '';
1710
  if ( $has_data ) {
1711
+ $hol_checked = ( '1' === $data->event_holiday ) ? ' checked="checked"' : '';
1712
+ $fifth_checked = ( '1' === $data->event_fifth_week ) ? ' checked="checked"' : '';
1713
  }
1714
  ?>
1715
  <div class="ui-sortable meta-box-sortables">
1734
  <?php
1735
  } else {
1736
  if ( $has_data ) {
1737
+ $event_holiday = ( '1' === $data->event_holiday ) ? 'true' : 'false';
1738
+ $event_fifth = ( '1' === $data->event_fifth_week ) ? 'true' : 'false';
1739
  } else {
1740
  $event_holiday = get_option( 'mc_skip_holidays' );
1741
  $event_fifth = get_option( 'mc_no_fifth_week' );
1773
  */
1774
  function mc_get_users( $group = 'authors' ) {
1775
  global $blog_id;
1776
+ $users = apply_filters( 'mc_get_users', false, $group, $blog_id );
1777
+ if ( $users ) {
1778
+ return $users;
1779
+ }
1780
  $count = count_users( 'time' );
1781
  $args = array(
1782
  'blog_id' => $blog_id,
1802
  $users = mc_get_users( $group );
1803
  $options = '';
1804
  foreach ( $users as $u ) {
1805
+ if ( in_array( $u->ID, $selected, true ) ) {
1806
  $checked = ' selected="selected"';
1807
  } else {
1808
  $checked = '';
1809
  }
1810
+ $display_name = ( '' === $u->display_name ) ? $u->user_nicename : $u->display_name;
1811
  $options .= '<option value="' . $u->ID . '"' . $checked . ">$display_name</option>\n";
1812
  }
1813
 
1869
  $label = $a;
1870
  $checked = '';
1871
  if ( is_array( $events_access ) ) {
1872
+ $checked = ( in_array( $k, $events_access, true ) || in_array( $a, $events_access, true ) ) ? ' checked="checked"' : '';
1873
  }
1874
  $item = sprintf( '<li><input type="checkbox" id="%1$s" name="events_access[]" value="%4$s" class="checkbox" %2$s /> <label for="%1$s">%3$s</label></li>', esc_attr( $id ), $checked, esc_html( $label ), esc_attr( $a ) );
1875
  $form .= $item;
1905
  $sortdir = 'default';
1906
  }
1907
 
1908
+ $default_direction = ( '' === get_option( 'mc_default_direction', '' ) ) ? 'ASC' : get_option( 'mc_default_direction' );
1909
  $sortbydirection = ( 'default' === $sortdir ) ? $default_direction : $sortdir;
1910
 
1911
  $sortby = ( isset( $_GET['sort'] ) ) ? $_GET['sort'] : get_option( 'mc_default_sort' );
1990
  if ( 'event_label' === $restrict ) {
1991
  $filter = "'$filter'";
1992
  }
1993
+ if ( '' === $limit && '' !== $filter ) {
1994
  $limit = "WHERE $restrict = $filter";
1995
+ } elseif ( '' !== $limit && '' !== $filter ) {
1996
  $limit .= "AND $restrict = $filter";
1997
  }
1998
+ if ( '' === $filter || ! $allow_filters ) {
1999
  $filtered = '';
2000
  } else {
2001
  $filtered = "<span class='dashicons dashicons-no' aria-hidden='true'></span><a href='" . admin_url( 'admin.php?page=my-calendar-manage' ) . "'>" . __( 'Clear filters', 'my-calendar' ) . '</a>';
2009
  $items_per_page = $screen->get_option( 'per_page', 'default' );
2010
  }
2011
  // Default limits.
2012
+ if ( '' === $limit ) {
2013
+ $limit .= ( 'event_flagged' !== $restrict ) ? ' WHERE event_flagged = 0' : '';
2014
  } else {
2015
+ $limit .= ( 'event_flagged' !== $restrict ) ? ' AND event_flagged = 0' : '';
2016
  }
2017
  if ( isset( $_POST['mcs'] ) ) {
2018
  $query = $_POST['mcs'];
2019
  $limit .= mc_prepare_search_query( $query );
2020
  }
2021
  $query_limit = ( ( $current - 1 ) * $items_per_page );
2022
+ $limit .= ( 'archived' !== $restrict ) ? ' AND event_status = 1' : ' AND event_status = 0';
2023
+ if ( 'event_category' !== $sortbyvalue ) {
2024
  $events = $wpdb->get_results( $wpdb->prepare( 'SELECT SQL_CALC_FOUND_ROWS event_id FROM ' . my_calendar_table() . " $limit ORDER BY $sortbyvalue $sortbydirection " . 'LIMIT %d, %d', $query_limit, $items_per_page ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
2025
  } else {
2026
  $limit = str_replace( array( 'WHERE ' ), '', $limit );
2101
  </div>
2102
  <div>
2103
  <label for="mc_search" class='screen-reader-text'><?php _e( 'Search', 'my-calendar' ); ?></label>
2104
+ <input type='text' role='search' name='mcs' id='mc_search' value='<?php echo esc_attr( $search_text ); ?>' />
2105
  <input type='submit' value='<?php _e( 'Search Events', 'my-calendar' ); ?>' class='button-secondary'/>
2106
  </div>
2107
  </form>
2150
  <tr>
2151
  <th scope="col" style="width: 50px;"><input type='checkbox' class='selectall' id='mass_edit'/>
2152
  <label for='mass_edit' class="screen-reader-text"><?php _e( 'Check/Uncheck all', 'my-calendar' ); ?></label>
2153
+ <a class="<?php echo ( 1 === (int) $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=1$sorting" ); ?>"><?php _e( 'ID', 'my-calendar' ); ?></a>
2154
  </th>
2155
  <th scope="col">
2156
+ <a class="<?php echo ( 2 === (int) $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=2$sorting" ); ?>"><?php _e( 'Title', 'my-calendar' ); ?></a>
2157
  </th>
2158
  <th scope="col">
2159
+ <a class="<?php echo ( 7 === (int) $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=7$sorting" ); ?>"><?php _e( 'Location', 'my-calendar' ); ?></a>
2160
  </th>
2161
  <th scope="col">
2162
+ <a class="<?php echo ( 4 === (int) $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=4$sorting" ); ?>"><?php _e( 'Date/Time', 'my-calendar' ); ?></a>
2163
  </th>
2164
  <th scope="col">
2165
+ <a class="<?php echo ( 5 === (int) $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=5$sorting" ); ?>"><?php _e( 'Author', 'my-calendar' ); ?></a>
2166
  </th>
2167
  <th scope="col">
2168
+ <a class="<?php echo ( 6 === (int) $sortby ) ? 'active' : ''; ?>" href="<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;sort=6$sorting" ); ?>"><?php _e( 'Category', 'my-calendar' ); ?></a>
2169
  </th>
2170
  </tr>
2171
  </thead>
2180
  continue;
2181
  }
2182
  $class = ( 'alternate' === $class ) ? 'even' : 'alternate';
2183
+ $pending = ( 0 === (int) $event->event_approved ) ? 'pending' : '';
2184
+ $trashed = ( 2 === (int) $event->event_approved ) ? 'trashed' : '';
2185
+ $author = ( 0 !== (int) $event->event_author ) ? get_userdata( $event->event_author ) : 'Public Submitter';
2186
 
2187
+ if ( 1 === (int) $event->event_flagged && ( isset( $_GET['restrict'] ) && 'flagged' === $_GET['restrict'] ) ) {
2188
  $spam = 'spam';
2189
  $pending = '';
2190
  $spam_label = '<strong>' . __( 'Possible spam', 'my-calendar' ) . ':</strong> ';
2193
  $spam_label = '';
2194
  }
2195
 
2196
+ $trash = ( '' !== $trashed ) ? ' - ' . __( 'Trash', 'my-calendar' ) : '';
2197
+ $draft = ( '' !== $pending ) ? ' - ' . __( 'Draft', 'my-calendar' ) : $trash;
2198
  $check = mc_test_occurrence_overlap( $event, true );
2199
+ $problem = ( '' !== $check ) ? 'problem' : '';
2200
  $edit_url = admin_url( "admin.php?page=my-calendar&amp;mode=edit&amp;event_id=$event->event_id" );
2201
  $copy_url = admin_url( "admin.php?page=my-calendar&amp;mode=copy&amp;event_id=$event->event_id" );
2202
  $view_url = mc_get_details_link( $event );
2207
  ?>
2208
  <tr class="<?php echo "$class $spam $pending $trashed $problem"; ?>">
2209
  <th scope="row">
2210
+ <input type="checkbox" value="<?php echo $event->event_id; ?>" name="mass_edit[]" id="mc<?php echo $event->event_id; ?>" <?php echo ( 1 === (int) $event->event_flagged ) ? 'checked="checked"' : ''; ?> />
2211
  <label for="mc<?php echo $event->event_id; ?>">
2212
  <?php
2213
  // Translators: Event ID.
2227
  echo strip_tags( stripslashes( $event->event_title ) );
2228
  if ( $can_edit ) {
2229
  echo '</a>';
2230
+ if ( '' !== $check ) {
2231
  // Translators: URL to edit event.
2232
  echo '<br /><strong class="error">' . sprintf( __( 'There is a problem with this event. <a href="%s">Edit</a>', 'my-calendar' ), $edit_url ) . '</strong>';
2233
  }
2268
  |
2269
  <?php
2270
  if ( current_user_can( 'mc_approve_events' ) && $can_edit ) {
2271
+ if ( 1 === (int) $event->event_approved ) {
2272
  $mo = 'reject';
2273
  $te = __( 'Trash', 'my-calendar' );
2274
  } else {
2295
  </td>
2296
  <td>
2297
  <?php
2298
+ if ( '' !== $event->event_label ) {
2299
  $elabel = urlencode( $event->event_label );
2300
  ?>
2301
  <a class='mc_filter' href='<?php echo admin_url( "admin.php?page=my-calendar-manage&amp;filter=$elabel&amp;restrict=where" ); ?>' title="<?php _e( 'Filter by location', 'my-calendar' ); ?>"><span class="screen-reader-text"><?php _e( 'Show only: ', 'my-calendar' ); ?></span><?php echo strip_tags( stripslashes( $event->event_label ) ); ?></a>
2305
  </td>
2306
  <td>
2307
  <?php
2308
+ if ( '23:59:59' !== $event->event_endtime ) {
2309
  $event_time = date_i18n( get_option( 'mc_time_format' ), mc_strtotime( $event->event_time ) );
2310
  } else {
2311
  $event_time = mc_notime_label( $event );
2346
  $string = '';
2347
  if ( is_array( $categories ) ) {
2348
  foreach ( $categories as $category ) {
2349
+ if ( (int) $category !== (int) $event->event_category ) {
2350
  $cats[] = mc_get_category_detail( $category, 'category_name' );
2351
  }
2352
  $string = implode( ', ', $cats );
2353
  }
2354
+ echo ( '' !== $string ) ? '(' . $string . ')' : '';
2355
  }
2356
  ?>
2357
  </td>
2558
  // ...AND there's no reason to allow it, since weekday events will NEVER happen on the weekend.
2559
  $begin = trim( $post['event_begin'][ $i ] );
2560
  $end = ( ! empty( $post['event_end'] ) ) ? trim( $post['event_end'][ $i ] ) : $post['event_begin'][ $i ];
2561
+ if ( 'E' === $recur && '0' === ( mc_date( 'w', mc_strtotime( $begin ), false ) || '6' === mc_date( 'w', mc_strtotime( $begin ), false ) ) ) {
2562
+ if ( 0 === (int) mc_date( 'w', mc_strtotime( $begin ), false ) ) {
2563
  $newbegin = my_calendar_add_date( $begin, 1 );
2564
  if ( ! empty( $post['event_end'][ $i ] ) ) {
2565
  $newend = my_calendar_add_date( $end, 1 );
2566
  } else {
2567
  $newend = $newbegin;
2568
  }
2569
+ } elseif ( 6 === (int) mc_date( 'w', mc_strtotime( $begin ), false ) ) {
2570
  $newbegin = my_calendar_add_date( $begin, 2 );
2571
  if ( ! empty( $post['event_end'][ $i ] ) ) {
2572
  $newend = my_calendar_add_date( $end, 2 );
2581
  $end = ! empty( $post['event_end'][ $i ] ) ? trim( $post['event_end'][ $i ] ) : $begin;
2582
  }
2583
 
2584
+ $begin = mc_date( 'Y-m-d', mc_strtotime( $begin ), false );// regardless of entry format, convert.
2585
  $time = ! empty( $post['event_time'][ $i ] ) ? trim( $post['event_time'][ $i ] ) : '';
2586
+ if ( '' !== $time ) {
2587
  $default_modifier = apply_filters( 'mc_default_event_length', '1 hour' );
2588
+ $endtime = ! empty( $post['event_endtime'][ $i ] ) ? trim( $post['event_endtime'][ $i ] ) : mc_date( 'H:i:s', mc_strtotime( $time . ' +' . $default_modifier ), false );
2589
+ if ( empty( $post['event_endtime'][ $i ] ) && mc_date( 'H', mc_strtotime( $endtime ), false ) === '00' ) {
2590
  // If one hour pushes event into next day, reset to 11:59pm.
2591
  $endtime = '23:59:00';
2592
  }
2593
  } else {
2594
  $endtime = ! empty( $post['event_endtime'][ $i ] ) ? trim( $post['event_endtime'][ $i ] ) : '';
2595
  }
2596
+ $time = ( '' === $time || '00:00:00' === $time ) ? '00:00:00' : $time; // Set at midnight if not provided.
2597
+ $endtime = ( '' === $endtime && '00:00:00' === $time ) ? '23:59:59' : $endtime; // Set at end of night if np.
2598
 
2599
  // Prevent setting enddate to incorrect value on copy.
2600
  if ( mc_strtotime( $end ) < mc_strtotime( $begin ) && 'copy' === $action ) {
2601
+ $end = mc_date( 'Y-m-d', ( mc_strtotime( $begin ) + ( mc_strtotime( $post['prev_event_end'] ) - mc_strtotime( $post['prev_event_begin'] ) ) ), false );
2602
  }
2603
  if ( isset( $post['event_allday'] ) && 0 !== (int) $post['event_allday'] ) {
2604
  $time = '00:00:00';
2606
  }
2607
 
2608
  // Verify formats.
2609
+ $time = mc_date( 'H:i:s', mc_strtotime( $time ), false );
2610
+ $endtime = mc_date( 'H:i:s', mc_strtotime( $endtime ), false );
2611
+ $end = mc_date( 'Y-m-d', mc_strtotime( $end ), false ); // regardless of entry format, convert.
2612
  $repeats = ( isset( $post['event_repeats'] ) ) ? trim( $post['event_repeats'] ) : 0;
2613
  $host = ! empty( $post['event_host'] ) ? $post['event_host'] : $user->ID;
2614
  $primary = false;
2621
  foreach ( $cats as $cat ) {
2622
  $private = mc_get_category_detail( $cat, 'category_private' );
2623
  // If a selected category is private, set that category as primary instead.
2624
+ if ( 1 === (int) $private ) {
2625
  $primary = $cat;
2626
  }
2627
  }
2636
  $expires = ! empty( $post['event_link_expires'] ) ? $post['event_link_expires'] : '0';
2637
  $approved = ( current_user_can( 'mc_approve_events' ) ) ? 1 : 0;
2638
  // Check for event_approved provides support for older versions of My Calendar Pro.
2639
+ if ( isset( $post['event_approved'] ) && $post['event_approved'] !== $approved ) {
2640
  $approved = absint( $post['event_approved'] );
2641
  }
2642
 
2648
  $event_holiday = ! empty( $post['event_holiday'] ) ? 1 : 0;
2649
  $group_id = (int) $post['event_group_id'];
2650
  $event_group_id = ( ( is_array( $post['event_begin'] ) && count( $post['event_begin'] ) > 1 ) || mc_event_is_grouped( $group_id ) ) ? $group_id : 0;
2651
+ $event_span = ( ! empty( $post['event_span'] ) && 0 !== (int) $event_group_id ) ? 1 : 0;
2652
  $event_hide_end = ( ! empty( $post['event_hide_end'] ) ) ? (int) $post['event_hide_end'] : 0;
2653
+ $event_hide_end = ( '' === $time || '23:59:59' === $time ) ? 1 : $event_hide_end; // Hide end time on all day events.
2654
  // Set location.
2655
+ if ( 'none' !== $location_preset && is_numeric( $location_preset ) ) {
2656
  $location = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM ' . my_calendar_locations_table() . ' WHERE location_id = %d', $location_preset ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2657
  $event_label = $location->location_label;
2658
  $event_street = $location->location_street;
2686
  $event_phone2 = ! empty( $post['event_phone2'] ) ? $post['event_phone2'] : '';
2687
  $event_access = ! empty( $post['event_access'] ) ? $post['event_access'] : '';
2688
  $event_access = ! empty( $post['event_access_hidden'] ) ? unserialize( $post['event_access_hidden'] ) : $event_access;
2689
+ if ( isset( $post['mc_copy_location'] ) && 'on' === $post['mc_copy_location'] && 0 === $i ) {
2690
  // Only the first event, if adding multiples.
2691
  $add_loc = array(
2692
  'location_label' => $event_label,
2722
  }
2723
 
2724
  // Check for a valid or empty time.
2725
+ $time = ( '' === $time ) ? '23:59:59' : mc_date( 'H:i:00', mc_strtotime( $time ), false );
2726
  $time_format_one = '/^([0-1][0-9]):([0-5][0-9]):([0-5][0-9])$/';
2727
  $time_format_two = '/^([2][0-3]):([0-5][0-9]):([0-5][0-9])$/';
2728
  if ( preg_match( $time_format_one, $time ) || preg_match( $time_format_two, $time ) ) {
2730
  $errors .= mc_show_error( __( 'The time field must either be blank or be entered in the format hh:mm am/pm', 'my-calendar' ), false );
2731
  }
2732
  // Check for a valid or empty end time.
2733
+ if ( preg_match( $time_format_one, $endtime ) || preg_match( $time_format_two, $endtime ) || '' === $endtime ) {
2734
  } else {
2735
  $errors .= mc_show_error( __( 'The end time field must either be blank or be entered in the format hh:mm am/pm', 'my-calendar' ), false );
2736
  }
2737
  // Check for valid URL (blank or starting with http://).
2738
+ if ( ! ( '' === $event_link || preg_match( '/^(http)(s?)(:)\/\//', $event_link ) ) ) {
2739
  $event_link = 'http://' . $event_link;
2740
  }
2741
  }
2746
  }
2747
  // Run checks on recurrence profile.
2748
  $valid_recur = array( 'W', 'B', 'M', 'U', 'Y', 'D', 'E' );
2749
+ if ( ( 0 === (int) $repeats && 'S' === $recur ) || ( ( $repeats >= 0 ) && in_array( $recur, $valid_recur, true ) ) ) {
2750
  $recur = $recur . $every;
2751
  } else {
2752
  // if it's not valid, assign a default value.
2764
  $errors .= mc_show_error( sprintf( __( 'That event conflicts with a <a href="%s">previously scheduled event</a>.', 'my-calendar' ), $conflict ), false );
2765
  }
2766
  }
2767
+ $spam_content = ( '' !== $desc ) ? $desc : $short;
2768
  $spam = mc_spam( $event_link, $spam_content, $post );
2769
  // Likelihood that event will be flagged as spam, have a zero start time and be legit is minimal. Just kill it.
2770
+ if ( 1 === (int) $spam && '1970-01-01' === $begin ) {
2771
  die;
2772
  }
2773
 
2774
  $current_user = wp_get_current_user();
2775
+ $event_author = ( $event_author === $current_user->ID || current_user_can( 'mc_manage_events' ) ) ? $event_author : $current_user->ID;
2776
  $primary = ( ! $primary ) ? 1 : $primary;
2777
  $cats = ( isset( $cats ) && is_array( $cats ) ) ? $cats : array( 1 );
 
2778
  $submit = array(
2779
  // Begin strings.
2780
  'event_begin' => $begin,
2821
  // Array: removed before DB insertion.
2822
  'event_categories' => $cats,
2823
  );
2824
+ $errors = apply_filters( 'mc_fields_required', '', $submit );
2825
 
2826
+ if ( '' === $errors ) {
2827
  $ok = true;
2828
 
2829
  $submit = array_map( 'mc_kses_post', $submit );
2896
  */
2897
  function mcs_check_conflicts( $begin, $time, $end, $endtime, $event_label ) {
2898
  global $wpdb;
2899
+ $select_location = ( '' !== $event_label ) ? "event_label = '" . esc_sql( $event_label ) . "' AND" : '';
2900
  $begin_time = $begin . ' ' . $time;
2901
  $end_time = $end . ' ' . $endtime;
2902
  // Need two queries; one to find outer events, one to find inner events.
2943
 
2944
  foreach ( $update as $k => $v ) {
2945
  // Event_recur and event_repeats always set to single and 0; event_begin and event_end need to be checked elsewhere.
2946
+ if ( 'event_recur' !== $k && 'event_repeats' !== $k && 'event_begin' !== $k && 'event_end' !== $k ) {
2947
  $update_string .= trim( $v );
2948
  $event_string .= trim( $event->$k );
2949
  }
2950
  }
2951
  $update_hash = md5( $update_string );
2952
  $event_hash = md5( $event_string );
2953
+ if ( $update_hash === $event_hash ) {
2954
  return false;
2955
  } else {
2956
  return true;
3045
 
3046
  global $wpdb;
3047
  $output = '';
3048
+ if ( true === $instance ) {
3049
  $sql = 'SELECT * FROM ' . my_calendar_event_table() . ' WHERE occur_id=%d ORDER BY occur_begin ASC';
3050
  } else {
3051
  $sql = 'SELECT * FROM ' . my_calendar_event_table() . ' WHERE occur_event_id=%d ORDER BY occur_begin ASC';
3057
  $event_id = $result->occur_id;
3058
  $event = mc_get_event( $event_id );
3059
  $array = mc_create_tags( $event );
3060
+ if ( in_array( $template, array( 'details', 'grid', 'list', 'mini' ), true ) || mc_key_exists( $template ) ) {
3061
+ if ( 1 === (int) get_option( 'mc_use_' . $template . '_template' ) ) {
3062
  $template = mc_get_template( $template );
3063
  } elseif ( mc_key_exists( $template ) ) {
3064
  $template = mc_get_custom_template( $template );
3066
  $details = my_calendar_draw_event( $event, 'single', $event->event_begin, $event->event_time, '' );
3067
  }
3068
  }
3069
+ $item = ( '' !== $list ) ? mc_draw_template( $array, $list ) : '';
3070
+ if ( '' === $details ) {
3071
+ $details = ( '' !== $template ) ? mc_draw_template( $array, $template ) : '';
3072
  }
3073
  $output .= $item;
3074
+ if ( '' === $list ) {
3075
  break;
3076
  }
3077
  }
3098
  $deleted = get_post_meta( $event_post, '_mc_deleted_instances', true );
3099
  if ( is_array( $results ) && is_admin() ) {
3100
  foreach ( $results as $result ) {
3101
+ $begin = "<span id='occur_date_$result->occur_id'>" . date_i18n( mc_date_format(), mc_strtotime( $result->occur_begin ) ) . ', ' . mc_date( get_option( 'mc_time_format' ), mc_strtotime( $result->occur_begin ), false ) . '</span>';
3102
+ if ( $result->occur_id === $occur ) {
3103
  $control = '';
3104
  $edit = '<em>' . __( 'Editing Now', 'my-calendar' ) . '</em>';
3105
  } else {
3122
  */
3123
  function mc_event_is_grouped( $group_id ) {
3124
  global $wpdb;
3125
+ if ( 0 === (int) $group_id ) {
3126
  return false;
3127
  } else {
3128
  $value = $wpdb->get_var( $wpdb->prepare( 'SELECT count( event_group_id ) FROM ' . my_calendar_table() . ' WHERE event_group_id = %d', $group_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
3166
 
3167
  if ( isset( $_GET['date'] ) ) {
3168
  $event = mc_get_event( (int) $_GET['date'] );
3169
+ $event_begin = mc_date( 'Y-m-d', mc_strtotime( $event->occur_begin ), false );
3170
+ $event_end = mc_date( 'Y-m-d', mc_strtotime( $event->occur_end ), false );
3171
  }
3172
  // Set event end to empty if matches begin. Makes input and changes easier.
3173
+ if ( $event_begin === $event_end ) {
3174
  $event_end = '';
3175
  }
3176
+ $starttime = ( mc_is_all_day( $data ) ) ? '' : mc_date( apply_filters( 'mc_time_format', 'h:i A' ), mc_strtotime( $data->event_time ), false );
3177
+ $endtime = ( mc_is_all_day( $data ) ) ? '' : mc_date( apply_filters( 'mc_time_format', 'h:i A' ), mc_strtotime( $data->event_endtime ), false );
3178
  } else {
3179
+ $event_begin = mc_date( 'Y-m-d' );
3180
  $event_end = '';
3181
  $starttime = '';
3182
  $endtime = '';
3183
  }
3184
 
3185
  $allday = ( $has_data && ( mc_is_all_day( $data ) ) ) ? ' checked="checked"' : '';
3186
+ $hide = ( $has_data && '1' === $data->event_hide_end ) ? ' checked="checked"' : '';
3187
  $allday_label = ( $has_data ) ? mc_notime_label( $data ) : get_option( 'mc_notime_text' );
3188
 
3189
+ $form .= '<div>
3190
+ <label for="mc_event_date" id="eblabel">' . __( 'Date (YYYY-MM-DD)', 'my-calendar' ) . '</label> <div class="picker-container"><input type="text" id="mc_event_date" class="mc-datepicker" name="event_begin[]" size="10" value="" data-value="' . esc_attr( $event_begin ) . '" /></div>
3191
  <label for="mc_event_time">' . __( 'From', 'my-calendar' ) . '</label>
3192
+ <div class="picker-container"><input type="text" id="mc_event_time" class="mc-timepicker" name="event_time[]" size="8" value="' . esc_attr( $starttime ) . '" /></div>
3193
  <label for="mc_event_endtime">' . __( 'To', 'my-calendar' ) . '</label>
3194
+ <div class="picker-container"><input type="text" id="mc_event_endtime" class="mc-timepicker" name="event_endtime[]" size="8" value="' . esc_attr( $endtime ) . '" /></div>
3195
+ </div>
3196
  <ul>
3197
  <li><input type="checkbox" value="1" id="e_allday" name="event_allday"' . $allday . ' /> <label for="e_allday">' . __( 'All day event', 'my-calendar' ) . '</label> <span class="event_time_label"><label for="e_time_label">' . __( 'Time label:', 'my-calendar' ) . '</label> <input type="text" name="event_time_label" id="e_time_label" value="' . esc_attr( $allday_label ) . '" /> </li>
3198
  <li><input type="checkbox" value="1" id="e_hide_end" name="event_hide_end"' . $hide . ' /> <label for="e_hide_end">' . __( 'Hide end time', 'my-calendar' ) . '</label></li>
3199
  </ul>
3200
+ <div>
3201
+ <label for="mc_event_enddate" id="eelabel"><em>' . __( 'End Date (YYYY-MM-DD, optional)', 'my-calendar' ) . '</em></label> <div class="picker-container"><input type="text" name="event_end[]" id="mc_event_enddate" class="mc-datepicker" size="10" value="" data-value="' . esc_attr( $event_end ) . '" /></div>
3202
+ </div>';
3203
 
3204
  return $form;
3205
  }
3207
  /**
3208
  * Date time inputs to add a single instance to recurring event info
3209
  *
3210
+ * @param object $data Source event data.
3211
+ *
3212
  * @return string form HTML
3213
  */
3214
+ function mc_recur_datetime_input( $data ) {
3215
+ $event_begin = ( $data->event_begin ) ? $data->event_begin : mc_date( 'Y-m-d' );
3216
+ $event_end = ( $data->event_end && $data->event_end !== $data->event_begin ) ? $data->event_end : '';
3217
+ $starttime = ( $data->event_time ) ? $data->event_time : '';
3218
+ $endtime = ( $data->event_endtime ) ? $data->event_endtime : '';
3219
 
3220
  $form = '<p>
3221
  <label for="r_begin">' . __( 'Date (YYYY-MM-DD)', 'my-calendar' ) . '</label> <input type="text" id="r_begin" class="mc-datepicker" name="recur_begin[]" size="10" value="" data-value="' . esc_attr( $event_begin ) . '" />
3269
  * @param int $id Post ID.
3270
  */
3271
  function mc_post_update_event( $id ) {
3272
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE || wp_is_post_revision( $id ) || ! ( get_post_type( $id ) === 'mc-events' ) ) {
3273
  return $id;
3274
  }
3275
  $post = get_post( $id );
3397
  if ( 'edit' === $mode ) {
3398
  $controls['prev_status'] = "<input type='hidden' name='prev_event_status' value='" . absint( $event->event_approved ) . "' />";
3399
  if ( current_user_can( 'mc_approve_events' ) || current_user_can( 'mc_publish_events' ) ) { // Added by Roland P.
3400
+ if ( $has_data && '1' === $event->event_approved ) {
3401
  $checked = ' checked="checked"';
3402
+ } elseif ( $has_data && 0 === (int) $event->event_approved ) {
3403
  $checked = '';
3404
  }
3405
  $status_control = "
3430
 
3431
  $controls_output = '';
3432
  foreach ( $controls as $key => $control ) {
3433
+ if ( 'prev_status' !== $key ) {
3434
  $control = '<li>' . $control . '</li>';
3435
  }
3436
 
3460
  $event = $result->occur_event_id;
3461
  $current = '<a href="' . admin_url( 'admin.php?page=my-calendar' ) . '&amp;mode=edit&amp;event_id=' . $event . '">';
3462
  $end = '</a>';
3463
+ $begin = date_i18n( mc_date_format(), strtotime( $result->occur_begin ) ) . ', ' . mc_date( get_option( 'mc_time_format' ), strtotime( $result->occur_begin ), false );
3464
  $template = $current . $begin . $end;
3465
  $output .= "<li>$template</li>";
3466
  }
3483
  $permissions = get_user_meta( $user, 'mc_user_permissions', true );
3484
  $permissions = apply_filters( 'mc_user_permissions', $permissions, $category, $user );
3485
 
3486
+ if ( ( ! $permissions || empty( $permissions ) ) || in_array( 'all', $permissions, true ) || in_array( $category, $permissions, true ) || current_user_can( 'manage_options' ) ) {
3487
  return true;
3488
  }
3489
 
3539
  }
3540
  $return = false;
3541
 
3542
+ if ( ( current_user_can( 'mc_manage_events' ) && $has_permissions ) || ( $user === $event_author ) ) {
3543
  $return = true;
3544
  }
3545
 
3562
  switch ( $recur ) {
3563
  case 'D':
3564
  // Translators: number of days between repetitions.
3565
+ $string = ( 1 === (int) $every ) ? __( 'Daily', 'my-calendar' ) : sprintf( __( 'Every %d days', 'my-calendar' ), $every );
3566
  break;
3567
  case 'E':
3568
  // Translators: number of days between repetitions.
3569
+ $string = ( 1 === (int) $every ) ? __( 'Weekdays', 'my-calendar' ) : sprintf( __( 'Every %d weekdays', 'my-calendar' ), $every );
3570
  break;
3571
  case 'W':
3572
  // Translators: number of weeks between repetitions.
3573
+ $string = ( 1 === (int) $every ) ? __( 'Weekly', 'my-calendar' ) : sprintf( __( 'Every %d weeks', 'my-calendar' ), $every );
3574
  break;
3575
  case 'B':
3576
  $string = __( 'Bi-Weekly', 'my-calendar' );
3577
  break;
3578
  case 'M':
3579
  // Translators: number of months between repetitions.
3580
+ $string = ( 1 === (int) $every ) ? __( 'Monthly (by date)', 'my-calendar' ) : sprintf( __( 'Every %d months (by date)', 'my-calendar' ), $every );
3581
  break;
3582
  case 'U':
3583
  $string = __( 'Monthly (by day)', 'my-calendar' );
3584
  break;
3585
  case 'Y':
3586
  // Translators: number of years between repetitions.
3587
+ $string = ( 1 === (int) $every ) ? __( 'Yearly', 'my-calendar' ) : sprintf( __( 'Every %d years', 'my-calendar' ), $every );
3588
  break;
3589
  }
3590
  $eternity = _mc_increment_values( $recur );
3591
+ if ( $event->event_repeats > 0 && 'S' !== $recur ) {
3592
  // Translators: number of repeats.
3593
  $string .= ' ' . sprintf( __( '&ndash; %d Times', 'my-calendar' ), $event->event_repeats );
3594
  } elseif ( $eternity ) {
3611
  $s = ( 'S' === $value ) ? ' selected="selected"' : '';
3612
  $d = ( 'D' === $value ) ? ' selected="selected"' : '';
3613
  $e = ( 'E' === $value ) ? ' selected="selected"' : '';
3614
+ $w = ( 'W' === $value || 'B' === $value ) ? ' selected="selected"' : '';
3615
  $m = ( 'M' === $value ) ? ' selected="selected"' : '';
3616
  $u = ( 'U' === $value ) ? ' selected="selected"' : '';
3617
  $y = ( 'Y' === $value ) ? ' selected="selected"' : '';
3676
  $return = array();
3677
 
3678
  foreach ( $results as $result ) {
3679
+ $key = sanitize_key( mc_date( 'Y-m-d', strtotime( $result->occur_begin ), false ) );
3680
  $return[ $key ] = $result->occur_id;
3681
  }
3682
 
3707
  * @return array new data to insert
3708
  */
3709
  function mc_reuse_id( $data, $begin, $instances ) {
3710
+ $begin = sanitize_key( mc_date( 'Y-m-d', $begin, false ) );
3711
  $keys = array_keys( $instances );
3712
+ if ( ! empty( $instances ) && in_array( $begin, $keys, true ) ) {
3713
  $restore_id = $instances[ $begin ];
3714
  $data['occur_id'] = $restore_id;
3715
  }
3728
  * @return array new formats for data
3729
  */
3730
  function mc_reuse_id_format( $format, $begin, $instances ) {
3731
+ $begin = sanitize_key( mc_date( 'Y-m-d', $begin, false ) );
3732
  $keys = array_keys( $instances );
3733
+ if ( ! empty( $instances ) && in_array( $begin, $keys, true ) ) {
3734
  $format = array( '%d', '%s', '%s', '%d', '%d' );
3735
  }
3736
 
3770
  $recur = $recurs[0];
3771
  // Can't use 2nd value directly if it's two digits.
3772
  $every = ( isset( $recurs[1] ) ) ? str_replace( $recurs[0], '', $event->event_recur ) : 1;
3773
+ if ( 'S' !== $recur ) {
3774
  // If this event had a rep of 0, translate that.
3775
+ $event_repetition = ( 0 !== (int) $event->event_repeats ) ? $event->event_repeats : _mc_increment_values( $recur );
3776
  $numforward = (int) $event_repetition;
3777
+ if ( 'S' !== $recur ) {
3778
  switch ( $recur ) {
3779
  case 'D':
3780
  for ( $i = 0; $i <= $numforward; $i ++ ) {
3783
 
3784
  $data = array(
3785
  'occur_event_id' => $id,
3786
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', $begin, false ),
3787
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', $end, false ),
3788
  'occur_group_id' => $group_id,
3789
  );
3790
  if ( 'test' === $test && $i > 0 ) {
3810
  for ( $i = 0; $i <= $numforward; $i ++ ) {
3811
  $begin = my_calendar_add_date( $orig_begin, $i * $every, 0, 0 );
3812
  $end = my_calendar_add_date( $orig_end, $i * $every, 0, 0 );
3813
+ if ( 0 !== (int) ( mc_date( 'w', $begin, false ) && 6 !== (int) mc_date( 'w', $begin, false ) ) ) {
3814
  $data = array(
3815
  'occur_event_id' => $id,
3816
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', $begin, false ),
3817
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', $end, false ),
3818
  'occur_group_id' => $group_id,
3819
  );
3820
  if ( 'test' === $test && $i > 0 ) {
3840
  $end = strtotime( $orig_end . ' ' . ( $every * $i ) . ' weekdays' );
3841
  $data = array(
3842
  'occur_event_id' => $id,
3843
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', $begin, false ),
3844
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', $end, false ),
3845
  'occur_group_id' => $group_id,
3846
  );
3847
  if ( 'test' === $test && $i > 0 ) {
3865
  $end = my_calendar_add_date( $orig_end, ( $i * 7 ) * $every, 0, 0 );
3866
  $data = array(
3867
  'occur_event_id' => $id,
3868
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', $begin, false ),
3869
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', $end, false ),
3870
  'occur_group_id' => $group_id,
3871
  );
3872
  if ( 'test' === $test && $i > 0 ) {
3889
  $end = my_calendar_add_date( $orig_end, ( $i * 14 ), 0, 0 );
3890
  $data = array(
3891
  'occur_event_id' => $id,
3892
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', $begin, false ),
3893
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', $end, false ),
3894
  'occur_group_id' => $group_id,
3895
  );
3896
  if ( 'test' === $test && $i > 0 ) {
3913
  $end = my_calendar_add_date( $orig_end, 0, $i * $every, 0 );
3914
  $data = array(
3915
  'occur_event_id' => $id,
3916
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', $begin, false ),
3917
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', $end, false ),
3918
  'occur_group_id' => $group_id,
3919
  );
3920
  if ( 'test' === $test && $i > 0 ) {
3933
  break;
3934
  case 'U':
3935
  // Important to keep track of which date variables are strings and which are timestamps.
3936
+ $week_of_event = week_of_month( mc_date( 'd', strtotime( $event->event_begin ), false ) );
3937
  $newbegin = my_calendar_add_date( $orig_begin, 28, 0, 0 );
3938
  $newend = my_calendar_add_date( $orig_end, 28, 0, 0 );
3939
  $fifth_week = $event->event_fifth_week;
3940
  $data = array(
3941
  'occur_event_id' => $id,
3942
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', strtotime( $orig_begin ), false ),
3943
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', strtotime( $orig_end ), false ),
3944
  'occur_group_id' => $group_id,
3945
  );
3946
 
3954
  }
3955
  $numforward = ( $numforward - 1 );
3956
  for ( $i = 0; $i <= $numforward; $i ++ ) {
3957
+ $next_week_diff = ( mc_date( 'm', $newbegin, false ) === mc_date( 'm', my_calendar_add_date( mc_date( 'Y-m-d', $newbegin, false ), 7, 0, 0 ) ) ) ? false : true;
3958
+ $move_event = ( ( 1 === (int) $fifth_week ) && ( ( week_of_month( mc_date( 'd', $newbegin ), false ) + 1 ) === (int) $week_of_event ) && true === $next_week_diff ) ? true : false;
3959
+ if ( week_of_month( mc_date( 'd', $newbegin, false ) ) === $week_of_event || true === $move_event ) {
3960
  } else {
3961
+ $newbegin = my_calendar_add_date( mc_date( 'Y-m-d H:i:s', $newbegin, false ), 7, 0, 0 );
3962
+ $newend = my_calendar_add_date( mc_date( 'Y-m-d H:i:s', $newend, false ), 7, 0, 0 );
3963
+ $move_event = ( 1 === (int) $fifth_week && week_of_month( mc_date( 'd', $newbegin ), false ) + 1 === (int) $week_of_event ) ? true : false;
3964
+ if ( week_of_month( mc_date( 'd', $newbegin, false ) ) === $week_of_event || true === $move_event ) {
3965
  } else {
3966
+ $newbegin = my_calendar_add_date( mc_date( 'Y-m-d H:i:s', $newbegin, false ), 14, 0, 0 );
3967
+ $newend = my_calendar_add_date( mc_date( 'Y-m-d H:i:s', $newend, false ), 14, 0, 0 );
3968
  }
3969
  }
3970
  $data = array(
3971
  'occur_event_id' => $id,
3972
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', $newbegin, false ),
3973
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', $newend, false ),
3974
  'occur_group_id' => $group_id,
3975
  );
3976
+ if ( 'test' === $test && $i > 0 ) {
3977
  return $data;
3978
  }
3979
  $return[] = $data;
3985
  $wpdb->insert( my_calendar_event_table(), $data, $format );
3986
  }
3987
  }
3988
+ $newbegin = my_calendar_add_date( mc_date( 'Y-m-d H:i:s', $newbegin, false ), 28, 0, 0 );
3989
+ $newend = my_calendar_add_date( mc_date( 'Y-m-d H:i:s', $newend, false ), 28, 0, 0 );
3990
  }
3991
  break;
3992
  case 'Y':
3995
  $end = my_calendar_add_date( $orig_end, 0, 0, $i * $every );
3996
  $data = array(
3997
  'occur_event_id' => $id,
3998
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', $begin, false ),
3999
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', $end, false ),
4000
  'occur_group_id' => $group_id,
4001
  );
4002
  if ( 'test' === $test && $i > 0 ) {
4020
  $end = strtotime( $orig_end );
4021
  $data = array(
4022
  'occur_event_id' => $id,
4023
+ 'occur_begin' => mc_date( 'Y-m-d H:i:s', $begin, false ),
4024
+ 'occur_end' => mc_date( 'Y-m-d H:i:s', $end, false ),
4025
  'occur_group_id' => $group_id,
4026
  );
4027
  if ( ! $test ) {
4034
  }
4035
  }
4036
 
4037
+ if ( true === $test ) {
4038
  return $return;
4039
  }
4040
 
my-calendar-events.php CHANGED
@@ -55,6 +55,25 @@ function mc_create_guid( $event ) {
55
  return $guid;
56
  }
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  /**
59
  * Grab all events for the requested dates from calendar
60
  *
@@ -117,12 +136,13 @@ function my_calendar_get_events( $args ) {
117
  $search = mc_prepare_search_query( $search );
118
  $exclude_categories = mc_private_categories();
119
  $arr_events = array();
 
120
 
121
  $site = apply_filters( 'mc_get_events_sites', $site, $args );
122
  if ( is_array( $site ) ) {
123
  foreach ( $site as $s ) {
124
  $event_query = '
125
- SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end
126
  FROM ' . my_calendar_event_table( $s ) . '
127
  JOIN ' . my_calendar_table( $s ) . ' AS e
128
  ON (event_id=occur_event_id)
@@ -169,7 +189,7 @@ function my_calendar_get_events( $args ) {
169
  }
170
  } else {
171
  $event_query = '
172
- SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end
173
  FROM ' . my_calendar_event_table( $site ) . '
174
  JOIN ' . my_calendar_table( $site ) . ' AS e
175
  ON (event_id=occur_event_id)
@@ -252,7 +272,8 @@ function mc_get_all_events( $args ) {
252
  $select_published = mc_select_published();
253
  $select_author = ( 'default' !== $author ) ? mc_select_author( $author ) : '';
254
  $select_host = ( 'default' !== $host ) ? mc_select_host( $host ) : '';
255
- $date = date( 'Y-m-d', current_time( 'timestamp' ) );
 
256
 
257
  $limit = "$select_published $select_category $select_author $select_host $select_location $select_access $search";
258
  $events1 = array();
@@ -263,7 +284,7 @@ function mc_get_all_events( $args ) {
263
  if ( $before > 0 ) {
264
  $before = $before + 15;
265
  $events1 = $mcdb->get_results(
266
- 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end
267
  FROM ' . my_calendar_event_table( $site ) . '
268
  JOIN ' . my_calendar_table( $site ) . " AS e
269
  ON (event_id=occur_event_id)
@@ -279,7 +300,7 @@ function mc_get_all_events( $args ) {
279
  // Events happening today.
280
  if ( 'yes' === $today ) {
281
  $events3 = $mcdb->get_results(
282
- 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end
283
  FROM ' . my_calendar_event_table( $site ) . '
284
  JOIN ' . my_calendar_table( $site ) . " AS e
285
  ON (event_id=occur_event_id)
@@ -288,14 +309,14 @@ function mc_get_all_events( $args ) {
288
  ON (e.event_category=c.category_id)
289
  WHERE $limit
290
  $exclude_categories
291
- AND ( ( DATE(occur_begin) < '$date' AND DATE(occur_end) > '$date' ) OR DATE(occur_begin) = '$date' )"
292
  );
293
  }
294
  // Upcoming Events.
295
  if ( $after > 0 ) {
296
  $after = $after + 15;
297
  $events2 = $mcdb->get_results(
298
- 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end
299
  FROM ' . my_calendar_event_table( $site ) . '
300
  JOIN ' . my_calendar_table( $site ) . " AS e
301
  ON (event_id=occur_event_id)
@@ -369,6 +390,7 @@ function mc_get_rss_events( $cat_id = false ) {
369
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
370
  $mcdb = mc_remote_db();
371
  }
 
372
  if ( $cat_id ) {
373
  $cat = "WHERE event_category = $cat_id AND event_approved = 1 AND event_flagged <> 1";
374
  } else {
@@ -378,7 +400,7 @@ function mc_get_rss_events( $cat_id = false ) {
378
  $limit = apply_filters( 'mc_rss_feed_date_range', 2 );
379
 
380
  $events = $mcdb->get_results(
381
- 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end
382
  FROM ' . my_calendar_event_table() . '
383
  JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id)
384
  JOIN ' . my_calendar_categories_table() . " AS c ON (event_category=category_id) $cat
@@ -389,7 +411,7 @@ function mc_get_rss_events( $cat_id = false ) {
389
 
390
  if ( empty( $events ) ) {
391
  $events = $mcdb->get_results(
392
- 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end
393
  FROM ' . my_calendar_event_table() . '
394
  JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id)
395
  JOIN ' . my_calendar_categories_table() . " AS c ON (event_category=category_id) $cat
@@ -489,7 +511,8 @@ function mc_get_event_core( $id, $rebuild = false ) {
489
  }
490
 
491
  global $wpdb;
492
- $mcdb = $wpdb;
 
493
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
494
  $mcdb = mc_remote_db();
495
  }
@@ -497,7 +520,7 @@ function mc_get_event_core( $id, $rebuild = false ) {
497
  if ( $rebuild ) {
498
  $event = $mcdb->get_row( $wpdb->prepare( 'SELECT * FROM ' . my_calendar_table() . ' JOIN ' . my_calendar_categories_table() . ' ON (event_category=category_id) WHERE event_id=%d', $id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
499
  } else {
500
- $event = $mcdb->get_row( $wpdb->prepare( 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end FROM ' . my_calendar_event_table() . ' JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id) JOIN ' . my_calendar_categories_table() . ' ON (event_category=category_id) WHERE event_id = %d ORDER BY occur_id ASC LIMIT 1', $id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
501
  $event = mc_event_object( $event );
502
  }
503
 
@@ -513,11 +536,12 @@ function mc_get_event_core( $id, $rebuild = false ) {
513
  */
514
  function mc_get_first_event( $id ) {
515
  global $wpdb;
516
- $mcdb = $wpdb;
 
517
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
518
  $mcdb = mc_remote_db();
519
  }
520
- $event = $mcdb->get_row( $wpdb->prepare( 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end FROM ' . my_calendar_event_table() . ' JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id) JOIN ' . my_calendar_categories_table() . ' ON (event_category=category_id) WHERE occur_event_id=%d', $id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
521
  $event = mc_event_object( $event );
522
 
523
  return $event;
@@ -532,11 +556,12 @@ function mc_get_first_event( $id ) {
532
  */
533
  function mc_get_nearest_event( $id ) {
534
  global $wpdb;
535
- $mcdb = $wpdb;
 
536
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
537
  $mcdb = mc_remote_db();
538
  }
539
- $event = $mcdb->get_row( $wpdb->prepare( 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end FROM ' . my_calendar_event_table() . ' JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id) JOIN ' . my_calendar_categories_table() . ' ON (event_category=category_id) WHERE occur_event_id=%d ORDER BY ABS( DATEDIFF( occur_begin, NOW() ) )', $id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
540
  $event = mc_event_object( $event );
541
 
542
  return $event;
@@ -554,19 +579,20 @@ function mc_get_event( $id, $type = 'object' ) {
554
  if ( ! is_numeric( $id ) ) {
555
  return false;
556
  }
 
557
 
558
  global $wpdb;
559
  $mcdb = $wpdb;
560
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
561
  $mcdb = mc_remote_db();
562
  }
563
- $event = $mcdb->get_row( $wpdb->prepare( 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end FROM ' . my_calendar_event_table() . ' JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id) JOIN ' . my_calendar_categories_table() . ' ON (event_category=category_id) WHERE occur_id=%d', $id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
564
  if ( 'object' === $type ) {
565
  $event = mc_event_object( $event );
566
  return $event;
567
  } else {
568
- $date = date( 'Y-m-d', strtotime( $event->occur_begin ) );
569
- $time = date( 'H:i:s', strtotime( $event->occur_begin ) );
570
  $value = '<div id="mc_event">' . my_calendar_draw_event( $event, 'single', $date, $time, 'single' ) . '</div>';
571
 
572
  return $value;
@@ -655,13 +681,14 @@ function my_calendar_events_now( $category = 'default', $template = '<strong>{li
655
  $join = ( isset( $cat_limit[0] ) ) ? $cat_limit[0] : '';
656
  $select_category = ( isset( $cat_limit[1] ) ) ? $cat_limit[1] : '';
657
  $exclude_categories = mc_private_categories();
 
658
 
659
  // May add support for location/author/host later.
660
  $select_location = '';
661
  $select_author = '';
662
  $select_host = '';
663
- $now = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) );
664
- $event_query = 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end
665
  FROM ' . my_calendar_event_table( $site ) . ' AS o
666
  JOIN ' . my_calendar_table( $site ) . " AS e
667
  ON (event_id=occur_event_id)
@@ -700,7 +727,6 @@ function my_calendar_events_now( $category = 'default', $template = '<strong>{li
700
  return $return;
701
  }
702
 
703
-
704
  /**
705
  * Get the next scheduled event, not currently happening.
706
  *
@@ -729,13 +755,14 @@ function my_calendar_events_next( $category = 'default', $template = '<strong>{l
729
  $join = ( isset( $cat_limit[0] ) ) ? $cat_limit[0] : '';
730
  $select_category = ( isset( $cat_limit[1] ) ) ? $cat_limit[1] : '';
731
  $exclude_categories = mc_private_categories();
 
732
 
733
  // May add support for location/author/host later.
734
  $select_location = '';
735
  $select_author = '';
736
  $select_host = '';
737
- $now = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) );
738
- $event_query = 'SELECT *, UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end
739
  FROM ' . my_calendar_event_table( $site ) . '
740
  JOIN ' . my_calendar_table( $site ) . " AS e
741
  ON (event_id=occur_event_id)
@@ -810,6 +837,58 @@ function mc_get_related( $id ) {
810
  return $results;
811
  }
812
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
813
  /**
814
  * Check whether this is a valid preview scenario.
815
  *
@@ -856,13 +935,13 @@ function mc_set_date_array( $events ) {
856
  $event_array = array();
857
  if ( is_array( $events ) && ! empty( $events ) ) {
858
  foreach ( $events as $event ) {
859
- $date = date( 'Y-m-d', strtotime( $event->occur_begin ) );
860
- $end = date( 'Y-m-d', strtotime( $event->occur_end ) );
861
  if ( $date !== $end ) {
862
  $start = strtotime( $date );
863
  $end = strtotime( $end );
864
  do {
865
- $date = date( 'Y-m-d', $start );
866
  $event_array[ $date ][] = $event;
867
  $start = strtotime( '+1 day', $start );
868
  } while ( $start <= $end );
@@ -893,7 +972,6 @@ function mc_get_event_post( $event_id ) {
893
  return false;
894
  }
895
 
896
-
897
  /**
898
  * Check the type of database, so handling of search queries is correct.
899
  *
55
  return $guid;
56
  }
57
 
58
+ /**
59
+ * Function for extracting event timestamps from MySQL.
60
+ *
61
+ * @return string
62
+ */
63
+ function mc_ts() {
64
+ global $wpdb;
65
+ $offset = $wpdb->get_var( 'SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);' );
66
+ $offset = substr( $offset, 0, -3 );
67
+ if ( strpos( $offset, '-' ) !== 0 ) {
68
+ $offset = '+' . $offset;
69
+ }
70
+ $wp_time = get_option( 'gmt_offset', '0' );
71
+ $wp_time = ( $wp_time < 0 ) ? '-' . str_pad( absint( $wp_time ), 2, 0, STR_PAD_LEFT ) : '+' . str_pad( $wp_time, 2, 0, STR_PAD_LEFT );
72
+ $wp_time .= ':00';
73
+ // return 'UNIX_TIMESTAMP(occur_begin) AS ts_occur_begin, UNIX_TIMESTAMP(occur_end) AS ts_occur_end'.
74
+ return "UNIX_TIMESTAMP( CONVERT_TZ( `occur_begin`, '$wp_time', '$offset' ) ) AS ts_occur_begin, UNIX_TIMESTAMP( CONVERT_TZ( `occur_end`, '$wp_time', '$offset' ) ) AS ts_occur_end ";
75
+ }
76
+
77
  /**
78
  * Grab all events for the requested dates from calendar
79
  *
136
  $search = mc_prepare_search_query( $search );
137
  $exclude_categories = mc_private_categories();
138
  $arr_events = array();
139
+ $ts_string = mc_ts();
140
 
141
  $site = apply_filters( 'mc_get_events_sites', $site, $args );
142
  if ( is_array( $site ) ) {
143
  foreach ( $site as $s ) {
144
  $event_query = '
145
+ SELECT *, ' . $ts_string . '
146
  FROM ' . my_calendar_event_table( $s ) . '
147
  JOIN ' . my_calendar_table( $s ) . ' AS e
148
  ON (event_id=occur_event_id)
189
  }
190
  } else {
191
  $event_query = '
192
+ SELECT *, ' . $ts_string . '
193
  FROM ' . my_calendar_event_table( $site ) . '
194
  JOIN ' . my_calendar_table( $site ) . ' AS e
195
  ON (event_id=occur_event_id)
272
  $select_published = mc_select_published();
273
  $select_author = ( 'default' !== $author ) ? mc_select_author( $author ) : '';
274
  $select_host = ( 'default' !== $host ) ? mc_select_host( $host ) : '';
275
+ $date = current_time( 'Y-m-d' );
276
+ $ts_string = mc_ts();
277
 
278
  $limit = "$select_published $select_category $select_author $select_host $select_location $select_access $search";
279
  $events1 = array();
284
  if ( $before > 0 ) {
285
  $before = $before + 15;
286
  $events1 = $mcdb->get_results(
287
+ 'SELECT *, ' . $ts_string . '
288
  FROM ' . my_calendar_event_table( $site ) . '
289
  JOIN ' . my_calendar_table( $site ) . " AS e
290
  ON (event_id=occur_event_id)
300
  // Events happening today.
301
  if ( 'yes' === $today ) {
302
  $events3 = $mcdb->get_results(
303
+ 'SELECT *, ' . $ts_string . '
304
  FROM ' . my_calendar_event_table( $site ) . '
305
  JOIN ' . my_calendar_table( $site ) . " AS e
306
  ON (event_id=occur_event_id)
309
  ON (e.event_category=c.category_id)
310
  WHERE $limit
311
  $exclude_categories
312
+ AND ( ( DATE(occur_begin) < '$date' AND DATE(occur_end) >= '$date' ) OR DATE(occur_begin) = '$date' )"
313
  );
314
  }
315
  // Upcoming Events.
316
  if ( $after > 0 ) {
317
  $after = $after + 15;
318
  $events2 = $mcdb->get_results(
319
+ 'SELECT *, ' . $ts_string . '
320
  FROM ' . my_calendar_event_table( $site ) . '
321
  JOIN ' . my_calendar_table( $site ) . " AS e
322
  ON (event_id=occur_event_id)
390
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
391
  $mcdb = mc_remote_db();
392
  }
393
+ $ts_string = mc_ts();
394
  if ( $cat_id ) {
395
  $cat = "WHERE event_category = $cat_id AND event_approved = 1 AND event_flagged <> 1";
396
  } else {
400
  $limit = apply_filters( 'mc_rss_feed_date_range', 2 );
401
 
402
  $events = $mcdb->get_results(
403
+ 'SELECT *, ' . $ts_string . '
404
  FROM ' . my_calendar_event_table() . '
405
  JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id)
406
  JOIN ' . my_calendar_categories_table() . " AS c ON (event_category=category_id) $cat
411
 
412
  if ( empty( $events ) ) {
413
  $events = $mcdb->get_results(
414
+ 'SELECT *, ' . $ts_string . '
415
  FROM ' . my_calendar_event_table() . '
416
  JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id)
417
  JOIN ' . my_calendar_categories_table() . " AS c ON (event_category=category_id) $cat
511
  }
512
 
513
  global $wpdb;
514
+ $mcdb = $wpdb;
515
+ $ts_string = mc_ts();
516
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
517
  $mcdb = mc_remote_db();
518
  }
520
  if ( $rebuild ) {
521
  $event = $mcdb->get_row( $wpdb->prepare( 'SELECT * FROM ' . my_calendar_table() . ' JOIN ' . my_calendar_categories_table() . ' ON (event_category=category_id) WHERE event_id=%d', $id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
522
  } else {
523
+ $event = $mcdb->get_row( $wpdb->prepare( 'SELECT *, ' . $ts_string . ' FROM ' . my_calendar_event_table() . ' JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id) JOIN ' . my_calendar_categories_table() . ' ON (event_category=category_id) WHERE event_id = %d ORDER BY occur_id ASC LIMIT 1', $id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
524
  $event = mc_event_object( $event );
525
  }
526
 
536
  */
537
  function mc_get_first_event( $id ) {
538
  global $wpdb;
539
+ $mcdb = $wpdb;
540
+ $ts_string = mc_ts();
541
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
542
  $mcdb = mc_remote_db();
543
  }
544
+ $event = $mcdb->get_row( $wpdb->prepare( 'SELECT *, ' . $ts_string . 'FROM ' . my_calendar_event_table() . ' JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id) JOIN ' . my_calendar_categories_table() . ' ON (event_category=category_id) WHERE occur_event_id=%d', $id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
545
  $event = mc_event_object( $event );
546
 
547
  return $event;
556
  */
557
  function mc_get_nearest_event( $id ) {
558
  global $wpdb;
559
+ $mcdb = $wpdb;
560
+ $ts_string = mc_ts();
561
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
562
  $mcdb = mc_remote_db();
563
  }
564
+ $event = $mcdb->get_row( $wpdb->prepare( 'SELECT *, ' . $ts_string . ' FROM ' . my_calendar_event_table() . ' JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id) JOIN ' . my_calendar_categories_table() . ' ON (event_category=category_id) WHERE occur_event_id=%d ORDER BY ABS( DATEDIFF( occur_begin, NOW() ) )', $id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
565
  $event = mc_event_object( $event );
566
 
567
  return $event;
579
  if ( ! is_numeric( $id ) ) {
580
  return false;
581
  }
582
+ $ts_string = mc_ts();
583
 
584
  global $wpdb;
585
  $mcdb = $wpdb;
586
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
587
  $mcdb = mc_remote_db();
588
  }
589
+ $event = $mcdb->get_row( $wpdb->prepare( 'SELECT *, ' . $ts_string . ' FROM ' . my_calendar_event_table() . ' JOIN ' . my_calendar_table() . ' ON (event_id=occur_event_id) JOIN ' . my_calendar_categories_table() . ' ON (event_category=category_id) WHERE occur_id=%d', $id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
590
  if ( 'object' === $type ) {
591
  $event = mc_event_object( $event );
592
  return $event;
593
  } else {
594
+ $date = mc_date( 'Y-m-d', strtotime( $event->occur_begin ), false );
595
+ $time = mc_date( 'H:i:s', strtotime( $event->occur_begin ), false );
596
  $value = '<div id="mc_event">' . my_calendar_draw_event( $event, 'single', $date, $time, 'single' ) . '</div>';
597
 
598
  return $value;
681
  $join = ( isset( $cat_limit[0] ) ) ? $cat_limit[0] : '';
682
  $select_category = ( isset( $cat_limit[1] ) ) ? $cat_limit[1] : '';
683
  $exclude_categories = mc_private_categories();
684
+ $ts_string = mc_ts();
685
 
686
  // May add support for location/author/host later.
687
  $select_location = '';
688
  $select_author = '';
689
  $select_host = '';
690
+ $now = current_time( 'Y-m-d H:i:s' );
691
+ $event_query = 'SELECT *, ' . $ts_string . '
692
  FROM ' . my_calendar_event_table( $site ) . ' AS o
693
  JOIN ' . my_calendar_table( $site ) . " AS e
694
  ON (event_id=occur_event_id)
727
  return $return;
728
  }
729
 
 
730
  /**
731
  * Get the next scheduled event, not currently happening.
732
  *
755
  $join = ( isset( $cat_limit[0] ) ) ? $cat_limit[0] : '';
756
  $select_category = ( isset( $cat_limit[1] ) ) ? $cat_limit[1] : '';
757
  $exclude_categories = mc_private_categories();
758
+ $ts_string = mc_ts();
759
 
760
  // May add support for location/author/host later.
761
  $select_location = '';
762
  $select_author = '';
763
  $select_host = '';
764
+ $now = current_time( 'Y-m-d H:i:s' );
765
+ $event_query = 'SELECT *, ' . $ts_string . '
766
  FROM ' . my_calendar_event_table( $site ) . '
767
  JOIN ' . my_calendar_table( $site ) . " AS e
768
  ON (event_id=occur_event_id)
837
  return $results;
838
  }
839
 
840
+
841
+ /**
842
+ * Get the events adjacent to the currently displayed event.
843
+ *
844
+ * @param integer $mc_id ID of current event.
845
+ * @param string $adjacent Next/Previous.
846
+ *
847
+ * @return array Event template array.
848
+ */
849
+ function mc_adjacent_event( $mc_id, $adjacent = 'previous' ) {
850
+ global $wpdb;
851
+ $mcdb = $wpdb;
852
+ if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
853
+ $mcdb = mc_remote_db();
854
+ }
855
+ $adjacence = ( 'next' === $adjacent ) ? '>' : '<';
856
+ $order = ( 'next' === $adjacent ) ? 'ASC' : 'DESC';
857
+ $site = false;
858
+ $arr_events = array();
859
+ $select_published = mc_select_published();
860
+ $exclude_categories = mc_private_categories();
861
+ $ts_string = mc_ts();
862
+ $source = mc_get_event( $mc_id );
863
+ $date = mc_date( 'Y-m-d H:i:s', strtotime( $source->occur_begin ), false );
864
+ $now = $date;
865
+
866
+ $event_query = 'SELECT *, ' . $ts_string . '
867
+ FROM ' . my_calendar_event_table( $site ) . '
868
+ JOIN ' . my_calendar_table( $site ) . ' AS e
869
+ ON (event_id=occur_event_id)
870
+ JOIN ' . my_calendar_categories_table( $site ) . " as c
871
+ ON (e.event_category=c.category_id)
872
+ WHERE $select_published $exclude_categories
873
+ AND occur_begin $adjacence CAST('$now' as DATETIME) ORDER BY occur_begin $order LIMIT 0,1";
874
+
875
+ $events = $mcdb->get_results( $event_query );
876
+ if ( ! empty( $events ) ) {
877
+ foreach ( array_keys( $events ) as $key ) {
878
+ $event =& $events[ $key ];
879
+ $arr_events[] = $event;
880
+ }
881
+ }
882
+ if ( ! empty( $arr_events ) ) {
883
+ $return = mc_create_tags( $arr_events[0] );
884
+ } else {
885
+ $return = array();
886
+ }
887
+
888
+ return $return;
889
+ }
890
+
891
+
892
  /**
893
  * Check whether this is a valid preview scenario.
894
  *
935
  $event_array = array();
936
  if ( is_array( $events ) && ! empty( $events ) ) {
937
  foreach ( $events as $event ) {
938
+ $date = mc_date( 'Y-m-d', strtotime( $event->occur_begin ), false );
939
+ $end = mc_date( 'Y-m-d', strtotime( $event->occur_end ), false );
940
  if ( $date !== $end ) {
941
  $start = strtotime( $date );
942
  $end = strtotime( $end );
943
  do {
944
+ $date = mc_date( 'Y-m-d', $start, false );
945
  $event_array[ $date ][] = $event;
946
  $start = strtotime( '+1 day', $start );
947
  } while ( $start <= $end );
972
  return false;
973
  }
974
 
 
975
  /**
976
  * Check the type of database, so handling of search queries is correct.
977
  *
my-calendar-generator.php CHANGED
@@ -43,14 +43,14 @@ function mc_generate() {
43
  $shortcode = 'my_calendar';
44
  }
45
  foreach ( $_POST as $key => $value ) {
46
- if ( 'generator' != $key && 'shortcode' != $key && '_wpnonce' != $key ) {
47
  if ( 'template' === $key ) {
48
  $template = mc_create_template( $value, array( 'mc_template_key' => $templatekey ) );
49
  $v = $template;
50
  $append = "<a href='" . add_query_arg( 'mc_template', $template, admin_url( 'admin.php?page=my-calendar-templates' ) ) . "'>" . __( 'Edit this Template', 'my-calendar' ) . ' &rarr;</a>';
51
  } else {
52
  if ( is_array( $value ) ) {
53
- if ( in_array( 'all', $value ) ) {
54
  unset( $value[0] );
55
  }
56
  $v = implode( ',', $value );
@@ -58,7 +58,7 @@ function mc_generate() {
58
  $v = $value;
59
  }
60
  }
61
- if ( '' != $v ) {
62
  $string .= " $key=&quot;$v&quot;";
63
  }
64
  }
@@ -172,8 +172,8 @@ function mc_generator( $type ) {
172
  $mcdb = mc_remote_db();
173
  }
174
  $query = 'SELECT event_begin FROM ' . my_calendar_table() . ' WHERE event_approved = 1 AND event_flagged <> 1 ORDER BY event_begin ASC LIMIT 0 , 1';
175
- $year1 = date( 'Y', strtotime( $mcdb->get_var( $query ) ) );
176
- $diff1 = date( 'Y' ) - $year1;
177
  $past = $diff1;
178
  $future = apply_filters( 'mc_jumpbox_future_years', 5, false );
179
  $fut = 1;
@@ -181,19 +181,19 @@ function mc_generator( $type ) {
181
  $p = '';
182
  while ( $past > 0 ) {
183
  $p .= '<option value="';
184
- $p .= date( 'Y', current_time( 'timestamp' ) ) - $past;
185
  $p .= '">';
186
- $p .= date( 'Y', current_time( 'timestamp' ) ) - $past . "</option>\n";
187
  $past = $past - 1;
188
  }
189
  while ( $fut < $future ) {
190
  $f .= '<option value="';
191
- $f .= date( 'Y', current_time( 'timestamp' ) ) + $fut;
192
  $f .= '">';
193
- $f .= date( 'Y', current_time( 'timestamp' ) ) + $fut . "</option>\n";
194
  $fut = $fut + 1;
195
  }
196
- echo $p . '<option value="' . date( 'Y' ) . '">' . date( 'Y' ) . "</option>\n" . $f;
197
  ?>
198
  </select>
199
  </p>
43
  $shortcode = 'my_calendar';
44
  }
45
  foreach ( $_POST as $key => $value ) {
46
+ if ( 'generator' !== $key && 'shortcode' !== $key && '_wpnonce' !== $key ) {
47
  if ( 'template' === $key ) {
48
  $template = mc_create_template( $value, array( 'mc_template_key' => $templatekey ) );
49
  $v = $template;
50
  $append = "<a href='" . add_query_arg( 'mc_template', $template, admin_url( 'admin.php?page=my-calendar-templates' ) ) . "'>" . __( 'Edit this Template', 'my-calendar' ) . ' &rarr;</a>';
51
  } else {
52
  if ( is_array( $value ) ) {
53
+ if ( in_array( 'all', $value, true ) ) {
54
  unset( $value[0] );
55
  }
56
  $v = implode( ',', $value );
58
  $v = $value;
59
  }
60
  }
61
+ if ( '' !== $v ) {
62
  $string .= " $key=&quot;$v&quot;";
63
  }
64
  }
172
  $mcdb = mc_remote_db();
173
  }
174
  $query = 'SELECT event_begin FROM ' . my_calendar_table() . ' WHERE event_approved = 1 AND event_flagged <> 1 ORDER BY event_begin ASC LIMIT 0 , 1';
175
+ $year1 = mc_date( 'Y', strtotime( $mcdb->get_var( $query ) ) );
176
+ $diff1 = mc_date( 'Y' ) - $year1;
177
  $past = $diff1;
178
  $future = apply_filters( 'mc_jumpbox_future_years', 5, false );
179
  $fut = 1;
181
  $p = '';
182
  while ( $past > 0 ) {
183
  $p .= '<option value="';
184
+ $p .= current_time( 'Y' ) - $past;
185
  $p .= '">';
186
+ $p .= current_time( 'Y' ) - $past . "</option>\n";
187
  $past = $past - 1;
188
  }
189
  while ( $fut < $future ) {
190
  $f .= '<option value="';
191
+ $f .= current_time( 'Y' ) + $fut;
192
  $f .= '">';
193
+ $f .= current_time( 'Y' ) + $fut . "</option>\n";
194
  $fut = $fut + 1;
195
  }
196
+ echo $p . '<option value="' . current_time( 'Y' ) . '">' . current_time( 'Y' ) . "</option>\n" . $f;
197
  ?>
198
  </select>
199
  </p>
my-calendar-install.php CHANGED
@@ -73,8 +73,6 @@ function mc_globals() {
73
  $mini_template = addslashes(
74
  '<span class="event-time value-title" title="{dtstart}">{time}<span class="time-separator"> - </span>{endtime before="<span class=\'end-time value-title\' title=\'{dtend}\'>" after="</span>"}</span>
75
 
76
- <h3 class="event-title">{title}</h3>
77
-
78
  <div class="sub-details">
79
  {excerpt before="<div class=\'excerpt\'>" after="</div>"}
80
  {hcard}
@@ -299,7 +297,7 @@ function mc_default_settings() {
299
  )
300
  );
301
  add_option( 'mc_skip_holidays', 'false' );
302
- add_option( 'mc_css_file', 'twentyeighteen.css' );
303
  add_option(
304
  'mc_style_vars',
305
  array(
73
  $mini_template = addslashes(
74
  '<span class="event-time value-title" title="{dtstart}">{time}<span class="time-separator"> - </span>{endtime before="<span class=\'end-time value-title\' title=\'{dtend}\'>" after="</span>"}</span>
75
 
 
 
76
  <div class="sub-details">
77
  {excerpt before="<div class=\'excerpt\'>" after="</div>"}
78
  {hcard}
297
  )
298
  );
299
  add_option( 'mc_skip_holidays', 'false' );
300
+ add_option( 'mc_css_file', 'twentytwenty.css' );
301
  add_option(
302
  'mc_style_vars',
303
  array(
my-calendar-limits.php CHANGED
@@ -29,7 +29,7 @@ function mc_prepare_search_query( $query ) {
29
  $query = esc_sql( $query );
30
  $search = ' AND MATCH(' . apply_filters( 'mc_search_fields', 'event_title,event_desc,event_short,event_label,event_city,event_postcode,event_registration' ) . ") AGAINST ( '$query' IN BOOLEAN MODE ) ";
31
  } else {
32
- $query = $wpdb->esc_like( $query );
33
  $search = " AND ( event_title LIKE '%$query%' OR event_desc LIKE '%$query%' OR event_short LIKE '%$query%' OR event_label LIKE '%$query%' OR event_city LIKE '%$query%' OR event_postcode LIKE '%$query%' OR event_registration LIKE '%$query%' ) ";
34
  }
35
  }
@@ -284,7 +284,7 @@ function mc_select_location( $ltype = '', $lvalue = '' ) {
284
  function mc_access_limit( $access ) {
285
  global $wpdb;
286
  $options = mc_event_access();
287
- $format = ( isset( $options[ $access ] ) ) ? $wpdb->esc_like( $options[ $access ] ) : false;
288
  $limit_string = ( $format ) ? "AND event_access LIKE '%$format%'" : '';
289
 
290
  return $limit_string;
29
  $query = esc_sql( $query );
30
  $search = ' AND MATCH(' . apply_filters( 'mc_search_fields', 'event_title,event_desc,event_short,event_label,event_city,event_postcode,event_registration' ) . ") AGAINST ( '$query' IN BOOLEAN MODE ) ";
31
  } else {
32
+ $query = esc_sql( $query );
33
  $search = " AND ( event_title LIKE '%$query%' OR event_desc LIKE '%$query%' OR event_short LIKE '%$query%' OR event_label LIKE '%$query%' OR event_city LIKE '%$query%' OR event_postcode LIKE '%$query%' OR event_registration LIKE '%$query%' ) ";
34
  }
35
  }
284
  function mc_access_limit( $access ) {
285
  global $wpdb;
286
  $options = mc_event_access();
287
+ $format = ( isset( $options[ $access ] ) ) ? esc_sql( $options[ $access ] ) : false;
288
  $limit_string = ( $format ) ? "AND event_access LIKE '%$format%'" : '';
289
 
290
  return $limit_string;
my-calendar-location-manager.php CHANGED
@@ -123,7 +123,7 @@ function mc_manage_locations() {
123
  $query = esc_sql( $query ); // Prepare query.
124
  $search = ' WHERE MATCH(' . apply_filters( 'mc_search_fields', 'location_label,location_city,location_state,location_region,location_street,location_street2,location_phone' ) . ") AGAINST ( '$query' IN BOOLEAN MODE ) ";
125
  } else {
126
- $query = $wpdb->esc_like( $query ); // Prepare query.
127
  $search = " WHERE location_label LIKE '%$query%' OR location_city LIKE '%$query%' OR location_state LIKE '%$query%' OR location_region LIKE '%$query%' OR location_street LIKE '%$query%' OR location_street2 LIKE '%$query%' OR location_phone LIKE '%$query%' ";
128
  }
129
  } else {
123
  $query = esc_sql( $query ); // Prepare query.
124
  $search = ' WHERE MATCH(' . apply_filters( 'mc_search_fields', 'location_label,location_city,location_state,location_region,location_street,location_street2,location_phone' ) . ") AGAINST ( '$query' IN BOOLEAN MODE ) ";
125
  } else {
126
+ $query = esc_sql( $query ); // Prepare query.
127
  $search = " WHERE location_label LIKE '%$query%' OR location_city LIKE '%$query%' OR location_state LIKE '%$query%' OR location_region LIKE '%$query%' OR location_street LIKE '%$query%' OR location_street2 LIKE '%$query%' OR location_phone LIKE '%$query%' ";
128
  }
129
  } else {
my-calendar-locations.php CHANGED
@@ -263,7 +263,12 @@ function mc_show_location_form( $view = 'add', $loc_id = '' ) {
263
  */
264
  function mc_get_location( $location_id ) {
265
  global $wpdb;
266
- $location = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM ' . my_calendar_locations_table() . ' WHERE location_id = %d', $location_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
 
 
 
 
 
267
 
268
  return $location;
269
  }
@@ -600,13 +605,23 @@ function mc_location_select( $location = false ) {
600
  $locs = mc_get_locations( 'select-locations' );
601
 
602
  foreach ( $locs as $loc ) {
 
 
 
 
 
 
 
 
 
 
603
  $l = '<option value="' . $loc->location_id . '"';
604
  if ( $location ) {
605
  if ( (int) $location === (int) $loc->location_id ) {
606
  $l .= ' selected="selected"';
607
  }
608
  }
609
- $l .= '>' . mc_kses_post( stripslashes( $loc->location_label ) ) . '</option>';
610
  $list .= $l;
611
  }
612
 
263
  */
264
  function mc_get_location( $location_id ) {
265
  global $wpdb;
266
+ $mcdb = $wpdb;
267
+ if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
268
+ $mcdb = mc_remote_db();
269
+ }
270
+
271
+ $location = $mcdb->get_row( $mcdb->prepare( 'SELECT * FROM ' . my_calendar_locations_table() . ' WHERE location_id = %d', $location_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
272
 
273
  return $location;
274
  }
605
  $locs = mc_get_locations( 'select-locations' );
606
 
607
  foreach ( $locs as $loc ) {
608
+ // If label is empty, display street.
609
+ if ( '' === (string) $loc->location_label ) {
610
+ $label = $loc->location_street;
611
+ } else {
612
+ $label = $loc->location_label;
613
+ }
614
+ // If neither label nor street, skip.
615
+ if ( '' === (string) $label ) {
616
+ continue;
617
+ }
618
  $l = '<option value="' . $loc->location_id . '"';
619
  if ( $location ) {
620
  if ( (int) $location === (int) $loc->location_id ) {
621
  $l .= ' selected="selected"';
622
  }
623
  }
624
+ $l .= '>' . mc_kses_post( stripslashes( $label ) ) . '</option>';
625
  $list .= $l;
626
  }
627
 
my-calendar-output.php CHANGED
@@ -56,41 +56,37 @@ function mc_time_html( $e, $type ) {
56
  $date_format = mc_date_format();
57
  $orig_format = $date_format;
58
  $time_format = get_option( 'mc_time_format' );
59
- $start = date( 'Y-m-d', strtotime( $e->occur_begin ) );
60
- $end = date( 'Y-m-d', strtotime( $e->occur_end ) );
61
  $has_time = ( '00:00:00' !== $e->event_time && '' !== $e->event_time ) ? true : false;
62
  $final = '';
63
  // Manipulate date_format based on event data.
64
  if ( $e->event_end !== $e->event_begin && ! $has_time ) {
65
  $mult_format = get_option( 'mc_multidate_format', '' );
66
  $mult_format = ( '' !== $mult_format ) ? $mult_format : 'F j-%d, Y';
67
- $date_format = str_replace( '%d', date( 'j', strtotime( $e->occur_end ) ), $mult_format );
68
  }
69
  // If this event crosses years or months, use original date format & show both dates.
70
- if ( date( 'Y', strtotime( $e->occur_end ) ) !== date( 'Y', strtotime( $e->occur_begin ) ) || date( 'm', strtotime( $e->occur_end ) ) !== date( 'm', strtotime( $e->occur_begin ) ) ) {
71
  $current = date_i18n( $orig_format, strtotime( $e->occur_begin ) ) . ' &ndash; ' . date_i18n( $orig_format, strtotime( $e->occur_end ) );
72
  } else {
73
  $current = date_i18n( $date_format, strtotime( $e->occur_begin ) );
74
  $final = ( $e->event_end !== $e->event_begin ) ? date_i18n( $date_format, strtotime( $e->occur_end ) ) : $final;
75
  }
76
  // Do not show info in list view.
77
- $time_content = ( 'list' === $type ) ? '' : "<span class='mc-event-date dtstart' itemprop='startDate' title='" . $start . 'T' . $e->event_time . "' content='" . $start . 'T' . $e->event_time . "'>$current</span>";
 
 
 
 
 
 
78
  // Handle cases.
79
  if ( $has_time ) {
80
- $time_content .= "\n
81
- <span class='event-time dtstart'>
82
- <time class='value-title' datetime='" . $start . 'T' . $e->event_time . "' title='" . $start . 'T' . $e->event_time . "'>" .
83
- date_i18n( $time_format, strtotime( $e->occur_begin ) ) . '
84
- </time>
85
- </span>';
86
- if ( 0 == $e->event_hide_end ) {
87
  if ( '' !== $e->event_endtime && $e->event_endtime !== $e->event_time ) {
88
- $time_content .= "
89
- <span class='time-separator'> &ndash; </span>$final
90
- <span class='end-time dtend'>
91
- <time class='value-title' datetime='" . $end . 'T' . $e->event_endtime . "' title='" . $end . 'T' . $e->event_endtime . "'>" . date_i18n( $time_format, strtotime( $e->occur_end ) ) . '
92
- </time>
93
- </span>';
94
  }
95
  }
96
  } else {
@@ -101,10 +97,13 @@ function mc_time_html( $e, $type ) {
101
  }
102
  $time_content .= apply_filters( 'mcs_end_time_block', '', $e );
103
  // Generate date/time meta data.
104
- $meta = ( 0 == $e->event_hide_end ) ? "<meta itemprop='endDate' content='" . $start . 'T' . $e->event_endtime . "'/>" : '';
105
  $meta .= '<meta itemprop="duration" content="' . mc_duration( $e ) . '"/>';
106
 
107
- $time = "<div class='time-block'><p>$time_content</p>$meta</div>";
 
 
 
108
 
109
  return apply_filters( 'mcs_time_block', $time, $e );
110
  }
@@ -122,7 +121,7 @@ function mc_category_icon( $event, $type = 'html' ) {
122
  $url = plugin_dir_url( __FILE__ );
123
  $image = '';
124
  if ( 'true' !== get_option( 'mc_hide_icons' ) ) {
125
- if ( '' != $event->category_icon ) {
126
  $path = ( mc_is_custom_icon() ) ? str_replace( 'my-calendar', 'my-calendar-custom', $url ) : plugins_url( 'images/icons', __FILE__ ) . '/';
127
  $hex = ( strpos( $event->category_color, '#' ) !== 0 ) ? '#' : '';
128
  if ( 'html' === $type ) {
@@ -194,6 +193,7 @@ function my_calendar_draw_events( $events, $params, $process_date, $template = '
194
  $end = '';
195
  if ( 'mini' === $type && count( $events ) > 0 ) {
196
  $begin .= "<div id='date-$process_date' class='calendar-events'>";
 
197
  }
198
  foreach ( array_keys( $events ) as $key ) {
199
  $event =& $events[ $key ];
@@ -264,7 +264,7 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
264
  $gcal = '';
265
  $image = '';
266
  $tickets = '';
267
- $data = mc_create_tags( $event );
268
  $details = '';
269
  if ( mc_show_details( $time, $type ) ) {
270
  $details = apply_filters( 'mc_custom_template', false, $data, $event, $type, $process_date, $time, $template );
@@ -289,14 +289,14 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
289
  $display_image = get_option( 'mc_image' );
290
  $display_title = get_option( 'mc_title' );
291
  $display_reg = get_option( 'mc_event_registration' );
292
- $day_id = date( 'd', strtotime( $process_date ) );
293
  $uid = 'mc_' . $type . '_' . $day_id . '_' . $event->occur_id;
294
  $image = mc_category_icon( $event );
295
  $img = '';
296
  $has_image = ( '' !== $image ) ? ' has-image' : '';
297
  $event_classes = mc_event_classes( $event, $day_id, $type );
298
  $nofollow = ( stripos( $event_classes, 'past-event' ) !== false ) ? 'rel="nofollow"' : '';
299
- $header .= "<div id='$uid-$type-$id' class='$event_classes'>\n";
300
 
301
  switch ( $type ) {
302
  case 'calendar':
@@ -326,7 +326,7 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
326
  $wrap = ( _mc_is_url( $details_link ) ) ? "<a href='$details_link' class='url summary$has_image' $nofollow>" : '<span class="no-link">';
327
  $balance = ( _mc_is_url( $details_link ) ) ? '</a>' : '</span>';
328
  } else {
329
- $wrap = "<a href='#$uid-$type-details' class='et_smooth_scroll_disabled url summary$has_image'>";
330
  $balance = '</a>';
331
  }
332
  } else {
@@ -334,20 +334,20 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
334
  $balance = '';
335
  }
336
 
337
- $group_class = ( 1 == $event->event_span ) ? ' multidate group' . $event->event_group_id : '';
338
  $hlevel = apply_filters( 'mc_heading_level_table', 'h3', $type, $time, $template );
339
  $inner_heading = apply_filters( 'mc_heading_inner_title', $wrap . $image . trim( $event_title ) . $balance, $event_title, $event );
340
- $header .= ( 'single' !== $type && 'list' !== $type ) ? "<$hlevel class='event-title summary$group_class' id='mc_$event->occur_id-title-$id'>$inner_heading</$hlevel>\n" : '';
341
  $event_title = ( 'single' === $type ) ? apply_filters( 'mc_single_event_title', $event_title, $event ) : $event_title;
342
- $title = ( 'single' === $type && ! is_singular( 'mc-events' ) ) ? "<h2 class='event-title summary'>$image $event_title</h2>\n" : '<span class="summary screen-reader-text">' . $event_title . '</span>';
343
  $title = apply_filters( 'mc_event_title', $title, $event, $event_title, $image );
344
- $header .= '<span class="summary">' . $title . '</span>';
345
 
346
- $close_image = apply_filters( 'mc_close_button', "<span class='dashicons dashicons-dismiss' aria-hidden='true'></span><span class='screen-reader-text'>Close</span>" );
347
- $close_button = "<button type='button' aria-controls='$uid-$type-details' class='mc-toggle close' data-action='shiftforward'>$close_image</button>";
348
 
349
  if ( mc_show_details( $time, $type ) ) {
350
- $close = ( 'calendar' === $type || 'mini' === $type ) ? $close_button : '';
 
351
 
352
  if ( false === $details ) {
353
  if ( ( 'true' === $display_address || 'true' === $display_map ) ) {
@@ -356,12 +356,12 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
356
  $time_html = mc_time_html( $event, $type );
357
  if ( 'list' === $type ) {
358
  $hlevel = apply_filters( 'mc_heading_level_list', 'h3', $type, $time, $template );
359
- $list_title = "<$hlevel class='event-title summary' id='mc_$event->occur_id-title-$id'>$image" . $event_title . "</$hlevel>\n";
360
  }
361
  if ( 'true' === $display_author ) {
362
- if ( 0 != $event->event_author ) {
363
  $e = get_userdata( $event->event_author );
364
- $author = '<p class="event-author">' . __( 'Posted by', 'my-calendar' ) . ' <span class="author-name">' . $e->display_name . "</span></p>\n";
365
  }
366
  }
367
 
@@ -371,7 +371,7 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
371
  // Translators: Event title.
372
  $aria = " aria-label='" . esc_attr( sprintf( __( 'Details about %s', 'my-calendar' ), strip_tags( $event_title ) ) ) . "'";
373
  if ( _mc_is_url( $details_link ) ) {
374
- $more = "<p class='mc_details'><a$aria itemprop='url' href='" . esc_url( $details_link ) . "'>$details_label</a></p>\n";
375
  } else {
376
  $more = '';
377
  }
@@ -379,11 +379,11 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
379
  $more = apply_filters( 'mc_details_grid_link', $more, $event );
380
 
381
  if ( 'true' === $display_gcal ) {
382
- $gcal = "<p class='gcal'>" . mc_draw_template( $data, '{gcal_link}' ) . '</p>';
383
  }
384
 
385
  if ( 'true' === $display_vcal ) {
386
- $vcal = "<p class='ical'>" . mc_draw_template( $data, '{ical_html}' ) . '</p>';
387
  }
388
 
389
  if ( 'true' === $display_image ) {
@@ -393,12 +393,14 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
393
  if ( 'calendar' === $type && 'true' === $display_title ) {
394
  // In all cases, this is semantically a duplicate of the title, but can be beneficial for sighted users.
395
  $headingtype = ( 'h3' === $hlevel ) ? 'h4' : 'h' . ( ( (int) str_replace( 'h', '', $hlevel ) ) - 1 );
396
- $inner_title = '<h4 class="mc-title" aria-hidden="true">' . $event_title . '</h4>';
397
  }
398
 
399
  if ( 'true' === $display_desc || 'single' === $type ) {
400
- $description = wpautop( stripcslashes( mc_kses_post( $event->event_desc ) ), 1 );
401
- $description = "<div class='longdesc description' itemprop='description'>$description</div>";
 
 
402
  }
403
 
404
  if ( 'true' === $display_reg ) {
@@ -406,17 +408,23 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
406
  $url = esc_url( $event->event_tickets );
407
  $external = ( $url && mc_external_link( $url ) ) ? 'external' : '';
408
  $tickets = ( $url ) ? "<a class='$external' href='" . $url . "'>" . __( 'Buy Tickets', 'my-calendar' ) . '</a>' : '';
409
- $tickets = $info . $tickets;
 
 
 
 
410
  }
411
 
412
  if ( 'true' === $display_short && 'single' !== $type ) {
413
- $short = wpautop( stripcslashes( mc_kses_post( $event->event_short ) ), 1 );
414
- $short = "<div class='shortdesc description'>$short</div>";
 
 
415
  }
416
 
417
  $status = apply_filters( 'mc_registration_state', '', $event );
418
  $return_url = apply_filters( 'mc_return_uri', mc_get_uri( $event ) );
419
- $return = ( 'single' === $type ) ? "<p class='view-full'><a href='$return_url'>" . __( 'View full calendar', 'my-calendar' ) . '</a></p>' : '';
420
 
421
  if ( ! mc_show_details( $time, $type ) ) {
422
  $description = '';
@@ -436,10 +444,27 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
436
  $link_template = ( '' !== mc_get_template( 'link' ) ) ? mc_get_template( 'link' ) : __( 'More information', 'my-calendar' );
437
  $link_text = mc_draw_template( $data, $link_template );
438
  $link = "
439
- <p>
440
- <a href='" . esc_url( $event_link ) . "' class='$external_class' aria-describedby='mc_$event->occur_id-title'>" . $link_text . '</a>
441
- </p>';
442
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
 
444
  $details = "\n"
445
  . $close
@@ -447,32 +472,28 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
447
  . $time_html
448
  . $list_title
449
  . $img
450
- . "<div class='location'>"
451
- . $map . $address
452
- . '</div>'
453
  . $description
454
  . $short
455
  . $link
456
  . $status
457
  . $tickets
458
  . $author
459
- . "<div class='sharing'>"
460
- . $vcal . $gcal . $more
461
- . '</div>'
462
  . $return;
463
  } else {
464
  // If a custom template is in use.
465
- $toggle = ( 'calendar' === $type || 'mini' === $type ) ? $close_button : '';
466
  $details = $toggle . $details . "\n";
467
  }
468
 
469
  $img_class = ( '' !== $img ) ? ' has-image' : ' no-image';
470
- $container = "<div id='$uid-$type-details-$id' class='details$img_class' role='alert' aria-labelledby='mc_$event->occur_id-title" . '-' . $id . "' itemscope itemtype='http://schema.org/Event'>\n";
471
- $container .= "<meta itemprop='name' content='" . esc_attr( strip_tags( $event->event_title ) ) . "' />";
472
  $container = apply_filters( 'mc_before_event', $container, $event, $type, $time );
473
  $details = $header . $container . apply_filters( 'mc_inner_content', $details, $event, $type, $time );
474
  $details .= apply_filters( 'mc_after_event', '', $event, $type, $time );
475
- $details .= '</div><!--end .details--></div>';
476
  $details = apply_filters( 'mc_event_content', $details, $event, $type, $time );
477
  } else {
478
  $details = apply_filters( 'mc_before_event_no_details', $container, $event, $type, $time ) . $header . apply_filters( 'mc_after_event_no_details', '', $event, $type, $time ) . '</div>';
@@ -481,6 +502,20 @@ function my_calendar_draw_event( $event, $type = 'calendar', $process_date, $tim
481
  return $details;
482
  }
483
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
  /**
485
  * Generate the details when using a custom template
486
  *
@@ -548,7 +583,7 @@ function mc_get_event_image( $event, $data ) {
548
  }
549
  $default_size = apply_filters( 'mc_default_image_size', $default_size );
550
 
551
- if ( is_numeric( $event->event_post ) && 0 != $event->event_post && ( isset( $data[ $default_size ] ) && '' != $data[ $default_size ] ) ) {
552
  $atts = apply_filters( 'mc_post_thumbnail_atts', array( 'class' => 'mc-image photo' ) );
553
  $image_url = get_the_post_thumbnail_url( $event->event_post, $default_size );
554
  $image = get_the_post_thumbnail( $event->event_post, $default_size, $atts );
@@ -592,9 +627,9 @@ add_filter( 'mc_disable_link', 'mc_disable_link', 10, 2 );
592
  */
593
  function mc_event_classes( $event, $uid, $type ) {
594
  $uid = 'mc_' . $type . '_' . $event->occur_id;
595
- $ts = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $event->ts_occur_begin ) ) );
596
- $end = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $event->ts_occur_end ) ) );
597
- $now = current_time( 'timestamp' );
598
  if ( $ts < $now && $end > $now ) {
599
  $date_relation = 'on-now';
600
  } elseif ( $now < $ts ) {
@@ -602,12 +637,14 @@ function mc_event_classes( $event, $uid, $type ) {
602
  } elseif ( $now > $ts ) {
603
  $date_relation = 'past-event';
604
  }
 
605
 
606
  $classes = array(
607
  'mc-' . $uid,
608
  $type . '-event',
609
  mc_category_class( $event, 'mc_' ),
610
  $date_relation,
 
611
  );
612
 
613
  if ( $event->event_begin !== $event->event_end ) {
@@ -695,11 +732,11 @@ function mc_edit_panel( $html, $event, $type, $time ) {
695
  $edit = '';
696
  if ( mc_can_edit_event( $event ) && get_option( 'mc_remote' ) !== 'true' ) {
697
  $mc_id = $event->occur_id;
698
- $groupedit = ( 0 != $event->event_group_id ) ? " &bull; <a href='" . admin_url( "admin.php?page=my-calendar-groups&amp;mode=edit&amp;event_id=$event->event_id&amp;group_id=$event->event_group_id" ) . "' class='group'>" . __( 'Edit Group', 'my-calendar' ) . "</a>\n" : '';
699
  $recurs = str_split( $event->event_recur, 1 );
700
  $recur = $recurs[0];
701
  $referer = urlencode( mc_get_current_url() );
702
- $edit = "<div class='mc_edit_links'><p>";
703
  if ( 'S' === $recur ) {
704
  $edit .= "<a href='" . admin_url( "admin.php?page=my-calendar&amp;mode=edit&amp;event_id=$event->event_id&amp;ref=$referer" ) . "' class='edit'>" . __( 'Edit', 'my-calendar' ) . "</a> &bull; <a href='" . admin_url( "admin.php?page=my-calendar-manage&amp;mode=delete&amp;event_id=$event->event_id&amp;ref=$referer" ) . "' class='delete'>" . __( 'Delete', 'my-calendar' ) . "</a>$groupedit";
705
  } else {
@@ -731,9 +768,9 @@ function mc_date_switcher( $type = 'calendar', $cid = 'all', $time = 'month', $d
731
  }
732
  global $wpdb;
733
  $mcdb = $wpdb;
734
- $c_month = isset( $date['month'] ) ? $date['month'] : date( 'n', current_time( 'timestamp' ) );
735
- $c_year = isset( $date['year'] ) ? $date['year'] : date( 'Y', current_time( 'timestamp' ) );
736
- $c_day = isset( $date['day'] ) ? $date['day'] : date( 'j', current_time( 'timestamp' ) );
737
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
738
  $mcdb = mc_remote_db();
739
  }
@@ -775,33 +812,33 @@ function mc_date_switcher( $type = 'calendar', $cid = 'all', $time = 'month', $d
775
  }
776
  $date_switcher .= '</select>' . "\n" . $day_switcher . ' <label class="maybe-hide" for="' . $cid . '-year">' . __( 'Year', 'my-calendar' ) . '</label> <select id="' . $cid . '-year" name="yr">' . "\n";
777
  // Query to identify oldest start date in the database.
778
- $year1 = date( 'Y', strtotime( $mcdb->get_var( 'SELECT event_begin FROM ' . my_calendar_table() . ' WHERE event_approved = 1 AND event_flagged <> 1 ORDER BY event_begin ASC LIMIT 0 , 1' ) ) );
779
- $diff1 = date( 'Y' ) - $year1;
780
  $past = $diff1;
781
  $future = apply_filters( 'mc_jumpbox_future_years', 5, $cid );
782
  $fut = 1;
783
  $f = '';
784
  $p = '';
785
- $time = current_time( 'timestamp' );
786
 
787
  while ( $past > 0 ) {
788
  $p .= '<option value="';
789
- $p .= date( 'Y', $time ) - $past;
790
- $p .= '"' . selected( date( 'Y', $time ) - $past, $c_year, false ) . '>';
791
- $p .= date( 'Y', $time ) - $past . "</option>\n";
792
  $past = $past - 1;
793
  }
794
 
795
  while ( $fut < $future ) {
796
  $f .= '<option value="';
797
- $f .= date( 'Y', $time ) + $fut;
798
- $f .= '"' . selected( date( 'Y', $time ) + $fut, $c_year, false ) . '>';
799
- $f .= date( 'Y', $time ) + $fut . "</option>\n";
800
  $fut = $fut + 1;
801
  }
802
 
803
  $date_switcher .= $p;
804
- $date_switcher .= '<option value="' . date( 'Y', $time ) . '"' . selected( date( 'Y', $time ), $c_year, false ) . '>' . date( 'Y', $time ) . "</option>\n";
805
  $date_switcher .= $f;
806
  $date_switcher .= '</select> <input type="submit" class="button" value="' . __( 'Go', 'my-calendar' ) . '" /></div></form></div>';
807
  $date_switcher = apply_filters( 'mc_jumpbox', $date_switcher );
@@ -862,16 +899,22 @@ function mc_format_toggle( $format, $toggle, $time ) {
862
  */
863
  function mc_time_toggle( $format, $time, $month, $year, $current, $start_of_week, $from ) {
864
  // if dy parameter not set, use today's date instead of first day of month.
 
865
  if ( isset( $_GET['dy'] ) ) {
866
- $current_day = absint( $_GET['dy'] );
 
 
 
 
 
 
 
867
  $current_set = mktime( 0, 0, 0, $month, $current_day, $year );
868
- if ( date( 'N', $current_set ) === $start_of_week ) {
869
  $weeks_day = mc_first_day_of_week( $current_set );
870
- } else {
871
- $weeks_day = mc_first_day_of_week( $current );
872
  }
873
  } else {
874
- $weeks_day = mc_first_day_of_week( current_time( 'timestamp' ) );
875
  }
876
  $day = $weeks_day[0];
877
  if ( isset( $_GET['time'] ) && 'day' === $_GET['time'] ) {
@@ -879,7 +922,7 @@ function mc_time_toggle( $format, $time, $month, $year, $current, $start_of_week
879
  } else {
880
  // if the current date is displayed and the week beginning day is greater than 20 in the month.
881
  if ( ! isset( $_GET['dy'] ) && $day > 20 ) {
882
- $day = date( 'j', strtotime( "$from + 1 week" ) );
883
  }
884
  }
885
  $adjust = ( isset( $weeks_day[1] ) ) ? $weeks_day[1] : 0;
@@ -888,8 +931,8 @@ function mc_time_toggle( $format, $time, $month, $year, $current, $start_of_week
888
  if ( 'mini' !== $format ) {
889
  $toggle = "<div class='mc-time'>";
890
  $current_url = mc_get_current_url();
891
- if ( -1 == $adjust ) {
892
- $wmonth = ( 1 != $month ) ? $month - 1 : 12;
893
  } else {
894
  $wmonth = $month;
895
  }
@@ -961,26 +1004,26 @@ function mc_date_array( $timestamp, $period ) {
961
  $timestamp = strtotime( '+1 month', $timestamp );
962
  }
963
  $start_of_week = get_option( 'start_of_week' );
964
- $first = date( 'N', $timestamp ); // ISO-8601.
965
- $sub = date( 'w', $timestamp ); // numeric (how WordPress option is stored).
966
- $n = ( 1 == $start_of_week ) ? $first - 1 : $first;
967
 
968
  if ( $sub === $start_of_week ) {
969
- $from = date( 'Y-m-d', $timestamp );
970
  } else {
971
  $start = strtotime( "-$n days", $timestamp );
972
- $from = date( 'Y-m-d', $start );
973
  }
974
- $endtime = mktime( 0, 0, 0, date( 'm', $timestamp ), date( 't', $timestamp ), date( 'Y', $timestamp ) );
975
 
976
  // This allows multiple months displayed. Will figure out splitting tables...
977
  // To handle: $endtime = strtotime( "+$months months",$endtime ); JCD TODO.
978
- $last = (int) date( 'N', $endtime );
979
  $n = ( '1' === get_option( 'start_of_week' ) ) ? 7 - $last : 6 - $last;
980
- if ( -1 === $n && '7' === date( 'N', $endtime ) ) {
981
  $n = 6;
982
  }
983
- $to = date( 'Y-m-d', strtotime( "+$n days", $endtime ) );
984
 
985
  $return = array(
986
  'from' => $from,
@@ -989,8 +1032,8 @@ function mc_date_array( $timestamp, $period ) {
989
  break;
990
  case 'week':
991
  // First day of the week is calculated prior to this function. Argument received is the first day of the week.
992
- $from = date( 'Y-m-d', $timestamp );
993
- $to = date( 'Y-m-d', strtotime( '+6 days', $timestamp ) );
994
 
995
  $return = array(
996
  'from' => $from,
@@ -1020,7 +1063,7 @@ function mc_events_class( $events, $date = false ) {
1020
  } else {
1021
  foreach ( array_keys( $events ) as $key ) {
1022
  $event =& $events[ $key ];
1023
- if ( '00:00:00' === $event->event_endtime && date( 'Y-m-d', strtotime( $event->occur_end ) ) === $date && date( 'Y-m-d', strtotime( $event->occur_begin ) ) !== $date ) {
1024
  continue;
1025
  }
1026
  $author = ' author' . $event->event_author;
@@ -1053,11 +1096,12 @@ function mc_events_class( $events, $date = false ) {
1053
  function mc_list_title( $events ) {
1054
  usort( $events, 'mc_time_cmp' );
1055
  $now = $events[0];
 
1056
  $count = count( $events ) - 1;
1057
- $event_title = apply_filters( 'mc_list_title_title', strip_tags( stripcslashes( $now->event_title ), mc_strip_tags() ), $now );
1058
  if ( 0 === $count ) {
1059
  $cstate = $event_title;
1060
- } elseif ( 1 == $count ) {
1061
  // Translators: %s Title of event.
1062
  $cstate = sprintf( __( '%s<span class="mc-list-extended"> and 1 other event</span>', 'my-calendar' ), $event_title );
1063
  } else {
@@ -1080,8 +1124,9 @@ function mc_list_titles( $events ) {
1080
  usort( $events, 'mc_time_cmp' );
1081
  $titles = array();
1082
 
1083
- foreach ( $events as $event ) {
1084
- $title = apply_filters( 'mc_list_event_title_hint', strip_tags( stripcslashes( $event->event_title ), mc_strip_tags() ), $event, $events );
 
1085
  $titles[] = $title;
1086
  }
1087
 
@@ -1382,14 +1427,14 @@ function mc_show_event_template( $content ) {
1382
  $mc_id = intval( $_GET['mc_id'] );
1383
  $event_id = get_post_meta( $post->ID, '_mc_event_id', true );
1384
  $event = mc_get_event( $mc_id, 'object' );
1385
- $date = date( 'Y-m-d', strtotime( $event->occur_begin ) );
1386
- $time = date( 'H:i:00', strtotime( $event->occur_begin ) );
1387
  } else {
1388
  $event_id = get_post_meta( $post->ID, '_mc_event_id', true );
1389
  if ( is_numeric( $event_id ) ) {
1390
  $event = mc_get_nearest_event( $event_id );
1391
- $date = date( 'Y-m-d', strtotime( $event->occur_begin ) );
1392
- $time = date( 'H:i:s', strtotime( $event->occur_begin ) );
1393
  } else {
1394
 
1395
  return $content;
@@ -1445,7 +1490,7 @@ function mc_list_related( $id, $this_id, $template = '{date}, {time}' ) {
1445
  if ( is_array( $results ) && ! empty( $results ) ) {
1446
  foreach ( $results as $result ) {
1447
  $event_id = $result->event_id;
1448
- if ( $event_id == $this_id ) {
1449
  continue;
1450
  }
1451
 
@@ -1457,7 +1502,7 @@ function mc_list_related( $id, $this_id, $template = '{date}, {time}' ) {
1457
  }
1458
  $html = mc_draw_template( $array, $template );
1459
  $classes = mc_event_classes( $event, '', 'related' );
1460
- $classes .= ( $event_id == $this_id ) ? ' current-event' : '';
1461
  $output .= "<li class='$classes'>$html</li>";
1462
  }
1463
  }
@@ -1476,7 +1521,7 @@ function mc_list_related( $id, $this_id, $template = '{date}, {time}' ) {
1476
  * @return boolean
1477
  */
1478
  function mc_event_published( $event ) {
1479
- if ( 1 == $event->event_approved ) {
1480
  return true;
1481
  }
1482
 
@@ -1532,7 +1577,7 @@ function mc_calendar_params( $args ) {
1532
  $sday = isset( $args['day'] ) ? $args['day'] : false;
1533
  $source = isset( $args['source'] ) ? $args['source'] : 'shortcode';
1534
  $search = isset( $args['search'] ) ? $args['search'] : '';
1535
- $site = ( isset( $args['site'] ) && '' != trim( $args['site'] ) ) ? $args['site'] : false;
1536
  $months = isset( $args['months'] ) ? $args['months'] : false;
1537
 
1538
  if ( ! in_array( $format, array( 'list', 'calendar', 'mini' ), true ) ) {
@@ -1656,12 +1701,12 @@ function my_calendar( $args ) {
1656
  $body .= mc_get_event( $mc_id, 'html' );
1657
  }
1658
  } else {
1659
- $end_of_week = ( 1 == $start_of_week ) ? 7 : 6;
1660
  $start_of_week = ( $show_weekends ) ? $start_of_week : 1;
1661
  $name_days = mc_name_days( $params['format'] );
1662
  $abbrevs = array( 'sun', 'mon', 'tues', 'wed', 'thur', 'fri', 'sat' );
1663
 
1664
- if ( 1 == $start_of_week ) {
1665
  $first = array_shift( $name_days );
1666
  $afirst = array_shift( $abbrevs );
1667
  $name_days[] = $first;
@@ -1711,8 +1756,8 @@ function my_calendar( $args ) {
1711
 
1712
  if ( 'day' === $params['time'] ) {
1713
  $body .= "<div class='mcjs " . esc_attr( $params['format'] . ' ' . $params['time'] ) . "'>" . $top;
1714
- $from = date( 'Y-m-d', $current );
1715
- $to = date( 'Y-m-d', $current );
1716
 
1717
  $query = array(
1718
  'from' => $from,
@@ -1765,9 +1810,9 @@ function my_calendar( $args ) {
1765
  } else {
1766
  $current_header = date_i18n( $month_format, $current );
1767
  }
1768
- $current_month_header = ( date( 'Y', $current ) === date( 'Y', $through_date ) ) ? date_i18n( 'F', $current ) : date_i18n( 'F Y', $current );
1769
  $through_month_header = date_i18n( $month_format, $through_date );
1770
- $values = array( 'date' => date( 'Y-m-d', $current ) );
1771
 
1772
  // Add the calendar table and heading.
1773
  $body .= $top;
@@ -1784,7 +1829,7 @@ function my_calendar( $args ) {
1784
  $list_heading = ( $months <= 1 ) ? $current_header . $caption_text . "\n" : $current_month_header . '&ndash;' . $through_month_header . $caption_text;
1785
  // Translators: time period displayed.
1786
  $list_heading = sprintf( __( 'Events in %s', 'my-calendar' ), $list_heading );
1787
- if ( isset( $_GET['searched'] ) && 1 == $_GET['searched'] ) {
1788
  $list_heading = __( 'Search Results', 'my-calendar' );
1789
  }
1790
  } else {
@@ -1804,57 +1849,57 @@ function my_calendar( $args ) {
1804
  if ( 'list' === $params['format'] ) {
1805
  $body .= "<ul id='list-$id' class='mc-list'>";
1806
  } else {
1807
- $body .= ( 'tr' === $tr ) ? "<thead>\n" : '<div class="mc-table-body">';
1808
- $body .= "<$tr class='mc-row'>\n";
1809
  if ( apply_filters( 'mc_show_week_number', false, $args ) ) {
1810
- $body .= "<th class='mc-week-number'>" . __( 'Week', 'my-calendar' ) . '</th>';
1811
  }
1812
  for ( $i = 0; $i <= 6; $i ++ ) {
1813
- if ( 0 == $start_of_week ) {
1814
  $class = ( $i < 6 && $i > 0 ) ? 'day-heading' : 'weekend-heading';
1815
  } else {
1816
  $class = ( $i < 5 ) ? 'day-heading' : 'weekend-heading';
1817
  }
1818
  $dayclass = sanitize_html_class( $abbrevs[ $i ] );
1819
  if ( ( 'weekend-heading' === $class && $show_weekends ) || 'weekend-heading' !== $class ) {
1820
- $body .= "<$th class='$class $dayclass'>" . $name_days[ $i ] . "</$close_th>\n";
1821
  }
1822
  }
1823
- $body .= "\n</$tr>\n";
1824
- $body .= ( 'tr' === $tr ) ? "</thead>\n<tbody>" : '';
1825
  }
1826
  $odd = 'odd';
1827
 
1828
  $show_all = apply_filters( 'mc_all_list_dates', false, $args );
1829
  if ( $no_events && 'list' === $params['format'] && false === $show_all ) {
1830
  // If there are no events in list format, just display that info.
1831
- $no_events = ( '' == $content ) ? __( 'There are no events scheduled during this period.', 'my-calendar' ) : $content;
1832
  $body .= "<li class='mc-events no-events'>$no_events</li>";
1833
  } else {
1834
  $start = strtotime( $from );
1835
  $end = strtotime( $to );
1836
  $week_number_shown = false;
1837
  do {
1838
- $date_is = date( 'Y-m-d', $start );
1839
- $is_weekend = ( date( 'N', $start ) < 6 ) ? false : true;
1840
  if ( $show_weekends || ( ! $show_weekends && ! $is_weekend ) ) {
1841
- if ( date( 'N', $start ) == $start_of_week && 'list' !== $params['format'] ) {
1842
  $body .= "<$tr class='mc-row'>";
1843
  }
1844
  $events = ( isset( $event_array[ $date_is ] ) ) ? $event_array[ $date_is ] : array();
1845
  $week_header = date_i18n( $week_format, $start );
1846
- $thisday_heading = ( 'week' === $params['time'] ) ? "<small>$week_header</small>" : date( 'j', $start );
1847
 
1848
  // Generate event classes & attributes.
1849
  $events_class = mc_events_class( $events, $date_is );
1850
- $monthclass = ( date( 'n', $start ) == $date['month'] || 'month' != $params['time'] ) ? '' : 'nextmonth';
1851
  $dateclass = mc_dateclass( $start );
1852
  $ariacurrent = ( false !== strpos( $dateclass, 'current-day' ) ) ? ' aria-current="date"' : '';
1853
 
1854
  $td = apply_filters( 'mc_grid_day_wrapper', 'td', $params['format'] );
1855
  if ( ! $week_number_shown ) {
1856
  $weeknumber = mc_show_week_number( $events, $args, $params['format'], $td, $start );
1857
- if ( '' != $weeknumber ) {
1858
  $body .= $weeknumber;
1859
  $week_number_shown = true;
1860
  }
@@ -1878,7 +1923,7 @@ function my_calendar( $args ) {
1878
  $link = mc_build_mini_url( $start, $params['category'], $events, $args, $date );
1879
  $element = "a href='$link'";
1880
  $close = 'a';
1881
- $trigger = 'trigger';
1882
  } else {
1883
  $element = 'span';
1884
  $close = 'span';
@@ -1889,25 +1934,25 @@ function my_calendar( $args ) {
1889
  $weekend_class = ( $is_weekend ) ? 'weekend' : '';
1890
  if ( 'list' === $params['format'] ) {
1891
  if ( 'true' === $list_info ) {
1892
- $title = ' - ' . mc_wrap_title( "<span class='mc-list-details select-event'>" . mc_list_title( $events ) . '</span>' );
1893
  } elseif ( 'true' === $list_events ) {
1894
- $title = ' - ' . mc_wrap_title( "<span class='mc-list-details all-events'>" . mc_list_titles( $events ) . '</span>' );
1895
  } else {
1896
  $title = '';
1897
  }
1898
  if ( '' !== $event_output ) {
1899
- $body .= "<li id='$params[format]-$date_is' $ariacurrent class='mc-events $dateclass $events_class $odd'><strong class=\"event-date\">" . mc_wrap_title( date_i18n( $date_format, $start ) ) . "$title</strong>" . $event_output . '</li>';
1900
  $odd = ( 'odd' === $odd ) ? 'even' : 'odd';
1901
  }
1902
  } else {
1903
- $body .= "<$td id='$params[format]-$date_is' $ariacurrent class='$dateclass $weekend_class $monthclass $events_class day-with-date'>" . "<$element class='mc-date $trigger'><span aria-hidden='true'>$thisday_heading</span><span class='screen-reader-text'>" . date_i18n( $date_format, strtotime( $date_is ) ) . "</span></$close>" . $event_output . "</$td>\n";
1904
  }
1905
  }
1906
  } else {
1907
  // If there are no events on this date within current params.
1908
  if ( 'list' !== $params['format'] ) {
1909
  $weekend_class = ( $is_weekend ) ? 'weekend' : '';
1910
- $body .= "<$td $ariacurrent class='no-events $dateclass $weekend_class $monthclass $events_class day-with-date'><span class='mc-date no-events'><span aria-hidden='true'>$thisday_heading</span><span class='screen-reader-text'>" . date_i18n( $date_format, strtotime( $date_is ) ) . "</span></span></$td>\n";
1911
  } else {
1912
  if ( true === $show_all ) {
1913
  $body .= "<li id='$params[format]-$date_is' $ariacurrent class='no-events $dateclass $events_class $odd'><strong class=\"event-date\">" . mc_wrap_title( date_i18n( $date_format, $start ) ) . '</strong></li>';
@@ -1916,9 +1961,9 @@ function my_calendar( $args ) {
1916
  }
1917
  }
1918
 
1919
- if ( date( 'N', $start ) == $end_of_week || ( date( 'N', $start ) == 5 && ! $show_weekends ) ) {
1920
  if ( 'list' !== $params['format'] ) {
1921
- $body .= "\n</$tr>\n"; // End of 'is beginning of week'.
1922
  }
1923
  $week_number_shown = false;
1924
  }
@@ -1961,22 +2006,23 @@ function mc_get_from_to( $show_months, $params, $date ) {
1961
  $num = $show_months - 1;
1962
  $c_month = $date['month'];
1963
  $c_year = $date['year'];
1964
-
 
1965
  // Grid calendar can't show multiple months.
1966
  if ( 'list' === $format && 'week' !== $time ) {
1967
- if ( $num > 0 && 'day' != $time && 'week' != $time ) {
1968
  if ( 'month+1' === $time ) {
1969
- $from = date( 'Y-m-d', strtotime( '+1 month', mktime( 0, 0, 0, $c_month, 1, $c_year ) ) );
1970
- $next = strtotime( "+$num months", strtotime( '+1 month', mktime( 0, 0, 0, $c_month, 1, $c_year ) ) );
1971
  } else {
1972
- $from = date( 'Y-m-d', mktime( 0, 0, 0, $c_month, 1, $c_year ) );
1973
- $next = strtotime( "+$num months", mktime( 0, 0, 0, $c_month, 1, $c_year ) );
1974
  }
1975
- $last = date( 't', $next );
1976
- $to = date( 'Y-m', $next ) . '-' . $last;
1977
  } else {
1978
- $from = date( 'Y-m-d', mktime( 0, 0, 0, $c_month, 1, $c_year ) );
1979
- $to = date( 'Y-m-d', mktime( 0, 0, 0, $c_month, date( 't', mktime( 0, 0, 0, $c_month, 1, $c_year ) ), $c_year ) );
1980
  }
1981
  $dates = array(
1982
  'from' => $from,
@@ -2104,7 +2150,7 @@ function mc_generate_calendar_nav( $params, $cat, $start_of_week, $show_months,
2104
  }
2105
 
2106
  // Set up format toggle.
2107
- $toggle = ( in_array( 'toggle', $used ) ) ? mc_format_toggle( $format, 'yes', $time ) : '';
2108
 
2109
  // Set up time toggle.
2110
  if ( in_array( 'timeframe', $used, true ) ) {
@@ -2126,8 +2172,8 @@ function mc_generate_calendar_nav( $params, $cat, $start_of_week, $show_months,
2126
 
2127
  // Set up exports.
2128
  if ( in_array( 'exports', $used, true ) ) {
2129
- $ical_m = ( isset( $_GET['month'] ) ) ? (int) $_GET['month'] : date( 'n' );
2130
- $ical_y = ( isset( $_GET['yr'] ) ) ? (int) $_GET['yr'] : date( 'Y' );
2131
  $next_link = my_calendar_next_link( $date, $format, $time, $show_months );
2132
  $exports = mc_export_links( $ical_y, $ical_m, $next_link, $add, $subtract );
2133
  }
@@ -2137,6 +2183,7 @@ function mc_generate_calendar_nav( $params, $cat, $start_of_week, $show_months,
2137
  $jump = mc_date_switcher( $format, $main_class, $time, $date );
2138
  }
2139
 
 
2140
  foreach ( $mc_toporder as $value ) {
2141
  if ( 'none' !== $value && in_array( $value, $used, true ) && in_array( $value, $available, true ) ) {
2142
  $value = trim( $value );
@@ -2144,6 +2191,7 @@ function mc_generate_calendar_nav( $params, $cat, $start_of_week, $show_months,
2144
  }
2145
  }
2146
 
 
2147
  foreach ( $mc_bottomorder as $value ) {
2148
  if ( 'none' !== $value && 'stop' !== $value && in_array( $value, $used, true ) && in_array( $value, $available, true ) ) {
2149
  $value = trim( $value );
@@ -2179,8 +2227,8 @@ function mc_generate_calendar_nav( $params, $cat, $start_of_week, $show_months,
2179
  function mc_show_week_number( $events, $args, $format, $td, $start ) {
2180
  $body = '';
2181
  if ( apply_filters( 'mc_show_week_number', false, $args ) ) {
2182
- $weeknumber = date( 'W', $start );
2183
- if ( 'list' != $format ) {
2184
  $body = "<$td class='week_number'>$weeknumber</$td>";
2185
  }
2186
  if ( 'list' === $format && ! empty( $events ) ) {
@@ -2207,31 +2255,31 @@ function mc_build_mini_url( $start, $category, $events, $args, $date ) {
2207
  if ( 'true' === $open_day_uri || 'false' === $open_day_uri ) {
2208
  // Yes, this is weird. it's from some old settings...
2209
  $target = array(
2210
- 'yr' => date( 'Y', $start ),
2211
- 'month' => date( 'm', $start ),
2212
- 'dy' => date( 'j', $start ),
2213
  'time' => 'day',
2214
  );
2215
- if ( '' != $category ) {
2216
  $target['mcat'] = $category;
2217
  }
2218
  $day_url = mc_build_url( $target, array( 'month', 'dy', 'yr', 'ltype', 'loc', 'mcat', 'cid', 'mc_id' ), apply_filters( 'mc_modify_day_uri', mc_get_uri( reset( $events ), $args ) ) );
2219
- $link = ( '' != $day_url ) ? $day_url : '#';
2220
  } else {
2221
  $mini_uri = get_option( 'mc_mini_uri' );
2222
  $atype = str_replace( 'anchor', '', $open_day_uri ); // List or grid.
2223
- $ad = str_pad( date( 'j', $start ), 2, '0', STR_PAD_LEFT ); // Need to match format in ID.
2224
  $am = str_pad( $date['month'], 2, '0', STR_PAD_LEFT );
2225
  $date_url = mc_build_url(
2226
  array(
2227
  'yr' => $date['year'],
2228
  'month' => $date['month'],
2229
- 'dy' => date( 'j', $start ),
2230
  ),
2231
  array( 'month', 'dy', 'yr', 'ltype', 'loc', 'mcat', 'cid', 'mc_id' ),
2232
  $mini_uri
2233
  );
2234
- $link = esc_url( ( '' != $mini_uri ) ? $date_url . '#' . $atype . '-' . $date['year'] . '-' . $am . '-' . $ad : '#' );
2235
  }
2236
 
2237
  return $link;
@@ -2312,71 +2360,80 @@ function mc_nav( $date, $format, $time, $show_months, $class ) {
2312
  * @return array
2313
  */
2314
  function mc_get_current_date( $main_class, $cid, $params ) {
2315
- $timestamp = current_time( 'timestamp' );
2316
- $time = $params['time'];
2317
- $smonth = $params['smonth'];
2318
- $syear = $params['syear'];
2319
- $sday = $params['sday'];
2320
- $c_m = 0;
2321
  if ( isset( $_GET['dy'] ) && $main_class === $cid && ( 'day' === $time || 'week' === $time ) ) {
2322
- $c_day = (int) $_GET['dy'];
 
 
 
 
 
 
 
 
 
 
2323
  } else {
2324
  if ( 'week' === $time ) {
2325
  $dm = mc_first_day_of_week();
2326
  $c_day = $dm[0];
2327
  $c_m = $dm[1];
2328
  } elseif ( 'day' === $time ) {
2329
- $c_day = date( 'd', $timestamp );
2330
  } else {
2331
  $c_day = 1;
2332
  }
2333
  }
2334
- if ( isset( $_GET['month'] ) && $main_class == $cid ) {
2335
  $c_month = (int) $_GET['month'];
2336
  if ( ! isset( $_GET['dy'] ) ) {
2337
  $c_day = 1;
2338
  }
2339
  } else {
2340
- $xnow = date( 'Y-m-d', $timestamp );
2341
- $c_month = ( 0 == $c_m ) ? date( 'm', $timestamp ) : date( 'm', strtotime( $xnow . ' -1 month' ) );
2342
  }
2343
 
2344
- $is_start_of_week = ( get_option( 'start_of_week' ) === date( 'N', $timestamp ) ) ? true : false;
2345
- if ( isset( $_GET['yr'] ) && $main_class == $cid ) {
2346
  $c_year = (int) $_GET['yr'];
2347
  } else {
2348
  if ( 'week' === $time && ! isset( $_GET['dy'] ) ) {
2349
  if ( $is_start_of_week ) {
2350
- $c_year = ( date( 'Y', current_time( 'timestamp' ) ) );
2351
  } else {
2352
- $current_year = date( 'Y', current_time( 'timestamp' ) );
2353
- $c_year = ( 0 == $dm[1] ) ? $current_year : false;
2354
  if ( ! $c_year ) {
2355
- $c_year = ( date( 'Y', strtotime( '-1 month' ) ) == $current_year ) ? $current_year : $current_year - 1;
2356
  }
2357
  }
2358
  } else {
2359
- $c_year = ( date( 'Y', current_time( 'timestamp' ) ) );
2360
  }
2361
  }
2362
  // Years get funny if we exceed 3000, so we use this check.
2363
  if ( ! ( $c_year <= 3000 && $c_year >= 0 ) ) {
2364
  // No valid year causes the calendar to default to today.
2365
- $c_year = date( 'Y', $timestamp );
2366
- $c_month = date( 'm', $timestamp );
2367
- $c_day = date( 'd', $timestamp );
2368
  }
2369
  if ( ! ( isset( $_GET['yr'] ) || isset( $_GET['month'] ) || isset( $_GET['dy'] ) ) ) {
2370
  // Month/year based on shortcode.
2371
- $shortcode_month = ( false != $smonth ) ? $smonth : $c_month;
2372
- $shortcode_year = ( false != $syear ) ? $syear : $c_year;
2373
- $shortcode_day = ( false != $sday ) ? $sday : $c_day;
2374
  // Override with filters.
2375
  $c_year = apply_filters( 'mc_filter_year', $shortcode_year, $params );
2376
  $c_month = apply_filters( 'mc_filter_month', $shortcode_month, $params );
2377
  $c_day = apply_filters( 'mc_filter_day', $shortcode_day, $params );
2378
  }
2379
- $c_day = ( 0 == $c_day ) ? 1 : $c_day; // c_day can't equal 0.
2380
  $current = mktime( 0, 0, 0, $c_month, $c_day, $c_year );
2381
  $c_month = str_pad( $c_month, 2, '0', STR_PAD_LEFT );
2382
 
@@ -2470,7 +2527,7 @@ function mc_category_key( $category ) {
2470
  } else {
2471
  $url = mc_build_url( array( 'mcat' => $selectable_categories ), array( 'mcat' ) );
2472
  }
2473
- if ( 1 == $cat->category_private ) {
2474
  $class .= ' private';
2475
  }
2476
  $cat_name = mc_kses_post( stripcslashes( $cat->category_name ) );
@@ -2508,14 +2565,13 @@ function mc_sub_links( $subtract ) {
2508
  $google = get_feed_link( 'my-calendar-google' );
2509
  $outlook = get_feed_link( 'my-calendar-outlook' );
2510
 
2511
- $rss = "\n <li class='rss'><a href='" . esc_url( $feed ) . "'>" . __( 'RSS', 'my-calendar' ) . '</a></li>';
2512
- $sub_google = "\n <li class='ics google'><a href='" . esc_url( $google ) . "'>" . __( 'Google', 'my-calendar' ) . '</a></li>';
2513
- $sub_outlook = "\n <li class='ics outlook'><a href='" . esc_url( $outlook ) . "'>" . __( 'Outlook', 'my-calendar' ) . '</a></li>';
2514
 
2515
- $output = "\n
2516
- <div class='mc-export'>
2517
  <ul>$rss$sub_google$sub_outlook</ul>
2518
- </div>\n";
2519
 
2520
  return $output;
2521
  }
@@ -2543,13 +2599,12 @@ function mc_export_links( $y, $m, $next, $add, $subtract ) {
2543
  $add['export'] = 'outlook';
2544
  $ics2 = mc_build_url( $add, $subtract, get_feed_link( 'my-calendar-ics' ) );
2545
 
2546
- $google = "\n <li class='ics google'><a href='" . $ics . "'>" . __( 'Google', 'my-calendar' ) . '</a></li>';
2547
- $outlook = "\n <li class='ics outlook'><a href='" . $ics2 . "'>" . __( 'Outlook', 'my-calendar' ) . '</a></li>';
2548
 
2549
- $output = "\n
2550
- <div class='mc-export'>
2551
  <ul>$google$outlook</ul>
2552
- </div>\n";
2553
 
2554
  return $output;
2555
  }
@@ -2573,7 +2628,7 @@ function my_calendar_next_link( $date, $format, $time = 'month', $months = 1 ) {
2573
  $mc_next = get_option( 'mc_next_events', '' );
2574
  $next_events = ( '' === $mc_next ) ? '<span class="maybe-hide">' . __( 'Next', 'my-calendar' ) . '</span>' : stripslashes( $mc_next );
2575
  if ( $months <= 1 || 'list' !== $format ) {
2576
- if ( 12 == $cur_month ) {
2577
  $month = 1;
2578
  $yr = $next_year;
2579
  } else {
@@ -2592,7 +2647,7 @@ function my_calendar_next_link( $date, $format, $time = 'month', $months = 1 ) {
2592
  }
2593
  }
2594
  $day = '';
2595
- if ( $yr != $cur_year ) {
2596
  $format = 'F, Y';
2597
  } else {
2598
  $format = 'F';
@@ -2600,10 +2655,10 @@ function my_calendar_next_link( $date, $format, $time = 'month', $months = 1 ) {
2600
  $date = date_i18n( $format, mktime( 0, 0, 0, $month, 1, $yr ) );
2601
  if ( 'week' === $time ) {
2602
  $nextdate = strtotime( "$cur_year-$cur_month-$cur_day" . '+ 7 days' );
2603
- $day = date( 'd', $nextdate );
2604
- $yr = date( 'Y', $nextdate );
2605
- $month = date( 'm', $nextdate );
2606
- if ( $yr != $cur_year ) {
2607
  $format = 'F j, Y';
2608
  } else {
2609
  $format = 'F j';
@@ -2613,10 +2668,10 @@ function my_calendar_next_link( $date, $format, $time = 'month', $months = 1 ) {
2613
  }
2614
  if ( 'day' === $time ) {
2615
  $nextdate = strtotime( "$cur_year-$cur_month-$cur_day" . '+ 1 days' );
2616
- $day = date( 'd', $nextdate );
2617
- $yr = date( 'Y', $nextdate );
2618
- $month = date( 'm', $nextdate );
2619
- if ( $yr != $cur_year ) {
2620
  $format = 'F j, Y';
2621
  } else {
2622
  $format = 'F j';
@@ -2650,10 +2705,10 @@ function my_calendar_prev_link( $date, $format, $time = 'month', $months = 1 ) {
2650
  $cur_day = $date['day'];
2651
 
2652
  $last_year = $cur_year - 1;
2653
- $mc_previous = get_option( 'mc_previous_events' );
2654
- $previous_events = ( '' == $mc_previous ) ? '<span class="maybe-hide">' . __( 'Previous', 'my-calendar' ) . '</span>' : stripslashes( $mc_previous );
2655
- if ( $months <= 1 || 'list' != $format ) {
2656
- if ( 1 == $cur_month ) {
2657
  $month = 12;
2658
  $yr = $last_year;
2659
  } else {
@@ -2671,7 +2726,7 @@ function my_calendar_prev_link( $date, $format, $time = 'month', $months = 1 ) {
2671
  $yr = $cur_year;
2672
  }
2673
  }
2674
- if ( $yr != $cur_year ) {
2675
  $format = 'F, Y';
2676
  } else {
2677
  $format = 'F';
@@ -2680,10 +2735,10 @@ function my_calendar_prev_link( $date, $format, $time = 'month', $months = 1 ) {
2680
  $day = '';
2681
  if ( 'week' === $time ) {
2682
  $prevdate = strtotime( "$cur_year-$cur_month-$cur_day" . '- 7 days' );
2683
- $day = date( 'd', $prevdate );
2684
- $yr = date( 'Y', $prevdate );
2685
- $month = date( 'm', $prevdate );
2686
- if ( $yr != $cur_year ) {
2687
  $format = 'F j, Y';
2688
  } else {
2689
  $format = 'F j';
@@ -2692,10 +2747,10 @@ function my_calendar_prev_link( $date, $format, $time = 'month', $months = 1 ) {
2692
  }
2693
  if ( 'day' === $time ) {
2694
  $prevdate = strtotime( "$cur_year-$cur_month-$cur_day" . '- 1 days' );
2695
- $day = date( 'd', $prevdate );
2696
- $yr = date( 'Y', $prevdate );
2697
- $month = date( 'm', $prevdate );
2698
- if ( $yr != $cur_year ) {
2699
  $format = 'F j, Y';
2700
  } else {
2701
  $format = 'F j';
56
  $date_format = mc_date_format();
57
  $orig_format = $date_format;
58
  $time_format = get_option( 'mc_time_format' );
59
+ $start = mc_date( 'Y-m-d', strtotime( $e->occur_begin ), false );
60
+ $end = mc_date( 'Y-m-d', strtotime( $e->occur_end ), false );
61
  $has_time = ( '00:00:00' !== $e->event_time && '' !== $e->event_time ) ? true : false;
62
  $final = '';
63
  // Manipulate date_format based on event data.
64
  if ( $e->event_end !== $e->event_begin && ! $has_time ) {
65
  $mult_format = get_option( 'mc_multidate_format', '' );
66
  $mult_format = ( '' !== $mult_format ) ? $mult_format : 'F j-%d, Y';
67
+ $date_format = str_replace( '%d', mc_date( 'j', strtotime( $e->occur_end ), false ), $mult_format );
68
  }
69
  // If this event crosses years or months, use original date format & show both dates.
70
+ if ( mc_date( 'Y', strtotime( $e->occur_end ), false ) !== mc_date( 'Y', strtotime( $e->occur_begin ), false ) || mc_date( 'm', strtotime( $e->occur_end ), false ) !== mc_date( 'm', strtotime( $e->occur_begin ), false ) ) {
71
  $current = date_i18n( $orig_format, strtotime( $e->occur_begin ) ) . ' &ndash; ' . date_i18n( $orig_format, strtotime( $e->occur_end ) );
72
  } else {
73
  $current = date_i18n( $date_format, strtotime( $e->occur_begin ) );
74
  $final = ( $e->event_end !== $e->event_begin ) ? date_i18n( $date_format, strtotime( $e->occur_end ) ) : $final;
75
  }
76
  // Do not show info in list view.
77
+ $offset = get_option( 'gmt_offset' );
78
+ $hours = (int) $offset;
79
+ $minutes = abs( ( $offset - (int) $offset ) * 60 );
80
+ $offset = sprintf( '%+03d:%02d', $hours, $minutes );
81
+ $dtstart = $start . 'T' . $e->event_time . $offset;
82
+ $dtend = $end . 'T' . $e->event_endtime . $offset;
83
+ $time_content = ( 'list' === $type ) ? '' : "<span class='mc-event-date dtstart' itemprop='startDate' title='" . $dtstart . "' content='" . $dtstart . "'>$current</span>";
84
  // Handle cases.
85
  if ( $has_time ) {
86
+ $time_content .= "<span class='event-time dtstart'><time class='value-title' datetime='" . $dtstart . "' title='" . $dtstart . "'>" . date_i18n( $time_format, strtotime( $e->occur_begin ) ) . '</time></span>';
87
+ if ( 0 === (int) $e->event_hide_end ) {
 
 
 
 
 
88
  if ( '' !== $e->event_endtime && $e->event_endtime !== $e->event_time ) {
89
+ $time_content .= "<span class='time-separator'> &ndash; </span>$final<span class='end-time dtend'><time class='value-title' datetime='" . $dtend . "' title='" . $dtend . "'>" . date_i18n( $time_format, strtotime( $e->occur_end ) ) . '</time></span>';
 
 
 
 
 
90
  }
91
  }
92
  } else {
97
  }
98
  $time_content .= apply_filters( 'mcs_end_time_block', '', $e );
99
  // Generate date/time meta data.
100
+ $meta = ( 0 === (int) $e->event_hide_end ) ? "<meta itemprop='endDate' content='" . $start . 'T' . $e->event_endtime . "'/>" : '';
101
  $meta .= '<meta itemprop="duration" content="' . mc_duration( $e ) . '"/>';
102
 
103
+ $time = "
104
+ <div class='time-block'>
105
+ <p>$time_content</p>$meta
106
+ </div>";
107
 
108
  return apply_filters( 'mcs_time_block', $time, $e );
109
  }
121
  $url = plugin_dir_url( __FILE__ );
122
  $image = '';
123
  if ( 'true' !== get_option( 'mc_hide_icons' ) ) {
124
+ if ( '' !== $event->category_icon ) {
125
  $path = ( mc_is_custom_icon() ) ? str_replace( 'my-calendar', 'my-calendar-custom', $url ) : plugins_url( 'images/icons', __FILE__ ) . '/';
126
  $hex = ( strpos( $event->category_color, '#' ) !== 0 ) ? '#' : '';
127
  if ( 'html' === $type ) {
193
  $end = '';
194
  if ( 'mini' === $type && count( $events ) > 0 ) {
195
  $begin .= "<div id='date-$process_date' class='calendar-events'>";
196
+ $begin .= mc_close_button( "date-$process_date" );
197
  }
198
  foreach ( array_keys( $events ) as $key ) {
199
  $event =& $events[ $key ];
264
  $gcal = '';
265
  $image = '';
266
  $tickets = '';
267
+ $data = mc_create_tags( $event, $id );
268
  $details = '';
269
  if ( mc_show_details( $time, $type ) ) {
270
  $details = apply_filters( 'mc_custom_template', false, $data, $event, $type, $process_date, $time, $template );
289
  $display_image = get_option( 'mc_image' );
290
  $display_title = get_option( 'mc_title' );
291
  $display_reg = get_option( 'mc_event_registration' );
292
+ $day_id = mc_date( 'd', strtotime( $process_date ), false );
293
  $uid = 'mc_' . $type . '_' . $day_id . '_' . $event->occur_id;
294
  $image = mc_category_icon( $event );
295
  $img = '';
296
  $has_image = ( '' !== $image ) ? ' has-image' : '';
297
  $event_classes = mc_event_classes( $event, $day_id, $type );
298
  $nofollow = ( stripos( $event_classes, 'past-event' ) !== false ) ? 'rel="nofollow"' : '';
299
+ $header .= "\n\n <div id='$uid-$type-$id' class='$event_classes'>\n";
300
 
301
  switch ( $type ) {
302
  case 'calendar':
326
  $wrap = ( _mc_is_url( $details_link ) ) ? "<a href='$details_link' class='url summary$has_image' $nofollow>" : '<span class="no-link">';
327
  $balance = ( _mc_is_url( $details_link ) ) ? '</a>' : '</span>';
328
  } else {
329
+ $wrap = "<a href='#$uid-$type-details-$id' class='et_smooth_scroll_disabled url summary$has_image'>";
330
  $balance = '</a>';
331
  }
332
  } else {
334
  $balance = '';
335
  }
336
 
337
+ $group_class = ( 1 === (int) $event->event_span ) ? ' multidate group' . $event->event_group_id : '';
338
  $hlevel = apply_filters( 'mc_heading_level_table', 'h3', $type, $time, $template );
339
  $inner_heading = apply_filters( 'mc_heading_inner_title', $wrap . $image . trim( $event_title ) . $balance, $event_title, $event );
340
+ $header .= ( 'single' !== $type && 'list' !== $type ) ? " <$hlevel class='event-title summary$group_class' id='mc_$event->occur_id-title-$id'>$inner_heading</$hlevel>\n" : '';
341
  $event_title = ( 'single' === $type ) ? apply_filters( 'mc_single_event_title', $event_title, $event ) : $event_title;
342
+ $title = ( 'single' === $type && ! is_singular( 'mc-events' ) ) ? " <h2 class='event-title summary'>$image $event_title</h2>\n" : ' <span class="summary screen-reader-text">' . $event_title . '</span>';
343
  $title = apply_filters( 'mc_event_title', $title, $event, $event_title, $image );
344
+ $header .= ( false === stripos( $title, 'summary' ) ) ? ' <span class="summary screen-reader-text">' . strip_tags( $title ) . '</span>' : $title;
345
 
346
+ $close_button = mc_close_button( "$uid-$type-details-$id" );
 
347
 
348
  if ( mc_show_details( $time, $type ) ) {
349
+ // Since 3.2.0, close button is added to event container in mini calendar.
350
+ $close = ( 'calendar' === $type ) ? $close_button : '';
351
 
352
  if ( false === $details ) {
353
  if ( ( 'true' === $display_address || 'true' === $display_map ) ) {
356
  $time_html = mc_time_html( $event, $type );
357
  if ( 'list' === $type ) {
358
  $hlevel = apply_filters( 'mc_heading_level_list', 'h3', $type, $time, $template );
359
+ $list_title = " <$hlevel class='event-title summary' id='mc_$event->occur_id-title-$id'>$image" . $event_title . "</$hlevel>\n";
360
  }
361
  if ( 'true' === $display_author ) {
362
+ if ( 0 !== (int) $event->event_author && is_numeric( $event->event_author ) ) {
363
  $e = get_userdata( $event->event_author );
364
+ $author = ' <p class="event-author">' . __( 'Posted by', 'my-calendar' ) . ' <span class="author-name">' . $e->display_name . "</span></p>\n";
365
  }
366
  }
367
 
371
  // Translators: Event title.
372
  $aria = " aria-label='" . esc_attr( sprintf( __( 'Details about %s', 'my-calendar' ), strip_tags( $event_title ) ) ) . "'";
373
  if ( _mc_is_url( $details_link ) ) {
374
+ $more = " <p class='mc_details'><a$aria itemprop='url' href='" . esc_url( $details_link ) . "'>$details_label</a></p>\n";
375
  } else {
376
  $more = '';
377
  }
379
  $more = apply_filters( 'mc_details_grid_link', $more, $event );
380
 
381
  if ( 'true' === $display_gcal ) {
382
+ $gcal = " <p class='gcal'>" . mc_draw_template( $data, '{gcal_link}' ) . '</p>';
383
  }
384
 
385
  if ( 'true' === $display_vcal ) {
386
+ $vcal = " <p class='ical'>" . mc_draw_template( $data, '{ical_html}' ) . '</p>';
387
  }
388
 
389
  if ( 'true' === $display_image ) {
393
  if ( 'calendar' === $type && 'true' === $display_title ) {
394
  // In all cases, this is semantically a duplicate of the title, but can be beneficial for sighted users.
395
  $headingtype = ( 'h3' === $hlevel ) ? 'h4' : 'h' . ( ( (int) str_replace( 'h', '', $hlevel ) ) - 1 );
396
+ $inner_title = ' <h4 class="mc-title" aria-hidden="true">' . $event_title . '</h4>';
397
  }
398
 
399
  if ( 'true' === $display_desc || 'single' === $type ) {
400
+ if ( '' !== trim( $event->event_desc ) ) {
401
+ $description = wpautop( stripcslashes( mc_kses_post( $event->event_desc ) ), 1 );
402
+ $description = " <div class='longdesc description' itemprop='description'>$description</div>";
403
+ }
404
  }
405
 
406
  if ( 'true' === $display_reg ) {
408
  $url = esc_url( $event->event_tickets );
409
  $external = ( $url && mc_external_link( $url ) ) ? 'external' : '';
410
  $tickets = ( $url ) ? "<a class='$external' href='" . $url . "'>" . __( 'Buy Tickets', 'my-calendar' ) . '</a>' : '';
411
+ if ( '' !== trim( $info . $tickets ) ) {
412
+ $tickets = $info . $tickets;
413
+ } else {
414
+ $tickets = '';
415
+ }
416
  }
417
 
418
  if ( 'true' === $display_short && 'single' !== $type ) {
419
+ if ( '' !== trim( $event->event_short ) ) {
420
+ $short = wpautop( stripcslashes( mc_kses_post( $event->event_short ) ), 1 );
421
+ $short = " <div class='shortdesc description'>$short</div>";
422
+ }
423
  }
424
 
425
  $status = apply_filters( 'mc_registration_state', '', $event );
426
  $return_url = apply_filters( 'mc_return_uri', mc_get_uri( $event ) );
427
+ $return = ( 'single' === $type ) ? " <p class='view-full'><a href='$return_url'>" . __( 'View full calendar', 'my-calendar' ) . '</a></p>' : '';
428
 
429
  if ( ! mc_show_details( $time, $type ) ) {
430
  $description = '';
444
  $link_template = ( '' !== mc_get_template( 'link' ) ) ? mc_get_template( 'link' ) : __( 'More information', 'my-calendar' );
445
  $link_text = mc_draw_template( $data, $link_template );
446
  $link = "
447
+ <p>
448
+ <a href='" . esc_url( $event_link ) . "' class='$external_class' aria-describedby='mc_$event->occur_id-title-$id'>" . $link_text . '</a>
449
+ </p>';
450
  }
451
+ $location = ( '' === trim( $map . $address ) ) ? '' : ' <div class="location">' . $map . $address . '</div>';
452
+ $sharing = ( '' === trim( $vcal . $gcal . $more ) ) ? '' : ' <div class="sharing">' . $vcal . $gcal . $more . '</div>';
453
+
454
+ $close = ( '' !== $close ) ? PHP_EOL . ' ' . $close : '';
455
+ $inner_title = ( $inner_title ) ? PHP_EOL . ' ' . $inner_title : '';
456
+ $time_html = ( $time_html ) ? PHP_EOL . ' ' . $time_html : '';
457
+ $list_title = ( $list_title ) ? PHP_EOL . ' ' . $list_title : '';
458
+ $img = ( $img ) ? PHP_EOL . ' ' . $img : '';
459
+ $location = ( $location ) ? PHP_EOL . ' ' . $location : '';
460
+ $description = ( $description ) ? PHP_EOL . ' ' . $description : '';
461
+ $short = ( $short ) ? PHP_EOL . ' ' . $short : '';
462
+ $link = ( $link ) ? PHP_EOL . ' ' . $link : '';
463
+ $status = ( $status ) ? PHP_EOL . ' ' . $status : '';
464
+ $tickets = ( $tickets ) ? PHP_EOL . ' ' . $tickets : '';
465
+ $author = ( $author ) ? PHP_EOL . ' ' . $author : '';
466
+ $sharing = ( $sharing ) ? PHP_EOL . ' ' . $sharing : '';
467
+ $return = ( $return ) ? PHP_EOL . ' ' . $return : '';
468
 
469
  $details = "\n"
470
  . $close
472
  . $time_html
473
  . $list_title
474
  . $img
475
+ . $location
 
 
476
  . $description
477
  . $short
478
  . $link
479
  . $status
480
  . $tickets
481
  . $author
482
+ . $sharing
 
 
483
  . $return;
484
  } else {
485
  // If a custom template is in use.
486
+ $toggle = ( 'calendar' === $type ) ? $close_button : '';
487
  $details = $toggle . $details . "\n";
488
  }
489
 
490
  $img_class = ( '' !== $img ) ? ' has-image' : ' no-image';
491
+ $container = "\n <div id='$uid-$type-details-$id' class='details$img_class' role='alert' aria-labelledby='mc_$event->occur_id-title" . '-' . $id . "' itemscope itemtype='http://schema.org/Event'>\n";
492
+ $container .= " <meta itemprop='name' content='" . esc_attr( strip_tags( $event_title ) ) . "' />";
493
  $container = apply_filters( 'mc_before_event', $container, $event, $type, $time );
494
  $details = $header . $container . apply_filters( 'mc_inner_content', $details, $event, $type, $time );
495
  $details .= apply_filters( 'mc_after_event', '', $event, $type, $time );
496
+ $details .= "\n" . ' </div><!--end .details-->' . "\n" . ' </div>' . "\n";
497
  $details = apply_filters( 'mc_event_content', $details, $event, $type, $time );
498
  } else {
499
  $details = apply_filters( 'mc_before_event_no_details', $container, $event, $type, $time ) . $header . apply_filters( 'mc_after_event_no_details', '', $event, $type, $time ) . '</div>';
502
  return $details;
503
  }
504
 
505
+ /**
506
+ * Generate close button.
507
+ *
508
+ * @param string $controls ID for object this controls.
509
+ *
510
+ * @return string
511
+ */
512
+ function mc_close_button( $controls ) {
513
+ $close_image = apply_filters( 'mc_close_button', "<span class='dashicons dashicons-dismiss' aria-hidden='true'></span><span class='screen-reader-text'>Close</span>" );
514
+ $close_button = " <button type='button' aria-controls='$controls' class='mc-toggle close' data-action='shiftforward'>$close_image</button>";
515
+
516
+ return $close_button;
517
+ }
518
+
519
  /**
520
  * Generate the details when using a custom template
521
  *
583
  }
584
  $default_size = apply_filters( 'mc_default_image_size', $default_size );
585
 
586
+ if ( is_numeric( $event->event_post ) && 0 !== (int) $event->event_post && ( isset( $data[ $default_size ] ) && '' !== $data[ $default_size ] ) ) {
587
  $atts = apply_filters( 'mc_post_thumbnail_atts', array( 'class' => 'mc-image photo' ) );
588
  $image_url = get_the_post_thumbnail_url( $event->event_post, $default_size );
589
  $image = get_the_post_thumbnail( $event->event_post, $default_size, $atts );
627
  */
628
  function mc_event_classes( $event, $uid, $type ) {
629
  $uid = 'mc_' . $type . '_' . $event->occur_id;
630
+ $ts = $event->ts_occur_begin;
631
+ $end = $event->ts_occur_end;
632
+ $now = time();
633
  if ( $ts < $now && $end > $now ) {
634
  $date_relation = 'on-now';
635
  } elseif ( $now < $ts ) {
637
  } elseif ( $now > $ts ) {
638
  $date_relation = 'past-event';
639
  }
640
+ $primary = 'mc_primary_' . sanitize_title( mc_get_category_detail( $event->event_category, 'category_name' ) );
641
 
642
  $classes = array(
643
  'mc-' . $uid,
644
  $type . '-event',
645
  mc_category_class( $event, 'mc_' ),
646
  $date_relation,
647
+ $primary,
648
  );
649
 
650
  if ( $event->event_begin !== $event->event_end ) {
732
  $edit = '';
733
  if ( mc_can_edit_event( $event ) && get_option( 'mc_remote' ) !== 'true' ) {
734
  $mc_id = $event->occur_id;
735
+ $groupedit = ( 0 !== (int) $event->event_group_id ) ? " &bull; <a href='" . admin_url( "admin.php?page=my-calendar-groups&amp;mode=edit&amp;event_id=$event->event_id&amp;group_id=$event->event_group_id" ) . "' class='group'>" . __( 'Edit Group', 'my-calendar' ) . "</a>\n" : '';
736
  $recurs = str_split( $event->event_recur, 1 );
737
  $recur = $recurs[0];
738
  $referer = urlencode( mc_get_current_url() );
739
+ $edit = " <div class='mc_edit_links'><p>";
740
  if ( 'S' === $recur ) {
741
  $edit .= "<a href='" . admin_url( "admin.php?page=my-calendar&amp;mode=edit&amp;event_id=$event->event_id&amp;ref=$referer" ) . "' class='edit'>" . __( 'Edit', 'my-calendar' ) . "</a> &bull; <a href='" . admin_url( "admin.php?page=my-calendar-manage&amp;mode=delete&amp;event_id=$event->event_id&amp;ref=$referer" ) . "' class='delete'>" . __( 'Delete', 'my-calendar' ) . "</a>$groupedit";
742
  } else {
768
  }
769
  global $wpdb;
770
  $mcdb = $wpdb;
771
+ $c_month = isset( $date['month'] ) ? $date['month'] : current_time( 'n' );
772
+ $c_year = isset( $date['year'] ) ? $date['year'] : current_time( 'Y' );
773
+ $c_day = isset( $date['day'] ) ? $date['day'] : current_time( 'j' );
774
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
775
  $mcdb = mc_remote_db();
776
  }
812
  }
813
  $date_switcher .= '</select>' . "\n" . $day_switcher . ' <label class="maybe-hide" for="' . $cid . '-year">' . __( 'Year', 'my-calendar' ) . '</label> <select id="' . $cid . '-year" name="yr">' . "\n";
814
  // Query to identify oldest start date in the database.
815
+ $year1 = mc_date( 'Y', strtotime( $mcdb->get_var( 'SELECT event_begin FROM ' . my_calendar_table() . ' WHERE event_approved = 1 AND event_flagged <> 1 ORDER BY event_begin ASC LIMIT 0 , 1' ), false ) );
816
+ $diff1 = mc_date( 'Y' ) - $year1;
817
  $past = $diff1;
818
  $future = apply_filters( 'mc_jumpbox_future_years', 5, $cid );
819
  $fut = 1;
820
  $f = '';
821
  $p = '';
822
+ $time = current_time( 'Y' );
823
 
824
  while ( $past > 0 ) {
825
  $p .= '<option value="';
826
+ $p .= $time - $past;
827
+ $p .= '"' . selected( $time - $past, $c_year, false ) . '>';
828
+ $p .= $time - $past . "</option>\n";
829
  $past = $past - 1;
830
  }
831
 
832
  while ( $fut < $future ) {
833
  $f .= '<option value="';
834
+ $f .= $time + $fut;
835
+ $f .= '"' . selected( $time + $fut, $c_year, false ) . '>';
836
+ $f .= $time + $fut . "</option>\n";
837
  $fut = $fut + 1;
838
  }
839
 
840
  $date_switcher .= $p;
841
+ $date_switcher .= '<option value="' . $time . '"' . selected( $time, $c_year, false ) . '>' . $time . "</option>\n";
842
  $date_switcher .= $f;
843
  $date_switcher .= '</select> <input type="submit" class="button" value="' . __( 'Go', 'my-calendar' ) . '" /></div></form></div>';
844
  $date_switcher = apply_filters( 'mc_jumpbox', $date_switcher );
899
  */
900
  function mc_time_toggle( $format, $time, $month, $year, $current, $start_of_week, $from ) {
901
  // if dy parameter not set, use today's date instead of first day of month.
902
+ $weeks_day = mc_first_day_of_week( $current );
903
  if ( isset( $_GET['dy'] ) ) {
904
+ if ( '' === $_GET['dy'] ) {
905
+ $current_day = $weeks_day[0];
906
+ if ( -1 === (int) $weeks_day[1] ) {
907
+ $month = $month - 1;
908
+ }
909
+ } else {
910
+ $current_day = absint( $_GET['dy'] );
911
+ }
912
  $current_set = mktime( 0, 0, 0, $month, $current_day, $year );
913
+ if ( mc_date( 'N', $current_set, false ) === $start_of_week ) {
914
  $weeks_day = mc_first_day_of_week( $current_set );
 
 
915
  }
916
  } else {
917
+ $weeks_day = mc_first_day_of_week();
918
  }
919
  $day = $weeks_day[0];
920
  if ( isset( $_GET['time'] ) && 'day' === $_GET['time'] ) {
922
  } else {
923
  // if the current date is displayed and the week beginning day is greater than 20 in the month.
924
  if ( ! isset( $_GET['dy'] ) && $day > 20 ) {
925
+ $day = mc_date( 'j', strtotime( "$from + 1 week" ), false );
926
  }
927
  }
928
  $adjust = ( isset( $weeks_day[1] ) ) ? $weeks_day[1] : 0;
931
  if ( 'mini' !== $format ) {
932
  $toggle = "<div class='mc-time'>";
933
  $current_url = mc_get_current_url();
934
+ if ( -1 === (int) $adjust ) {
935
+ $wmonth = ( 1 !== (int) $month ) ? $month - 1 : 12;
936
  } else {
937
  $wmonth = $month;
938
  }
1004
  $timestamp = strtotime( '+1 month', $timestamp );
1005
  }
1006
  $start_of_week = get_option( 'start_of_week' );
1007
+ $first = mc_date( 'N', $timestamp, false ); // ISO-8601.
1008
+ $sub = mc_date( 'w', $timestamp, false ); // numeric (how WordPress option is stored).
1009
+ $n = ( 1 === (int) $start_of_week ) ? $first - 1 : $first;
1010
 
1011
  if ( $sub === $start_of_week ) {
1012
+ $from = mc_date( 'Y-m-d', $timestamp, false );
1013
  } else {
1014
  $start = strtotime( "-$n days", $timestamp );
1015
+ $from = mc_date( 'Y-m-d', $start, false );
1016
  }
1017
+ $endtime = mktime( 0, 0, 0, mc_date( 'm', $timestamp, false ), mc_date( 't', $timestamp, false ), mc_date( 'Y', $timestamp, false ) );
1018
 
1019
  // This allows multiple months displayed. Will figure out splitting tables...
1020
  // To handle: $endtime = strtotime( "+$months months",$endtime ); JCD TODO.
1021
+ $last = (int) mc_date( 'N', $endtime, false );
1022
  $n = ( '1' === get_option( 'start_of_week' ) ) ? 7 - $last : 6 - $last;
1023
+ if ( -1 === $n && '7' === mc_date( 'N', $endtime, false ) ) {
1024
  $n = 6;
1025
  }
1026
+ $to = mc_date( 'Y-m-d', strtotime( "+$n days", $endtime ), false );
1027
 
1028
  $return = array(
1029
  'from' => $from,
1032
  break;
1033
  case 'week':
1034
  // First day of the week is calculated prior to this function. Argument received is the first day of the week.
1035
+ $from = mc_date( 'Y-m-d', $timestamp, false );
1036
+ $to = mc_date( 'Y-m-d', strtotime( '+6 days', $timestamp ), false );
1037
 
1038
  $return = array(
1039
  'from' => $from,
1063
  } else {
1064
  foreach ( array_keys( $events ) as $key ) {
1065
  $event =& $events[ $key ];
1066
+ if ( '00:00:00' === $event->event_endtime && mc_date( 'Y-m-d', strtotime( $event->occur_end ), false ) === $date && mc_date( 'Y-m-d', strtotime( $event->occur_begin ), false ) !== $date ) {
1067
  continue;
1068
  }
1069
  $author = ' author' . $event->event_author;
1096
  function mc_list_title( $events ) {
1097
  usort( $events, 'mc_time_cmp' );
1098
  $now = $events[0];
1099
+ $event = mc_create_tags( $now );
1100
  $count = count( $events ) - 1;
1101
+ $event_title = apply_filters( 'mc_list_title_title', strip_tags( stripcslashes( $event['title'] ), mc_strip_tags() ), $now );
1102
  if ( 0 === $count ) {
1103
  $cstate = $event_title;
1104
+ } elseif ( 1 === $count ) {
1105
  // Translators: %s Title of event.
1106
  $cstate = sprintf( __( '%s<span class="mc-list-extended"> and 1 other event</span>', 'my-calendar' ), $event_title );
1107
  } else {
1124
  usort( $events, 'mc_time_cmp' );
1125
  $titles = array();
1126
 
1127
+ foreach ( $events as $now ) {
1128
+ $event = mc_create_tags( $now );
1129
+ $title = apply_filters( 'mc_list_event_title_hint', strip_tags( stripcslashes( $event['title'] ), mc_strip_tags() ), $now, $events );
1130
  $titles[] = $title;
1131
  }
1132
 
1427
  $mc_id = intval( $_GET['mc_id'] );
1428
  $event_id = get_post_meta( $post->ID, '_mc_event_id', true );
1429
  $event = mc_get_event( $mc_id, 'object' );
1430
+ $date = mc_date( 'Y-m-d', strtotime( $event->occur_begin ), false );
1431
+ $time = mc_date( 'H:i:00', strtotime( $event->occur_begin ), false );
1432
  } else {
1433
  $event_id = get_post_meta( $post->ID, '_mc_event_id', true );
1434
  if ( is_numeric( $event_id ) ) {
1435
  $event = mc_get_nearest_event( $event_id );
1436
+ $date = mc_date( 'Y-m-d', strtotime( $event->occur_begin ), false );
1437
+ $time = mc_date( 'H:i:s', strtotime( $event->occur_begin ), false );
1438
  } else {
1439
 
1440
  return $content;
1490
  if ( is_array( $results ) && ! empty( $results ) ) {
1491
  foreach ( $results as $result ) {
1492
  $event_id = $result->event_id;
1493
+ if ( (int) $event_id === (int) $this_id ) {
1494
  continue;
1495
  }
1496
 
1502
  }
1503
  $html = mc_draw_template( $array, $template );
1504
  $classes = mc_event_classes( $event, '', 'related' );
1505
+ $classes .= ( (int) $event_id === (int) $this_id ) ? ' current-event' : '';
1506
  $output .= "<li class='$classes'>$html</li>";
1507
  }
1508
  }
1521
  * @return boolean
1522
  */
1523
  function mc_event_published( $event ) {
1524
+ if ( 1 === (int) $event->event_approved ) {
1525
  return true;
1526
  }
1527
 
1577
  $sday = isset( $args['day'] ) ? $args['day'] : false;
1578
  $source = isset( $args['source'] ) ? $args['source'] : 'shortcode';
1579
  $search = isset( $args['search'] ) ? $args['search'] : '';
1580
+ $site = ( isset( $args['site'] ) && '' !== trim( $args['site'] ) ) ? $args['site'] : false;
1581
  $months = isset( $args['months'] ) ? $args['months'] : false;
1582
 
1583
  if ( ! in_array( $format, array( 'list', 'calendar', 'mini' ), true ) ) {
1701
  $body .= mc_get_event( $mc_id, 'html' );
1702
  }
1703
  } else {
1704
+ $end_of_week = ( 1 === (int) $start_of_week ) ? 7 : 6;
1705
  $start_of_week = ( $show_weekends ) ? $start_of_week : 1;
1706
  $name_days = mc_name_days( $params['format'] );
1707
  $abbrevs = array( 'sun', 'mon', 'tues', 'wed', 'thur', 'fri', 'sat' );
1708
 
1709
+ if ( 1 === (int) $start_of_week ) {
1710
  $first = array_shift( $name_days );
1711
  $afirst = array_shift( $abbrevs );
1712
  $name_days[] = $first;
1756
 
1757
  if ( 'day' === $params['time'] ) {
1758
  $body .= "<div class='mcjs " . esc_attr( $params['format'] . ' ' . $params['time'] ) . "'>" . $top;
1759
+ $from = mc_date( 'Y-m-d', $current, false );
1760
+ $to = mc_date( 'Y-m-d', $current, false );
1761
 
1762
  $query = array(
1763
  'from' => $from,
1810
  } else {
1811
  $current_header = date_i18n( $month_format, $current );
1812
  }
1813
+ $current_month_header = ( mc_date( 'Y', $current, false ) === mc_date( 'Y', $through_date, false ) ) ? date_i18n( 'F', $current ) : date_i18n( 'F Y', $current );
1814
  $through_month_header = date_i18n( $month_format, $through_date );
1815
+ $values = array( 'date' => mc_date( 'Y-m-d', $current, false ) );
1816
 
1817
  // Add the calendar table and heading.
1818
  $body .= $top;
1829
  $list_heading = ( $months <= 1 ) ? $current_header . $caption_text . "\n" : $current_month_header . '&ndash;' . $through_month_header . $caption_text;
1830
  // Translators: time period displayed.
1831
  $list_heading = sprintf( __( 'Events in %s', 'my-calendar' ), $list_heading );
1832
+ if ( isset( $_GET['searched'] ) && 1 === (int) $_GET['searched'] ) {
1833
  $list_heading = __( 'Search Results', 'my-calendar' );
1834
  }
1835
  } else {
1849
  if ( 'list' === $params['format'] ) {
1850
  $body .= "<ul id='list-$id' class='mc-list'>";
1851
  } else {
1852
+ $body .= ( 'tr' === $tr ) ? '<thead>' : '<div class="mc-table-body">';
1853
+ $body .= "\n <$tr class='mc-row'>\n";
1854
  if ( apply_filters( 'mc_show_week_number', false, $args ) ) {
1855
+ $body .= " <$th class='mc-week-number'>" . __( 'Week', 'my-calendar' ) . "</$close_th>\n";
1856
  }
1857
  for ( $i = 0; $i <= 6; $i ++ ) {
1858
+ if ( 0 === (int) $start_of_week ) {
1859
  $class = ( $i < 6 && $i > 0 ) ? 'day-heading' : 'weekend-heading';
1860
  } else {
1861
  $class = ( $i < 5 ) ? 'day-heading' : 'weekend-heading';
1862
  }
1863
  $dayclass = sanitize_html_class( $abbrevs[ $i ] );
1864
  if ( ( 'weekend-heading' === $class && $show_weekends ) || 'weekend-heading' !== $class ) {
1865
+ $body .= " <$th class='$class $dayclass'>" . $name_days[ $i ] . "</$close_th>\n";
1866
  }
1867
  }
1868
+ $body .= " </$tr>\n";
1869
+ $body .= ( 'tr' === $tr ) ? "</thead>\n<tbody>\n" : '';
1870
  }
1871
  $odd = 'odd';
1872
 
1873
  $show_all = apply_filters( 'mc_all_list_dates', false, $args );
1874
  if ( $no_events && 'list' === $params['format'] && false === $show_all ) {
1875
  // If there are no events in list format, just display that info.
1876
+ $no_events = ( '' === $content ) ? __( 'There are no events scheduled during this period.', 'my-calendar' ) : $content;
1877
  $body .= "<li class='mc-events no-events'>$no_events</li>";
1878
  } else {
1879
  $start = strtotime( $from );
1880
  $end = strtotime( $to );
1881
  $week_number_shown = false;
1882
  do {
1883
+ $date_is = mc_date( 'Y-m-d', $start, false );
1884
+ $is_weekend = ( mc_date( 'N', $start, false ) < 6 ) ? false : true;
1885
  if ( $show_weekends || ( ! $show_weekends && ! $is_weekend ) ) {
1886
+ if ( mc_date( 'N', $start, false ) === (string) $start_of_week && 'list' !== $params['format'] ) {
1887
  $body .= "<$tr class='mc-row'>";
1888
  }
1889
  $events = ( isset( $event_array[ $date_is ] ) ) ? $event_array[ $date_is ] : array();
1890
  $week_header = date_i18n( $week_format, $start );
1891
+ $thisday_heading = ( 'week' === $params['time'] ) ? "<small>$week_header</small>" : mc_date( 'j', $start, false );
1892
 
1893
  // Generate event classes & attributes.
1894
  $events_class = mc_events_class( $events, $date_is );
1895
+ $monthclass = ( mc_date( 'n', $start, false ) === (string) (int) $date['month'] || 'month' !== $params['time'] ) ? '' : 'nextmonth';
1896
  $dateclass = mc_dateclass( $start );
1897
  $ariacurrent = ( false !== strpos( $dateclass, 'current-day' ) ) ? ' aria-current="date"' : '';
1898
 
1899
  $td = apply_filters( 'mc_grid_day_wrapper', 'td', $params['format'] );
1900
  if ( ! $week_number_shown ) {
1901
  $weeknumber = mc_show_week_number( $events, $args, $params['format'], $td, $start );
1902
+ if ( ! ( '' === $weeknumber ) ) {
1903
  $body .= $weeknumber;
1904
  $week_number_shown = true;
1905
  }
1923
  $link = mc_build_mini_url( $start, $params['category'], $events, $args, $date );
1924
  $element = "a href='$link'";
1925
  $close = 'a';
1926
+ $trigger = ' trigger';
1927
  } else {
1928
  $element = 'span';
1929
  $close = 'span';
1934
  $weekend_class = ( $is_weekend ) ? 'weekend' : '';
1935
  if ( 'list' === $params['format'] ) {
1936
  if ( 'true' === $list_info ) {
1937
+ $title = '<span class="mc-list-details-separator"> - </span>' . mc_wrap_title( "<span class='mc-list-details select-event'>" . mc_list_title( $events ) . '</span>' );
1938
  } elseif ( 'true' === $list_events ) {
1939
+ $title = '<span class="mc-list-details-separator"> - </span>' . mc_wrap_title( "<span class='mc-list-details all-events'>" . mc_list_titles( $events ) . '</span>' );
1940
  } else {
1941
  $title = '';
1942
  }
1943
  if ( '' !== $event_output ) {
1944
+ $body .= "<li id='$params[format]-$date_is'$ariacurrent class='mc-events $dateclass $events_class $odd'><strong class=\"event-date\">" . mc_wrap_title( date_i18n( $date_format, $start ) ) . "$title</strong>" . $event_output . '</li>';
1945
  $odd = ( 'odd' === $odd ) ? 'even' : 'odd';
1946
  }
1947
  } else {
1948
+ $body .= "<$td id='$params[format]-$date_is'$ariacurrent class='$dateclass $weekend_class $monthclass $events_class day-with-date'>" . "\n <$element class='mc-date$trigger'><span aria-hidden='true'>$thisday_heading</span><span class='screen-reader-text'>" . date_i18n( $date_format, strtotime( $date_is ) ) . "</span></$close>" . $event_output . "\n</$td>\n";
1949
  }
1950
  }
1951
  } else {
1952
  // If there are no events on this date within current params.
1953
  if ( 'list' !== $params['format'] ) {
1954
  $weekend_class = ( $is_weekend ) ? 'weekend' : '';
1955
+ $body .= "<$td$ariacurrent class='no-events $dateclass $weekend_class $monthclass $events_class day-with-date'><span class='mc-date no-events'><span aria-hidden='true'>$thisday_heading</span><span class='screen-reader-text'>" . date_i18n( $date_format, strtotime( $date_is ) ) . "</span></span>\n</$td>\n";
1956
  } else {
1957
  if ( true === $show_all ) {
1958
  $body .= "<li id='$params[format]-$date_is' $ariacurrent class='no-events $dateclass $events_class $odd'><strong class=\"event-date\">" . mc_wrap_title( date_i18n( $date_format, $start ) ) . '</strong></li>';
1961
  }
1962
  }
1963
 
1964
+ if ( mc_date( 'N', $start, false ) === (string) $end_of_week || ( mc_date( 'N', $start, false ) === '5' && ! $show_weekends ) ) {
1965
  if ( 'list' !== $params['format'] ) {
1966
+ $body .= "</$tr>\n<!-- End Event Row -->\n"; // End of 'is beginning of week'.
1967
  }
1968
  $week_number_shown = false;
1969
  }
2006
  $num = $show_months - 1;
2007
  $c_month = $date['month'];
2008
  $c_year = $date['year'];
2009
+ // The first day of the current month.
2010
+ $month_first = mktime( 0, 0, 0, $c_month, 1, $c_year );
2011
  // Grid calendar can't show multiple months.
2012
  if ( 'list' === $format && 'week' !== $time ) {
2013
+ if ( $num > 0 && 'day' !== $time && 'week' !== $time ) {
2014
  if ( 'month+1' === $time ) {
2015
+ $from = mc_date( 'Y-m-d', strtotime( '+1 month', $month_first ), false );
2016
+ $next = strtotime( "+$num months", strtotime( '+1 month', $month_first ) );
2017
  } else {
2018
+ $from = mc_date( 'Y-m-d', $month_first, false );
2019
+ $next = strtotime( "+$num months", $month_first );
2020
  }
2021
+ $last = mc_date( 't', $next, false );
2022
+ $to = mc_date( 'Y-m', $next, false ) . '-' . $last;
2023
  } else {
2024
+ $from = mc_date( 'Y-m-d', $month_first, false );
2025
+ $to = mc_date( 'Y-m-d', mktime( 0, 0, 0, $c_month, mc_date( 't', $month_first, false ), $c_year ), false );
2026
  }
2027
  $dates = array(
2028
  'from' => $from,
2150
  }
2151
 
2152
  // Set up format toggle.
2153
+ $toggle = ( in_array( 'toggle', $used, true ) ) ? mc_format_toggle( $format, 'yes', $time ) : '';
2154
 
2155
  // Set up time toggle.
2156
  if ( in_array( 'timeframe', $used, true ) ) {
2172
 
2173
  // Set up exports.
2174
  if ( in_array( 'exports', $used, true ) ) {
2175
+ $ical_m = ( isset( $_GET['month'] ) ) ? (int) $_GET['month'] : mc_date( 'n' );
2176
+ $ical_y = ( isset( $_GET['yr'] ) ) ? (int) $_GET['yr'] : mc_date( 'Y' );
2177
  $next_link = my_calendar_next_link( $date, $format, $time, $show_months );
2178
  $exports = mc_export_links( $ical_y, $ical_m, $next_link, $add, $subtract );
2179
  }
2183
  $jump = mc_date_switcher( $format, $main_class, $time, $date );
2184
  }
2185
 
2186
+ $mc_toporder = apply_filters( 'mc_header_navigation', $mc_toporder, $used, $params );
2187
  foreach ( $mc_toporder as $value ) {
2188
  if ( 'none' !== $value && in_array( $value, $used, true ) && in_array( $value, $available, true ) ) {
2189
  $value = trim( $value );
2191
  }
2192
  }
2193
 
2194
+ $mc_bottomorder = apply_filters( 'mc_footer_navigation', $mc_bottomorder, $used, $params );
2195
  foreach ( $mc_bottomorder as $value ) {
2196
  if ( 'none' !== $value && 'stop' !== $value && in_array( $value, $used, true ) && in_array( $value, $available, true ) ) {
2197
  $value = trim( $value );
2227
  function mc_show_week_number( $events, $args, $format, $td, $start ) {
2228
  $body = '';
2229
  if ( apply_filters( 'mc_show_week_number', false, $args ) ) {
2230
+ $weeknumber = mc_date( 'W', $start, false );
2231
+ if ( 'list' !== $format ) {
2232
  $body = "<$td class='week_number'>$weeknumber</$td>";
2233
  }
2234
  if ( 'list' === $format && ! empty( $events ) ) {
2255
  if ( 'true' === $open_day_uri || 'false' === $open_day_uri ) {
2256
  // Yes, this is weird. it's from some old settings...
2257
  $target = array(
2258
+ 'yr' => mc_date( 'Y', $start, false ),
2259
+ 'month' => mc_date( 'm', $start, false ),
2260
+ 'dy' => mc_date( 'j', $start, false ),
2261
  'time' => 'day',
2262
  );
2263
+ if ( ! ( '' === $category ) ) {
2264
  $target['mcat'] = $category;
2265
  }
2266
  $day_url = mc_build_url( $target, array( 'month', 'dy', 'yr', 'ltype', 'loc', 'mcat', 'cid', 'mc_id' ), apply_filters( 'mc_modify_day_uri', mc_get_uri( reset( $events ), $args ) ) );
2267
+ $link = ( '' !== $day_url ) ? $day_url : '#';
2268
  } else {
2269
  $mini_uri = get_option( 'mc_mini_uri' );
2270
  $atype = str_replace( 'anchor', '', $open_day_uri ); // List or grid.
2271
+ $ad = str_pad( mc_date( 'j', $start, false ), 2, '0', STR_PAD_LEFT ); // Need to match format in ID.
2272
  $am = str_pad( $date['month'], 2, '0', STR_PAD_LEFT );
2273
  $date_url = mc_build_url(
2274
  array(
2275
  'yr' => $date['year'],
2276
  'month' => $date['month'],
2277
+ 'dy' => mc_date( 'j', $start, false ),
2278
  ),
2279
  array( 'month', 'dy', 'yr', 'ltype', 'loc', 'mcat', 'cid', 'mc_id' ),
2280
  $mini_uri
2281
  );
2282
+ $link = esc_url( ( '' !== $mini_uri ) ? $date_url . '#' . $atype . '-' . $date['year'] . '-' . $am . '-' . $ad : '#' );
2283
  }
2284
 
2285
  return $link;
2360
  * @return array
2361
  */
2362
  function mc_get_current_date( $main_class, $cid, $params ) {
2363
+ $time = $params['time'];
2364
+ $smonth = $params['smonth'];
2365
+ $syear = $params['syear'];
2366
+ $sday = $params['sday'];
2367
+ $c_m = 0;
 
2368
  if ( isset( $_GET['dy'] ) && $main_class === $cid && ( 'day' === $time || 'week' === $time ) ) {
2369
+ if ( '' === $_GET['dy'] ) {
2370
+ $today = current_time( 'j' );
2371
+ $month = ( isset( $_GET['month'] ) ) ? $_GET['month'] : current_time( 'n' );
2372
+ $year = ( isset( $_GET['yr'] ) ) ? $_GET['yr'] : current_time( 'Y' );
2373
+ $time = strtotime( "$year-$month-$today" );
2374
+ $dm = mc_first_day_of_week( $time );
2375
+ $c_day = $dm[0];
2376
+ $c_m = $dm[1];
2377
+ } else {
2378
+ $c_day = (int) $_GET['dy'];
2379
+ }
2380
  } else {
2381
  if ( 'week' === $time ) {
2382
  $dm = mc_first_day_of_week();
2383
  $c_day = $dm[0];
2384
  $c_m = $dm[1];
2385
  } elseif ( 'day' === $time ) {
2386
+ $c_day = current_time( 'd' );
2387
  } else {
2388
  $c_day = 1;
2389
  }
2390
  }
2391
+ if ( isset( $_GET['month'] ) && $main_class === $cid ) {
2392
  $c_month = (int) $_GET['month'];
2393
  if ( ! isset( $_GET['dy'] ) ) {
2394
  $c_day = 1;
2395
  }
2396
  } else {
2397
+ $xnow = current_time( 'Y-m-d' );
2398
+ $c_month = ( 0 === (int) $c_m ) ? current_time( 'm' ) : mc_date( 'm', strtotime( $xnow . ' -1 month' ), false );
2399
  }
2400
 
2401
+ $is_start_of_week = ( get_option( 'start_of_week' ) === current_time( 'N' ) ) ? true : false;
2402
+ if ( isset( $_GET['yr'] ) && $main_class === $cid ) {
2403
  $c_year = (int) $_GET['yr'];
2404
  } else {
2405
  if ( 'week' === $time && ! isset( $_GET['dy'] ) ) {
2406
  if ( $is_start_of_week ) {
2407
+ $c_year = ( current_time( 'Y' ) );
2408
  } else {
2409
+ $current_year = current_time( 'Y' );
2410
+ $c_year = ( 0 === (int) $dm[1] ) ? $current_year : false;
2411
  if ( ! $c_year ) {
2412
+ $c_year = ( mc_date( 'Y', strtotime( '-1 month' ), false ) === $current_year ) ? $current_year : $current_year - 1;
2413
  }
2414
  }
2415
  } else {
2416
+ $c_year = ( current_time( 'Y' ) );
2417
  }
2418
  }
2419
  // Years get funny if we exceed 3000, so we use this check.
2420
  if ( ! ( $c_year <= 3000 && $c_year >= 0 ) ) {
2421
  // No valid year causes the calendar to default to today.
2422
+ $c_year = current_time( 'Y' );
2423
+ $c_month = current_time( 'm' );
2424
+ $c_day = current_time( 'd' );
2425
  }
2426
  if ( ! ( isset( $_GET['yr'] ) || isset( $_GET['month'] ) || isset( $_GET['dy'] ) ) ) {
2427
  // Month/year based on shortcode.
2428
+ $shortcode_month = ( false !== $smonth ) ? $smonth : $c_month;
2429
+ $shortcode_year = ( false !== $syear ) ? $syear : $c_year;
2430
+ $shortcode_day = ( false !== $sday ) ? $sday : $c_day;
2431
  // Override with filters.
2432
  $c_year = apply_filters( 'mc_filter_year', $shortcode_year, $params );
2433
  $c_month = apply_filters( 'mc_filter_month', $shortcode_month, $params );
2434
  $c_day = apply_filters( 'mc_filter_day', $shortcode_day, $params );
2435
  }
2436
+ $c_day = ( 0 === (int) $c_day ) ? 1 : $c_day; // c_day can't equal 0.
2437
  $current = mktime( 0, 0, 0, $c_month, $c_day, $c_year );
2438
  $c_month = str_pad( $c_month, 2, '0', STR_PAD_LEFT );
2439
 
2527
  } else {
2528
  $url = mc_build_url( array( 'mcat' => $selectable_categories ), array( 'mcat' ) );
2529
  }
2530
+ if ( 1 === (int) $cat->category_private ) {
2531
  $class .= ' private';
2532
  }
2533
  $cat_name = mc_kses_post( stripcslashes( $cat->category_name ) );
2565
  $google = get_feed_link( 'my-calendar-google' );
2566
  $outlook = get_feed_link( 'my-calendar-outlook' );
2567
 
2568
+ $rss = "<li class='rss'><a href='" . esc_url( $feed ) . "'>" . __( 'RSS', 'my-calendar' ) . '</a></li>';
2569
+ $sub_google = "<li class='ics google'><a href='" . esc_url( $google ) . "'>" . __( '<span class="maybe-hide">Subscribe in </span>Google', 'my-calendar' ) . '</a></li>';
2570
+ $sub_outlook = "<li class='ics outlook'><a href='" . esc_url( $outlook ) . "'>" . __( '<span class="maybe-hide">Subscribe in </span>Outlook', 'my-calendar' ) . '</a></li>';
2571
 
2572
+ $output = "<div class='mc-export mc-subscribe'>
 
2573
  <ul>$rss$sub_google$sub_outlook</ul>
2574
+ </div>";
2575
 
2576
  return $output;
2577
  }
2599
  $add['export'] = 'outlook';
2600
  $ics2 = mc_build_url( $add, $subtract, get_feed_link( 'my-calendar-ics' ) );
2601
 
2602
+ $google = "<li class='ics google'><a href='" . $ics . "'>" . __( '<span class="maybe-hide">Export for </span>Google', 'my-calendar' ) . '</a></li>';
2603
+ $outlook = "<li class='ics outlook'><a href='" . $ics2 . "'>" . __( '<span class="maybe-hide">Export for </span>Outlook', 'my-calendar' ) . '</a></li>';
2604
 
2605
+ $output = "<div class='mc-export mc-download'>
 
2606
  <ul>$google$outlook</ul>
2607
+ </div>";
2608
 
2609
  return $output;
2610
  }
2628
  $mc_next = get_option( 'mc_next_events', '' );
2629
  $next_events = ( '' === $mc_next ) ? '<span class="maybe-hide">' . __( 'Next', 'my-calendar' ) . '</span>' : stripslashes( $mc_next );
2630
  if ( $months <= 1 || 'list' !== $format ) {
2631
+ if ( 12 === (int) $cur_month ) {
2632
  $month = 1;
2633
  $yr = $next_year;
2634
  } else {
2647
  }
2648
  }
2649
  $day = '';
2650
+ if ( (int) $yr !== (int) $cur_year ) {
2651
  $format = 'F, Y';
2652
  } else {
2653
  $format = 'F';
2655
  $date = date_i18n( $format, mktime( 0, 0, 0, $month, 1, $yr ) );
2656
  if ( 'week' === $time ) {
2657
  $nextdate = strtotime( "$cur_year-$cur_month-$cur_day" . '+ 7 days' );
2658
+ $day = mc_date( 'd', $nextdate, false );
2659
+ $yr = mc_date( 'Y', $nextdate, false );
2660
+ $month = mc_date( 'm', $nextdate, false );
2661
+ if ( (int) $yr !== (int) $cur_year ) {
2662
  $format = 'F j, Y';
2663
  } else {
2664
  $format = 'F j';
2668
  }
2669
  if ( 'day' === $time ) {
2670
  $nextdate = strtotime( "$cur_year-$cur_month-$cur_day" . '+ 1 days' );
2671
+ $day = mc_date( 'd', $nextdate, false );
2672
+ $yr = mc_date( 'Y', $nextdate, false );
2673
+ $month = mc_date( 'm', $nextdate, false );
2674
+ if ( (int) $yr !== (int) $cur_year ) {
2675
  $format = 'F j, Y';
2676
  } else {
2677
  $format = 'F j';
2705
  $cur_day = $date['day'];
2706
 
2707
  $last_year = $cur_year - 1;
2708
+ $mc_previous = get_option( 'mc_previous_events', '' );
2709
+ $previous_events = ( '' === $mc_previous ) ? '<span class="maybe-hide">' . __( 'Previous', 'my-calendar' ) . '</span>' : stripslashes( $mc_previous );
2710
+ if ( $months <= 1 || 'list' !== $format ) {
2711
+ if ( 1 === (int) $cur_month ) {
2712
  $month = 12;
2713
  $yr = $last_year;
2714
  } else {
2726
  $yr = $cur_year;
2727
  }
2728
  }
2729
+ if ( (int) $yr !== (int) $cur_year ) {
2730
  $format = 'F, Y';
2731
  } else {
2732
  $format = 'F';
2735
  $day = '';
2736
  if ( 'week' === $time ) {
2737
  $prevdate = strtotime( "$cur_year-$cur_month-$cur_day" . '- 7 days' );
2738
+ $day = mc_date( 'd', $prevdate, false );
2739
+ $yr = mc_date( 'Y', $prevdate, false );
2740
+ $month = mc_date( 'm', $prevdate, false );
2741
+ if ( (int) $yr !== (int) $cur_year ) {
2742
  $format = 'F j, Y';
2743
  } else {
2744
  $format = 'F j';
2747
  }
2748
  if ( 'day' === $time ) {
2749
  $prevdate = strtotime( "$cur_year-$cur_month-$cur_day" . '- 1 days' );
2750
+ $day = mc_date( 'd', $prevdate, false );
2751
+ $yr = mc_date( 'Y', $prevdate, false );
2752
+ $month = mc_date( 'm', $prevdate, false );
2753
+ if ( (int) $yr !== (int) $cur_year ) {
2754
  $format = 'F j, Y';
2755
  } else {
2756
  $format = 'F j';
my-calendar-settings.php CHANGED
@@ -214,6 +214,8 @@ function my_calendar_settings() {
214
  $mc_uri = isset( $_POST['mc_uri'] ) ? $_POST['mc_uri'] : get_option( 'mc_uri' );
215
  }
216
  }
 
 
217
  update_option( 'mc_uri', $mc_uri );
218
  update_option( 'mc_uri_id', absint( $_POST['mc_uri_id'] ) );
219
  // End handling of primary URL.
@@ -226,7 +228,14 @@ function my_calendar_settings() {
226
  $mc_current_table = ( isset( $_POST['mc_current_table'] ) ) ? (int) $_POST['mc_current_table'] : 0;
227
  update_option( 'mc_current_table', $mc_current_table );
228
  }
229
- mc_show_notice( __( 'My Calendar Management Settings saved', 'my-calendar' ) . ". $clear" );
 
 
 
 
 
 
 
230
  }
231
  if ( isset( $_POST['mc_permissions'] ) ) {
232
  $perms = $_POST['mc_caps'];
@@ -259,9 +268,7 @@ function my_calendar_settings() {
259
  }
260
  // Output.
261
  if ( isset( $_POST['mc_show_months'] ) ) {
262
- $permalinks = get_option( 'mc_use_permalinks' );
263
  $mc_open_day_uri = ( ! empty( $_POST['mc_open_day_uri'] ) ) ? $_POST['mc_open_day_uri'] : '';
264
- update_option( 'mc_use_permalinks', ( ! empty( $_POST['mc_use_permalinks'] ) ) ? 'true' : 'false' );
265
  update_option( 'mc_open_uri', ( ! empty( $_POST['mc_open_uri'] ) && 'on' === $_POST['mc_open_uri'] && '' !== get_option( 'mc_uri', '' ) ) ? 'true' : 'false' );
266
  update_option( 'mc_no_link', ( ! empty( $_POST['mc_no_link'] ) && 'on' === $_POST['mc_no_link'] ) ? 'true' : 'false' );
267
  update_option( 'mc_mini_uri', $_POST['mc_mini_uri'] );
@@ -309,14 +316,8 @@ function my_calendar_settings() {
309
  update_option( 'mc_show_weekends', ( ! empty( $_POST['mc_show_weekends'] ) && 'on' === $_POST['mc_show_weekends'] ) ? 'true' : 'false' );
310
  update_option( 'mc_title', ( ! empty( $_POST['mc_title'] ) && 'on' === $_POST['mc_title'] ) ? 'true' : 'false' );
311
  update_option( 'mc_convert', ( ! empty( $_POST['mc_convert'] ) ) ? $_POST['mc_convert'] : 'false' );
312
- if ( ( isset( $_POST['mc_use_permalinks'] ) && 'true' === get_option( 'mc_use_permalinks' ) ) && 'true' !== $permalinks ) {
313
- $url = admin_url( 'options-permalink.php#mc_cpt_base' );
314
- // Translators: URL to permalink settings page.
315
- $note = ' ' . sprintf( __( 'You activated My Calendar permalinks. Go to <a href="%s">permalink settings</a> to set the base URL for My Calendar Events.', 'my-calendar' ), $url );
316
- } else {
317
- $note = '';
318
- }
319
- mc_show_notice( __( 'Output Settings saved', 'my-calendar' ) . $note );
320
  }
321
  // INPUT.
322
  if ( isset( $_POST['mc_input'] ) ) {
@@ -557,6 +558,16 @@ function my_calendar_settings() {
557
  );
558
  ?>
559
  </li>
 
 
 
 
 
 
 
 
 
 
560
  <li><?php mc_settings_field( 'mc_remote', __( 'Get data (events, categories and locations) from a remote database.', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
561
  <?php
562
  if ( 'true' === get_option( 'mc_remote' ) && ! function_exists( 'mc_remote_db' ) ) {
@@ -575,6 +586,26 @@ function mc_remote_db() {
575
  }
576
  ?>
577
  <li><?php mc_settings_field( 'mc_api_enabled', __( 'Enable external API.', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
  <li><?php mc_settings_field( 'remigrate', __( 'Re-generate event occurrences table.', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
579
  <li><?php mc_settings_field( 'mc_drop_tables', __( 'Drop MySQL tables on uninstall', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
580
  <?php
@@ -678,16 +709,6 @@ function mc_remote_db() {
678
  <fieldset>
679
  <legend><?php _e( 'Calendar Link Targets', 'my-calendar' ); ?></legend>
680
  <ul>
681
- <?php
682
- if ( isset( $_POST['mc_use_permalinks'] ) && '' !== $note ) {
683
- $url = admin_url( 'options-permalink.php#mc_cpt_base' );
684
- // Translators: URL for WordPress Settings > Permalinks.
685
- $note = ' <span class="mc-notice">' . sprintf( __( 'Go to <a href="%s">permalink settings</a> to set the base URL for events.', 'my-calendar' ) . '</span>', $url );
686
- } else {
687
- $note = '';
688
- }
689
- ?>
690
- <li><?php mc_settings_field( 'mc_use_permalinks', __( 'Use Pretty Permalinks for Events', 'my-calendar' ), '', $note, array(), 'checkbox-single' ); ?></li>
691
  <li><?php mc_settings_field( 'mc_open_uri', __( 'Open calendar links to event details', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
692
  <li><?php mc_settings_field( 'mc_no_link', __( 'Disable calendar links', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
693
  <li><?php mc_settings_field( 'mc_mini_uri', __( 'Target <abbr title="Uniform resource locator">URL</abbr> for mini calendar date links:', 'my-calendar' ), '', '', array( 'size' => '60' ), 'url' ); ?></li>
@@ -864,26 +885,30 @@ function mc_remote_db() {
864
  );
865
 
866
  // If input options isn't an array, assume that plugin wasn't upgraded, and reset to default.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
867
  if ( ! is_array( $input_options ) ) {
868
  update_option(
869
  'mc_input_options',
870
- array(
871
- 'event_location_dropdown' => 'on',
872
- 'event_short' => 'on',
873
- 'event_desc' => 'on',
874
- 'event_category' => 'on',
875
- 'event_image' => 'on',
876
- 'event_link' => 'on',
877
- 'event_recurs' => 'on',
878
- 'event_open' => 'on',
879
- 'event_location' => 'off',
880
- 'event_specials' => 'on',
881
- 'event_access' => 'on',
882
- 'event_host' => 'on',
883
- )
884
  );
885
  $input_options = get_option( 'mc_input_options' );
886
  }
 
 
887
  foreach ( $input_options as $key => $value ) {
888
  $checked = ( 'on' === $value ) ? "checked='checked'" : '';
889
  if ( isset( $input_labels[ $key ] ) ) {
214
  $mc_uri = isset( $_POST['mc_uri'] ) ? $_POST['mc_uri'] : get_option( 'mc_uri' );
215
  }
216
  }
217
+ $permalinks = get_option( 'mc_use_permalinks' );
218
+ update_option( 'mc_use_permalinks', ( ! empty( $_POST['mc_use_permalinks'] ) ) ? 'true' : 'false' );
219
  update_option( 'mc_uri', $mc_uri );
220
  update_option( 'mc_uri_id', absint( $_POST['mc_uri_id'] ) );
221
  // End handling of primary URL.
228
  $mc_current_table = ( isset( $_POST['mc_current_table'] ) ) ? (int) $_POST['mc_current_table'] : 0;
229
  update_option( 'mc_current_table', $mc_current_table );
230
  }
231
+ if ( ( isset( $_POST['mc_use_permalinks'] ) && 'true' === get_option( 'mc_use_permalinks' ) ) && 'true' !== $permalinks ) {
232
+ $url = admin_url( 'options-permalink.php#mc_cpt_base' );
233
+ // Translators: URL to permalink settings page.
234
+ $note = ' ' . sprintf( __( 'You activated My Calendar permalinks. Go to <a href="%s">permalink settings</a> to set the base URL for My Calendar Events.', 'my-calendar' ), $url );
235
+ } else {
236
+ $note = '';
237
+ }
238
+ mc_show_notice( __( 'My Calendar Management Settings saved', 'my-calendar' ) . ". $clear" . $note );
239
  }
240
  if ( isset( $_POST['mc_permissions'] ) ) {
241
  $perms = $_POST['mc_caps'];
268
  }
269
  // Output.
270
  if ( isset( $_POST['mc_show_months'] ) ) {
 
271
  $mc_open_day_uri = ( ! empty( $_POST['mc_open_day_uri'] ) ) ? $_POST['mc_open_day_uri'] : '';
 
272
  update_option( 'mc_open_uri', ( ! empty( $_POST['mc_open_uri'] ) && 'on' === $_POST['mc_open_uri'] && '' !== get_option( 'mc_uri', '' ) ) ? 'true' : 'false' );
273
  update_option( 'mc_no_link', ( ! empty( $_POST['mc_no_link'] ) && 'on' === $_POST['mc_no_link'] ) ? 'true' : 'false' );
274
  update_option( 'mc_mini_uri', $_POST['mc_mini_uri'] );
316
  update_option( 'mc_show_weekends', ( ! empty( $_POST['mc_show_weekends'] ) && 'on' === $_POST['mc_show_weekends'] ) ? 'true' : 'false' );
317
  update_option( 'mc_title', ( ! empty( $_POST['mc_title'] ) && 'on' === $_POST['mc_title'] ) ? 'true' : 'false' );
318
  update_option( 'mc_convert', ( ! empty( $_POST['mc_convert'] ) ) ? $_POST['mc_convert'] : 'false' );
319
+
320
+ mc_show_notice( __( 'Output Settings saved', 'my-calendar' ) );
 
 
 
 
 
 
321
  }
322
  // INPUT.
323
  if ( isset( $_POST['mc_input'] ) ) {
558
  );
559
  ?>
560
  </li>
561
+ <?php
562
+ if ( isset( $_POST['mc_use_permalinks'] ) && '' !== $note ) {
563
+ $url = admin_url( 'options-permalink.php#mc_cpt_base' );
564
+ // Translators: URL for WordPress Settings > Permalinks.
565
+ $note = ' <span class="mc-notice">' . sprintf( __( 'Go to <a href="%s">permalink settings</a> to set the base URL for events.', 'my-calendar' ) . '</span>', $url );
566
+ } else {
567
+ $note = '';
568
+ }
569
+ ?>
570
+ <li><?php mc_settings_field( 'mc_use_permalinks', __( 'Use Pretty Permalinks for Events', 'my-calendar' ), '', $note, array(), 'checkbox-single' ); ?></li>
571
  <li><?php mc_settings_field( 'mc_remote', __( 'Get data (events, categories and locations) from a remote database.', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
572
  <?php
573
  if ( 'true' === get_option( 'mc_remote' ) && ! function_exists( 'mc_remote_db' ) ) {
586
  }
587
  ?>
588
  <li><?php mc_settings_field( 'mc_api_enabled', __( 'Enable external API.', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
589
+ <?php
590
+ if ( 'true' === get_option( 'mc_api_enabled' ) ) {
591
+ ?>
592
+ <li>
593
+ <?php
594
+ $url = add_query_arg(
595
+ array(
596
+ 'to' => current_time( 'Y-m-d' ),
597
+ 'from' => mc_date( 'Y-m-d', time() - MONTH_IN_SECONDS ),
598
+ 'mc-api' => 'json',
599
+ ),
600
+ home_url()
601
+ );
602
+ // Translators: Linked URL to API endpoint.
603
+ printf( __( 'API URL: %s', 'my-calendar' ), '<a href="' . $url . '">' . $url . '</a>' );
604
+ ?>
605
+ </li>
606
+ <?php
607
+ }
608
+ ?>
609
  <li><?php mc_settings_field( 'remigrate', __( 'Re-generate event occurrences table.', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
610
  <li><?php mc_settings_field( 'mc_drop_tables', __( 'Drop MySQL tables on uninstall', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
611
  <?php
709
  <fieldset>
710
  <legend><?php _e( 'Calendar Link Targets', 'my-calendar' ); ?></legend>
711
  <ul>
 
 
 
 
 
 
 
 
 
 
712
  <li><?php mc_settings_field( 'mc_open_uri', __( 'Open calendar links to event details', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
713
  <li><?php mc_settings_field( 'mc_no_link', __( 'Disable calendar links', 'my-calendar' ), '', '', array(), 'checkbox-single' ); ?></li>
714
  <li><?php mc_settings_field( 'mc_mini_uri', __( 'Target <abbr title="Uniform resource locator">URL</abbr> for mini calendar date links:', 'my-calendar' ), '', '', array( 'size' => '60' ), 'url' ); ?></li>
885
  );
886
 
887
  // If input options isn't an array, assume that plugin wasn't upgraded, and reset to default.
888
+ // Array of all options in off position.
889
+ $defaults = array(
890
+ 'event_location_dropdown' => 'on',
891
+ 'event_short' => 'on',
892
+ 'event_desc' => 'on',
893
+ 'event_category' => 'on',
894
+ 'event_image' => 'on',
895
+ 'event_link' => 'on',
896
+ 'event_recurs' => 'on',
897
+ 'event_open' => 'on',
898
+ 'event_location' => 'off',
899
+ 'event_specials' => 'on',
900
+ 'event_access' => 'on',
901
+ 'event_host' => 'on',
902
+ );
903
  if ( ! is_array( $input_options ) ) {
904
  update_option(
905
  'mc_input_options',
906
+ $defaults
 
 
 
 
 
 
 
 
 
 
 
 
 
907
  );
908
  $input_options = get_option( 'mc_input_options' );
909
  }
910
+ // Merge saved input options with default off, so all are displayed.
911
+ $input_options = array_merge( $defaults, $input_options );
912
  foreach ( $input_options as $key => $value ) {
913
  $checked = ( 'on' === $value ) ? "checked='checked'" : '';
914
  if ( isset( $input_labels[ $key ] ) ) {
my-calendar-styles.php CHANGED
@@ -158,7 +158,7 @@ function my_calendar_style_edit() {
158
  } else {
159
  $delete = '';
160
  }
161
- $output .= "<li><label for='$var_id'>" . esc_html( $var ) . "</label><input type='text' id='$var_id' name='style_vars[$var]' value='" . esc_attr( $style ) . "' />$delete</li>";
162
  }
163
  if ( $output ) {
164
  echo "<ul class='checkboxes'>$output</ul>";
@@ -285,6 +285,10 @@ function mc_get_style_path( $filename = false, $type = 'path' ) {
285
  if ( ! $filename ) {
286
  $filename = get_option( 'mc_css_file' );
287
  }
 
 
 
 
288
  if ( 0 === strpos( $filename, 'mc_custom_' ) ) {
289
  $filename = str_replace( 'mc_custom_', '', $filename );
290
  $stylefile = ( 'path' === $type ) ? str_replace( '/my-calendar/', '', $dir ) . '/my-calendar-custom/styles/' . $filename : str_replace( '/my-calendar/', '', $url ) . '/my-calendar-custom/styles/' . $filename;
@@ -367,7 +371,7 @@ function mc_css_list( $directory ) {
367
  $results = array();
368
  $handler = opendir( $directory );
369
  // Keep going until all files in directory have been read.
370
- while ( $file = readdir( $handler ) ) {
371
  // If $file isn't this directory or parent, add it to the results array.
372
  if ( '.' !== $file && '..' !== $file ) {
373
  $results[] = $file;
158
  } else {
159
  $delete = '';
160
  }
161
+ $output .= "<li><label for='$var_id'>" . esc_html( $var ) . "</label> <input type='text' id='$var_id' name='style_vars[$var]' value='" . esc_attr( $style ) . "' /><span aria-hidden='true' class='variable-color' style='background-color: " . esc_attr( $style ) . "'></span>$delete</li>";
162
  }
163
  if ( $output ) {
164
  echo "<ul class='checkboxes'>$output</ul>";
285
  if ( ! $filename ) {
286
  $filename = get_option( 'mc_css_file' );
287
  }
288
+ if ( ! $filename ) {
289
+ // If no value is saved, return default.
290
+ $filename = 'twentytwenty.css';
291
+ }
292
  if ( 0 === strpos( $filename, 'mc_custom_' ) ) {
293
  $filename = str_replace( 'mc_custom_', '', $filename );
294
  $stylefile = ( 'path' === $type ) ? str_replace( '/my-calendar/', '', $dir ) . '/my-calendar-custom/styles/' . $filename : str_replace( '/my-calendar/', '', $url ) . '/my-calendar-custom/styles/' . $filename;
371
  $results = array();
372
  $handler = opendir( $directory );
373
  // Keep going until all files in directory have been read.
374
+ while ( false !== ( $file = readdir( $handler ) ) ) { // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
375
  // If $file isn't this directory or parent, add it to the results array.
376
  if ( '.' !== $file && '..' !== $file ) {
377
  $results[] = $file;
my-calendar-templates.php CHANGED
@@ -324,6 +324,10 @@ function mc_create_tags( $event, $context = 'filters' ) {
324
  if ( ! is_object( $event ) ) {
325
  return;
326
  }
 
 
 
 
327
  $site = ( isset( $event->site_id ) ) ? $event->site_id : false;
328
  $event = mc_clean_location( $event, 'event' );
329
  $e = array();
@@ -349,15 +353,17 @@ function mc_create_tags( $event, $context = 'filters' ) {
349
  $e['date_utc'] = date_i18n( apply_filters( 'mc_date_format', $date_format, 'template_begin_ts' ), $event->ts_occur_begin );
350
  $e['date_end_utc'] = date_i18n( apply_filters( 'mc_date_format', $date_format, 'template_end_ts' ), $event->ts_occur_end );
351
  $notime = esc_html( mc_notime_label( $event ) );
352
- $e['time'] = ( '00:00:00' === date( 'H:i:s', strtotime( $real_begin_date ) ) ) ? $notime : date( get_option( 'mc_time_format' ), strtotime( $real_begin_date ) );
353
- $e['time24'] = ( '00:00' === date( 'G:i', strtotime( $real_begin_date ) ) ) ? $notime : date( get_option( 'mc_time_format' ), strtotime( $real_begin_date ) );
354
- $endtime = ( '23:59:59' === $event->event_end ) ? '00:00:00' : date( 'H:i:s', strtotime( $real_end_date ) );
355
- $e['endtime'] = ( $real_end_date === $real_begin_date || '1' === $event->event_hide_end || '23:59:59' === date( 'H:i:s', strtotime( $real_end_date ) ) ) ? '' : date_i18n( get_option( 'mc_time_format' ), strtotime( $endtime ) );
356
  $e['runtime'] = mc_runtime( $event->ts_occur_begin, $event->ts_occur_end, $event );
357
  $e['duration'] = mc_duration( $event );
358
- $e['dtstart'] = date( 'Y-m-d\TH:i:s', strtotime( $real_begin_date ) ); // Date: hcal formatted.
359
- $e['dtend'] = date( 'Y-m-d\TH:i:s', strtotime( $real_end_date ) ); // Date: hcal formatted end.
360
- $e['rssdate'] = date( 'D, d M Y H:i:s +0000', strtotime( $event->event_added ) );
 
 
361
  $date = date_i18n( apply_filters( 'mc_date_format', $date_format, 'template_begin' ), strtotime( $real_begin_date ) );
362
  $date_end = date_i18n( apply_filters( 'mc_date_format', $date_format, 'template_end' ), strtotime( $real_end_date ) );
363
  $date_arr = array(
@@ -374,8 +380,8 @@ function mc_create_tags( $event, $context = 'filters' ) {
374
  $e['date'] = ( '1' !== $event->event_span ) ? $date : mc_format_date_span( $dates, 'simple', $date );
375
  $e['enddate'] = $date_end;
376
  $e['daterange'] = ( $date === $date_end ) ? "<span class='mc_db'>$date</span>" : "<span class='mc_db'>$date</span> <span>&ndash;</span> <span class='mc_de'>$date_end</span>";
377
- $e['timerange'] = ( ( $e['time'] === $e['endtime'] ) || 1 == $event->event_hide_end || '23:59:59' === date( 'H:i:s', strtotime( $real_end_date ) ) ) ? $e['time'] : "<span class='mc_tb'>" . $e['time'] . "</span> <span>&ndash;</span> <span class='mc_te'>" . $e['endtime'] . '</span>';
378
- $e['datespan'] = ( 1 == $event->event_span || ( $e['date'] != $e['enddate'] ) ) ? mc_format_date_span( $dates ) : $date;
379
  $e['multidate'] = mc_format_date_span( $dates, 'complex', "<span class='fallback-date'>$date</span><span class='separator'>,</span> <span class='fallback-time'>$e[time]</span>&ndash;<span class='fallback-endtime'>$e[endtime]</span>" );
380
  $e['began'] = $event->event_begin; // returns date of first occurrence of an event.
381
  $e['recurs'] = mc_event_recur_string( $event, $real_begin_date );
@@ -390,7 +396,7 @@ function mc_create_tags( $event, $context = 'filters' ) {
390
  $e['ical_categories'] = strip_tags( ( property_exists( $event, 'categories' ) ) ? mc_categories_html( $event->categories, $event->event_category ) : mc_get_categories( $event, 'html' ) );
391
  $e['term'] = intval( $event->category_term );
392
  $e['icon'] = mc_category_icon( $event, 'img' );
393
- $e['icon_html'] = ( '' != $e['icon'] ) ? "<img src='$e[icon]' class='mc-category-icon' alt='" . __( 'Category', 'my-calendar' ) . ': ' . esc_attr( $event->category_name ) . "' />" : '';
394
  $e['color'] = $event->category_color;
395
 
396
  $hex = ( strpos( $event->category_color, '#' ) !== 0 ) ? '#' : '';
@@ -402,8 +408,8 @@ function mc_create_tags( $event, $context = 'filters' ) {
402
  $e['close_color_css'] = '</span>';
403
 
404
  // Special.
405
- $e['skip_holiday'] = ( 0 == $event->event_holiday ) ? 'false' : 'true';
406
- $e['event_status'] = ( 1 == $event->event_approved ) ? __( 'Published', 'my-calendar' ) : __( 'Draft', 'my-calendar' );
407
 
408
  // General text fields.
409
  $e['title'] = stripslashes( $event->event_title );
@@ -424,7 +430,7 @@ function mc_create_tags( $event, $context = 'filters' ) {
424
  $e_template = apply_filters( 'mc_details_template', $e_template );
425
  $tags = array( '{title}', '{location}', '{color}', '{icon}', '{date}', '{time}' );
426
  $replacements = array(
427
- stripslashes( $event->event_title ),
428
  stripslashes( $event->event_label ),
429
  $event->category_color,
430
  $event->category_icon,
@@ -448,10 +454,10 @@ function mc_create_tags( $event, $context = 'filters' ) {
448
 
449
  $e['details_link'] = $e_link;
450
  $e['details'] = "<a href='" . esc_url( $e_link ) . "' class='mc-details' $nofollow>$e_label</a>";
451
- $e['linking'] = ( '' != $e['link'] ) ? $event->event_link : $e_link;
452
- $e['linking_title'] = ( '' != $e['linking'] ) ? "<a href='" . esc_url( $e['linking'] ) . "' $nofollow>" . $e['title'] . '</a>' : $e['title'];
453
 
454
- if ( 'related' != $context && ( is_singular( 'mc-events' ) || isset( $_GET['mc_id'] ) ) ) {
455
  $related_template = apply_filters( 'mc_related_template', '{date}, {time}', $event );
456
  $e['related'] = '<ul class="related-events">' . mc_list_related( $event->event_group_id, $event->event_id, $related_template ) . '</ul>';
457
  } else {
@@ -507,8 +513,8 @@ function mc_create_tags( $event, $context = 'filters' ) {
507
  }
508
 
509
  $strip_desc = mc_newline_replace( strip_tags( $event->event_desc ) ) . ' ' . $e['link'];
510
- $e['gcal'] = mc_google_cal( $dtstart, $dtend, $e_link, stripcslashes( $event->event_title ), $map_gcal, $strip_desc );
511
- $e['gcal_link'] = "<a href='" . esc_url( $e['gcal'] ) . "' class='gcal external' rel='nofollow' aria-describedby='mc_$event->occur_id-title'>" . __( 'Google Calendar', 'my-calendar' ) . '</a>';
512
 
513
  // IDs.
514
  $e['dateid'] = $event->occur_id; // Unique ID for this date of this event.
@@ -523,7 +529,7 @@ function mc_create_tags( $event, $context = 'filters' ) {
523
  $e['ical_description'] = str_replace( "\r", '=0D=0A=', $event->event_desc );
524
  $e['ical_desc'] = $strip_desc;
525
  $e['ical_start'] = $dtstart;
526
- $e['ical_end'] = ( mc_is_all_day( $event ) ) ? date( 'Ymd\THi00', strtotime( $dtend ) + 60 ) : $dtend;
527
  $ical_link = mc_build_url(
528
  array( 'vcal' => $event->occur_id ),
529
  array(
@@ -539,7 +545,7 @@ function mc_create_tags( $event, $context = 'filters' ) {
539
  mc_get_uri( $event )
540
  );
541
  $e['ical'] = $ical_link;
542
- $e['ical_html'] = "<a class='ical' rel='nofollow' href='" . esc_url( $ical_link ) . "' aria-describedby='mc_$event->occur_id-title'>" . __( 'iCal', 'my-calendar' ) . '</a>';
543
  $e = apply_filters( 'mc_filter_shortcodes', $e, $event );
544
 
545
  return $e;
@@ -588,7 +594,7 @@ function mc_get_details_link( $event ) {
588
  $permalinks = apply_filters( 'mc_use_permalinks', get_option( 'mc_use_permalinks' ) );
589
  $permalinks = ( 1 === $permalinks || true === $permalinks || 'true' === $permalinks ) ? true : false;
590
  $details_link = mc_event_link( $event );
591
- if ( 0 != $event->event_post && 'true' !== get_option( 'mc_remote' ) && $permalinks ) {
592
  $details_link = add_query_arg( 'mc_id', $event->occur_id, get_permalink( $event->event_post ) );
593
  } else {
594
  if ( mc_get_uri( 'boolean' ) ) {
@@ -711,15 +717,15 @@ function mc_format_timestamp( $os, $source ) {
711
  $timezone_object = timezone_open( $timezone_string );
712
  $date_object = date_create( null, $timezone_object );
713
 
714
- $date_object->setTime( date( 'H', $os ), date( 'i', $os ) );
715
- $date_object->setDate( date( 'Y', $os ), date( 'm', $os ), date( 'd', $os ) );
716
 
717
  $timestamp = $date_object->getTimestamp();
718
  $time = gmdate( 'Ymd\THi00', $timestamp ) . 'Z';
719
 
720
  } else {
721
- $os_time = mktime( date( 'H', $os ), date( 'i', $os ), date( 's', $os ), date( 'm', $os ), date( 'd', $os ), date( 'Y', $os ) );
722
- $time = date( 'Ymd\THi00', $os_time );
723
  }
724
 
725
  return $time;
@@ -736,7 +742,7 @@ function mc_format_timestamp( $os, $source ) {
736
  */
737
  function mc_runtime( $start, $end, $event ) {
738
  $return = '';
739
- if ( ! ( $event->event_hide_end || $start == $end || '23:59:59' === date( 'H:i:s', strtotime( $end ) ) ) ) {
740
  $return = human_time_diff( $start, $end );
741
  }
742
 
@@ -759,16 +765,16 @@ function mc_duration( $event ) {
759
  $interval = $datetime1->diff( $datetime2 );
760
 
761
  $duration = '';
762
- $duration .= ( 0 != $interval->y ) ? $interval->y . 'Y' : '';
763
- $duration .= ( 0 != $interval->m ) ? $interval->m . 'M' : '';
764
- if ( '23' == $interval->h && '59' == $interval->i ) {
765
- $d = ( 0 == $interval->d ) ? 1 : $interval->d + 1;
766
  $duration .= 'D' . $d;
767
  $duration .= 'TH0M0';
768
  } else {
769
- $duration .= ( 0 != $interval->d ) ? $interval->d . 'D' : '';
770
- $duration .= ( 0 != $interval->h ) ? 'T' . $interval->h . 'H' : '';
771
- $duration .= ( 0 != $interval->i ) ? $interval->i . 'M' : '';
772
  }
773
  $duration = 'P' . $duration;
774
 
@@ -788,7 +794,7 @@ function mc_event_link( $event ) {
788
  return $link;
789
  }
790
  $expired = mc_event_expired( $event );
791
- if ( 0 == $event->event_link_expires ) {
792
  $link = esc_url( $event->event_link );
793
  } else {
794
  if ( $expired ) {
@@ -810,7 +816,7 @@ function mc_event_link( $event ) {
810
  */
811
  function mc_event_expired( $event ) {
812
  if ( is_object( $event ) ) {
813
- if ( my_calendar_date_xcomp( $event->occur_end, date( 'Y-m-d', current_time( 'timestamp' ) ) ) ) {
814
  do_action( 'mc_event_expired', $event );
815
 
816
  return true;
@@ -837,7 +843,7 @@ function mc_generate_map( $event, $source = 'event' ) {
837
  if ( $api_key ) {
838
  $id = rand();
839
  $source = ( 'event' === $source ) ? 'event' : 'location';
840
- $zoom = ( 0 != $event->{$source . '_zoom'} ) ? $event->{$source . '_zoom'} : '15';
841
  $category_icon = mc_category_icon( $event, 'img' );
842
  if ( ! $category_icon ) {
843
  $category_icon = '//maps.google.com/mapfiles/marker_green.png';
@@ -958,7 +964,7 @@ function mc_event_date_span( $group_id, $event_span, $dates = array() ) {
958
  $mcdb = mc_remote_db();
959
  }
960
  $group_id = (int) $group_id;
961
- if ( 0 == $group_id && 1 != $event_span ) {
962
 
963
  return $dates;
964
  } else {
@@ -995,8 +1001,8 @@ function mc_format_date_span( $dates, $display = 'simple', $default = '' ) {
995
  foreach ( $dates as $date ) {
996
  $begin = $date->occur_begin;
997
  $end = $date->occur_end;
998
- $day_begin = date( 'Y-m-d', strtotime( $begin ) );
999
- $day_end = date( 'Y-m-d', strtotime( $end ) );
1000
  $bformat = '<span class="multidate-date">' . date_i18n( mc_date_format(), strtotime( $begin ) ) . "</span> <span class='multidate-time'>" . date_i18n( get_option( 'mc_time_format' ), strtotime( $begin ) ) . '</span>';
1001
  $endtimeformat = ( '00:00:00' === $date->occur_end ) ? '' : ' ' . get_option( 'mc_time_format' );
1002
  $eformat = ( $day_begin !== $day_end ) ? mc_date_format() . $endtimeformat : $endtimeformat;
@@ -1020,7 +1026,7 @@ add_filter( 'mc_insert_author_data', 'mc_author_data', 10, 2 );
1020
  * @return array $e
1021
  */
1022
  function mc_author_data( $e, $event ) {
1023
- if ( 0 != $event->event_author ) {
1024
  $author = get_userdata( $event->event_author );
1025
  $host = get_userdata( $event->event_host );
1026
  if ( $author ) {
@@ -1128,15 +1134,15 @@ function mc_event_recur_string( $event, $begin ) {
1128
  $recurs = str_split( $event->event_recur, 1 );
1129
  $recur = $recurs[0];
1130
  $every = ( isset( $recurs[1] ) ) ? str_replace( $recurs[0], '', $event->event_recur ) : 1;
1131
- $month_date = date( 'dS', strtotime( $begin ) );
1132
  $day_name = date_i18n( 'l', strtotime( $begin ) );
1133
- $week_number = mc_ordinal( week_of_month( date( 'j', strtotime( $begin ) ) ) + 1 );
1134
  switch ( $recur ) {
1135
  case 'S':
1136
  $event_recur = __( 'Does not recur', 'my-calendar' );
1137
  break;
1138
  case 'D':
1139
- if ( 1 == $every ) {
1140
  $event_recur = __( 'Daily', 'my-calendar' );
1141
  } else {
1142
  // Translators: Number of days between recurrences.
@@ -1147,7 +1153,7 @@ function mc_event_recur_string( $event, $begin ) {
1147
  $event_recur = __( 'Daily, weekdays only', 'my-calendar' );
1148
  break;
1149
  case 'W':
1150
- if ( 1 == $every ) {
1151
  $event_recur = __( 'Weekly', 'my-calendar' );
1152
  } else {
1153
  // Translators: Number of weeks between recurrences.
@@ -1158,7 +1164,7 @@ function mc_event_recur_string( $event, $begin ) {
1158
  $event_recur = __( 'Bi-weekly', 'my-calendar' );
1159
  break;
1160
  case 'M':
1161
- if ( 1 == $every ) {
1162
  // Translators: The ordinal number of the month for the recurrence.
1163
  $event_recur = sprintf( __( 'the %s of each month', 'my-calendar' ), $month_date );
1164
  } else {
@@ -1171,7 +1177,7 @@ function mc_event_recur_string( $event, $begin ) {
1171
  $event_recur = sprintf( __( 'the %1$s %2$s of each month', 'my-calendar' ), $week_number, $day_name );
1172
  break;
1173
  case 'Y':
1174
- if ( 1 == $every ) {
1175
  $event_recur = __( 'Annually', 'my-calendar' );
1176
  } else {
1177
  // Translators: Number of years.
324
  if ( ! is_object( $event ) ) {
325
  return;
326
  }
327
+ $calendar_id = '';
328
+ if ( 'filters' !== $context && 'related' !== $context ) {
329
+ $calendar_id = $context;
330
+ }
331
  $site = ( isset( $event->site_id ) ) ? $event->site_id : false;
332
  $event = mc_clean_location( $event, 'event' );
333
  $e = array();
353
  $e['date_utc'] = date_i18n( apply_filters( 'mc_date_format', $date_format, 'template_begin_ts' ), $event->ts_occur_begin );
354
  $e['date_end_utc'] = date_i18n( apply_filters( 'mc_date_format', $date_format, 'template_end_ts' ), $event->ts_occur_end );
355
  $notime = esc_html( mc_notime_label( $event ) );
356
+ $e['time'] = ( '00:00:00' === mc_date( 'H:i:s', strtotime( $real_begin_date ), false ) ) ? $notime : mc_date( get_option( 'mc_time_format' ), strtotime( $real_begin_date ), false );
357
+ $e['time24'] = ( '00:00' === mc_date( 'G:i', strtotime( $real_begin_date ), false ) ) ? $notime : mc_date( get_option( 'mc_time_format' ), strtotime( $real_begin_date ), false );
358
+ $endtime = ( '23:59:59' === $event->event_end ) ? '00:00:00' : mc_date( 'H:i:s', strtotime( $real_end_date ), false );
359
+ $e['endtime'] = ( $real_end_date === $real_begin_date || '1' === $event->event_hide_end || '23:59:59' === mc_date( 'H:i:s', strtotime( $real_end_date ), false ) ) ? '' : date_i18n( get_option( 'mc_time_format' ), strtotime( $endtime ) );
360
  $e['runtime'] = mc_runtime( $event->ts_occur_begin, $event->ts_occur_end, $event );
361
  $e['duration'] = mc_duration( $event );
362
+ $e['dtstart'] = mc_date( 'Y-m-d\TH:i:s', strtotime( $real_begin_date ), false ); // Date: hcal formatted.
363
+ $e['dtend'] = mc_date( 'Y-m-d\TH:i:s', strtotime( $real_end_date ), false ); // Date: hcal formatted end.
364
+ $e['userstart'] = '<time class="mc-user-time" data-label="' . __( 'Local time:', 'my-calendar' ) . '">' . mc_date( 'Y-m-d\TH:i:s\Z', $event->ts_occur_begin, false ) . '</time>';
365
+ $e['userend'] = '<time class="mc-user-time" data-label="' . __( 'Local time:', 'my-calendar' ) . '">' . mc_date( 'Y-m-d\TH:i:s\Z', $event->ts_occur_end, false ) . '</time>';
366
+ $e['rssdate'] = mc_date( 'D, d M Y H:i:s +0000', strtotime( $event->event_added ), false );
367
  $date = date_i18n( apply_filters( 'mc_date_format', $date_format, 'template_begin' ), strtotime( $real_begin_date ) );
368
  $date_end = date_i18n( apply_filters( 'mc_date_format', $date_format, 'template_end' ), strtotime( $real_end_date ) );
369
  $date_arr = array(
380
  $e['date'] = ( '1' !== $event->event_span ) ? $date : mc_format_date_span( $dates, 'simple', $date );
381
  $e['enddate'] = $date_end;
382
  $e['daterange'] = ( $date === $date_end ) ? "<span class='mc_db'>$date</span>" : "<span class='mc_db'>$date</span> <span>&ndash;</span> <span class='mc_de'>$date_end</span>";
383
+ $e['timerange'] = ( ( $e['time'] === $e['endtime'] ) || 1 === (int) $event->event_hide_end || '23:59:59' === mc_date( 'H:i:s', strtotime( $real_end_date ), false ) ) ? $e['time'] : "<span class='mc_tb'>" . $e['time'] . "</span> <span>&ndash;</span> <span class='mc_te'>" . $e['endtime'] . '</span>';
384
+ $e['datespan'] = ( 1 === (int) $event->event_span || ( $e['date'] !== $e['enddate'] ) ) ? mc_format_date_span( $dates ) : $date;
385
  $e['multidate'] = mc_format_date_span( $dates, 'complex', "<span class='fallback-date'>$date</span><span class='separator'>,</span> <span class='fallback-time'>$e[time]</span>&ndash;<span class='fallback-endtime'>$e[endtime]</span>" );
386
  $e['began'] = $event->event_begin; // returns date of first occurrence of an event.
387
  $e['recurs'] = mc_event_recur_string( $event, $real_begin_date );
396
  $e['ical_categories'] = strip_tags( ( property_exists( $event, 'categories' ) ) ? mc_categories_html( $event->categories, $event->event_category ) : mc_get_categories( $event, 'html' ) );
397
  $e['term'] = intval( $event->category_term );
398
  $e['icon'] = mc_category_icon( $event, 'img' );
399
+ $e['icon_html'] = ( '' !== $e['icon'] ) ? "<img src='$e[icon]' class='mc-category-icon' alt='" . __( 'Category', 'my-calendar' ) . ': ' . esc_attr( $event->category_name ) . "' />" : '';
400
  $e['color'] = $event->category_color;
401
 
402
  $hex = ( strpos( $event->category_color, '#' ) !== 0 ) ? '#' : '';
408
  $e['close_color_css'] = '</span>';
409
 
410
  // Special.
411
+ $e['skip_holiday'] = ( 0 === (int) $event->event_holiday ) ? 'false' : 'true';
412
+ $e['event_status'] = ( 1 === (int) $event->event_approved ) ? __( 'Published', 'my-calendar' ) : __( 'Draft', 'my-calendar' );
413
 
414
  // General text fields.
415
  $e['title'] = stripslashes( $event->event_title );
430
  $e_template = apply_filters( 'mc_details_template', $e_template );
431
  $tags = array( '{title}', '{location}', '{color}', '{icon}', '{date}', '{time}' );
432
  $replacements = array(
433
+ stripslashes( $e['title'] ),
434
  stripslashes( $event->event_label ),
435
  $event->category_color,
436
  $event->category_icon,
454
 
455
  $e['details_link'] = $e_link;
456
  $e['details'] = "<a href='" . esc_url( $e_link ) . "' class='mc-details' $nofollow>$e_label</a>";
457
+ $e['linking'] = ( '' !== $e['link'] ) ? $event->event_link : $e_link;
458
+ $e['linking_title'] = ( '' !== $e['linking'] ) ? "<a href='" . esc_url( $e['linking'] ) . "' $nofollow>" . $e['title'] . '</a>' : $e['title'];
459
 
460
+ if ( 'related' !== $context && ( is_singular( 'mc-events' ) || isset( $_GET['mc_id'] ) ) ) {
461
  $related_template = apply_filters( 'mc_related_template', '{date}, {time}', $event );
462
  $e['related'] = '<ul class="related-events">' . mc_list_related( $event->event_group_id, $event->event_id, $related_template ) . '</ul>';
463
  } else {
513
  }
514
 
515
  $strip_desc = mc_newline_replace( strip_tags( $event->event_desc ) ) . ' ' . $e['link'];
516
+ $e['gcal'] = mc_google_cal( $dtstart, $dtend, $e_link, stripcslashes( $e['title'] ), $map_gcal, $strip_desc );
517
+ $e['gcal_link'] = "<a href='" . esc_url( $e['gcal'] ) . "' class='gcal external' rel='nofollow' aria-describedby='mc_$event->occur_id-title-$calendar_id'>" . __( 'Google Calendar', 'my-calendar' ) . '</a>';
518
 
519
  // IDs.
520
  $e['dateid'] = $event->occur_id; // Unique ID for this date of this event.
529
  $e['ical_description'] = str_replace( "\r", '=0D=0A=', $event->event_desc );
530
  $e['ical_desc'] = $strip_desc;
531
  $e['ical_start'] = $dtstart;
532
+ $e['ical_end'] = ( mc_is_all_day( $event ) ) ? mc_date( 'Ymd\THi00', strtotime( $dtend ) + 60, false ) : $dtend;
533
  $ical_link = mc_build_url(
534
  array( 'vcal' => $event->occur_id ),
535
  array(
545
  mc_get_uri( $event )
546
  );
547
  $e['ical'] = $ical_link;
548
+ $e['ical_html'] = "<a class='ical' rel='nofollow' href='" . esc_url( $ical_link ) . "' aria-describedby='mc_$event->occur_id-title-$calendar_id'>" . __( 'iCal', 'my-calendar' ) . '</a>';
549
  $e = apply_filters( 'mc_filter_shortcodes', $e, $event );
550
 
551
  return $e;
594
  $permalinks = apply_filters( 'mc_use_permalinks', get_option( 'mc_use_permalinks' ) );
595
  $permalinks = ( 1 === $permalinks || true === $permalinks || 'true' === $permalinks ) ? true : false;
596
  $details_link = mc_event_link( $event );
597
+ if ( 0 !== (int) $event->event_post && 'true' !== get_option( 'mc_remote' ) && $permalinks ) {
598
  $details_link = add_query_arg( 'mc_id', $event->occur_id, get_permalink( $event->event_post ) );
599
  } else {
600
  if ( mc_get_uri( 'boolean' ) ) {
717
  $timezone_object = timezone_open( $timezone_string );
718
  $date_object = date_create( null, $timezone_object );
719
 
720
+ $date_object->setTime( mc_date( 'H', $os, false ), mc_date( 'i', $os, false ) );
721
+ $date_object->setDate( mc_date( 'Y', $os, false ), mc_date( 'm', $os, false ), mc_date( 'd', $os, false ) );
722
 
723
  $timestamp = $date_object->getTimestamp();
724
  $time = gmdate( 'Ymd\THi00', $timestamp ) . 'Z';
725
 
726
  } else {
727
+ $os_time = mktime( mc_date( 'H', $os, false ), mc_date( 'i', $os, false ), mc_date( 's', $os, false ), mc_date( 'm', $os, false ), mc_date( 'd', $os, false ), mc_date( 'Y', $os, false ) );
728
+ $time = mc_date( 'Ymd\THi00', $os_time, false );
729
  }
730
 
731
  return $time;
742
  */
743
  function mc_runtime( $start, $end, $event ) {
744
  $return = '';
745
+ if ( ! ( $event->event_hide_end || $start === $end || '23:59:59' === mc_date( 'H:i:s', strtotime( $end ), false ) ) ) {
746
  $return = human_time_diff( $start, $end );
747
  }
748
 
765
  $interval = $datetime1->diff( $datetime2 );
766
 
767
  $duration = '';
768
+ $duration .= ( 0 !== (int) $interval->y ) ? $interval->y . 'Y' : '';
769
+ $duration .= ( 0 !== (int) $interval->m ) ? $interval->m . 'M' : '';
770
+ if ( '23' === (string) $interval->h && '59' === (string) $interval->i ) {
771
+ $d = ( 0 === (int) $interval->d ) ? 1 : $interval->d + 1;
772
  $duration .= 'D' . $d;
773
  $duration .= 'TH0M0';
774
  } else {
775
+ $duration .= ( 0 !== (int) $interval->d ) ? $interval->d . 'D' : '';
776
+ $duration .= ( 0 !== (int) $interval->h ) ? 'T' . $interval->h . 'H' : '';
777
+ $duration .= ( 0 !== (int) $interval->i ) ? $interval->i . 'M' : '';
778
  }
779
  $duration = 'P' . $duration;
780
 
794
  return $link;
795
  }
796
  $expired = mc_event_expired( $event );
797
+ if ( 0 === (int) $event->event_link_expires ) {
798
  $link = esc_url( $event->event_link );
799
  } else {
800
  if ( $expired ) {
816
  */
817
  function mc_event_expired( $event ) {
818
  if ( is_object( $event ) ) {
819
+ if ( my_calendar_date_xcomp( $event->occur_end, current_time( 'Y-m-d' ) ) ) {
820
  do_action( 'mc_event_expired', $event );
821
 
822
  return true;
843
  if ( $api_key ) {
844
  $id = rand();
845
  $source = ( 'event' === $source ) ? 'event' : 'location';
846
+ $zoom = ( 0 !== (int) $event->{$source . '_zoom'} ) ? $event->{$source . '_zoom'} : '15';
847
  $category_icon = mc_category_icon( $event, 'img' );
848
  if ( ! $category_icon ) {
849
  $category_icon = '//maps.google.com/mapfiles/marker_green.png';
964
  $mcdb = mc_remote_db();
965
  }
966
  $group_id = (int) $group_id;
967
+ if ( 0 === (int) $group_id && 1 !== (int) $event_span ) {
968
 
969
  return $dates;
970
  } else {
1001
  foreach ( $dates as $date ) {
1002
  $begin = $date->occur_begin;
1003
  $end = $date->occur_end;
1004
+ $day_begin = mc_date( 'Y-m-d', strtotime( $begin ), false );
1005
+ $day_end = mc_date( 'Y-m-d', strtotime( $end ), false );
1006
  $bformat = '<span class="multidate-date">' . date_i18n( mc_date_format(), strtotime( $begin ) ) . "</span> <span class='multidate-time'>" . date_i18n( get_option( 'mc_time_format' ), strtotime( $begin ) ) . '</span>';
1007
  $endtimeformat = ( '00:00:00' === $date->occur_end ) ? '' : ' ' . get_option( 'mc_time_format' );
1008
  $eformat = ( $day_begin !== $day_end ) ? mc_date_format() . $endtimeformat : $endtimeformat;
1026
  * @return array $e
1027
  */
1028
  function mc_author_data( $e, $event ) {
1029
+ if ( 0 !== (int) $event->event_author ) {
1030
  $author = get_userdata( $event->event_author );
1031
  $host = get_userdata( $event->event_host );
1032
  if ( $author ) {
1134
  $recurs = str_split( $event->event_recur, 1 );
1135
  $recur = $recurs[0];
1136
  $every = ( isset( $recurs[1] ) ) ? str_replace( $recurs[0], '', $event->event_recur ) : 1;
1137
+ $month_date = mc_date( 'dS', strtotime( $begin ), false );
1138
  $day_name = date_i18n( 'l', strtotime( $begin ) );
1139
+ $week_number = mc_ordinal( week_of_month( mc_date( 'j', strtotime( $begin ), false ) ) + 1 );
1140
  switch ( $recur ) {
1141
  case 'S':
1142
  $event_recur = __( 'Does not recur', 'my-calendar' );
1143
  break;
1144
  case 'D':
1145
+ if ( 1 === (int) $every ) {
1146
  $event_recur = __( 'Daily', 'my-calendar' );
1147
  } else {
1148
  // Translators: Number of days between recurrences.
1153
  $event_recur = __( 'Daily, weekdays only', 'my-calendar' );
1154
  break;
1155
  case 'W':
1156
+ if ( 1 === (int) $every ) {
1157
  $event_recur = __( 'Weekly', 'my-calendar' );
1158
  } else {
1159
  // Translators: Number of weeks between recurrences.
1164
  $event_recur = __( 'Bi-weekly', 'my-calendar' );
1165
  break;
1166
  case 'M':
1167
+ if ( 1 === (int) $every ) {
1168
  // Translators: The ordinal number of the month for the recurrence.
1169
  $event_recur = sprintf( __( 'the %s of each month', 'my-calendar' ), $month_date );
1170
  } else {
1177
  $event_recur = sprintf( __( 'the %1$s %2$s of each month', 'my-calendar' ), $week_number, $day_name );
1178
  break;
1179
  case 'Y':
1180
+ if ( 1 === (int) $every ) {
1181
  $event_recur = __( 'Annually', 'my-calendar' );
1182
  } else {
1183
  // Translators: Number of years.
my-calendar-widgets.php CHANGED
@@ -82,69 +82,69 @@ function my_calendar_upcoming_events( $args ) {
82
  if ( ! $display_events ) {
83
  $temp_array = array();
84
  if ( 'days' === $display_type ) {
85
- $from = date( 'Y-m-d', strtotime( "-$before days" ) );
86
- $to = date( 'Y-m-d', strtotime( "+$after days" ) );
87
  }
88
  if ( 'month' === $display_type ) {
89
- $from = date( 'Y-m-1' );
90
- $to = date( 'Y-m-t' );
91
  }
92
  if ( 'custom' === $display_type && '' !== $from && '' !== $to ) {
93
- $from = date( 'Y-m-d', strtotime( $from ) );
94
- $to = ( 'today' === $to ) ? date( 'Y-m-d', current_time( 'timestamp' ) ) : date( 'Y-m-d', strtotime( $to ) );
95
  }
96
  /* Yes, this is crude. But sometimes simplicity works best. There are only 12 possibilities, after all. */
97
  if ( 'month+1' === $display_type ) {
98
- $from = date( 'Y-m-1', strtotime( '+1 month' ) );
99
- $to = date( 'Y-m-t', strtotime( '+1 month' ) );
100
  }
101
  if ( 'month+2' === $display_type ) {
102
- $from = date( 'Y-m-1', strtotime( '+2 month' ) );
103
- $to = date( 'Y-m-t', strtotime( '+2 month' ) );
104
  }
105
  if ( 'month+3' === $display_type ) {
106
- $from = date( 'Y-m-1', strtotime( '+3 month' ) );
107
- $to = date( 'Y-m-t', strtotime( '+3 month' ) );
108
  }
109
  if ( 'month+4' === $display_type ) {
110
- $from = date( 'Y-m-1', strtotime( '+4 month' ) );
111
- $to = date( 'Y-m-t', strtotime( '+4 month' ) );
112
  }
113
  if ( 'month+5' === $display_type ) {
114
- $from = date( 'Y-m-1', strtotime( '+5 month' ) );
115
- $to = date( 'Y-m-t', strtotime( '+5 month' ) );
116
  }
117
  if ( 'month+6' === $display_type ) {
118
- $from = date( 'Y-m-1', strtotime( '+6 month' ) );
119
- $to = date( 'Y-m-t', strtotime( '+6 month' ) );
120
  }
121
  if ( 'month+7' === $display_type ) {
122
- $from = date( 'Y-m-1', strtotime( '+7 month' ) );
123
- $to = date( 'Y-m-t', strtotime( '+7 month' ) );
124
  }
125
  if ( 'month+8' === $display_type ) {
126
- $from = date( 'Y-m-1', strtotime( '+8 month' ) );
127
- $to = date( 'Y-m-t', strtotime( '+8 month' ) );
128
  }
129
  if ( 'month+9' === $display_type ) {
130
- $from = date( 'Y-m-1', strtotime( '+9 month' ) );
131
- $to = date( 'Y-m-t', strtotime( '+9 month' ) );
132
  }
133
  if ( 'month+10' === $display_type ) {
134
- $from = date( 'Y-m-1', strtotime( '+10 month' ) );
135
- $to = date( 'Y-m-t', strtotime( '+10 month' ) );
136
  }
137
  if ( 'month+11' === $display_type ) {
138
- $from = date( 'Y-m-1', strtotime( '+11 month' ) );
139
- $to = date( 'Y-m-t', strtotime( '+11 month' ) );
140
  }
141
  if ( 'month+12' === $display_type ) {
142
- $from = date( 'Y-m-1', strtotime( '+12 month' ) );
143
- $to = date( 'Y-m-t', strtotime( '+12 month' ) );
144
  }
145
  if ( 'year' === $display_type ) {
146
- $from = date( 'Y-1-1' );
147
- $to = date( 'Y-12-31' );
148
  }
149
  $from = apply_filters( 'mc_upcoming_date_from', $from, $args );
150
  $to = apply_filters( 'mc_upcoming_date_to', $to, $args );
@@ -191,8 +191,8 @@ function my_calendar_upcoming_events( $args ) {
191
  if ( $i < $skip && 0 !== $skip ) {
192
  $i ++;
193
  } else {
194
- $today = date( 'Y-m-d H:i', current_time( 'timestamp' ) );
195
- $date = date( 'Y-m-d H:i', strtotime( $details['dtstart'] ) );
196
  $class = ( true === my_calendar_date_comp( $date, $today ) ) ? 'past-event' : 'future-event';
197
  $category = mc_category_class( $details, 'mc_' );
198
  $classes = mc_event_classes( $event, $event->occur_id, 'upcoming' );
@@ -300,8 +300,7 @@ function mc_produce_upcoming_events( $events, $template, $type = 'list', $order
300
  $temp_array = array();
301
  $past = 1;
302
  $future = 1;
303
- $now = current_time( 'timestamp' );
304
- $today = date( 'Y-m-d', $now );
305
  uksort( $events, 'mc_timediff_cmp' ); // Sort all events by proximity to current date.
306
  $count = count( $events );
307
  $group = array();
@@ -334,7 +333,7 @@ function mc_produce_upcoming_events( $events, $template, $type = 'list', $order
334
  $beginning = $span_time[0];
335
  $end = $span_time[1];
336
  }
337
- $current = date( 'Y-m-d H:i:00', current_time( 'timestamp' ) );
338
  if ( $e ) {
339
  // If a multi-day event, show only once.
340
  if ( '0' !== $e->occur_group_id && '1' === $e->event_span && in_array( $e->occur_group_id, $group, true ) || in_array( $e->occur_id, $occur, true ) ) {
@@ -408,8 +407,9 @@ function mc_produce_upcoming_events( $events, $template, $type = 'list', $order
408
  foreach ( reverse_array( $temp_array, true, $order ) as $event ) {
409
  $details = mc_create_tags( $event, $context );
410
  if ( ! in_array( $details['group'], $groups, true ) ) {
411
- $date = date( 'Y-m-d H:i:s', strtotime( $details['dtstart'] ) );
412
- $class = ( true === my_calendar_date_comp( $date, $today . ' ' . date( 'H:i', current_time( 'timestamp' ) ) ) ) ? 'past-event' : 'future-event';
 
413
  $category = mc_category_class( $details, 'mc_' );
414
  $classes = mc_event_classes( $event, $event->occur_id, 'upcoming' );
415
 
@@ -511,11 +511,11 @@ function my_calendar_todays_events( $args ) {
511
  $category = ( 'default' === $category ) ? $defaults['today']['category'] : $category;
512
  $no_event_text = ( '' === $substitute ) ? $defaults['today']['text'] : $substitute;
513
  if ( $date ) {
514
- $from = date( 'Y-m-d', strtotime( $date ) );
515
- $to = date( 'Y-m-d', strtotime( $date ) );
516
  } else {
517
- $from = date( 'Y-m-d', current_time( 'timestamp' ) );
518
- $to = date( 'Y-m-d', current_time( 'timestamp' ) );
519
  }
520
 
521
  $args = array(
@@ -543,9 +543,9 @@ function my_calendar_todays_events( $args ) {
543
  foreach ( $today as $e ) {
544
  if ( ! mc_private_event( $e ) && ! in_array( $e->event_group_id, $groups, true ) ) {
545
  $event_details = mc_create_tags( $e );
546
- $ts = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $e->ts_occur_begin ) ) );
547
- $end = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $e->ts_occur_end ) ) );
548
- $now = current_time( 'timestamp' );
549
  $category = mc_category_class( $e, 'mc_' );
550
  if ( $ts < $now && $end > $now ) {
551
  $class = 'on-now';
82
  if ( ! $display_events ) {
83
  $temp_array = array();
84
  if ( 'days' === $display_type ) {
85
+ $from = mc_date( 'Y-m-d', strtotime( "-$before days" ), false );
86
+ $to = mc_date( 'Y-m-d', strtotime( "+$after days" ), false );
87
  }
88
  if ( 'month' === $display_type ) {
89
+ $from = mc_date( 'Y-m-1' );
90
+ $to = mc_date( 'Y-m-t' );
91
  }
92
  if ( 'custom' === $display_type && '' !== $from && '' !== $to ) {
93
+ $from = mc_date( 'Y-m-d', strtotime( $from ), false );
94
+ $to = ( 'today' === $to ) ? current_time( 'Y-m-d' ) : mc_date( 'Y-m-d', strtotime( $to ), false );
95
  }
96
  /* Yes, this is crude. But sometimes simplicity works best. There are only 12 possibilities, after all. */
97
  if ( 'month+1' === $display_type ) {
98
+ $from = mc_date( 'Y-m-1', strtotime( '+1 month' ), false );
99
+ $to = mc_date( 'Y-m-t', strtotime( '+1 month' ), false );
100
  }
101
  if ( 'month+2' === $display_type ) {
102
+ $from = mc_date( 'Y-m-1', strtotime( '+2 month' ), false );
103
+ $to = mc_date( 'Y-m-t', strtotime( '+2 month' ), false );
104
  }
105
  if ( 'month+3' === $display_type ) {
106
+ $from = mc_date( 'Y-m-1', strtotime( '+3 month' ), false );
107
+ $to = mc_date( 'Y-m-t', strtotime( '+3 month' ), false );
108
  }
109
  if ( 'month+4' === $display_type ) {
110
+ $from = mc_date( 'Y-m-1', strtotime( '+4 month' ), false );
111
+ $to = mc_date( 'Y-m-t', strtotime( '+4 month' ), false );
112
  }
113
  if ( 'month+5' === $display_type ) {
114
+ $from = mc_date( 'Y-m-1', strtotime( '+5 month' ), false );
115
+ $to = mc_date( 'Y-m-t', strtotime( '+5 month' ), false );
116
  }
117
  if ( 'month+6' === $display_type ) {
118
+ $from = mc_date( 'Y-m-1', strtotime( '+6 month' ), false );
119
+ $to = mc_date( 'Y-m-t', strtotime( '+6 month' ), false );
120
  }
121
  if ( 'month+7' === $display_type ) {
122
+ $from = mc_date( 'Y-m-1', strtotime( '+7 month' ), false );
123
+ $to = mc_date( 'Y-m-t', strtotime( '+7 month' ), false );
124
  }
125
  if ( 'month+8' === $display_type ) {
126
+ $from = mc_date( 'Y-m-1', strtotime( '+8 month' ), false );
127
+ $to = mc_date( 'Y-m-t', strtotime( '+8 month' ), false );
128
  }
129
  if ( 'month+9' === $display_type ) {
130
+ $from = mc_date( 'Y-m-1', strtotime( '+9 month' ), false );
131
+ $to = mc_date( 'Y-m-t', strtotime( '+9 month' ), false );
132
  }
133
  if ( 'month+10' === $display_type ) {
134
+ $from = mc_date( 'Y-m-1', strtotime( '+10 month' ), false );
135
+ $to = mc_date( 'Y-m-t', strtotime( '+10 month' ), false );
136
  }
137
  if ( 'month+11' === $display_type ) {
138
+ $from = mc_date( 'Y-m-1', strtotime( '+11 month' ), false );
139
+ $to = mc_date( 'Y-m-t', strtotime( '+11 month' ), false );
140
  }
141
  if ( 'month+12' === $display_type ) {
142
+ $from = mc_date( 'Y-m-1', strtotime( '+12 month' ), false );
143
+ $to = mc_date( 'Y-m-t', strtotime( '+12 month' ), false );
144
  }
145
  if ( 'year' === $display_type ) {
146
+ $from = mc_date( 'Y-1-1' );
147
+ $to = mc_date( 'Y-12-31' );
148
  }
149
  $from = apply_filters( 'mc_upcoming_date_from', $from, $args );
150
  $to = apply_filters( 'mc_upcoming_date_to', $to, $args );
191
  if ( $i < $skip && 0 !== $skip ) {
192
  $i ++;
193
  } else {
194
+ $today = current_time( 'Y-m-d H:i' );
195
+ $date = mc_date( 'Y-m-d H:i', strtotime( $details['dtstart'], false ) );
196
  $class = ( true === my_calendar_date_comp( $date, $today ) ) ? 'past-event' : 'future-event';
197
  $category = mc_category_class( $details, 'mc_' );
198
  $classes = mc_event_classes( $event, $event->occur_id, 'upcoming' );
300
  $temp_array = array();
301
  $past = 1;
302
  $future = 1;
303
+ $today = current_time( 'Y-m-d' );
 
304
  uksort( $events, 'mc_timediff_cmp' ); // Sort all events by proximity to current date.
305
  $count = count( $events );
306
  $group = array();
333
  $beginning = $span_time[0];
334
  $end = $span_time[1];
335
  }
336
+ $current = current_time( 'Y-m-d H:i:00' );
337
  if ( $e ) {
338
  // If a multi-day event, show only once.
339
  if ( '0' !== $e->occur_group_id && '1' === $e->event_span && in_array( $e->occur_group_id, $group, true ) || in_array( $e->occur_id, $occur, true ) ) {
407
  foreach ( reverse_array( $temp_array, true, $order ) as $event ) {
408
  $details = mc_create_tags( $event, $context );
409
  if ( ! in_array( $details['group'], $groups, true ) ) {
410
+ // dtstart is already in current time zone.
411
+ $date = mc_date( 'Y-m-d H:i:s', strtotime( $details['dtstart'] ), false );
412
+ $class = ( true === my_calendar_date_comp( $date, $today . ' ' . current_time( 'H:i' ) ) ) ? 'past-event' : 'future-event';
413
  $category = mc_category_class( $details, 'mc_' );
414
  $classes = mc_event_classes( $event, $event->occur_id, 'upcoming' );
415
 
511
  $category = ( 'default' === $category ) ? $defaults['today']['category'] : $category;
512
  $no_event_text = ( '' === $substitute ) ? $defaults['today']['text'] : $substitute;
513
  if ( $date ) {
514
+ $from = mc_date( 'Y-m-d', strtotime( $date ), false );
515
+ $to = mc_date( 'Y-m-d', strtotime( $date ), false );
516
  } else {
517
+ $from = current_time( 'Y-m-d' );
518
+ $to = current_time( 'Y-m-d' );
519
  }
520
 
521
  $args = array(
543
  foreach ( $today as $e ) {
544
  if ( ! mc_private_event( $e ) && ! in_array( $e->event_group_id, $groups, true ) ) {
545
  $event_details = mc_create_tags( $e );
546
+ $ts = $e->ts_occur_begin;
547
+ $end = $e->ts_occur_end;
548
+ $now = time();
549
  $category = mc_category_class( $e, 'mc_' );
550
  if ( $ts < $now && $end > $now ) {
551
  $class = 'on-now';
my-calendar.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package MyCalendar
6
  * @author Joe Dolson
7
- * @copyright 2009-2019 Joe Dolson
8
  * @license GPL-2.0+
9
  *
10
  * @wordpress-plugin
@@ -17,11 +17,11 @@
17
  * License: GPL-2.0+
18
  * License URI: http://www.gnu.org/license/gpl-2.0.txt
19
  * Domain Path: lang
20
- * Version: 3.1.18
21
  */
22
 
23
  /*
24
- Copyright 2009-2019 Joe Dolson (email : joe@joedolson.com)
25
 
26
  This program is free software; you can redistribute it and/or modify
27
  it under the terms of the GNU General Public License as published by
@@ -42,7 +42,7 @@ if ( ! defined( 'ABSPATH' ) ) {
42
  }
43
 
44
  global $mc_version, $wpdb;
45
- $mc_version = '3.1.18';
46
 
47
  define( 'MC_DEBUG', false );
48
 
@@ -52,7 +52,7 @@ register_deactivation_hook( __FILE__, 'mc_plugin_deactivated' );
52
  * Actions to execute on activation.
53
  */
54
  function mc_plugin_activated() {
55
- $required_php_version = '5.3.0';
56
 
57
  if ( version_compare( PHP_VERSION, $required_php_version, '<' ) ) {
58
  $plugin_data = get_plugin_data( __FILE__, false );
@@ -118,10 +118,10 @@ function mc_load_textdomain() {
118
 
119
  // Add actions.
120
  add_action( 'admin_menu', 'my_calendar_menu' );
121
- add_action( 'wp_head', 'my_calendar_head' );
122
  add_action( 'delete_user', 'mc_deal_with_deleted_user' );
123
  add_action( 'widgets_init', 'mc_register_widgets' );
124
- add_action( 'init', 'my_calendar_add_feed' );
125
  add_action( 'wp_footer', 'mc_footer_js' );
126
  add_action( 'init', 'mc_export_vcal', 200 );
127
  // Add filters.
@@ -372,8 +372,8 @@ function my_calendar_menu() {
372
  }
373
  }
374
  if ( function_exists( 'add_submenu_page' ) ) {
375
- add_action( 'admin_head', 'my_calendar_write_js' );
376
- add_action( 'admin_enqueue_scripts', 'my_calendar_add_styles' );
377
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
378
  // If we're accessing a remote site, remove these pages.
379
  } else {
4
  *
5
  * @package MyCalendar
6
  * @author Joe Dolson
7
+ * @copyright 2009-2020 Joe Dolson
8
  * @license GPL-2.0+
9
  *
10
  * @wordpress-plugin
17
  * License: GPL-2.0+
18
  * License URI: http://www.gnu.org/license/gpl-2.0.txt
19
  * Domain Path: lang
20
+ * Version: 3.2.0
21
  */
22
 
23
  /*
24
+ Copyright 2009-2020 Joe Dolson (email : joe@joedolson.com)
25
 
26
  This program is free software; you can redistribute it and/or modify
27
  it under the terms of the GNU General Public License as published by
42
  }
43
 
44
  global $mc_version, $wpdb;
45
+ $mc_version = '3.2.0';
46
 
47
  define( 'MC_DEBUG', false );
48
 
52
  * Actions to execute on activation.
53
  */
54
  function mc_plugin_activated() {
55
+ $required_php_version = '5.6.0';
56
 
57
  if ( version_compare( PHP_VERSION, $required_php_version, '<' ) ) {
58
  $plugin_data = get_plugin_data( __FILE__, false );
118
 
119
  // Add actions.
120
  add_action( 'admin_menu', 'my_calendar_menu' );
121
+ add_action( 'wp_head', 'mc_head' );
122
  add_action( 'delete_user', 'mc_deal_with_deleted_user' );
123
  add_action( 'widgets_init', 'mc_register_widgets' );
124
+ add_action( 'init', 'mc_add_feed' );
125
  add_action( 'wp_footer', 'mc_footer_js' );
126
  add_action( 'init', 'mc_export_vcal', 200 );
127
  // Add filters.
372
  }
373
  }
374
  if ( function_exists( 'add_submenu_page' ) ) {
375
+ add_action( 'admin_head', 'mc_write_js' );
376
+ add_action( 'admin_enqueue_scripts', 'mc_add_styles' );
377
  if ( 'true' === get_option( 'mc_remote' ) && function_exists( 'mc_remote_db' ) ) {
378
  // If we're accessing a remote site, remove these pages.
379
  } else {
readme.txt CHANGED
@@ -3,9 +3,9 @@ Contributors: joedolson
3
  Donate link: http://www.joedolson.com/donate/
4
  Tags: calendar, dates, times, event, events, scheduling, schedule, event manager, event calendar, class, concert, venue, location, box office, tickets, registration
5
  Requires at least: 4.4
6
- Tested up to: 5.3
7
- Requires PHP: 5.3
8
- Stable tag: 3.1.18
9
  Text domain: my-calendar
10
  License: GPLv2 or later
11
 
@@ -83,6 +83,38 @@ Translating my plug-ins is always appreciated. Visit <a href="https://translate.
83
 
84
  == Changelog ==
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  = 3.1.18 =
87
 
88
  * Add filters to 'Add to Google Calendar' link: mc_gcal_location & mc_gcal_description
@@ -213,194 +245,6 @@ Translating my plug-ins is always appreciated. Visit <a href="https://translate.
213
  * Bug fix: Category relationships not retained when Group editing applied.
214
  * Bug fix: aria-describedby ID mismatch.
215
 
216
- = 3.0.19 =
217
-
218
- * Bug fix: Fatal error in export API when location object included.
219
- * BUg fix: my calendar categories queried private categories instead of public.
220
-
221
- = 3.0.18 =
222
-
223
- * Bug fix: Invalid setting in bottom nav defaults.
224
- * Bug fix: Generate feeds by date added rather than fixed number. If empty, get most recent regardless.
225
- * Bug fix: Legitimate HTML escaped in visual editor in group event editor.
226
-
227
- = 3.0.17 =
228
-
229
- * Bug fix: Group event editing was broken.
230
- * Bug fix: Eliminate four PHP notices in the Today's Events widget.
231
- * Added: Filter to control whether CSS should be loaded on archives.
232
-
233
- = 3.0.16 =
234
-
235
- * Changed display UID to avoid duplicate IDs when multiple calendars shown.
236
- * Add option to display heading in details pop-up.
237
- * Unify position and size of close button in Twentyeighteen mini calendar.
238
- * Eliminate multi category parameter from CSV output (doesn't support multidimensional data)
239
- * Add GUID to export data.
240
-
241
- = 3.0.15 =
242
-
243
- * Bug fix: prevent some PHP notices when running Pro importer.
244
- * Bug fix: Display of multidate time string when crossing months or years.
245
- * Bug fix: Variable written as constant prevented event_span from saving correctly.
246
- * Bug fix: Trash counter updated with incorrect values.
247
- * Bug fix: Two cases where status counter not updated.
248
- * Change: Add DB version to debugging info
249
-
250
- = 3.0.14 =
251
-
252
- * Bug fix: incorrect value passed for instance parameter on single event shortcode.
253
- * Bug fix: hide HTML wrapper for category color when colors disabled.
254
- * Bug fix: Remove transparent background in Twenty eighteen; blocks category colors
255
- * Bug fix: Invalid ordering parameter for location lists
256
- * Feature: Ability to select multiple categories (props Josef Fällman)
257
- * Moved changelogs for 2.5 & earlier to changelog.txt
258
-
259
- = 3.0.13 =
260
-
261
- * Bug fix: missing function call when accessing custom mini templates
262
- * Bug fix: Syntax error in SQL query checking for conflicts
263
- * Change: pass short description to Akismet if long desc absent
264
-
265
- = 3.0.12 =
266
-
267
- * Bug fix: My Calendar could prevent canonical link from displaying if canonical link being filtered by another application.
268
- * Modernize & improve Akismet integration.
269
- * Add filter to disable Akismet checks.
270
-
271
- = 3.0.11 =
272
-
273
- * SECURITY: XSS - Canonical URL not properly sanitized. Affects 3.0.0 and up.
274
-
275
- = 3.0.10 =
276
-
277
- * Bug fix: invalid method used to sort location lists.
278
- * Bug fix: shortcode generator missing input value
279
- * Bug fix: datepicker did not reflect start of week settings
280
- * Stylesheet CSS change
281
-
282
- = 3.0.9 =
283
-
284
- * Bug fix: Error thrown if Akismet had previously been configured, then deleted.
285
- * Bug fix: location type was added to params if category key was set.
286
- * Bug fix: remove a couple notices
287
- * Bug fix: category relationships not carried over when recurring events split
288
-
289
- = 3.0.8 =
290
-
291
- * Bug fix: need to allow <a> elements in mc_strip_tags so calendar linkscan point to non-calendar URLs
292
-
293
- = 3.0.7 =
294
-
295
- * Bug fix: Case where events ending at midnight (AM) of current day were displayed
296
- * Bug fix: trim spaces from values earlier when parsing filter elements
297
- * Change: don't declare font-family in older stylesheets.
298
-
299
- = 3.0.6 =
300
-
301
- * Bug fix: Shortcode for locations forms always rendered as if in a group filter.
302
- * Bug fix: If the default length 1 hr event pushes into next day, adjust length.
303
- * Bug fix: Incorrectly nested parentheses caused math error in months-by-day recurrence
304
-
305
- = 3.0.5 =
306
-
307
- * Bug fix: If only one event on a day, event title did not show in list view with show title option.
308
- * Bug fix: Incorrect array key for fallback parameter in widget
309
- * Bug fix: custom template query expected 25 chars instead of 32
310
- * Re-allow <br> in event titles.
311
-
312
- = 3.0.4 =
313
-
314
- * Bug fix: aria-current test was broken for current date
315
- * Bug fix: Private categories not disambiguated in MySQL query when excluded
316
- * Improve: Rewrite my_calendar_copyr backup functions to use WP core functions.
317
-
318
- = 3.0.3 =
319
-
320
- * Bug fix: Category key needed to use a 'WHERE' not an 'AND'; broke output if limiting by category
321
- * Bug fix: Error thrown in style editor & category editor if custom directory did not exist
322
-
323
- = 3.0.2 =
324
-
325
- * 3.0.1 did not correct the right error. Correct fix.
326
-
327
- = 3.0.1 =
328
-
329
- * Bug fix: install error on update.
330
-
331
- = 3.0.0 =
332
-
333
- * Bug fix: If category deleted, set events with that category to default cat, not cat ID 1.
334
- * Bug fix: Date/time comparison used front-end date value instead of dtstamp in upcoming events.
335
- * Bug fix: Navigation issue if beginning of week is in previous month
336
- * Bug fix: Event conflict didn't catch events 100% contained inside other events.
337
- * Bug fix: Private categories should not be visible to public users in submission forms or category lists
338
- * Bug fix: aria-current key term value was translatable
339
- * Bug fix: If editing single instance, location is removed
340
- * Bug fix: don't show location control notices on front-end
341
- * Bug fix: correcting event recurrence did not always remove meta flag
342
- * Bug fix: Only output map HTML if API key provided
343
- * Bug fix: character set and collation determination on install & update
344
- * Bug fix: When changing recurring events, only change instance IDs if the date of the instance has changed.
345
- * Bug fix: Event post should not change post date on update
346
- * Bug fix: All day events should export correctly to Outlook & Apple Calendar
347
- * Bug fix: Location control accordion was not accessible.
348
- * Bug fix: Term ID was not set in category manager if term already existed.
349
- * Bug fix: Make sure that the 's' query var is not automatically added to My Calendar URLs
350
-
351
- * Add: several new filters
352
- * Add: notice to alert users if their calendar configured for remote event source.
353
- * Add: map display to back-end location manager.
354
- * Add: location search in location manager
355
- * Add: ability to filter location lists used to submit data 'mc_get_locations'
356
- * Add: Support for multiple categories on events.
357
- * Add: stylesheet (Twenty Eighteen)
358
- * Add: CSS variables support
359
- * Add: list of problem events in Manage Events sidebar
360
- * Add: add months shown in list view to shortcode parameters
361
- * Add: support for auto-refresh of cache for a variety of caching plug-ins.
362
- * Add: Option to remove event data on uninstall
363
- * Add: filter to define events as private via custom methods
364
- * Add: event preview
365
- * Add: location support to mini calendar widget
366
- * Add: CSS code editor available in Style editing
367
- * Add: HTML code editor available in Template editing
368
- * Add: Schema.org address markup
369
- * Add: Schema.org event markup
370
- * Add: Include event link in 'Add to Google Cal' content.
371
- * Add: date format for multi-day dates in grid view.
372
-
373
- * Removed: event open & event closed text settings
374
- * Removed: event_open event status (little used and confusing; replaced by My Tickets)
375
- * Removed: guessing calendar install location
376
- * Removed: event cache code
377
- * Removed: upgrade routines from 1.11.x
378
- * Removed: mc_widget_defaults option
379
- * Removed: user's guide references
380
-
381
- * Change: default image sizes from 'medium' to 'large'
382
- * Change: Remove ability to disable event approval; remap "approval" to "draft"
383
- * Change: default number of results to show in advanced event search.
384
- * Change: Switched from image to icon font for close button
385
- * Change: Major changes to event fetching
386
- * Change: Major changes to code organization
387
- * Change: Added caching on database engine query
388
- * Change: if event location set in dropdown, event will always display location as shown in location manager
389
- * Change: changed argument style for major functions to arrays of arguments
390
- * Change: move Location Manager to separate page; add location sorting.
391
- * Change: Move exif_ fallback function into utilities include
392
- * Change: Moved location & category specific settings
393
- * Change: Simplified texts in several locations
394
- * Change: Clearer UI on location input limits
395
- * Change: autotoggle end date minimum input when start date set
396
- * Change: Reorganized input fields
397
- * Change: Generate separate iCal exports for Google Calendar or Outlook
398
- * Change: Constrain tabbing within details pop-up
399
- * Change: Close details pop-up with Esc key
400
- * Change: Audited options to remove unused or unneeded options
401
- * Change: Create a referential template when shortcode generated
402
- * Change: Feeds nav panel now shows subscription links; exports are available in 'exports' panel.
403
-
404
  = Future Changes =
405
 
406
  * Refactor options storage
@@ -441,4 +285,4 @@ The search feature in My Calendar is pretty basic; but [buying My Calendar Pro](
441
 
442
  == Upgrade Notice ==
443
 
444
- * 3.1.10 IMPORTANT SECURITY UPDATE: XSS Scripting Vulnerability
3
  Donate link: http://www.joedolson.com/donate/
4
  Tags: calendar, dates, times, event, events, scheduling, schedule, event manager, event calendar, class, concert, venue, location, box office, tickets, registration
5
  Requires at least: 4.4
6
+ Tested up to: 5.4
7
+ Requires PHP: 5.6
8
+ Stable tag: 3.2.0
9
  Text domain: my-calendar
10
  License: GPLv2 or later
11
 
83
 
84
  == Changelog ==
85
 
86
+ = 3.2.0 =
87
+
88
+ * Auto-toggle admin time format if display time format set to European format.
89
+ * Show API endpoint when API enabled.
90
+ * Add alternate alias for API endpoint.
91
+ * Add style variables with category colors to style output.
92
+ * Add color output icon with CSS variables in style editor.
93
+ * Add new default stylesheet: Twentytwenty.css
94
+ * Move permalink setting to general settings panel.
95
+ * Change event timestamps to use a real UTC timestamp for reference.
96
+ * Switch from using date() to gmdate().
97
+ * Update Pickadate to 3.6.4. Resolves some bugs, but introduces an accessibility issue.
98
+ * Customizations to Pickadate 3.6.4 to repair accessibility
99
+ * don't move focus to picker
100
+ * add 'close' button to time picker.
101
+ * Switch Pickadate to classic theme (modified).
102
+ * Improvements to output code layout.
103
+ * Eliminate empty HTML wrappers in content.
104
+ * New filter: mc_get_users. Use custom arguments to get users.
105
+ * New filters: mc_header_navigation, mc_footer_navigation
106
+ * New template tags: {userstart}, {userend} - date/time in local users timezone.
107
+ * Bug fix: Misc. ARIA/id relationships broken.
108
+ * Bug fix: remote locations sometimes pulled from local database.
109
+ * Bug fix: Long-standing issues in user input settings.
110
+ * Bug fix: Don't duplicate .summary values.
111
+ * Bug fix: Only render one close button in mini calendar.
112
+ * Collapse 'View Calendar' and 'Add Event' adminbar menus into a single menu.
113
+ * Remove upgrade path from 2.2.10.
114
+ * Remove .mc-event-visible from style output. Unused since 2011.
115
+ * Remove numerous deprecated functions.
116
+ * Conformance with latest WordPress PHPCS ruleset.
117
+
118
  = 3.1.18 =
119
 
120
  * Add filters to 'Add to Google Calendar' link: mc_gcal_location & mc_gcal_description
245
  * Bug fix: Category relationships not retained when Group editing applied.
246
  * Bug fix: aria-describedby ID mismatch.
247
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  = Future Changes =
249
 
250
  * Refactor options storage
285
 
286
  == Upgrade Notice ==
287
 
288
+ * 3.2.0 Major release to conform with new WordPress PHP standards.
styles/twentytwenty.css ADDED
@@ -0,0 +1,687 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .my-calendar-header *, .mc_bottomnav *, .mc-main * {
2
+ line-height: 1.62;
3
+ }
4
+
5
+ .mc-main .my-calendar-header, .mc-main .mc_bottomnav {
6
+ padding: 0;
7
+ }
8
+
9
+ .mc-main a {
10
+ border-bottom: none;
11
+ display: inline;
12
+ }
13
+
14
+ .mc-main .details ul, .mc-main .details ol, .mc-main details li {
15
+ margin: .25em 0 .5em 3em;
16
+ }
17
+
18
+ .my-calendar-header > div, .mc_bottomnav > div {
19
+ display: inline-block;
20
+ }
21
+
22
+ .mc-main .maybe-hide {
23
+ border: 0;
24
+ clip: rect(1px, 1px, 1px, 1px);
25
+ clip-path: inset(50%);
26
+ height: 1px;
27
+ margin: -1px;
28
+ overflow: hidden;
29
+ padding: 0;
30
+ position: absolute !important;
31
+ width: 1px;
32
+ word-wrap: normal !important;
33
+ color: inherit;
34
+ }
35
+
36
+ .my-calendar-header > div:nth-of-type(1), .mc_bottomnav > div:nth-of-type(1) {
37
+ margin-left: 0;
38
+ }
39
+
40
+ .my-calendar-header > div:nth-of-type(last), .mc_bottomnav > div:nth-of-type(last) {
41
+ margin-right: 0;
42
+ }
43
+
44
+ .mc-main .my-calendar-header span, .mc-main .my-calendar-header a,
45
+ .mc-main .mc_bottomnav span, .mc-main .mc_bottomnav a,
46
+ .mc-main .my-calendar-header select, .mc-main .my-calendar-header input,
47
+ .mc-main .mc_bottomnav select, .mc-main .mc_bottomnav input,
48
+ .mc-main .my-calendar-header input[type=submit], .mc-main .mc_bottomnav input[type=submit] {
49
+ padding: 4px 6px !important;
50
+ font-size: 16px;
51
+ line-height: 1.5;
52
+ font-weight: 400;
53
+ text-decoration: none;
54
+ }
55
+
56
+ .mc-main .my-calendar-header select,
57
+ .mc-main .mc_bottmnav select {
58
+ padding: 2px 6px !important;
59
+ }
60
+
61
+ .mc-main span.category-color-sample {
62
+ border: none !important;
63
+ box-shadow: none !important;
64
+ }
65
+
66
+ .mc-main .my-calendar-header input:hover, .mc-main .my-calendar-header input:focus,
67
+ .mc-main .my-calendar-header a:hover, .mc-main .mc_bottomnav a:hover,
68
+ .mc-main .my-calendar-header a:focus, .mc-main .mc_bottomnav a:focus {
69
+ text-decoration: underline;
70
+ }
71
+
72
+ .mc-main.calendar, .mc-main table {
73
+ width: 100% !important;
74
+ }
75
+
76
+ .mc-main table {
77
+ width: 100%;
78
+ position: relative;
79
+ border-collapse: collapse;
80
+ table-layout: fixed;
81
+ }
82
+
83
+ .mc-main caption, .mc-main.list .my-calendar-month, .mc-main .heading {
84
+ font-size: 20px;
85
+ color: #313233;
86
+ color: var(--primary-dark);
87
+ text-align: right;
88
+ margin: 0;
89
+ }
90
+
91
+ .mc-main.mini caption {
92
+ font-size: 16px;
93
+ }
94
+
95
+ .mc-main th {
96
+ font-size: 16px;
97
+ line-height: 1.5;
98
+ text-align: center;
99
+ padding: 4px 0;
100
+ background: #fff !important;
101
+ background: var(--primary-light) !important;
102
+ color: #313233 !important;
103
+ color: var(--primary-dark) !important;
104
+ border-bottom: 1px solid var(--primary-dark);
105
+ }
106
+
107
+ .mc-main th abbr, .mc-main .event-time abbr {
108
+ border-bottom: none;
109
+ text-decoration: none;
110
+ }
111
+
112
+ .mc-main td {
113
+ border: 1px solid #efefef;
114
+ border: 1px solid var(--highlight-light);
115
+ padding: 0 !important;
116
+ height: 6em;
117
+ }
118
+
119
+ .mc-main.mini td {
120
+ height: auto;
121
+ }
122
+
123
+ .mc-main td .event-title {
124
+ font-size: 12px;
125
+ }
126
+
127
+ .mc-main {
128
+ position: relative;
129
+ }
130
+
131
+ .mc-main .event-title {
132
+ margin: 0 !important;
133
+ font-size: 24px;
134
+ text-transform: none;
135
+ letter-spacing: normal;
136
+ }
137
+
138
+ .mc-main .event-title a {
139
+ display: block;
140
+ line-height: 1.5;
141
+ padding: 4px 6px;
142
+ position: relative;
143
+ border-bottom: none;
144
+ box-shadow: none;
145
+ }
146
+
147
+ .my-calendar-prev a:before,
148
+ .my-calendar-next a:after,
149
+ .mc-export a:before,
150
+ .mc-main .time-block:before,
151
+ .mc-main .sharing .ical a:before,
152
+ .mc-main .sharing .gcal a:before,
153
+ .mc-main .sharing .mc_details a:before,
154
+ .mc-main .mc-format a:before,
155
+ .mc-main .mc-format span:before,
156
+ .mc-main .mc-print a:before,
157
+ .mc-main .mc-list .event-date button:nth-of-type(1):before {
158
+ font-family: 'dashicons';
159
+ vertical-align: middle;
160
+ position: relative;
161
+ top: -2px;
162
+ margin-right: 2px;
163
+ }
164
+
165
+ .mc-main .event-title .has-image {
166
+ padding-left: 24px;
167
+ }
168
+
169
+ .mc-main.mini .event-title {
170
+ padding: 10px 30px 10px 5px;
171
+ }
172
+
173
+ .mc-main.mini .has-events .active-toggle {
174
+ background: #efefef;
175
+ background: var(--highlight-light);
176
+ color: #000;
177
+ color: var(--secondary-dark);
178
+ }
179
+
180
+ .mc-main.mini .event-title img {
181
+ position: relative;
182
+ margin-right: 4px;
183
+ top: 0;
184
+ left: 0;
185
+ }
186
+
187
+ .mc-main .mc-print a:before {
188
+ content: "\f497";
189
+ }
190
+
191
+ .mc-main .mc-format .list:before {
192
+ content: "\f163";
193
+ }
194
+
195
+ .mc-main .mc-format .grid:before {
196
+ content: "\f508";
197
+ }
198
+
199
+ .mc-main .event-title img, .mc-main .category-color-sample img {
200
+ position: absolute;
201
+ top: 6px;
202
+ left: 4px;
203
+ box-shadow: none;
204
+ background: transparent;
205
+ display: inline;
206
+ vertical-align: middle;
207
+ }
208
+
209
+ .mc-main .category-key .category-color-sample {
210
+ padding: 4px 4px 4px 0;
211
+ }
212
+
213
+ .mc-main .category-color-sample img {
214
+ position: static;
215
+ top: 0;
216
+ left: 0;
217
+ }
218
+
219
+ .mc-main .calendar-event .details, .mc-main .calendar-events {
220
+ position: absolute;
221
+ left: 3%;
222
+ width: 94%;
223
+ z-index: 3;
224
+ background: #fff;
225
+ background: var(--primary-light);
226
+ box-shadow: 0 0 4px;
227
+ color: #333;
228
+ color: var(--primary-dark);
229
+ }
230
+
231
+ .mc-main .calendar-events {
232
+ width: 110%;
233
+ left: -5%;
234
+ }
235
+
236
+ .mc-main .vevent {
237
+ word-break: normal;
238
+ }
239
+
240
+ .mc-main .calendar-events .vevent:nth-of-type(1n+1) {
241
+ border-top: 1px solid var(--highlight-dark);
242
+ }
243
+
244
+ .mc-main .details {
245
+ padding: 10px 40px;
246
+ }
247
+
248
+ .mc-main .single-event .details {
249
+ padding: 0;
250
+ }
251
+
252
+ .mc-main.mini .details {
253
+ padding: 16px;
254
+ border-top: 1px solid #666;
255
+ border-top: 1px solid var(--highlight-dark);
256
+ }
257
+
258
+ .mc-main .list-event .details {
259
+ padding: 0;
260
+ }
261
+
262
+ .mc-main .list-event .event-title {
263
+ padding: .25em;
264
+ border-radius: 0 10px 10px 0;
265
+ }
266
+
267
+ .mc-main .mc-list {
268
+ border-top: 1px solid var(--highlight-light);
269
+ border-left: 1px solid var(--highlight-light);
270
+ }
271
+
272
+ .mc-main .mc-list .event-date button {
273
+ display: inline-block;
274
+ width: auto;
275
+ text-align: left;
276
+ background-color: transparent;
277
+ color: #000;
278
+ color: var(--primary-dark);
279
+ }
280
+
281
+ .mc-main .mc-list .event-date button:hover,
282
+ .mc-main .mc-list .event-date button:focus {
283
+ background: transparent;
284
+ }
285
+
286
+ .mc-main .mc-list .event-date button:nth-of-type(1):before {
287
+ content: "\f132";
288
+ top: 0;
289
+ margin-right: 3px;
290
+ }
291
+
292
+ .mc-main .mc-list .details > div {
293
+ padding: 0 .5em;
294
+ }
295
+
296
+ .mc-main .close img {
297
+ width: auto !important;
298
+ height: auto !important;
299
+ padding: 2px 2px 0;
300
+ }
301
+
302
+ .mc-main button.close {
303
+ position: absolute;
304
+ left: 0px;
305
+ top: 0px;
306
+ padding: 10px !important;
307
+ background: rgba( 200, 200, 200, .1 );
308
+ border-radius: 20px;
309
+ }
310
+
311
+ .mc-main button.close, .mc-main button.close * {
312
+ padding: 0;
313
+ line-height: 1;
314
+ background: #fff;
315
+ border-radius: 10px;
316
+ opacity: 1;
317
+ }
318
+
319
+ .mc-main.mini .close {
320
+ left: auto;
321
+ right: 0;
322
+ font-size: 18px;
323
+ }
324
+
325
+ .mc-main .close:hover, .mc-main .close:focus {
326
+ background: #fff;
327
+ background: var(--primary-light);
328
+ }
329
+
330
+ .mc-main .details .category-icon {
331
+ width: auto;
332
+ }
333
+
334
+ .mc-main .details img.alignleft {
335
+ width: auto;
336
+ float: left;
337
+ margin: 0 20px 10px 0;
338
+ }
339
+
340
+ .mc-main .details img.alignright {
341
+ width: auto;
342
+ float: left;
343
+ margin: 0 0 10px 20px;
344
+ }
345
+
346
+ .mc-main .details img.aligncenter {
347
+ width: auto;
348
+ display: block;
349
+ margin: 0 auto 10px;
350
+ }
351
+
352
+ .mc-main .details p {
353
+ margin: 0 0 20px;
354
+ }
355
+
356
+ /* Date/times */
357
+ .mc-main .time-block {
358
+ float: right;
359
+ }
360
+
361
+ .mc-main.mini .time-block {
362
+ float: none;
363
+ font-size: 14px;
364
+ }
365
+
366
+ .mc-main .time-block p {
367
+ color: #000;
368
+ color: var(--secondary-dark);
369
+ display: inline-block;
370
+ margin: 0 !important;
371
+ background: #fff;
372
+ background: var(--primary-light);
373
+ padding: 0 .25em !important;
374
+ }
375
+
376
+ .mc-main .time-block:before {
377
+ content: "\f469";
378
+ vertical-align: top;
379
+ margin-right: 4px;
380
+ }
381
+
382
+ .mc-main .time-block .mc-event-date {
383
+ display: block;
384
+ }
385
+
386
+ .mc-main .mc-event-date {
387
+ font-weight: 700;
388
+ color: #333;
389
+ color: var(--primary-dark);
390
+ }
391
+
392
+ .mc-main .mc-date {
393
+ display: block;
394
+ padding: 0 8px;
395
+ font-size: 16px;
396
+ text-align: right;
397
+ }
398
+
399
+ .mc-main.mini .mc-date {
400
+ text-align: center;
401
+ padding: 0;
402
+ font-size: 14px;
403
+ }
404
+
405
+ .mc-main.mini .has-events.current-day a.mc-date {
406
+ color: #000;
407
+ color: var(--primary-dark);
408
+ background: #eee;
409
+ background: var(--highlight-light);
410
+ border-top: 0px solid;
411
+ }
412
+
413
+ .mc-main.mini .has-events.current-day a.mc-date:hover,
414
+ .mc-main.mini .has-events.current-day a.mc-date:focus {
415
+ background: #000;
416
+ background: var(--primary-dark);
417
+ color: #eee;
418
+ color: var(--highlight-light);
419
+ }
420
+
421
+ .mc-main .nextmonth {
422
+ background: rgba( 200,200,200,.1 );
423
+ }
424
+
425
+ .mc-main .nextmonth .mc-date {
426
+ background: transparent;
427
+ }
428
+
429
+ .mc-main .has-events .mc-date {
430
+ font-weight: 700;
431
+ background: #333;
432
+ background: var(--primary-dark);
433
+ color: #fff;
434
+ color: var(--primary-light);
435
+ }
436
+
437
+ .mc-main .current-day {
438
+ border-top: 1px solid #313233;
439
+ border-top: 1px solid var(--highlight-dark);
440
+ background: linear-gradient(to bottom, #fff 0%, var(--secondary-light) 30%, var(--highlight-light) 100%)
441
+ }
442
+
443
+ .mc-main .current-day .mc-date {
444
+ border-top: 1px solid #313233;
445
+ border-top: 1px solid var(--highlight-dark);
446
+ }
447
+
448
+ .mc-main .has-events a.mc-date {
449
+ color: #fff;
450
+ color: var(--primary-light);
451
+ background: #333;
452
+ background: var(--primary-dark);
453
+ }
454
+
455
+ .mc-main .has-events a.mc-date:hover,
456
+ .mc-main .has-events a.mc-date:focus {
457
+ color: #333;
458
+ color: var(--primary-dark);
459
+ background: #fff;
460
+ background: var(--primary-light);
461
+ }
462
+
463
+ .mc-main .mc-single {
464
+ font-size: 24px;
465
+ margin: 0 0 .5em;
466
+ }
467
+
468
+ /* Navigation */
469
+ .my-calendar-nav ul, .mc-main .category-key ul, .mc-main .mc-export ul, .mc-main .mc-list {
470
+ margin: 0 !important;
471
+ padding: 0 !important;
472
+ }
473
+
474
+ .my-calendar-nav ul li, .mc-main .category-key ul li, .mc-main .mc-export ul li {
475
+ display: inline-block;
476
+ list-style-type: none;
477
+ margin: 0 0 6px;
478
+ }
479
+
480
+ .my-calendar-nav .my-calendar-prev a {
481
+ border-right: 1px solid #bbb;
482
+ }
483
+
484
+ .my-calendar-nav .my-calendar-next a {
485
+ border-left: 1px solid #fff;
486
+ }
487
+
488
+ .mc-main .mc-time .month {
489
+ border-right: 1px solid #bbb;
490
+ }
491
+
492
+ .mc-main .mc-time .week {
493
+ border-right: 1px solid #bbb;
494
+ }
495
+
496
+ .mc-export a:before {
497
+ margin-right: 3px;
498
+ }
499
+
500
+ .mc-export .rss a:before {
501
+ content: '\f303';
502
+ }
503
+
504
+ .mc-export .ics a:before {
505
+ content: '\f508';
506
+ }
507
+
508
+ .mc-download .google a:before,
509
+ .mc-download .outlook a:before {
510
+ content: "\f316";
511
+ }
512
+
513
+ .my-calendar-prev a:before {
514
+ content: '\f341';
515
+ }
516
+
517
+ .my-calendar-next a:after {
518
+ content: '\f345';
519
+ margin-left: 3px;
520
+ }
521
+
522
+ /* Category Key */
523
+ .mc-main .category-key h3 {
524
+ margin: 0 0 10px 0 !important;
525
+ }
526
+
527
+ .mc-main .category-key li.current a {
528
+ border: 1px solid #000;
529
+ background: #fff;
530
+ }
531
+
532
+ .mc-main .my-calendar-header .no-icon,
533
+ .mc-main .mc_bottomnav .no-icon {
534
+ display: inline-block;
535
+ width: 16px;
536
+ height: 16px;
537
+ vertical-align: middle;
538
+ margin: 0 .25em;
539
+ border-radius: 16px;
540
+ position: relative;
541
+ top: -2px;
542
+ border: 1px solid #fff;
543
+ }
544
+
545
+ /* hCard */
546
+ .mc-main .location {
547
+ clear: right;
548
+ }
549
+
550
+ .mc-main .vcard {
551
+ margin: 0 0 1em 1em;
552
+ float: right;
553
+ padding: 10px;
554
+ width: 250px;
555
+ max-width: 50%;
556
+ font-size: 14px;
557
+ background: rgba( 0, 0, 0, .05 );
558
+ }
559
+
560
+ .mc-main.mini .vcard {
561
+ margin: 15px 0;
562
+ float: none;
563
+ width: 100%;
564
+ max-width: 100%;
565
+ }
566
+
567
+ .mc-main .vcard .street-address {
568
+ display: inline;
569
+ }
570
+
571
+ .mc-main .vcard .street-address:nth-of-type(2):before {
572
+ content: ', ';
573
+ }
574
+
575
+ /* Jumpbox */
576
+ .mc-main .my-calendar-date-switcher select {
577
+ width: auto;
578
+ margin: 0;
579
+ height: auto;
580
+ }
581
+
582
+ .mc-main .my-calendar-date-switcher input[type=submit] {
583
+ min-width: 2em;
584
+ width: auto;
585
+ }
586
+
587
+ /* List View */
588
+ .mc-main .mc-list li, #mc-day {
589
+ position: relative;
590
+ }
591
+
592
+ .mc-main li.current-day {
593
+ border-left: 5px solid;
594
+ }
595
+
596
+ .mc-main li.current-day button:nth-of-type(1) {
597
+ position: relative;
598
+ left: -5px;
599
+ }
600
+
601
+ .mc-main .mc-list .mc-events {
602
+ list-style-type: none !important;
603
+ padding: 10px;
604
+ background: rgba(0, 0, 0, .05);
605
+ margin: 0;
606
+ }
607
+
608
+ .mc-main .mc-list .mc-events.odd {
609
+ padding: 10px;
610
+ background: none;
611
+ }
612
+
613
+ .mc-main .list-event .event-title {
614
+ margin: 0 0 1em!important;
615
+ display: inline-block;
616
+ }
617
+
618
+ .mc-main .details .sharing {
619
+ clear: both;
620
+ }
621
+
622
+ .mc-main .sharing p {
623
+ display: inline-block;
624
+ padding: .5em .5em .5em 0;
625
+ }
626
+
627
+ .mc-main.mini .sharing p {
628
+ font-size: 14px;
629
+ padding: 0 .25em 0 0;
630
+ margin-bottom: 10px;
631
+ }
632
+
633
+ .mc-main .sharing .ical a:before, .mc-main .sharing .gcal a:before {
634
+ content: "\f502";
635
+ }
636
+
637
+ .mc-main .sharing .mc_details a:before {
638
+ content: "\f242";
639
+ }
640
+
641
+ .mc-main .mc-list .event-date {
642
+ font-size: 16px;
643
+ font-weight: 600;
644
+ }
645
+
646
+ .mc-main .list-event {
647
+ border-top: 1px solid #d1d1d1;
648
+ margin: .5em -10px;
649
+ }
650
+
651
+ .mc-main .day .list-event, .mc-main .day .details {
652
+ padding: 0;
653
+ margin: 0;
654
+ }
655
+
656
+ .mc-main .mc-list-extended {
657
+ font-size: 14px;
658
+ font-style: italic;
659
+ }
660
+
661
+ .mc-main .details .mc-image {
662
+ max-width: 100%;
663
+ height: auto;
664
+ }
665
+
666
+ .mc-main .list-event .event-title img {
667
+ margin-right: .5em;
668
+ position: relative;
669
+ top: -1px;
670
+ }
671
+
672
+ /* Single view */
673
+ .single-event .event-title {
674
+ padding: .5em;
675
+ font-size: inherit;
676
+ }
677
+
678
+ .single-event .event-title img {
679
+ margin-right: 10px;
680
+ position: static;
681
+ }
682
+
683
+ .mc-list-details.all-events {
684
+ text-align: left;
685
+ display: inline-block;
686
+ text-transform: none;
687
+ }
templates/twentytwenty.css ADDED
@@ -0,0 +1,687 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .my-calendar-header *, .mc_bottomnav *, .mc-main * {
2
+ line-height: 1.62;
3
+ }
4
+
5
+ .mc-main .my-calendar-header, .mc-main .mc_bottomnav {
6
+ padding: 0;
7
+ }
8
+
9
+ .mc-main a {
10
+ border-bottom: none;
11
+ display: inline;
12
+ }
13
+
14
+ .mc-main .details ul, .mc-main .details ol, .mc-main details li {
15
+ margin: .25em 0 .5em 3em;
16
+ }
17
+
18
+ .my-calendar-header > div, .mc_bottomnav > div {
19
+ display: inline-block;
20
+ }
21
+
22
+ .mc-main .maybe-hide {
23
+ border: 0;
24
+ clip: rect(1px, 1px, 1px, 1px);
25
+ clip-path: inset(50%);
26
+ height: 1px;
27
+ margin: -1px;
28
+ overflow: hidden;
29
+ padding: 0;
30
+ position: absolute !important;
31
+ width: 1px;
32
+ word-wrap: normal !important;
33
+ color: inherit;
34
+ }
35
+
36
+ .my-calendar-header > div:nth-of-type(1), .mc_bottomnav > div:nth-of-type(1) {
37
+ margin-left: 0;
38
+ }
39
+
40
+ .my-calendar-header > div:nth-of-type(last), .mc_bottomnav > div:nth-of-type(last) {
41
+ margin-right: 0;
42
+ }
43
+
44
+ .mc-main .my-calendar-header span, .mc-main .my-calendar-header a,
45
+ .mc-main .mc_bottomnav span, .mc-main .mc_bottomnav a,
46
+ .mc-main .my-calendar-header select, .mc-main .my-calendar-header input,
47
+ .mc-main .mc_bottomnav select, .mc-main .mc_bottomnav input,
48
+ .mc-main .my-calendar-header input[type=submit], .mc-main .mc_bottomnav input[type=submit] {
49
+ padding: 4px 6px !important;
50
+ font-size: 16px;
51
+ line-height: 1.5;
52
+ font-weight: 400;
53
+ text-decoration: none;
54
+ }
55
+
56
+ .mc-main .my-calendar-header select,
57
+ .mc-main .mc_bottmnav select {
58
+ padding: 2px 6px !important;
59
+ }
60
+
61
+ .mc-main span.category-color-sample {
62
+ border: none !important;
63
+ box-shadow: none !important;
64
+ }
65
+
66
+ .mc-main .my-calendar-header input:hover, .mc-main .my-calendar-header input:focus,
67
+ .mc-main .my-calendar-header a:hover, .mc-main .mc_bottomnav a:hover,
68
+ .mc-main .my-calendar-header a:focus, .mc-main .mc_bottomnav a:focus {
69
+ text-decoration: underline;
70
+ }
71
+
72
+ .mc-main.calendar, .mc-main table {
73
+ width: 100% !important;
74
+ }
75
+
76
+ .mc-main table {
77
+ width: 100%;
78
+ position: relative;
79
+ border-collapse: collapse;
80
+ table-layout: fixed;
81
+ }
82
+
83
+ .mc-main caption, .mc-main.list .my-calendar-month, .mc-main .heading {
84
+ font-size: 20px;
85
+ color: #313233;
86
+ color: var(--primary-dark);
87
+ text-align: right;
88
+ margin: 0;
89
+ }
90
+
91
+ .mc-main.mini caption {
92
+ font-size: 16px;
93
+ }
94
+
95
+ .mc-main th {
96
+ font-size: 16px;
97
+ line-height: 1.5;
98
+ text-align: center;
99
+ padding: 4px 0;
100
+ background: #fff !important;
101
+ background: var(--primary-light) !important;
102
+ color: #313233 !important;
103
+ color: var(--primary-dark) !important;
104
+ border-bottom: 1px solid var(--primary-dark);
105
+ }
106
+
107
+ .mc-main th abbr, .mc-main .event-time abbr {
108
+ border-bottom: none;
109
+ text-decoration: none;
110
+ }
111
+
112
+ .mc-main td {
113
+ border: 1px solid #efefef;
114
+ border: 1px solid var(--highlight-light);
115
+ padding: 0 !important;
116
+ height: 6em;
117
+ }
118
+
119
+ .mc-main.mini td {
120
+ height: auto;
121
+ }
122
+
123
+ .mc-main td .event-title {
124
+ font-size: 12px;
125
+ }
126
+
127
+ .mc-main {
128
+ position: relative;
129
+ }
130
+
131
+ .mc-main .event-title {
132
+ margin: 0 !important;
133
+ font-size: 24px;
134
+ text-transform: none;
135
+ letter-spacing: normal;
136
+ }
137
+
138
+ .mc-main .event-title a {
139
+ display: block;
140
+ line-height: 1.5;
141
+ padding: 4px 6px;
142
+ position: relative;
143
+ border-bottom: none;
144
+ box-shadow: none;
145
+ }
146
+
147
+ .my-calendar-prev a:before,
148
+ .my-calendar-next a:after,
149
+ .mc-export a:before,
150
+ .mc-main .time-block:before,
151
+ .mc-main .sharing .ical a:before,
152
+ .mc-main .sharing .gcal a:before,
153
+ .mc-main .sharing .mc_details a:before,
154
+ .mc-main .mc-format a:before,
155
+ .mc-main .mc-format span:before,
156
+ .mc-main .mc-print a:before,
157
+ .mc-main .mc-list .event-date button:nth-of-type(1):before {
158
+ font-family: 'dashicons';
159
+ vertical-align: middle;
160
+ position: relative;
161
+ top: -2px;
162
+ margin-right: 2px;
163
+ }
164
+
165
+ .mc-main .event-title .has-image {
166
+ padding-left: 24px;
167
+ }
168
+
169
+ .mc-main.mini .event-title {
170
+ padding: 10px 30px 10px 5px;
171
+ }
172
+
173
+ .mc-main.mini .has-events .active-toggle {
174
+ background: #efefef;
175
+ background: var(--highlight-light);
176
+ color: #000;
177
+ color: var(--secondary-dark);
178
+ }
179
+
180
+ .mc-main.mini .event-title img {
181
+ position: relative;
182
+ margin-right: 4px;
183
+ top: 0;
184
+ left: 0;
185
+ }
186
+
187
+ .mc-main .mc-print a:before {
188
+ content: "\f497";
189
+ }
190
+
191
+ .mc-main .mc-format .list:before {
192
+ content: "\f163";
193
+ }
194
+
195
+ .mc-main .mc-format .grid:before {
196
+ content: "\f508";
197
+ }
198
+
199
+ .mc-main .event-title img, .mc-main .category-color-sample img {
200
+ position: absolute;
201
+ top: 6px;
202
+ left: 4px;
203
+ box-shadow: none;
204
+ background: transparent;
205
+ display: inline;
206
+ vertical-align: middle;
207
+ }
208
+
209
+ .mc-main .category-key .category-color-sample {
210
+ padding: 4px 4px 4px 0;
211
+ }
212
+
213
+ .mc-main .category-color-sample img {
214
+ position: static;
215
+ top: 0;
216
+ left: 0;
217
+ }
218
+
219
+ .mc-main .calendar-event .details, .mc-main .calendar-events {
220
+ position: absolute;
221
+ left: 3%;
222
+ width: 94%;
223
+ z-index: 3;
224
+ background: #fff;
225
+ background: var(--primary-light);
226
+ box-shadow: 0 0 4px;
227
+ color: #333;
228
+ color: var(--primary-dark);
229
+ }
230
+
231
+ .mc-main .calendar-events {
232
+ width: 110%;
233
+ left: -5%;
234
+ }
235
+
236
+ .mc-main .vevent {
237
+ word-break: normal;
238
+ }
239
+
240
+ .mc-main .calendar-events .vevent:nth-of-type(1n+1) {
241
+ border-top: 1px solid var(--highlight-dark);
242
+ }
243
+
244
+ .mc-main .details {
245
+ padding: 10px 40px;
246
+ }
247
+
248
+ .mc-main .single-event .details {
249
+ padding: 0;
250
+ }
251
+
252
+ .mc-main.mini .details {
253
+ padding: 16px;
254
+ border-top: 1px solid #666;
255
+ border-top: 1px solid var(--highlight-dark);
256
+ }
257
+
258
+ .mc-main .list-event .details {
259
+ padding: 0;
260
+ }
261
+
262
+ .mc-main .list-event .event-title {
263
+ padding: .25em;
264
+ border-radius: 0 10px 10px 0;
265
+ }
266
+
267
+ .mc-main .mc-list {
268
+ border-top: 1px solid var(--highlight-light);
269
+ border-left: 1px solid var(--highlight-light);
270
+ }
271
+
272
+ .mc-main .mc-list .event-date button {
273
+ display: inline-block;
274
+ width: auto;
275
+ text-align: left;
276
+ background-color: transparent;
277
+ color: #000;
278
+ color: var(--primary-dark);
279
+ }
280
+
281
+ .mc-main .mc-list .event-date button:hover,
282
+ .mc-main .mc-list .event-date button:focus {
283
+ background: transparent;
284
+ }
285
+
286
+ .mc-main .mc-list .event-date button:nth-of-type(1):before {
287
+ content: "\f132";
288
+ top: 0;
289
+ margin-right: 3px;
290
+ }
291
+
292
+ .mc-main .mc-list .details > div {
293
+ padding: 0 .5em;
294
+ }
295
+
296
+ .mc-main .close img {
297
+ width: auto !important;
298
+ height: auto !important;
299
+ padding: 2px 2px 0;
300
+ }
301
+
302
+ .mc-main button.close {
303
+ position: absolute;
304
+ left: 0px;
305
+ top: 0px;
306
+ padding: 10px !important;
307
+ background: rgba( 200, 200, 200, .1 );
308
+ border-radius: 20px;
309
+ }
310
+
311
+ .mc-main button.close, .mc-main button.close * {
312
+ padding: 0;
313
+ line-height: 1;
314
+ background: #fff;
315
+ border-radius: 10px;
316
+ opacity: 1;
317
+ }
318
+
319
+ .mc-main.mini .close {
320
+ left: auto;
321
+ right: 0;
322
+ font-size: 18px;
323
+ }
324
+
325
+ .mc-main .close:hover, .mc-main .close:focus {
326
+ background: #fff;
327
+ background: var(--primary-light);
328
+ }
329
+
330
+ .mc-main .details .category-icon {
331
+ width: auto;
332
+ }
333
+
334
+ .mc-main .details img.alignleft {
335
+ width: auto;
336
+ float: left;
337
+ margin: 0 20px 10px 0;
338
+ }
339
+
340
+ .mc-main .details img.alignright {
341
+ width: auto;
342
+ float: left;
343
+ margin: 0 0 10px 20px;
344
+ }
345
+
346
+ .mc-main .details img.aligncenter {
347
+ width: auto;
348
+ display: block;
349
+ margin: 0 auto 10px;
350
+ }
351
+
352
+ .mc-main .details p {
353
+ margin: 0 0 20px;
354
+ }
355
+
356
+ /* Date/times */
357
+ .mc-main .time-block {
358
+ float: right;
359
+ }
360
+
361
+ .mc-main.mini .time-block {
362
+ float: none;
363
+ font-size: 14px;
364
+ }
365
+
366
+ .mc-main .time-block p {
367
+ color: #000;
368
+ color: var(--secondary-dark);
369
+ display: inline-block;
370
+ margin: 0 !important;
371
+ background: #fff;
372
+ background: var(--primary-light);
373
+ padding: 0 .25em !important;
374
+ }
375
+
376
+ .mc-main .time-block:before {
377
+ content: "\f469";
378
+ vertical-align: top;
379
+ margin-right: 4px;
380
+ }
381
+
382
+ .mc-main .time-block .mc-event-date {
383
+ display: block;
384
+ }
385
+
386
+ .mc-main .mc-event-date {
387
+ font-weight: 700;
388
+ color: #333;
389
+ color: var(--primary-dark);
390
+ }
391
+
392
+ .mc-main .mc-date {
393
+ display: block;
394
+ padding: 0 8px;
395
+ font-size: 16px;
396
+ text-align: right;
397
+ }
398
+
399
+ .mc-main.mini .mc-date {
400
+ text-align: center;
401
+ padding: 0;
402
+ font-size: 14px;
403
+ }
404
+
405
+ .mc-main.mini .has-events.current-day a.mc-date {
406
+ color: #000;
407
+ color: var(--primary-dark);
408
+ background: #eee;
409
+ background: var(--highlight-light);
410
+ border-top: 0px solid;
411
+ }
412
+
413
+ .mc-main.mini .has-events.current-day a.mc-date:hover,
414
+ .mc-main.mini .has-events.current-day a.mc-date:focus {
415
+ background: #000;
416
+ background: var(--primary-dark);
417
+ color: #eee;
418
+ color: var(--highlight-light);
419
+ }
420
+
421
+ .mc-main .nextmonth {
422
+ background: rgba( 200,200,200,.1 );
423
+ }
424
+
425
+ .mc-main .nextmonth .mc-date {
426
+ background: transparent;
427
+ }
428
+
429
+ .mc-main .has-events .mc-date {
430
+ font-weight: 700;
431
+ background: #333;
432
+ background: var(--primary-dark);
433
+ color: #fff;
434
+ color: var(--primary-light);
435
+ }
436
+
437
+ .mc-main .current-day {
438
+ border-top: 1px solid #313233;
439
+ border-top: 1px solid var(--highlight-dark);
440
+ background: linear-gradient(to bottom, #fff 0%, var(--secondary-light) 30%, var(--highlight-light) 100%)
441
+ }
442
+
443
+ .mc-main .current-day .mc-date {
444
+ border-top: 1px solid #313233;
445
+ border-top: 1px solid var(--highlight-dark);
446
+ }
447
+
448
+ .mc-main .has-events a.mc-date {
449
+ color: #fff;
450
+ color: var(--primary-light);
451
+ background: #333;
452
+ background: var(--primary-dark);
453
+ }
454
+
455
+ .mc-main .has-events a.mc-date:hover,
456
+ .mc-main .has-events a.mc-date:focus {
457
+ color: #333;
458
+ color: var(--primary-dark);
459
+ background: #fff;
460
+ background: var(--primary-light);
461
+ }
462
+
463
+ .mc-main .mc-single {
464
+ font-size: 24px;
465
+ margin: 0 0 .5em;
466
+ }
467
+
468
+ /* Navigation */
469
+ .my-calendar-nav ul, .mc-main .category-key ul, .mc-main .mc-export ul, .mc-main .mc-list {
470
+ margin: 0 !important;
471
+ padding: 0 !important;
472
+ }
473
+
474
+ .my-calendar-nav ul li, .mc-main .category-key ul li, .mc-main .mc-export ul li {
475
+ display: inline-block;
476
+ list-style-type: none;
477
+ margin: 0 0 6px;
478
+ }
479
+
480
+ .my-calendar-nav .my-calendar-prev a {
481
+ border-right: 1px solid #bbb;
482
+ }
483
+
484
+ .my-calendar-nav .my-calendar-next a {
485
+ border-left: 1px solid #fff;
486
+ }
487
+
488
+ .mc-main .mc-time .month {
489
+ border-right: 1px solid #bbb;
490
+ }
491
+
492
+ .mc-main .mc-time .week {
493
+ border-right: 1px solid #bbb;
494
+ }
495
+
496
+ .mc-export a:before {
497
+ margin-right: 3px;
498
+ }
499
+
500
+ .mc-export .rss a:before {
501
+ content: '\f303';
502
+ }
503
+
504
+ .mc-export .ics a:before {
505
+ content: '\f508';
506
+ }
507
+
508
+ .mc-download .google a:before,
509
+ .mc-download .outlook a:before {
510
+ content: "\f316";
511
+ }
512
+
513
+ .my-calendar-prev a:before {
514
+ content: '\f341';
515
+ }
516
+
517
+ .my-calendar-next a:after {
518
+ content: '\f345';
519
+ margin-left: 3px;
520
+ }
521
+
522
+ /* Category Key */
523
+ .mc-main .category-key h3 {
524
+ margin: 0 0 10px 0 !important;
525
+ }
526
+
527
+ .mc-main .category-key li.current a {
528
+ border: 1px solid #000;
529
+ background: #fff;
530
+ }
531
+
532
+ .mc-main .my-calendar-header .no-icon,
533
+ .mc-main .mc_bottomnav .no-icon {
534
+ display: inline-block;
535
+ width: 16px;
536
+ height: 16px;
537
+ vertical-align: middle;
538
+ margin: 0 .25em;
539
+ border-radius: 16px;
540
+ position: relative;
541
+ top: -2px;
542
+ border: 1px solid #fff;
543
+ }
544
+
545
+ /* hCard */
546
+ .mc-main .location {
547
+ clear: right;
548
+ }
549
+
550
+ .mc-main .vcard {
551
+ margin: 0 0 1em 1em;
552
+ float: right;
553
+ padding: 10px;
554
+ width: 250px;
555
+ max-width: 50%;
556
+ font-size: 14px;
557
+ background: rgba( 0, 0, 0, .05 );
558
+ }
559
+
560
+ .mc-main.mini .vcard {
561
+ margin: 15px 0;
562
+ float: none;
563
+ width: 100%;
564
+ max-width: 100%;
565
+ }
566
+
567
+ .mc-main .vcard .street-address {
568
+ display: inline;
569
+ }
570
+
571
+ .mc-main .vcard .street-address:nth-of-type(2):before {
572
+ content: ', ';
573
+ }
574
+
575
+ /* Jumpbox */
576
+ .mc-main .my-calendar-date-switcher select {
577
+ width: auto;
578
+ margin: 0;
579
+ height: auto;
580
+ }
581
+
582
+ .mc-main .my-calendar-date-switcher input[type=submit] {
583
+ min-width: 2em;
584
+ width: auto;
585
+ }
586
+
587
+ /* List View */
588
+ .mc-main .mc-list li, #mc-day {
589
+ position: relative;
590
+ }
591
+
592
+ .mc-main li.current-day {
593
+ border-left: 5px solid;
594
+ }
595
+
596
+ .mc-main li.current-day button:nth-of-type(1) {
597
+ position: relative;
598
+ left: -5px;
599
+ }
600
+
601
+ .mc-main .mc-list .mc-events {
602
+ list-style-type: none !important;
603
+ padding: 10px;
604
+ background: rgba(0, 0, 0, .05);
605
+ margin: 0;
606
+ }
607
+
608
+ .mc-main .mc-list .mc-events.odd {
609
+ padding: 10px;
610
+ background: none;
611
+ }
612
+
613
+ .mc-main .list-event .event-title {
614
+ margin: 0 0 1em!important;
615
+ display: inline-block;
616
+ }
617
+
618
+ .mc-main .details .sharing {
619
+ clear: both;
620
+ }
621
+
622
+ .mc-main .sharing p {
623
+ display: inline-block;
624
+ padding: .5em .5em .5em 0;
625
+ }
626
+
627
+ .mc-main.mini .sharing p {
628
+ font-size: 14px;
629
+ padding: 0 .25em 0 0;
630
+ margin-bottom: 10px;
631
+ }
632
+
633
+ .mc-main .sharing .ical a:before, .mc-main .sharing .gcal a:before {
634
+ content: "\f502";
635
+ }
636
+
637
+ .mc-main .sharing .mc_details a:before {
638
+ content: "\f242";
639
+ }
640
+
641
+ .mc-main .mc-list .event-date {
642
+ font-size: 16px;
643
+ font-weight: 600;
644
+ }
645
+
646
+ .mc-main .list-event {
647
+ border-top: 1px solid #d1d1d1;
648
+ margin: .5em -10px;
649
+ }
650
+
651
+ .mc-main .day .list-event, .mc-main .day .details {
652
+ padding: 0;
653
+ margin: 0;
654
+ }
655
+
656
+ .mc-main .mc-list-extended {
657
+ font-size: 14px;
658
+ font-style: italic;
659
+ }
660
+
661
+ .mc-main .details .mc-image {
662
+ max-width: 100%;
663
+ height: auto;
664
+ }
665
+
666
+ .mc-main .list-event .event-title img {
667
+ margin-right: .5em;
668
+ position: relative;
669
+ top: -1px;
670
+ }
671
+
672
+ /* Single view */
673
+ .single-event .event-title {
674
+ padding: .5em;
675
+ font-size: inherit;
676
+ }
677
+
678
+ .single-event .event-title img {
679
+ margin-right: 10px;
680
+ position: static;
681
+ }
682
+
683
+ .mc-list-details.all-events {
684
+ text-align: left;
685
+ display: inline-block;
686
+ text-transform: none;
687
+ }