My Calendar - Version 2.5.9

Version Description

  • Bug fix: class .mc-main appeared twice in day view
  • Bug fix: iCal output fetches no data on subsites in multisite networks
  • Bug fix: broken image upload script due to localization change
  • Bug fix: sorting events by category should sort by name, not ID
  • Add site name to .ics output file
Download this release

Release Info

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

Code changes from version 2.5.0 to 2.5.9

css/mc-print.css CHANGED
@@ -24,15 +24,19 @@ td {
24
font-size: 12px;
25
vertical-align: top;
26
width: 14.285%;
27
}
28
29
.details {
30
- border-bottom: 1px solid #ddd;
31
color: #444;
32
margin-bottom: 2px;
33
}
34
35
- .details a, .details img {
36
display: none;
37
}
38
@@ -58,12 +62,14 @@ abbr {
58
59
a {
60
text-decoration: none;
61
- color: #f00
62
}
63
64
.mc-date {
65
font-weight: 700;
66
font-size: 1.2em;
67
padding: 2px 4px;
68
line-height: 1;
69
margin-left: 3px;
@@ -80,4 +86,13 @@ a {
80
font-weight: 700;
81
font-size: 1.5em;
82
text-align: center;
83
}
24
font-size: 12px;
25
vertical-align: top;
26
width: 14.285%;
27
+ height: 4em;
28
}
29
30
.details {
31
color: #444;
32
margin-bottom: 2px;
33
}
34
35
+ .vevent:not(:last-child) .details {
36
+ border-bottom: 1px solid #ddd;
37
+ }
38
+
39
+ .details * {
40
display: none;
41
}
42
62
63
a {
64
text-decoration: none;
65
+ color: #d00
66
}
67
68
.mc-date {
69
font-weight: 700;
70
font-size: 1.2em;
71
+ width: 1em;
72
+ text-align: center;
73
padding: 2px 4px;
74
line-height: 1;
75
margin-left: 3px;
86
font-weight: 700;
87
font-size: 1.5em;
88
text-align: center;
89
+ text-decoration: underline;
90
+ }
91
+
92
+ .return:hover, .return:focus {
93
+ text-decoration: none;
94
+ }
95
+
96
+ @media print {
97
+ .return { display: none; }
98
}
css/mc-styles.css CHANGED
@@ -12,20 +12,6 @@
12
line-height: 1.5
13
}
14
15
- .mc-button {
16
- text-align: center;
17
- font-size: 1.4em;
18
- padding: 10px 0 0
19
- }
20
-
21
- .mc-button a {
22
- padding: 3px 8px;
23
- border: 1px outset;
24
- border-radius: 7px;
25
- background: #fff;
26
- font-weight: 700;
27
- }
28
-
29
.mcd {
30
text-align: center;
31
margin: 0;
@@ -70,7 +56,7 @@ ul.links li {
70
font-size: .9em
71
}
72
73
- .jd-my-calendar .metabox-holder .postbox > h2 {
74
font-size: 14px;
75
padding: 8px 12px;
76
margin: 0;
@@ -93,19 +79,19 @@ span.mc-notice {
93
border: 1px solid #900;
94
}
95
96
- .jd-my-calendar .spam {
97
background: #ffa
98
}
99
100
- .jd-my-calendar .pending {
101
background: #eee
102
}
103
104
- .jd-my-calendar .pending td, .jd-my-calendar .row-actions {
105
color: #666;
106
}
107
108
- .jd-my-calendar fieldset fieldset {
109
margin: 0 0 20px 0;
110
padding-top: 2px
111
}
@@ -167,12 +153,12 @@ span.mc-notice {
167
column-gap: 30px
168
}
169
170
- .jd-my-calendar .event_image {
171
float: right;
172
margin-left: 10px;
173
}
174
175
- .jd-my-calendar .event_image img {
176
width: 150px;
177
height: auto;
178
margin: 2px 0;
@@ -189,52 +175,52 @@ span.mc-notice {
189
width: 98%
190
}
191
192
- .jd-my-calendar .postbox {
193
margin: 10px 10px 0 0
194
}
195
196
- .jd-my-calendar .postbox.wptab {
197
margin: 0 10px 0 0!important;
198
border: 1px solid #e5e5e5;
199
}
200
201
- .jd-my-calendar .postbox .inside {
202
overflow: visible !important
203
}
204
205
206
207
/* some plugins change this, but I need it at WP default. */
208
- .jd-my-calendar .meta-box-sortables {
209
min-height: 0
210
}
211
212
- .jd-my-calendar textarea {
213
width: 100%
214
}
215
216
- .jd-my-calendar pre {
217
background: #fff;
218
padding: 5px;
219
border: 1px solid #ddd;
220
box-shadow: 1px 1px 2px #ddd
221
}
222
223
- .jd-my-calendar label span.required {
224
font-size: .9em;
225
color: #c33
226
}
227
228
- .jd-my-calendar .default {
229
background: #fff
230
}
231
232
- .jd-my-calendar .button-adjust {
233
top: 10px;
234
right: 0
235
}
236
237
- .jd-my-calendar hr {
238
width: 20%;
239
margin: 0 auto;
240
border: none;
@@ -247,7 +233,7 @@ span.mc-notice {
247
display: inline-block
248
}
249
250
- .jd-my-calendar .tablenav {
251
float: right
252
}
253
@@ -282,17 +268,17 @@ strong.label {
282
z-index: 10;
283
}
284
285
- .jd-my-calendar .counter {
286
padding-right: 6px;
287
border-right: 16px solid green;
288
border-radius: 20px;
289
}
290
291
- .jd-my-calendar .counter.warning {
292
border-color: orange;
293
}
294
295
- .jd-my-calendar .counter.exceeded {
296
border-color: red;
297
}
298
@@ -353,7 +339,7 @@ strong.label {
353
display: none;
354
}
355
356
- .jd-my-calendar .ui-accordion-header, .mc-settings-page #mc-sortable li {
357
border: 1px solid #ddd;
358
background: rgba(0, 0, 0, .10);
359
padding: .5em 1em;
@@ -369,7 +355,13 @@ strong.label {
369
width: 7em;
370
}
371
372
- .jd-my-calendar .ui-accordion-header.ui-state-hover, .ui-accordion-header.ui-state-focus, .mc-settings-page #mc-sortable li:hover {
373
background: #f6f6f6;
374
box-shadow: 0 0 2px #ddd;
375
}
@@ -389,15 +381,15 @@ input[name="mc_uri"] {
389
padding: 1em;
390
}
391
392
- .jd-my-calendar .ui-accordion-header-active {
393
background: rgba(0, 0, 0, .05);
394
}
395
396
- .jd-my-calendar .ui-accordion-header .dashicons:before {
397
content: "\f132";
398
}
399
400
- .jd-my-calendar .ui-accordion-header-active .dashicons:before {
401
content: "\f460";
402
}
403
@@ -412,6 +404,10 @@ input[name="mc_uri"] {
412
color: #eee;
413
}
414
415
#mc-sortable li.mc-stop:hover {
416
background-color: #000;
417
color: #bbb;
@@ -428,10 +424,10 @@ input[name="mc_uri"] {
428
text-align: center;
429
}
430
431
- .jd-my-calendar .checkboxes {
432
margin: 0;
433
}
434
- .jd-my-calendar .checkboxes:after {
435
content: '';
436
display: table;
437
clear: both;
@@ -444,7 +440,7 @@ input[name="mc_uri"] {
444
margin-bottom: 1em;
445
}
446
447
- .jd-my-calendar .mc_permissions .checkboxes li {
448
display: block;
449
}
450
@@ -452,14 +448,14 @@ input[name="mc_uri"] {
452
padding: 1em;
453
}
454
455
- .jd-my-calendar .checkboxes li {
456
display: inline-block;
457
padding: 5px;
458
background: rgba(0, 0, 0, .05);
459
margin: 2px;
460
}
461
462
- .jd-my-calendar .checkboxes li:hover {
463
background: #fff;
464
}
465
@@ -471,7 +467,7 @@ input[name="mc_uri"] {
471
clear: left;
472
}
473
474
- .jd-my-calendar fieldset legend {
475
font-weight: 700;
476
padding: 0;
477
font-size: 1.1em;
@@ -590,7 +586,7 @@ input[name="mc_uri"] {
590
content: "\f132";
591
}
592
593
- .jd-my-calendar .postbox .hndle {
594
cursor: auto;
595
}
596
@@ -620,7 +616,7 @@ input[name="mc_uri"] {
620
text-shadow: 1px 0 0 #000;
621
}
622
623
- .jd-my-calendar .error .button-secondary {
624
vertical-align: baseline;
625
}
626
@@ -681,7 +677,7 @@ tr.problem .error {
681
color: #fff !important;
682
}
683
684
- .jd-my-calendar .mc-none {
685
clear: both;
686
}
687
@@ -692,7 +688,7 @@ tr.problem .error {
692
}
693
694
@media (max-width: 782px) {
695
- .jd-my-calendar .tablenav {
696
float: none;
697
}
698
12
line-height: 1.5
13
}
14
15
.mcd {
16
text-align: center;
17
margin: 0;
56
font-size: .9em
57
}
58
59
+ .my-calendar-admin .metabox-holder .postbox > h2 {
60
font-size: 14px;
61
padding: 8px 12px;
62
margin: 0;
79
border: 1px solid #900;
80
}
81
82
+ .my-calendar-admin .spam {
83
background: #ffa
84
}
85
86
+ .my-calendar-admin .pending {
87
background: #eee
88
}
89
90
+ .my-calendar-admin .pending td, .my-calendar-admin .row-actions {
91
color: #666;
92
}
93
94
+ .my-calendar-admin fieldset fieldset {
95
margin: 0 0 20px 0;
96
padding-top: 2px
97
}
153
column-gap: 30px
154
}
155
156
+ .my-calendar-admin .event_image {
157
float: right;
158
margin-left: 10px;
159
}
160
161
+ .my-calendar-admin .event_image img {
162
width: 150px;
163
height: auto;
164
margin: 2px 0;
175
width: 98%
176
}
177
178
+ .my-calendar-admin .postbox {
179
margin: 10px 10px 0 0
180
}
181
182
+ .my-calendar-admin .postbox.wptab {
183
margin: 0 10px 0 0!important;
184
border: 1px solid #e5e5e5;
185
}
186
187
+ .my-calendar-admin .postbox .inside {
188
overflow: visible !important
189
}
190
191
192
193
/* some plugins change this, but I need it at WP default. */
194
+ .my-calendar-admin .meta-box-sortables {
195
min-height: 0
196
}
197
198
+ .my-calendar-admin textarea {
199
width: 100%
200
}
201
202
+ .my-calendar-admin pre {
203
background: #fff;
204
padding: 5px;
205
border: 1px solid #ddd;
206
box-shadow: 1px 1px 2px #ddd
207
}
208
209
+ .my-calendar-admin label span.required {
210
font-size: .9em;
211
color: #c33
212
}
213
214
+ .my-calendar-admin .default {
215
background: #fff
216
}
217
218
+ .my-calendar-admin .button-adjust {
219
top: 10px;
220
right: 0
221
}
222
223
+ .my-calendar-admin hr {
224
width: 20%;
225
margin: 0 auto;
226
border: none;
233
display: inline-block
234
}
235
236
+ .my-calendar-admin .tablenav {
237
float: right
238
}
239
268
z-index: 10;
269
}
270
271
+ .my-calendar-admin .counter {
272
padding-right: 6px;
273
border-right: 16px solid green;
274
border-radius: 20px;
275
}
276
277
+ .my-calendar-admin .counter.warning {
278
border-color: orange;
279
}
280
281
+ .my-calendar-admin .counter.exceeded {
282
border-color: red;
283
}
284
339
display: none;
340
}
341
342
+ .my-calendar-admin .ui-accordion-header, .mc-settings-page #mc-sortable li {
343
border: 1px solid #ddd;
344
background: rgba(0, 0, 0, .10);
345
padding: .5em 1em;
355
width: 7em;
356
}
357
358
+ #mc-sortable li:nth-of-type(1) .mc-buttons .up, #mc-sortable li:nth-of-type(9) .mc-buttons .down {
359
+ background: none;
360
+ border: 1px solid transparent;
361
+ color: rgba( 0,0,0,.4 );
362
+ }
363
+
364
+ .my-calendar-admin .ui-accordion-header.ui-state-hover, .ui-accordion-header.ui-state-focus, .mc-settings-page #mc-sortable li:hover {
365
background: #f6f6f6;
366
box-shadow: 0 0 2px #ddd;
367
}
381
padding: 1em;
382
}
383
384
+ .my-calendar-admin .ui-accordion-header-active {
385
background: rgba(0, 0, 0, .05);
386
}
387
388
+ .my-calendar-admin .ui-accordion-header .dashicons:before {
389
content: "\f132";
390
}
391
392
+ .my-calendar-admin .ui-accordion-header-active .dashicons:before {
393
content: "\f460";
394
}
395
404
color: #eee;
405
}
406
407
+ #mc-sortable li.mc-stop.mc-updated {
408
+ color: #000;
409
+ }
410
+
411
#mc-sortable li.mc-stop:hover {
412
background-color: #000;
413
color: #bbb;
424
text-align: center;
425
}
426
427
+ .my-calendar-admin .checkboxes {
428
margin: 0;
429
}
430
+ .my-calendar-admin .checkboxes:after {
431
content: '';
432
display: table;
433
clear: both;
440
margin-bottom: 1em;
441
}
442
443
+ .my-calendar-admin .mc_permissions .checkboxes li {
444
display: block;
445
}
446
448
padding: 1em;
449
}
450
451
+ .my-calendar-admin .checkboxes li {
452
display: inline-block;
453
padding: 5px;
454
background: rgba(0, 0, 0, .05);
455
margin: 2px;
456
}
457
458
+ .my-calendar-admin .checkboxes li:hover {
459
background: #fff;
460
}
461
467
clear: left;
468
}
469
470
+ .my-calendar-admin fieldset legend {
471
font-weight: 700;
472
padding: 0;
473
font-size: 1.1em;
586
content: "\f132";
587
}
588
589
+ .my-calendar-admin .postbox .hndle {
590
cursor: auto;
591
}
592
616
text-shadow: 1px 0 0 #000;
617
}
618
619
+ .my-calendar-admin .error .button-secondary {
620
vertical-align: baseline;
621
}
622
677
color: #fff !important;
678
}
679
680
+ .my-calendar-admin .mc-none {
681
clear: both;
682
}
683
688
}
689
690
@media (max-width: 782px) {
691
+ .my-calendar-admin .tablenav {
692
float: none;
693
}
694
css/reset.css CHANGED
@@ -140,5 +140,5 @@ button.mc-text-button:hover, button .mc-text-button:focus {
140
max-width: none ! important;
141
}
142
143
- .mcjs .mc-main .details, .mcjs .mc-main .calendar-events { display: none; }
144
- .mcjs .mc-main .single-event .details, .mcjs .mc-main .list.day .details { display: block; }
140
max-width: none ! important;
141
}
142
143
+ .mcjs.mc-main .details, .mcjs.mc-main .calendar-events { display: none; }
144
+ .mcjs.mc-main .single-event .details, .mcjs.mc-main .list.day .details { display: block; }
includes/kses.php CHANGED
@@ -34,44 +34,44 @@ function mc_allowed_tags( $tags, $context ) {
34
'readonly' => true,
35
'min' => true,
36
'max' => true,
37
);
38
$tags['select'] = array(
39
'name' => true,
40
'id' => true,
41
'class' => true
42
);
43
- $tags['span'] = array(
44
- 'dir' => true,
45
- 'align' => true,
46
- 'lang' => true,
47
- 'xml:lang' => true,
48
'itemprop' => true,
49
'itemscope' => true,
50
'itemtype' => true,
51
- );
52
- $tags['button'] = array(
53
'name' => true,
54
'type' => true,
55
'disabled' => true,
56
- );
57
- $tags['form'] = array(
58
'action' => true,
59
'method' => true,
60
'class' => true,
61
'id' => true,
62
'tabindex' => true,
63
- );
64
- $tags['div'] = array(
65
'class' => true,
66
'id' => true,
67
'aria-live' => true,
68
- );
69
- $tags['fieldset'] = array();
70
- $tags['legend'] = array();
71
- $tags['p'] = array(
72
'class' => true,
73
- );
74
- $tags['img'] = array(
75
'class' => true,
76
'src' => true,
77
'alt' => true,
@@ -80,8 +80,14 @@ function mc_allowed_tags( $tags, $context ) {
80
'id' => true,
81
'longdesc' => true,
82
'tabindex' => true
83
);
84
}
85
86
- return $tags;
87
}
34
'readonly' => true,
35
'min' => true,
36
'max' => true,
37
+ 'id' => true,
38
+ 'checked' => true,
39
+ 'required' => true
40
);
41
$tags['select'] = array(
42
'name' => true,
43
'id' => true,
44
'class' => true
45
);
46
+ $tags['span'] = array_merge( $tags['span'], array(
47
'itemprop' => true,
48
'itemscope' => true,
49
'itemtype' => true,
50
+ ) );
51
+ $tags['button'] = array_merge( $tags['button'], array(
52
'name' => true,
53
'type' => true,
54
'disabled' => true,
55
+ 'class' => true,
56
+ ) );
57
+ $tags['form'] = array_merge( $tags['form'], array(
58
'action' => true,
59
'method' => true,
60
'class' => true,
61
'id' => true,
62
'tabindex' => true,
63
+ ) );
64
+ $tags['div'] = array_merge( $tags['div'], array(
65
'class' => true,
66
'id' => true,
67
'aria-live' => true,
68
+ ) );
69
+ $tags['fieldset'] = array_merge( $tags['fieldset'], array() );
70
+ $tags['legend'] = array_merge( $tags['legend'], array() );
71
+ $tags['p'] = array_merge( $tags['p'], array(
72
'class' => true,
73
+ ) );
74
+ $tags['img'] = array_merge( $tags['img'], array(
75
'class' => true,
76
'src' => true,
77
'alt' => true,
80
'id' => true,
81
'longdesc' => true,
82
'tabindex' => true
83
+ ) );
84
+ $tags['iframe'] = array(
85
+ 'width' => true,
86
+ 'height' => true,
87
+ 'src' => true,
88
+ 'frameborder' => true
89
);
90
}
91
92
+ return apply_filters( 'mc_kses_post', $tags );
93
}
js/gmap3.js DELETED
@@ -1,1131 +0,0 @@
1
- /*!
2
- * GMAP3 Plugin for jQuery
3
- * Version : 7.1
4
- * Date : 2016/04/17
5
- * Author : DEMONTE Jean-Baptiste
6
- * Contact : jbdemonte@gmail.com
7
- * Web site : http://gmap3.net
8
- * Licence : GPL-3.0+
9
- */
10
- (function ($, window, document) {
11
- "use strict";
12
-
13
- var gm, services = {}, loadOptions,
14
-
15
- // Proxify functions to get shorter minimized code
16
- when = $.when,
17
- extend = $.extend,
18
- isArray = $.isArray,
19
- isFunction = $.isFunction,
20
- deferred = $.Deferred;
21
-
22
- /**
23
- * Duplicate option to never modify original object
24
- * @param {Object} options
25
- * @returns {Object}
26
- */
27
- function dupOpts(options) {
28
- return extend(true, {}, options || {});
29
- }
30
-
31
- /**
32
- * Slice an array like
33
- * @params {Array|Object}
34
- * @params {Number} [start]
35
- * @params {Number} [end]
36
- * @returns {Array}
37
- */
38
- function slice() {
39
- var fn = Array.prototype.slice,
40
- args = fn.call(arguments, 1);
41
- return fn.apply(arguments[0], args);
42
- }
43
-
44
- /**
45
- * Return true if value is undefined
46
- * @param {*} value
47
- * @returns {Boolean}
48
- */
49
- function isUndefined(value) {
50
- return typeof value === 'undefined';
51
- }
52
-
53
- /**
54
- * Equivalent to Promise.all
55
- * @param {Deferred[]} deferreds
56
- * @returns {Deferred}
57
- */
58
- function all(deferreds) {
59
- return when.apply($, deferreds);
60
- }
61
-
62
- /**
63
- * Equivalent to Promise.resolve
64
- * @param {*} value
65
- * @returns {Deferred}
66
- */
67
- function resolved(value) {
68
- return when().then(function () {
69
- return value;
70
- });
71
- }
72
-
73
- /**
74
- * return the distance between 2 latLng in meters
75
- * @param {LatLng} origin
76
- * @param {LatLng} destination
77
- * @returns {Number}
78
- **/
79
- function distanceInMeter(origin, destination) {
80
- var m = Math,
81
- pi = m.PI,
82
- e = pi * origin.lat() / 180,
83
- f = pi * origin.lng() / 180,
84
- g = pi * destination.lat() / 180,
85
- h = pi * destination.lng() / 180,
86
- cos = m.cos,
87
- sin = m.sin;
88
- return 1000 * 6371 * m.acos(m.min(cos(e) * cos(g) * cos(f) * cos(h) + cos(e) * sin(f) * cos(g) * sin(h) + sin(e) * sin(g), 1));
89
- }
90
-
91
- function ready(fn) {
92
- if (document.readyState != 'loading'){
93
- fn();
94
- } else {
95
- document.addEventListener('DOMContentLoaded', fn);
96
- }
97
- }
98
-
99
- function serialize(obj) {
100
- return objectKeys(obj).map(function (key) {
101
- return encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]);
102
- }).join("&");
103
- }
104
-
105
- // Auto-load google maps library if needed
106
- (function () {
107
- var dfd = deferred(),
108
- cbName = '__gmap3',
109
- script;
110
-
111
- $.holdReady(true);
112
-
113
- ready(function () {
114
- if (window.google && window.google.maps || loadOptions === false) {
115
- dfd.resolve();
116
- } else {
117
- // callback function - resolving promise after maps successfully loaded
118
- window[cbName] = function () {
119
- delete window[cbName];
120
- dfd.resolve();
121
- };
122
- script = document.createElement('script');
123
- script.type = 'text/javascript';
124
- script.src = 'https://maps.googleapis.com/maps/api/js?callback=' + cbName + (loadOptions ? '&' + (typeof loadOptions === 'string' ? loadOptions : serialize(loadOptions)) : '');
125
- $("head").append(script);
126
- }
127
- });
128
-
129
- return dfd.promise();
130
- })().then(function () {
131
- $.holdReady(false);
132
- });
133
-
134
- /**
135
- * Instantiate only once a google service
136
- * @param {String} name
137
- * @returns {Object}
138
- */
139
- function service(name) {
140
- if (!services[name]) {
141
- services[name] = gmElement(name);
142
- }
143
- return services[name];
144
- }
145
-
146
- /**
147
- * Return GoogleMap Class (or overwritten by user) instance
148
- * @param {String} name
149
- * @returns {Object}
150
- */
151
- function gmElement(name) {
152
- var cls = gm[name];
153
-
154
- function F(args) {
155
- return cls.apply(this, args);
156
- }
157
- F.prototype = cls.prototype;
158
-
159
- return new F(slice(arguments, 1));
160
- }
161
-
162
- /**
163
- * Resolve a GeocodeRequest
164
- * https://developers.google.com/maps/documentation/javascript/geocoding
165
- * @param {String|Object} request
166
- * @returns {Deferred}
167
- */
168
- function geocode(request) {
169
- var dfd = deferred();
170
- if (typeof request === 'string') {
171
- request = {
172
- address: request
173
- };
174
- }
175
- service('Geocoder').geocode(request, function(results, status) {
176
- if (status === gm.GeocoderStatus.OK) {
177
- dfd.resolve(results[0].geometry.location);
178
- } else {
179
- dfd.reject();
180
- }
181
- });
182
- return dfd;
183
- }
184
-
185
- /**
186
- * Callable function taking a parameter as string
187
- * @callback StringCallback
188
- * @param {String}
189
- */
190
-
191
- /**
192
- * Split a string and execute a function on each item
193
- * @param {String} str - Space separated list of items
194
- * @param {StringCallback} fn - Callback function
195
- */
196
- function foreachStr(str, fn) {
197
- str.split(' ').forEach(fn);
198
- }
199
-
200
- /**
201
- * Execute a function on each items if items is an array and on items as a single element if it is not an array
202
- * @param {Array|*} items - Items to execute foreach callback on
203
- * @param {Function} fn - Callback function
204
- */
205
- function foreach(items, fn) {
206
- (isArray(items) ? items : [items]).forEach(fn);
207
- }
208
-
209
- /**
210
- * Return Object keys
211
- * @param {Object} obj
212
- * @returns {String[]}
213
- */
214
- function objectKeys(obj) {
215
- return Object.keys(obj);
216
- }
217
-
218
- /**
219
- * Return Object values
220
- * @param {Object} obj
221
- * @returns {*[]}
222
- */
223
- function objectValues(obj) {
224
- return objectKeys(obj).map(function (key) {
225
- return obj[key];
226
- });
227
- }
228
-
229
- /**
230
- * Resolution function
231
- * @callback OptionCallback
232
- * @param {Object} options
233
- * @returns {Deferred|*}
234
- */
235
-
236
- /**
237
- * Convert bounds from array [ n, e, s, w ] to google.maps.LatLngBounds
238
- * @param {Object} options - Container of options.bounds
239
- * @param {OptionCallback} fn
240
- * @returns {Deferred}
241
- */
242
- function resolveLatLngBounds(options, fn) {
243
- options = dupOpts(options);
244
- if (options.bounds) {
245
- options.bounds = toLatLngBound(options.bounds);
246
- }
247
- return resolved(fn(options));
248
- }
249
-
250
- /**
251
- * Resolve an address location / convert a LatLng array to google.maps.LatLng object
252
- * @param {Object} options
253
- * @param {String} key - LatLng key name in options object
254
- * @param {OptionCallback} fn
255
- * @returns {Deferred}
256
- */
257
- function resolveLatLng(options, key, fn) {
258
- var dfd = deferred();
259
- options = dupOpts(options);
260
- when()
261
- .then(function () {
262
- var address = options.address;
263
- if (address) {
264
- delete options.address;
265
- return geocode(address).then(function (latLng) {
266
- options[key] = latLng;
267
- });
268
- }
269
- options[key] = toLatLng(options[key]);
270
- })
271
- .then(function () {
272
- dfd.resolve(fn(options));
273
- });
274
- return dfd;
275
- }
276
-
277
- /**
278
- * Convert an array of mixed LatLng to google.maps.LatLng object
279
- * No address resolution here
280
- * @param {Object} options
281
- * @param {String} key - Array key name in options object
282
- * @param {OptionCallback} fn
283
- * @returns {Deferred}
284
- */
285
- function resolveArrayOfLatLng(options, key, fn) {
286
- options = dupOpts(options);
287
- options[key] = (options[key] || []).map(function (item) {
288
- return toLatLng(item);
289
- });
290
- return resolved(fn(options));
291
- }
292
-
293
- /**
294
- * Convert a LatLng array to google.maps.LatLng
295
- * @param {Array|*} mixed
296
- * @param {Boolean} [convertLiteral]
297
- * @returns {LatLng}
298
- */
299
- function toLatLng(mixed, convertLiteral) {
300
- return isArray(mixed) ? new gm.LatLng(mixed[0], mixed[1]) : (convertLiteral && mixed && !(mixed instanceof gm.LatLng) ? new gm.LatLng(mixed.lat, mixed.lng) : mixed);
301
- }
302
-
303
- /**
304
- * Convert a LatLngBound array to google.maps.LatLngBound
305
- * @param {Array|*} mixed
306
- * @param {Boolean} [convertLiteral]
307
- * @returns {LatLngBounds}
308
- */
309
- function toLatLngBound(mixed, convertLiteral) {
310
- if (isArray(mixed)) {
311
- return new gm.LatLngBounds({lat: mixed[2], lng: mixed[3]}, {lat: mixed[0], lng: mixed[1]});
312
- } else if (convertLiteral && !mixed.getCenter){
313
- return new gm.LatLngBounds({lat: mixed.south, lng: mixed.west}, {lat: mixed.north, lng: mixed.east});
314
- }
315
- return mixed;
316
- }
317
-
318
- /**
319
- * Create a custom overlay view
320
- * @param {Map} map
321
- * @param {Object} options
322
- * @returns {OverlayView}
323
- */
324
- function createOverlayView(map, options) {
325
-
326
- var GMOverlayView = gm.OverlayView;
327
-
328
- var $div = $(document.createElement("div"))
329
- .css({
330
- border: "none",
331
- borderWidth: 0,
332
- position: "absolute"
333
- })
334
- .append(options.content);
335
-
336
- options = extend({x: 0, y: 0}, options);
337
-
338
- if (options.position) {
339
- options.position = toLatLng(options.position, true);
340
- } else if (options.bounds) {
341
- options.bounds = toLatLngBound(options.bounds, true);
342
- }
343
-
344
- /**
345
- * Class OverlayView
346
- * @constructor
347
- */
348
- function OverlayView() {
349
- var self = this,
350
- listeners = [];
351
-
352
- GMOverlayView.call(self);
353
- self.setMap(map);
354
-
355
- function fromLatLngToDivPixel(latlng) {
356
- return self.getProjection().fromLatLngToDivPixel(latlng);
357
- }
358
-
359
- self.onAdd = function () {
360
- var panes = self.getPanes();
361
- panes.overlayMouseTarget.appendChild($div[0]);
362
- };
363
-
364
- if (options.position) {
365
- self.getPosition = function () {
366
- return options.position;
367
- };
368
-
369
- self.setPosition = function (latlng) {
370
- options.position = latlng;
371
- self.draw();
372
- };
373
-
374
- self.draw = function () {
375
- var ps = fromLatLngToDivPixel(options.position);
376
- $div.css({
377
- left: (ps.x + options.x) + 'px',
378
- top: (ps.y + options.y) + 'px'
379
- });
380
- };
381
- } else {
382
- self.getBounds = function () {
383
- return options.bounds;
384
- };
385
-
386
- self.setBounds = function (bounds) {
387
- options.bounds = bounds;
388
- self.draw();
389
- };
390
-
391
- self.draw = function() {
392
- var sw = fromLatLngToDivPixel(options.bounds.getSouthWest());
393
- var ne = fromLatLngToDivPixel(options.bounds.getNorthEast());
394
-
395
- $div.css({
396
- left: (sw.x + options.x) + 'px',
397
- top: (ne.y + options.y) + 'px',
398
- width: (ne.x - sw.x + options.x) + 'px',
399
- height: (sw.y - ne.y + options.y) + 'px'
400
- });
401
- };
402
- }
403
-
404
- self.onRemove = function () {
405
- listeners.map(function (handler) {
406
- gm.event.removeListener(handler);
407
- });
408
- $div.remove();
409
- self.$ = $div = null; // mem leaks
410
- };
411
-
412
- self.$ = $div;
413
- }
414
-
415
- OverlayView.prototype = new GMOverlayView();
416
-
417
- return new OverlayView();
418
- }
419
-
420
- /**
421
- * Return a map projection
422
- * @param {Map} map
423
- * @returns {*}
424
- */
425
- function getProjection(map) {
426
- function Overlay() {
427
- var self = this;
428
- self.onAdd = self.onRemove = self.draw = function () {};
429
- return gm.OverlayView.call(self);
430
- }
431
- Overlay.prototype = new gm.OverlayView();
432
- var overlay = new Overlay();
433
- overlay.setMap(map);
434
- return overlay.getProjection();
435
- }
436
-
437
- /**
438
- * Class used as event first parameter on clustering overlays
439
- * @param {Cluster} cluster
440
- * @param {Marker[]} markers
441
- * @param {OverlayView} overlay
442
- * @param {LatLngBounds} bounds
443
- * @constructor
444
- */
445
- function ClusterOverlay(cluster, markers, overlay, bounds) {
446
- var self = this;
447
- self.cluster = cluster;
448
- self.markers = markers;
449
- self.$ = overlay.$;
450
- self.overlay = overlay;
451
-
452
- overlay.getBounds = function () {
453
- return gmElement('LatLngBounds', bounds.getSouthWest(), bounds.getNorthEast());
454
- };
455
- }
456
-
457
- /**
458
- * Cluster Group definition.
459
- * @typedef {Object} ClusterGroupDef
460
- * @property {String|jQuery} content
461
- * @property {Number} [x] Offset
462
- * @property {Number} [y] Offset
463
- */
464
-
465
- /**
466
- * Cluster evaluation function
467
- * @callback clusterCallback
468
- * @param {Marker[]} markers
469
- * @return {ClusterGroupDef|undefined}
470
- */
471
-
472
- /**
473
- * Class used to handle clustering
474
- * @param {Map} map
475
- * @param {Object} options
476
- * @param {Integer} [options.size]
477
- * @param {Object[]} [options.markers] markers definition
478
- * @param {clusterCallback} [options.cb] callback used to evaluate clustering elements
479
- * @constructor
480
- */
481
- function Cluster(map, options) {
482
- var timer, igniter, previousViewHash, projection, filter,
483
- self = this,
484
- markers = [],
485
- radius = (options.size || 200) >> 1,
486
- enabled = true,
487
- overlays = {},
488
- handlers = [];
489
-
490
- options = options || {};
491
- options.markers = options.markers || [];
492
-
493
- /**
494
- * Cluster evaluation function
495
- * @callback bindCallback
496
- * @param {ClusterOverlay[]} instances
497
- */
498
-
499
- /**
500
- * Bind a function to each current or future overlays
501
- * @param {bindCallback} fn
502
- */
503
- self._b = function (fn) {
504
- fn(objectValues(overlays));
505
- handlers.push(fn);
506
- };
507
-
508
- /**
509
- * Get the marker list
510
- * @returns {Marker[]}
511
- */
512
- self.markers = function () {
513
- return slice(markers);
514
- };
515
-
516
- /**
517
- * Get the current groups
518
- * @returns {ClusterOverlay[]}
519
- */
520
- self.groups = function () {
521
- return objectValues(overlays);
522
- };
523
-
524
- /**
525
- * Enable the clustering feature
526
- */
527
- self.enable = function () {
528
- if (!enabled) {
529
- enabled = true;
530
- previousViewHash = '';
531
- delayRedraw();
532
- }
533
- };
534
-
535
-
536
- /**
537
- * Disable the clustering feature
538
- */
539
- self.disable = function () {
540
- if (enabled) {
541
- enabled = false;
542
- previousViewHash = '';
543
- delayRedraw();
544
- }
545
- };
546
-
547
- /**
548
- * Add a marker
549
- * @param {Marker} marker
550
- */
551
- self.add = function (marker) {
552
- markers.push(marker);
553
- previousViewHash = '';
554
- delayRedraw();
555
- };
556
-
557
- /**
558
- * Remove a marker
559
- * @param {Marker} marker
560
- */
561
- self.remove = function (marker) {
562
- markers = markers.filter(function (item) {
563
- return item !== marker;
564
- });
565
- previousViewHash = '';
566
- delayRedraw();
567
- };
568
-
569
- /**
570
- * Filtering function, Cluster only handle those who return true
571
- * @callback filterCallback
572
- * @param {Marker} marker
573
- * @returns {Boolean}
574
- */
575
-
576
- /**
577
- * Set a filter function
578
- * @param {filterCallback} fn
579
- */
580
- self.filter = function (fn) {
581
- if (filter !== fn) {
582
- filter = fn;
583
- previousViewHash = '';
584
- delayRedraw();
585
- }
586
- };
587
-
588
- /**
589
- * Generate extended visible bounds
590
- * @returns {LatLngBounds}
591
- */
592
- function extendsMapBounds() {
593
- var circle = gmElement('Circle', {
594
- center: map.getCenter(),
595
- radius: 1.15 * distanceInMeter(map.getCenter(), map.getBounds().getNorthEast()) // + 15%
596
- });
597
- return circle.getBounds();
598
- }
599
-
600
- /**
601
- * Generate bounds extended by radius
602
- * @param {LatLng} latLng
603
- * @returns {LatLngBounds}
604
- */
605
- function extendsBounds(latLng) {
606
- var p = projection.fromLatLngToDivPixel(latLng);
607
- return gmElement('LatLngBounds',
608
- projection.fromDivPixelToLatLng(gmElement('Point', p.x - radius, p.y + radius)),
609
- projection.fromDivPixelToLatLng(gmElement('Point', p.x + radius, p.y - radius))
610
- );
611
- }
612
-
613
- options.markers.map(function (opts) {
614
- opts.position = toLatLng(opts.position);
615
- markers.push(gmElement('Marker', opts));
616
- });
617
-
618
- /**
619
- * Redraw clusters
620
- */
621
- function redraw() {
622
- var keys, bounds, overlayOptions, hash, currentMarkers, viewHash,
623
- zoom = map.getZoom(),
624
- currentHashes = {},
625
- newOverlays = [],
626
- ignore = {};
627
-
628
- viewHash = '' + zoom;
629
-
630
- if (zoom > 3) {
631
- bounds = extendsMapBounds();
632
- foreach(markers, function (marker, index) {
633
- if (!bounds.contains(marker.getPosition())) {
634
- viewHash += '-' + index;
635
- ignore[index] = true;
636
- if (marker.getMap()) {
637
- marker.setMap(null);
638
- }
639
- }
640
- });
641
- }
642
- if (filter) {
643
- foreach(markers, function (marker, index) {
644
- if (!ignore[index] && !filter(marker)) {
645
- viewHash += '-' + index;
646
- ignore[index] = true;
647
- if (marker.getMap()) {
648
- marker.setMap(null);
649
- }
650
- }
651
- });
652
- }
653
-
654
- if (viewHash === previousViewHash) {
655
- return;
656
- }
657
- previousViewHash = viewHash;
658
-
659
- foreach(markers, function (marker, index) {
660
- if (ignore[index]) {
661
- return;
662
- }
663
-
664
- keys = [index];
665
- bounds = extendsBounds(marker.getPosition());
666
-
667
- if (enabled) {
668
- foreach(slice(markers, index + 1), function (marker, idx) {
669
- idx += index + 1;
670
- if (!ignore[idx] && bounds.contains(marker.getPosition())) {
671
- keys.push(idx);
672
- ignore[idx] = true;
673
- }
674
- });
675
- }
676
-
677
- hash = keys.join('-');
678
- currentHashes[hash] = true;
679
-
680
- if (overlays[hash]) { // hash is already set
681
- return;
682
- }
683
-
684
- currentMarkers = keys.map(function (key) {
685
- return markers[key];
686
- });
687
-
688
- // ask the user callback on this subset (may be composed by only one marker)
689
- overlayOptions = options.cb(slice(currentMarkers));
690
-
691
- // create an overlay if cb returns its properties
692
- if (overlayOptions) {
693
- bounds = gmElement('LatLngBounds');
694
- foreach(currentMarkers, function (marker) {
695
- bounds.extend(marker.getPosition());
696
- if (marker.getMap()) {
697
- marker.setMap(null);
698
- }
699
- });
700
-
701
- overlayOptions = dupOpts(overlayOptions);
702
- overlayOptions.position = bounds.getCenter();
703
- overlays[hash] = new ClusterOverlay(self, slice(currentMarkers), createOverlayView(map, overlayOptions), bounds);
704
- newOverlays.push(overlays[hash]);
705
-
706
- } else {
707
- foreach(currentMarkers, function (marker) {
708
- if (!marker.getMap()) { // to avoid marker blinking
709
- marker.setMap(map);
710
- }
711
- });
712
- }
713
-
714
- });
715
-
716
- // remove previous overlays
717
- foreach(objectKeys(overlays), function (key) {
718
- if (!currentHashes[key]) {
719
- overlays[key].overlay.setMap(null);
720
- delete overlays[key];
721
- }
722
- });
723
-
724
- if (newOverlays.length) {
725
- foreach(handlers, function (fn) {
726
- fn(newOverlays);
727
- });
728
- }
729
- }
730
-
731
- /**
732
- * Restart redraw timer
733
- */
734
- function delayRedraw() {
735
- clearTimeout(timer);
736
- timer = setTimeout(redraw, 100);
737
- }
738
-
739
- /**
740
- * Init clustering
741
- */
742
- function init() {
743
- gm.event.addListener(map, "zoom_changed", delayRedraw);
744
- gm.event.addListener(map, "bounds_changed", delayRedraw);
745
- redraw();
746
- }
747
-
748
- igniter = setInterval(function () {
749
- projection = getProjection(map);
750
- if (projection) {
751
- clearInterval(igniter);
752
- init();
753
- }
754
- }, 10);
755
- }
756
-
757
- /**
758
- * Configure google maps loading library
759
- * @param {string|object} options
760
- */
761
- $.gmap3 = function (options) {
762
- loadOptions = options;
763
- };
764
-
765
- /**
766
- * jQuery Plugin
767
- */
768
- $.fn.gmap3 = function (options) {
769
- var items = [];
770
- gm = window.google.maps; // once gmap3 is loaded, google.maps library should be loaded
771
- this.each(function () {
772
- var $this = $(this), gmap3 = $this.data("gmap3");
773
- if (!gmap3) {
774
- gmap3 = new Gmap3($this, options);
775
- $this.data("gmap3", gmap3);
776
- }
777
- items.push(gmap3);
778
- });
779
-
780
- return new Handler(this, items);
781
- };
782
-
783
- /**
784
- * Class Handler
785
- * Chainable objet which handle all Gmap3 items associated to all jQuery elements in the current command set
786
- * @param {jQuery} chain - "this" to return to maintain the jQuery chain
787
- * @param {Gmap3[]} items
788
- * @constructor
789
- */
790
- function Handler(chain, items) {
791
- var self = this;
792
-
793
- // Map all functions from Gmap3 class
794
- objectKeys(items[0]).forEach(function (name) {
795
- self[name] = function () {
796
- var results = [],
797
- args = slice(arguments);
798
- items.forEach(function (item) {
799
- results.push(item[name].apply(item, args));
800
- });
801
- return name === 'get' ? (results.length > 1 ? results : results[0]) : self;
802
- };
803
- });
804
-
805
- self.$ = chain;
806
- }
807
-
808
- /**
809
- * Class Gmap3
810
- * Handle a Google.maps.Map instance
811
- * @param {jQuery} $container - Element to display the map in
812
- * @param {Object} options - MapOptions
813
- * @constructor
814
- */
815
- function Gmap3($container, options) {
816
- var map,
817
- previousResults = [],
818
- promise = when(),
819
- self = this;
820
-
821
- function context() {
822
- return {
823
- $: $container,
824
- get: self.get
825
- };
826
- }
827
-
828
- /**
829
- * Attach events to instances
830
- * @param {Object } events
831
- * @param {Array|Object} instances
832
- * @param {array} [args] arguments to add
833
- * @param {Boolean} once
834
- */
835
- function attachEvents(events, instances, args, once) {
836
- var hasArgs = arguments.length > 3;
837
- if (!hasArgs) {
838
- once = args;
839
- }
840
- $.each(events, function (eventName, handlers) {
841
- foreach(instances, function (instance) {
842
- var isClusterOverlay = instance instanceof ClusterOverlay;
843
- var isDom = isClusterOverlay || (instance instanceof gm.OverlayView);
844
- var eventListener = isDom ? instance.$.get(0) : instance;
845
- gm.event['add' + (isDom ? 'Dom' : '') + 'Listener' + (once ? 'Once' : '')](eventListener, eventName, function (event) {
846
- foreach(handlers, function (handler) {
847
- if (isFunction(handler)) {
848
- if (isClusterOverlay) {
849
- handler.call(context(), undefined /* marker */, instance, instance.cluster, event);
850
- } else if (hasArgs) {
851
- var buffer = slice(args);
852
- buffer.unshift(instance);
853
- buffer.push(event);
854
- handler.apply(context(), buffer);
855
- } else {
856
- handler.call(context(), instance, event);
857
- }
858
- }
859
- });
860
- });
861
- });
862
- });
863
- }
864
-
865
- /**
866
- * Decorator to handle multiple call based on array of options
867
- * @param {Function} fn
868
- * @returns {Deferred}
869
- */
870
- function multiple(fn) {
871
- return function (options) {
872
- if (isArray(options)) {
873
- var instances = [];
874
- var promises = options.map(function (opts) {
875
- return fn.call(self, opts).then(function (instance) {
876
- instances.push(instance);
877
- });
878
- });
879
- return all(promises).then(function () {
880
- previousResults.push(instances);
881
- return instances;
882
- });
883
- } else {
884
- return fn.apply(self, arguments).then(function (instance) {
885
- previousResults.push(instance);
886
- return instance;
887
- });
888
- }
889
- };
890
- }
891
-
892
- /**
893
- * Decorator to chain promise result onto the main promise chain
894
- * @param {Function} fn
895
- * @returns {Deferred}
896
- */
897
- function chainToPromise(fn) {
898
- return function () {
899
- var args = slice(arguments);
900
- promise = promise.then(function (instance) {
901
- if (isFunction(args[0])) {
902
- // handle return as a deferred / promise to support both sync & async result
903
- return when(args[0].call(context(), instance)).then(function (value) {
904
- args[0] = value;
905
- return fn.apply(self, args);
906
- });
907
- }
908
-
909
- return when(fn.apply(self, args));
910
- });
911
- return promise;
912
- };
913
- }
914
-
915
- self.map = chainToPromise(function (options) {
916
- return map || resolveLatLng(options, 'center', function (opts) {
917
- map = gmElement('Map', $container.get(0), opts);
918
- previousResults.push(map);
919
- return map;
920
- });
921
- });
922
-
923
- // Space separated string of : separated element
924
- // (google.maps class name) : (latLng property name) : (add map - 0|1 - default = 1)
925
- foreachStr('Marker:position Circle:center InfoWindow:position:0 Polyline:path Polygon:paths', function (item) {
926
- item = item.split(':');
927
- var property = item[1] || '';
928
- self[item[0].toLowerCase()] = chainToPromise(multiple(function (options) {
929
- return (property.match(/^path/) ? resolveArrayOfLatLng : resolveLatLng)(options, property, function (opts) {
930
- if (item[2] !== '0') {
931
- opts.map = map;
932
- }
933
- return gmElement(item[0], opts);
934
- });
935
- }));
936
- });
937
-
938
- foreachStr('TrafficLayer TransitLayer BicyclingLayer', function (item) {
939
- self[item.toLowerCase()] = chainToPromise(function () {
940
- var instance = gmElement(item);
941
- previousResults.push(instance);
942
- instance.setMap(map);
943
- return instance;
944
- });
945
- });
946
-
947
- self.kmllayer = chainToPromise(multiple(function (options) {
948
- options = dupOpts(options);
949
- options.map = map;
950
- return when(gmElement('KmlLayer', options));
951
- }));
952
-
953
- self.rectangle = chainToPromise(multiple(function (options) {
954
- return resolveLatLngBounds(options, function (opts) {
955
- opts.map = map;
956
- return gmElement('Rectangle', opts);
957
- });
958
- }));
959
-
960
- self.overlay = chainToPromise(multiple(function (options) {
961
- function fn(opts) {
962
- return createOverlayView(map, opts);
963
- }
964
-
965
- options = dupOpts(options);
966
- return options.bounds ? resolveLatLngBounds(options, fn) : resolveLatLng(options, 'position', fn);
967
- }));
968
-
969
- self.groundoverlay = chainToPromise(function (url, bounds, options) {
970
- return resolveLatLngBounds({bounds: bounds}, function (opts) {
971
- options = dupOpts(options);
972
- options.map = map;
973
- var instance = gmElement('GroundOverlay', url, opts.bounds, options);
974
- previousResults.push(instance);
975
- return instance;
976
- });
977
- });
978
-
979
- self.styledmaptype = chainToPromise(function (styleId, styles, options) {
980
- var instance = gmElement('StyledMapType', styles, options);
981
- previousResults.push(instance);
982
- map.mapTypes.set(styleId, instance);
983
- return instance;
984
- });
985
-
986
- self.streetviewpanorama = chainToPromise(function (container, options) {
987
- return resolveLatLng(options, 'position', function (opts) {
988
- var instance = gmElement('StreetViewPanorama', $(container).get(0), opts);
989
- map.setStreetView(instance);
990
- previousResults.push(instance);
991
- return instance;
992
- });
993
- });
994
-
995
- self.route = chainToPromise(function (options) {
996
- var dfd = deferred();
997
- options = dupOpts(options);
998
- options.origin = toLatLng(options.origin);
999
- options.destination = toLatLng(options.destination);
1000
- service('DirectionsService').route(options, function (results, status) {
1001
- previousResults.push(results);
1002
- dfd.resolve(status === gm.DirectionsStatus.OK ? results : false);
1003
- });
1004
- return dfd;
1005
- });
1006
-
1007
- self.cluster = chainToPromise(function (options) {
1008
- var cluster = new Cluster(map, dupOpts(options));
1009
- previousResults.push(cluster);
1010
- return resolved(cluster);
1011
- });
1012
-
1013
- self.directionsrenderer = chainToPromise(function (options) {
1014
- var instance;
1015
- if (options) {
1016
- options = dupOpts(options);
1017
- options.map = map;
1018
- if (options.panel) {
1019
- options.panel = $(options.panel).get(0);
1020
- }
1021
- instance = gmElement('DirectionsRenderer', options);
1022
- }
1023
- previousResults.push(instance);
1024
- return instance;
1025
- });
1026
-
1027
- self.latlng = chainToPromise(multiple(function (options) {
1028
- return resolveLatLng(options, 'latlng', function (opts) {
1029
- previousResults.push(opts.latlng);
1030
- return opts.latlng;
1031
- });
1032
- }));
1033
-
1034
- self.fit = chainToPromise(function () {
1035
- var bounds = gmElement('LatLngBounds');
1036
- foreach(previousResults, function (instances) {
1037
- if (instances !== map) {
1038
- foreach(instances, function (instance) {
1039
- if (instance) {
1040
- if (instance.getPosition && instance.getPosition()) {
1041
- bounds.extend(instance.getPosition());
1042
- } else if (instance.getBounds && instance.getBounds()) {
1043
- bounds.extend(instance.getBounds().getNorthEast());
1044
- bounds.extend(instance.getBounds().getSouthWest());
1045
- } else if (instance.getPaths && instance.getPaths()) {
1046
- foreach(instance.getPaths().getArray(), function (path) {
1047
- foreach(path.getArray(), function (latLng) {
1048
- bounds.extend(latLng);
1049
- });
1050
- });
1051
- } else if (instance.getPath && instance.getPath()) {
1052
- foreach(instance.getPath().getArray(), function (latLng) {
1053
- bounds.extend(latLng);
1054
- });
1055
- } else if (instance.getCenter && instance.getCenter()) {
1056
- bounds.extend(instance.getCenter());
1057
- }
1058
- }
1059
- });
1060
- }
1061
- });
1062
- if (!bounds.isEmpty()) {
1063
- map.fitBounds(bounds);
1064
- }
1065
- return true;
1066
- });
1067
-
1068
- self.wait = function (duration) {
1069
- promise = promise.then(function (instance) {
1070
- var dfd = deferred();
1071
- setTimeout(function () {
1072
- dfd.resolve(instance);
1073
- }, duration);
1074
- return dfd;
1075
- });
1076
- };
1077
-
1078
- self.then = function (fn) {
1079
- if (isFunction(fn)) {
1080
- promise = promise.then(function (instance) {
1081
- return when(fn.call(context(), instance)).then(function (newInstance) {
1082
- return isUndefined(newInstance) ? instance : newInstance;
1083
- });
1084
- });
1085
- }
1086
- };
1087
-
1088
- foreachStr('on once', function (name, once) {
1089
- self[name] = function () {
1090
- var events = arguments[0];
1091
- if (events) {
1092
- if (typeof events === 'string') { // cast call on('click', handler) to on({click: handler})
1093
- events = {};
1094
- events[arguments[0]] = slice(arguments, 1);
1095
- }
1096
- promise.then(function (instances) {
1097
- if (instances) {
1098
- if (instances instanceof Cluster) {
1099
- instances._b(function (items) {
1100
- if (items && items.length) {
1101
- attachEvents(events, items, once);
1102
- }
1103
- });
1104
- return attachEvents(events, instances.markers(), [undefined, instances], once);
1105
- }
1106
- attachEvents(events, instances, once);
1107
- }
1108
- });
1109
- }
1110
- };
1111
- });
1112
-
1113
- self.get = function (index) {
1114
- if (isUndefined(index)) {
1115
- return previousResults.map(function (instance) {
1116
- return isArray(instance) ? instance.slice() : instance;
1117
- });
1118
- } else {
1119
- if (index < 0) {
1120
- index = previousResults.length + index;
1121
- }
1122
- return isArray(previousResults[index]) ? previousResults[index].slice() : previousResults[index];
1123
- }
1124
- };
1125
-
1126
- if (options) {
1127
- self.map(options);
1128
- }
1129
- }
1130
-
1131
- })(jQuery, window, document);
js/jquery.addfields.js DELETED
@@ -1,31 +0,0 @@
1
- jQuery(document).ready(function ($) {
2
- $('#add_field').on('click', function () {
3
- $('#event_span').show();
4
- var num = $('.clonedInput').length; // how many "duplicatable" input fields we currently have
5
- var newNum = new Number(num + 1); // the numeric ID of the new input field being added
6
- // create the new element via clone(), and manipulate it's ID using newNum value
7
- var newElem = $('#event' + num).clone().attr('id', 'event' + newNum);
8
- // insert the new element after the last "duplicatable" input field
9
- $('#event' + num).after(newElem);
10
- // enable the "remove" button
11
- $('#del_field').removeAttr('disabled');
12
- // business rule: you can only add 10 occurrences
13
- if ( newNum == 20 ) {
14
- $('#add_field').attr('disabled', 'disabled');
15
- }
16
- });
17
-
18
- $('#del_field').on('click', function () {
19
- var num = $('.clonedInput').length; // how many "duplicatable" input fields we currently have
20
- $('#event' + num).remove(); // remove the last element
21
- // enable the "add" button
22
- $('#add_field').removeAttr('disabled');
23
- // if only one element remains, disable the "remove" button
24
- if ( num - 1 == 1 ) {
25
- $('#del_field').attr('disabled', 'disabled');
26
- }
27
- $('#event_span').hide();
28
- });
29
- $('#del_field').attr('disabled', 'disabled');
30
- $('#event_span').hide();
31
- });
js/jquery.admin.js ADDED
@@ -0,0 +1,150 @@
1
+ jQuery(document).ready(function ($) {
2
+ $('#add_field').on('click', function () {
3
+ $('#event_span').show();
4
+ var num = $('.clonedInput').length; // how many "duplicatable" input fields we currently have
5
+ var newNum = new Number(num + 1); // the numeric ID of the new input field being added
6
+ // create the new element via clone(), and manipulate it's ID using newNum value
7
+ var newElem = $('#event' + num).clone().attr('id', 'event' + newNum);
8
+ // insert the new element after the last "duplicatable" input field
9
+ $('#event' + num).after(newElem);
10
+ // enable the "remove" button
11
+ $('#del_field').removeAttr('disabled');
12
+ // business rule: you can only add 10 occurrences
13
+ if ( newNum == 20 ) {
14
+ $('#add_field').attr('disabled', 'disabled');
15
+ }
16
+ });
17
+
18
+ $('#del_field').on('click', function () {
19
+ var num = $('.clonedInput').length; // how many "duplicatable" input fields we currently have
20
+ $('#event' + num).remove(); // remove the last element
21
+ // enable the "add" button
22
+ $('#add_field').removeAttr('disabled');
23
+ // if only one element remains, disable the "remove" button
24
+ if ( num - 1 == 1 ) {
25
+ $('#del_field').attr('disabled', 'disabled');
26
+ }
27
+ $('#event_span').hide();
28
+ });
29
+ $('#del_field').attr('disabled', 'disabled');
30
+ $('#event_span').hide();
31
+ });
32
+
33
+ jQuery(document).ready(function ($) {
34
+ $(".selectall").click(function () {
35
+ var checked_status = $(this).prop('checked');
36
+ var checkbox_name = $(this).attr('id');
37
+ $('input[name="' + checkbox_name + '[]"]').each(function () {
38
+ $(this).prop('checked', checked_status);
39
+ });
40
+ });
41
+ });
42
+
43
+ jQuery(document).ready(function ($) {
44
+ $( '.mc-tabs' ).each( function ( index ) {
45
+ var tabs = $('.mc-tabs .wptab').length;
46
+ var firstItem = window.location.hash;
47
+ if ( ! firstItem ) {
48
+ var firstItem = '#' + $( '.mc-tabs .wptab:nth-of-type(1)' ).attr( 'id' );
49
+ }
50
+ $('.mc-tabs .tabs a[href="' + firstItem + '"]').addClass('active').attr( 'aria-selected', 'true' );
51
+ if ( tabs > 1 ) {
52
+ $( '.mc-tabs .wptab' ).not( firstItem ).hide();
53
+ $( firstItem ).show();
54
+ $( '.mc-tabs .tabs a' ).on( 'click', function (e) {
55
+ e.preventDefault();
56
+ $('.mc-tabs .tabs a').removeClass('active').attr( 'aria-selected', 'false' );
57
+ $(this).addClass('active').attr( 'aria-selected', 'true' );
58
+ var target = $(this).attr('href');
59
+ window.location.hash = target;
60
+ $('.mc-tabs .wptab').not(target).hide();
61
+ $(target).show().attr('tabindex','-1').focus();
62
+ });
63
+ }
64
+ });
65
+
66
+ $( '#mc-generator .custom' ).hide();
67
+ $( '#mc-generator select[name=type]' ).on( 'change', function () {
68
+ var selected = $( this ).val();
69
+ if ( selected == 'custom' ) {
70
+ $( '#mc-generator .custom' ).show();
71
+ } else {
72
+ $( '#mc-generator .custom' ).hide();
73
+ }
74
+ });
75
+ });
76
+
77
+ var mediaPopup = '';
78
+ (function ($) {
79
+ "use strict";
80
+ $(function () {
81
+ /**
82
+ * Clears any existing Media Manager instances
83
+ *
84
+ * @author Gabe Shackle <gabe@hereswhatidid.com>
85
+ * @modified Joe Dolson <plugins@joedolson.com>
86
+ * @return void
87
+ */
88
+ function clear_existing() {
89
+ if (typeof mediaPopup !== 'string') {
90
+ mediaPopup.detach();
91
+ mediaPopup = '';
92
+ }
93
+ }
94
+
95
+ $('.mc-image-upload')
96
+ .on('click', '.textfield-field', function (e) {
97
+ e.preventDefault();
98
+ var $self = $(this),
99
+ $inpField = $self.parent('.field-holder').find('#e_image'),
100
+ $idField = $self.parent('.field-holder').find('#e_image_id'),
101
+ $displayField = $self.parent('.field-holder').find('.event_image');
102
+ clear_existing();
103
+ mediaPopup = wp.media({
104
+ multiple: false, // add, reset, false
105
+ title: 'Choose an Uploaded Document',
106
+ button: {
107
+ text: 'Select'
108
+ }
109
+ });
110
+
111
+ mediaPopup.on('select', function () {
112
+ var selection = mediaPopup.state().get('selection'),
113
+ id = '',
114
+ img = '',
115
+ height = '',
116
+ width = '';
117
+ if (selection) {
118
+ id = selection.first().attributes.id;
119
+ height = thumbHeight;
120
+ width = ( ( selection.first().attributes.width ) / ( selection.first().attributes.height ) ) * thumbHeight;
121
+ img = "<img src='" + selection.first().attributes.url + "' width='" + width + "' height='" + height + "' />";
122
+ $inpField.val(selection.first().attributes.url);
123
+ $idField.val(id);
124
+ $displayField.html(img);
125
+ }
126
+ });
127
+ mediaPopup.open();
128
+ })
129
+ });
130
+ })(jQuery);
131
+
132
+ jQuery(document).ready(function ($) {
133
+ $('#mc-sortable').sortable({
134
+ update: function (event, ui) {
135
+ $('#mc-sortable-update').html( 'Submit form to save changes' );
136
+ }
137
+ });
138
+ $('#mc-sortable .up').on('click', function (e) {
139
+ e.preventDefault();
140
+ $(this).parents('li').insertBefore($(this).parents('li').prev());
141
+ $( '#mc-sortable li' ).removeClass( 'mc-updated' );
142
+ $(this).parents('li').addClass( 'mc-updated' );
143
+ });
144
+ $('#mc-sortable .down').on('click', function (e) {
145
+ e.preventDefault();
146
+ $(this).parents('li').insertAfter($(this).parents('li').next());
147
+ $( '#mc-sortable li' ).removeClass( 'mc-updated' );
148
+ $(this).parents('li').addClass( 'mc-updated' );
149
+ });
150
+ });
js/jquery.checkall.js DELETED
@@ -1,9 +0,0 @@
1
- jQuery(document).ready(function ($) {
2
- $(".selectall").click(function () {
3
- var checked_status = $(this).prop('checked');
4
- var checkbox_name = $(this).attr('id');
5
- $('input[name="' + checkbox_name + '[]"]').each(function () {
6
- $(this).prop('checked', checked_status);
7
- });
8
- });
9
- });
js/jquery.public.js ADDED
@@ -0,0 +1,19 @@
1
+ (function ($) {
2
+ $(function () {
3
+ // Delete single instances of recurring events.
4
+ $( '.mc_response' ).hide();
5
+ $('button.delete_occurrence').on( 'click', function () {
6
+ var value = $(this).attr( 'data-value' );
7
+ var data = {
8
+ 'action': mc_data.action,
9
+ 'occur_id': value,
10
+ 'security': mc_data.security
11
+ };
12
+ $.post( ajaxurl, data, function (response) {
13
+ if ( response.success == 1 ) {
14
+ $( "button[data-value='"+value+"']" ).parent( 'li' ).hide();
15
+ }
16
+ $('.mc_response').text( response.response ).show( 300 );
17
+ }, "json" );
18
+ });
19
+ }(jQuery));
js/mc-ajax.js CHANGED
@@ -1,39 +1,26 @@
1
(function ($) {
2
'use strict';
3
$(function () {
4
- $(document).on('click', '.calendar .my-calendar-nav a', function (e) {
5
e.preventDefault();
6
var link = $(this).attr('href');
7
- var height = $('.mc-main.calendar' ).height();
8
- var ref = $(this).attr('data-rel');
9
- $('#' + ref).html('<div class=\"mc-loading\"></div><div class=\"loading\" style=\"height:' + height + 'px\"><span class="screen-reader-text">Loading...</span></div>');
10
- $('#' + ref).load(link + ' #' + ref + ' > *', function () {
11
- $('.calendar-event').children().not('.event-title').hide();
12
- $('#' + ref).attr('tabindex', '-1').focus();
13
- });
14
- });
15
- $(document).on('click', '.list .my-calendar-nav a', function (e) {
16
- e.preventDefault();
17
- var link = $(this).attr('href');
18
- var ref = $(this).attr('data-rel');
19
- var height = $('.mc-main.list' ).height();
20
$('#' + ref).html('<div class=\"mc-loading\"></div><div class=\"loading\" style=\"height:' + height + 'px\"><span class="screen-reader-text">Loading...</span></div>');
21
$('#' + ref).load(link + ' #' + ref + ' > *', function () {
22
$('li.mc-events').children().not('.event-date').hide();
23
$('li.current-day').children().show();
24
- $('#' + ref).attr('tabindex', '-1').focus();
25
- });
26
- });
27
- $(document).on('click', '.mini .my-calendar-nav a', function (e) {
28
- e.preventDefault();
29
- var link = $(this).attr('href');
30
- var ref = $(this).attr('data-rel');
31
- var height = $('.mc-main.mini' ).height();
32
- $('#' + ref).html('<div class=\"mc-loading\"></div><div class=\"loading\" style=\"height:' + height + 'px\"><span class="screen-reader-text">Loading...</span></div>');
33
- $('#' + ref).load(link + ' #' + ref + ' > *', function () {
34
- $('.mini .has-events').children().not('.trigger, .mc-date, .event-date').hide();
35
- $('#' + ref).attr('tabindex', '-1').focus();
36
});
37
- });
38
});
39
- }(jQuery));
1
(function ($) {
2
'use strict';
3
$(function () {
4
+ $(document).on('click', '.my-calendar-header a.mcajax', function (e) {
5
+ var calendar = $( this ).closest( '.mc-main' );
6
+ var ref = calendar.attr('id');
7
e.preventDefault();
8
var link = $(this).attr('href');
9
+ var height = $('.mc-main' ).height();
10
$('#' + ref).html('<div class=\"mc-loading\"></div><div class=\"loading\" style=\"height:' + height + 'px\"><span class="screen-reader-text">Loading...</span></div>');
11
$('#' + ref).load(link + ' #' + ref + ' > *', function () {
12
+ // functions to execute when new view loads.
13
+ // List view
14
$('li.mc-events').children().not('.event-date').hide();
15
$('li.current-day').children().show();
16
+ // Grid view
17
+ $('.calendar .calendar-event').children().not('.event-title').hide();
18
+ // Mini view
19
+ $('.mini .has-events').children().not('.trigger, .mc-date, .event-date').hide();
20
+ // All views
21
+ $( '#' + ref ).attr('tabindex', '-1').focus();
22
+ // Your Custom ajax load changes if needed
23
});
24
+ });
25
});
26
+ }(jQuery));
js/mc-list.js CHANGED
@@ -10,10 +10,10 @@
10
$( this ).closest( '.mc-events' ).find( '.vevent' ).toggle();
11
vevent.attr("tabindex", "-1").focus();
12
var visible = $(this).closest( '.mc-events' ).find(".vevent").is(":visible");
13
- if (visible) {
14
- $(this).closest( '.mc-events' ).attr("aria-expanded", "true");
15
} else {
16
- $(this).closest( '.mc-events' ).attr("aria-expanded", "false");
17
}
18
});
19
});
10
$( this ).closest( '.mc-events' ).find( '.vevent' ).toggle();
11
vevent.attr("tabindex", "-1").focus();
12
var visible = $(this).closest( '.mc-events' ).find(".vevent").is(":visible");
13
+ if ( visible ) {
14
+ $(this).attr("aria-expanded", "true");
15
} else {
16
+ $(this).attr("aria-expanded", "false");
17
}
18
});
19
});
js/mcjs.js ADDED
@@ -0,0 +1 @@
1
+ (function ($) { 'use strict'; $(function () { $( '.mc-main' ).removeClass( 'mcjs' ); });}(jQuery));
js/sortable.js DELETED
@@ -1,19 +0,0 @@
1
- jQuery(document).ready(function ($) {
2
- $('#mc-sortable').sortable({
3
- update: function (event, ui) {
4
- $('#mc-sortable-update').html( 'Submit form to save changes' );
5
- }
6
- });
7
- $('#mc-sortable .up').on('click', function (e) {
8
- e.preventDefault();
9
- $(this).parents('li').insertBefore($(this).parents('li').prev());
10
- $( '#mc-sortable li' ).removeClass( 'mc-updated' );
11
- $(this).parents('li').addClass( 'mc-updated' );
12
- });
13
- $('#mc-sortable .down').on('click', function (e) {
14
- e.preventDefault();
15
- $(this).parents('li').insertAfter($(this).parents('li').next());
16
- $( '#mc-sortable li' ).removeClass( 'mc-updated' );
17
- $(this).parents('li').addClass( 'mc-updated' );
18
- });
19
- });
js/tabs.js DELETED
@@ -1,33 +0,0 @@
1
- jQuery(document).ready(function ($) {
2
- $( '.mc-tabs' ).each( function ( index ) {
3
- var tabs = $('.mc-tabs .wptab').length;
4
- var firstItem = window.location.hash;
5
- if ( ! firstItem ) {
6
- var firstItem = '#' + $( '.mc-tabs .wptab:nth-of-type(1)' ).attr( 'id' );
7
- }
8
- $('.mc-tabs .tabs a[href="' + firstItem + '"]').addClass('active').attr( 'aria-selected', 'true' );
9
- if ( tabs > 1 ) {
10
- $( '.mc-tabs .wptab' ).not( firstItem ).hide();
11
- $( firstItem ).show();
12
- $( '.mc-tabs .tabs a' ).on( 'click', function (e) {
13
- e.preventDefault();
14
- $('.mc-tabs .tabs a').removeClass('active').attr( 'aria-selected', 'false' );
15
- $(this).addClass('active').attr( 'aria-selected', 'true' );
16
- var target = $(this).attr('href');
17
- window.location.hash = target;
18
- $('.mc-tabs .wptab').not(target).hide();
19
- $(target).show().attr('tabindex','-1').focus();
20
- });
21
- }
22
- });
23
-
24
- $( '#mc-generator .custom' ).hide();
25
- $( '#mc-generator select[name=type]' ).on( 'change', function () {
26
- var selected = $( this ).val();
27
- if ( selected == 'custom' ) {
28
- $( '#mc-generator .custom' ).show();
29
- } else {
30
- $( '#mc-generator .custom' ).hide();
31
- }
32
- });
33
- });
js/upload.js DELETED
@@ -1,54 +0,0 @@
1
- var mediaPopup = '';
2
- (function ($) {
3
- "use strict";
4
- $(function () {
5
- /**
6
- * Clears any existing Media Manager instances
7
- *
8
- * @author Gabe Shackle <gabe@hereswhatidid.com>
9
- * @modified Joe Dolson <plugins@joedolson.com>
10
- * @return void
11
- */
12
- function clear_existing() {
13
- if (typeof mediaPopup !== 'string') {
14
- mediaPopup.detach();
15
- mediaPopup = '';
16
- }
17
- }
18
-
19
- $('.mc-image-upload')
20
- .on('click', '.textfield-field', function (e) {
21
- e.preventDefault();
22
- var $self = $(this),
23
- $inpField = $self.parent('.field-holder').find('#e_image'),
24
- $idField = $self.parent('.field-holder').find('#e_image_id'),
25
- $displayField = $self.parent('.field-holder').find('.event_image');
26
- clear_existing();
27
- mediaPopup = wp.media({
28
- multiple: false, // add, reset, false
29
- title: 'Choose an Uploaded Document',
30
- button: {
31
- text: 'Select'
32
- }
33
- });
34
-
35
- mediaPopup.on('select', function () {
36
- var selection = mediaPopup.state().get('selection'),
37
- id = '',
38
- img = '',
39
- height = '',
40
- width = '';
41
- if (selection) {
42
- id = selection.first().attributes.id;
43
- height = thumbHeight;
44
- width = ( ( selection.first().attributes.width ) / ( selection.first().attributes.height ) ) * thumbHeight;
45
- img = "<img src='" + selection.first().attributes.url + "' width='" + width + "' height='" + height + "' />";
46
- $inpField.val(selection.first().attributes.url);
47
- $idField.val(id);
48
- $displayField.html(img);
49
- }
50
- });
51
- mediaPopup.open();
52
- })
53
- });
54
- })(jQuery);