27 |
28 |
28 welcomePanelHide.click( function() { |
29 welcomePanelHide.click( function() { |
29 welcomePanel.toggleClass('hidden', ! this.checked ); |
30 welcomePanel.toggleClass('hidden', ! this.checked ); |
30 updateWelcomePanel( this.checked ? 1 : 0 ); |
31 updateWelcomePanel( this.checked ? 1 : 0 ); |
31 }); |
32 }); |
|
33 |
|
34 var tryGutenbergPanel = $( '#try-gutenberg-panel' ), |
|
35 tryGutenbergPanelHide = $('#wp_try_gutenberg_panel-hide'), |
|
36 updateTryGutenbergPanel, installGutenbergSuccess; |
|
37 |
|
38 updateTryGutenbergPanel = function( visible ) { |
|
39 $.post( ajaxurl, { |
|
40 action: 'update-try-gutenberg-panel', |
|
41 visible: visible, |
|
42 trygutenbergpanelnonce: $( '#trygutenbergpanelnonce' ).val() |
|
43 }); |
|
44 }; |
|
45 |
|
46 installGutenbergSuccess = function( response ) { |
|
47 response.activateUrl += '&from=try-gutenberg'; |
|
48 response.activateLabel = wp.updates.l10n.activatePluginLabel.replace( '%s', response.pluginName ); |
|
49 wp.updates.installPluginSuccess( response ); |
|
50 }; |
|
51 |
|
52 if ( tryGutenbergPanel.hasClass( 'hidden' ) && tryGutenbergPanelHide.prop( 'checked' ) ) { |
|
53 tryGutenbergPanel.removeClass( 'hidden' ); |
|
54 } |
|
55 |
|
56 $( '.try-gutenberg-panel-close, .try-gutenberg-panel-dismiss a', tryGutenbergPanel ).click( function( e ) { |
|
57 e.preventDefault(); |
|
58 tryGutenbergPanel.addClass( 'hidden' ); |
|
59 updateTryGutenbergPanel( 0 ); |
|
60 $('#wp_try_gutenberg_panel-hide').prop( 'checked', false ); |
|
61 }); |
|
62 |
|
63 tryGutenbergPanelHide.click( function() { |
|
64 tryGutenbergPanel.toggleClass( 'hidden', ! this.checked ); |
|
65 updateTryGutenbergPanel( this.checked ? 1 : 0 ); |
|
66 }); |
|
67 |
|
68 tryGutenbergPanel.on( 'click', '.install-now', function( e ) { |
|
69 e.preventDefault(); |
|
70 var args = { |
|
71 slug: $( e.target ).data( 'slug' ), |
|
72 success: installGutenbergSuccess |
|
73 }; |
|
74 wp.updates.installPlugin( args ); |
|
75 } ); |
32 |
76 |
33 // These widgets are sometimes populated via ajax |
77 // These widgets are sometimes populated via ajax |
34 ajaxWidgets = ['dashboard_primary']; |
78 ajaxWidgets = ['dashboard_primary']; |
35 |
79 |
36 ajaxPopulateWidgets = function(el) { |
80 ajaxPopulateWidgets = function(el) { |
186 $this.css('height', editorHeight + 'px'); |
229 $this.css('height', editorHeight + 'px'); |
187 }); |
230 }); |
188 } |
231 } |
189 |
232 |
190 } ); |
233 } ); |
|
234 |
|
235 jQuery( function( $ ) { |
|
236 'use strict'; |
|
237 |
|
238 var communityEventsData = window.communityEventsData || {}, |
|
239 app; |
|
240 |
|
241 app = window.wp.communityEvents = { |
|
242 initialized: false, |
|
243 model: null, |
|
244 |
|
245 /** |
|
246 * Initializes the wp.communityEvents object. |
|
247 * |
|
248 * @since 4.8.0 |
|
249 */ |
|
250 init: function() { |
|
251 if ( app.initialized ) { |
|
252 return; |
|
253 } |
|
254 |
|
255 var $container = $( '#community-events' ); |
|
256 |
|
257 /* |
|
258 * When JavaScript is disabled, the errors container is shown, so |
|
259 * that "This widget requires JavaScript" message can be seen. |
|
260 * |
|
261 * When JS is enabled, the container is hidden at first, and then |
|
262 * revealed during the template rendering, if there actually are |
|
263 * errors to show. |
|
264 * |
|
265 * The display indicator switches from `hide-if-js` to `aria-hidden` |
|
266 * here in order to maintain consistency with all the other fields |
|
267 * that key off of `aria-hidden` to determine their visibility. |
|
268 * `aria-hidden` can't be used initially, because there would be no |
|
269 * way to set it to false when JavaScript is disabled, which would |
|
270 * prevent people from seeing the "This widget requires JavaScript" |
|
271 * message. |
|
272 */ |
|
273 $( '.community-events-errors' ) |
|
274 .attr( 'aria-hidden', 'true' ) |
|
275 .removeClass( 'hide-if-js' ); |
|
276 |
|
277 $container.on( 'click', '.community-events-toggle-location, .community-events-cancel', app.toggleLocationForm ); |
|
278 |
|
279 $container.on( 'submit', '.community-events-form', function( event ) { |
|
280 var location = $.trim( $( '#community-events-location' ).val() ); |
|
281 |
|
282 event.preventDefault(); |
|
283 |
|
284 /* |
|
285 * Don't trigger a search if the search field is empty or the |
|
286 * search term was made of only spaces before being trimmed. |
|
287 */ |
|
288 if ( ! location ) { |
|
289 return; |
|
290 } |
|
291 |
|
292 app.getEvents({ |
|
293 location: location |
|
294 }); |
|
295 }); |
|
296 |
|
297 if ( communityEventsData && communityEventsData.cache && communityEventsData.cache.location && communityEventsData.cache.events ) { |
|
298 app.renderEventsTemplate( communityEventsData.cache, 'app' ); |
|
299 } else { |
|
300 app.getEvents(); |
|
301 } |
|
302 |
|
303 app.initialized = true; |
|
304 }, |
|
305 |
|
306 /** |
|
307 * Toggles the visibility of the Edit Location form. |
|
308 * |
|
309 * @since 4.8.0 |
|
310 * |
|
311 * @param {event|string} action 'show' or 'hide' to specify a state; |
|
312 * or an event object to flip between states. |
|
313 */ |
|
314 toggleLocationForm: function( action ) { |
|
315 var $toggleButton = $( '.community-events-toggle-location' ), |
|
316 $cancelButton = $( '.community-events-cancel' ), |
|
317 $form = $( '.community-events-form' ), |
|
318 $target = $(); |
|
319 |
|
320 if ( 'object' === typeof action ) { |
|
321 // The action is the event object: get the clicked element. |
|
322 $target = $( action.target ); |
|
323 /* |
|
324 * Strict comparison doesn't work in this case because sometimes |
|
325 * we explicitly pass a string as value of aria-expanded and |
|
326 * sometimes a boolean as the result of an evaluation. |
|
327 */ |
|
328 action = 'true' == $toggleButton.attr( 'aria-expanded' ) ? 'hide' : 'show'; |
|
329 } |
|
330 |
|
331 if ( 'hide' === action ) { |
|
332 $toggleButton.attr( 'aria-expanded', 'false' ); |
|
333 $cancelButton.attr( 'aria-expanded', 'false' ); |
|
334 $form.attr( 'aria-hidden', 'true' ); |
|
335 /* |
|
336 * If the Cancel button has been clicked, bring the focus back |
|
337 * to the toggle button so users relying on screen readers don't |
|
338 * lose their place. |
|
339 */ |
|
340 if ( $target.hasClass( 'community-events-cancel' ) ) { |
|
341 $toggleButton.focus(); |
|
342 } |
|
343 } else { |
|
344 $toggleButton.attr( 'aria-expanded', 'true' ); |
|
345 $cancelButton.attr( 'aria-expanded', 'true' ); |
|
346 $form.attr( 'aria-hidden', 'false' ); |
|
347 } |
|
348 }, |
|
349 |
|
350 /** |
|
351 * Sends REST API requests to fetch events for the widget. |
|
352 * |
|
353 * @since 4.8.0 |
|
354 * |
|
355 * @param {object} requestParams |
|
356 */ |
|
357 getEvents: function( requestParams ) { |
|
358 var initiatedBy, |
|
359 app = this, |
|
360 $spinner = $( '.community-events-form' ).children( '.spinner' ); |
|
361 |
|
362 requestParams = requestParams || {}; |
|
363 requestParams._wpnonce = communityEventsData.nonce; |
|
364 requestParams.timezone = window.Intl ? window.Intl.DateTimeFormat().resolvedOptions().timeZone : ''; |
|
365 |
|
366 initiatedBy = requestParams.location ? 'user' : 'app'; |
|
367 |
|
368 $spinner.addClass( 'is-active' ); |
|
369 |
|
370 wp.ajax.post( 'get-community-events', requestParams ) |
|
371 .always( function() { |
|
372 $spinner.removeClass( 'is-active' ); |
|
373 }) |
|
374 |
|
375 .done( function( response ) { |
|
376 if ( 'no_location_available' === response.error ) { |
|
377 if ( requestParams.location ) { |
|
378 response.unknownCity = requestParams.location; |
|
379 } else { |
|
380 /* |
|
381 * No location was passed, which means that this was an automatic query |
|
382 * based on IP, locale, and timezone. Since the user didn't initiate it, |
|
383 * it should fail silently. Otherwise, the error could confuse and/or |
|
384 * annoy them. |
|
385 */ |
|
386 delete response.error; |
|
387 } |
|
388 } |
|
389 app.renderEventsTemplate( response, initiatedBy ); |
|
390 }) |
|
391 |
|
392 .fail( function() { |
|
393 app.renderEventsTemplate({ |
|
394 'location' : false, |
|
395 'error' : true |
|
396 }, initiatedBy ); |
|
397 }); |
|
398 }, |
|
399 |
|
400 /** |
|
401 * Renders the template for the Events section of the Events & News widget. |
|
402 * |
|
403 * @since 4.8.0 |
|
404 * |
|
405 * @param {Object} templateParams The various parameters that will get passed to wp.template. |
|
406 * @param {string} initiatedBy 'user' to indicate that this was triggered manually by the user; |
|
407 * 'app' to indicate it was triggered automatically by the app itself. |
|
408 */ |
|
409 renderEventsTemplate: function( templateParams, initiatedBy ) { |
|
410 var template, |
|
411 elementVisibility, |
|
412 l10nPlaceholder = /%(?:\d\$)?s/g, // Match `%s`, `%1$s`, `%2$s`, etc. |
|
413 $toggleButton = $( '.community-events-toggle-location' ), |
|
414 $locationMessage = $( '#community-events-location-message' ), |
|
415 $results = $( '.community-events-results' ); |
|
416 |
|
417 /* |
|
418 * Hide all toggleable elements by default, to keep the logic simple. |
|
419 * Otherwise, each block below would have to turn hide everything that |
|
420 * could have been shown at an earlier point. |
|
421 * |
|
422 * The exception to that is that the .community-events container is hidden |
|
423 * when the page is first loaded, because the content isn't ready yet, |
|
424 * but once we've reached this point, it should always be shown. |
|
425 */ |
|
426 elementVisibility = { |
|
427 '.community-events' : true, |
|
428 '.community-events-loading' : false, |
|
429 '.community-events-errors' : false, |
|
430 '.community-events-error-occurred' : false, |
|
431 '.community-events-could-not-locate' : false, |
|
432 '#community-events-location-message' : false, |
|
433 '.community-events-toggle-location' : false, |
|
434 '.community-events-results' : false |
|
435 }; |
|
436 |
|
437 /* |
|
438 * Determine which templates should be rendered and which elements |
|
439 * should be displayed. |
|
440 */ |
|
441 if ( templateParams.location.ip ) { |
|
442 /* |
|
443 * If the API determined the location by geolocating an IP, it will |
|
444 * provide events, but not a specific location. |
|
445 */ |
|
446 $locationMessage.text( communityEventsData.l10n.attend_event_near_generic ); |
|
447 |
|
448 if ( templateParams.events.length ) { |
|
449 template = wp.template( 'community-events-event-list' ); |
|
450 $results.html( template( templateParams ) ); |
|
451 } else { |
|
452 template = wp.template( 'community-events-no-upcoming-events' ); |
|
453 $results.html( template( templateParams ) ); |
|
454 } |
|
455 |
|
456 elementVisibility['#community-events-location-message'] = true; |
|
457 elementVisibility['.community-events-toggle-location'] = true; |
|
458 elementVisibility['.community-events-results'] = true; |
|
459 |
|
460 } else if ( templateParams.location.description ) { |
|
461 template = wp.template( 'community-events-attend-event-near' ); |
|
462 $locationMessage.html( template( templateParams ) ); |
|
463 |
|
464 if ( templateParams.events.length ) { |
|
465 template = wp.template( 'community-events-event-list' ); |
|
466 $results.html( template( templateParams ) ); |
|
467 } else { |
|
468 template = wp.template( 'community-events-no-upcoming-events' ); |
|
469 $results.html( template( templateParams ) ); |
|
470 } |
|
471 |
|
472 if ( 'user' === initiatedBy ) { |
|
473 wp.a11y.speak( communityEventsData.l10n.city_updated.replace( l10nPlaceholder, templateParams.location.description ), 'assertive' ); |
|
474 } |
|
475 |
|
476 elementVisibility['#community-events-location-message'] = true; |
|
477 elementVisibility['.community-events-toggle-location'] = true; |
|
478 elementVisibility['.community-events-results'] = true; |
|
479 |
|
480 } else if ( templateParams.unknownCity ) { |
|
481 template = wp.template( 'community-events-could-not-locate' ); |
|
482 $( '.community-events-could-not-locate' ).html( template( templateParams ) ); |
|
483 wp.a11y.speak( communityEventsData.l10n.could_not_locate_city.replace( l10nPlaceholder, templateParams.unknownCity ) ); |
|
484 |
|
485 elementVisibility['.community-events-errors'] = true; |
|
486 elementVisibility['.community-events-could-not-locate'] = true; |
|
487 |
|
488 } else if ( templateParams.error && 'user' === initiatedBy ) { |
|
489 /* |
|
490 * Errors messages are only shown for requests that were initiated |
|
491 * by the user, not for ones that were initiated by the app itself. |
|
492 * Showing error messages for an event that user isn't aware of |
|
493 * could be confusing or unnecessarily distracting. |
|
494 */ |
|
495 wp.a11y.speak( communityEventsData.l10n.error_occurred_please_try_again ); |
|
496 |
|
497 elementVisibility['.community-events-errors'] = true; |
|
498 elementVisibility['.community-events-error-occurred'] = true; |
|
499 } else { |
|
500 $locationMessage.text( communityEventsData.l10n.enter_closest_city ); |
|
501 |
|
502 elementVisibility['#community-events-location-message'] = true; |
|
503 elementVisibility['.community-events-toggle-location'] = true; |
|
504 } |
|
505 |
|
506 // Set the visibility of toggleable elements. |
|
507 _.each( elementVisibility, function( isVisible, element ) { |
|
508 $( element ).attr( 'aria-hidden', ! isVisible ); |
|
509 }); |
|
510 |
|
511 $toggleButton.attr( 'aria-expanded', elementVisibility['.community-events-toggle-location'] ); |
|
512 |
|
513 if ( templateParams.location && ( templateParams.location.ip || templateParams.location.latitude ) ) { |
|
514 // Hide the form when there's a valid location. |
|
515 app.toggleLocationForm( 'hide' ); |
|
516 |
|
517 if ( 'user' === initiatedBy ) { |
|
518 /* |
|
519 * When the form is programmatically hidden after a user search, |
|
520 * bring the focus back to the toggle button so users relying |
|
521 * on screen readers don't lose their place. |
|
522 */ |
|
523 $toggleButton.focus(); |
|
524 } |
|
525 } else { |
|
526 app.toggleLocationForm( 'show' ); |
|
527 } |
|
528 } |
|
529 }; |
|
530 |
|
531 if ( $( '#dashboard_primary' ).is( ':visible' ) ) { |
|
532 app.init(); |
|
533 } else { |
|
534 $( document ).on( 'postbox-toggled', function( event, postbox ) { |
|
535 var $postbox = $( postbox ); |
|
536 |
|
537 if ( 'dashboard_primary' === $postbox.attr( 'id' ) && $postbox.is( ':visible' ) ) { |
|
538 app.init(); |
|
539 } |
|
540 }); |
|
541 } |
|
542 }); |