diff --git a/functions.php b/functions.php
index c494b505..424fd984 100644
--- a/functions.php
+++ b/functions.php
@@ -820,20 +820,97 @@ function metabox_order( $order ) {
);
}
+
/**
- * Add ACF fields to WP REST API JSON output
+ * Add custom fields to 'post' API endpoint
*
* @link https://gist.github.com/rileypaulsen/9b4505cdd0ac88d5ef51
+ *
+ * @param Object $data The data being added to the post object.
+ * @param Object $post The post being augmented.
+ * @param String $context Unused.
*/
-function wp_api_encode_acf( $data, $post, $context ) {
+function mitlib_api_v1_alter( $data, $post, $context ) {
$customMeta = (array) get_fields( $post['ID'] );
$data['meta'] = array_merge( $data['meta'], $customMeta );
return $data;
}
-if ( function_exists( 'get_fields' ) ) {
- add_filter( 'json_prepare_post', 'wp_api_encode_acf', 10, 3 );
+/**
+ * Adds custom fields to 'post' and 'experts' API endpoints
+ *
+ * @link http://v2.wp-api.org/extending/modifying/
+ * @link https://gist.github.com/rileypaulsen/9b4505cdd0ac88d5ef51#gistcomment-1622466
+ */
+function mitlib_api_v2_alter() {
+ // Add custom fields to posts endpoint.
+ register_rest_field( 'post',
+ 'meta',
+ array(
+ 'get_callback' => function( $data, $field, $request, $type ) {
+ if ( function_exists( 'get_fields' ) ) {
+ return get_fields( $data['id'] );
+ }
+ return array();
+ },
+ 'update_callback' => null,
+ 'schema' => null,
+ )
+ );
+
+ // Add custom fields to experts endpoint.
+ register_rest_field( 'experts',
+ 'meta',
+ array(
+ 'get_callback' => function( $data, $field, $request, $type ) {
+ if ( function_exists( 'get_fields' ) ) {
+ return get_fields( $data['id'] );
+ }
+ return array();
+ },
+ 'update_callback' => null,
+ 'schema' => null,
+ )
+ );
+
+ // Switch featured_media field from media ID to URL of the image.
+ register_rest_field( 'experts',
+ 'featured_media',
+ array(
+ 'get_callback' => 'mitlib_api_get_image',
+ 'update_callback' => null,
+ 'schema' => null,
+ )
+ );
+}
+
+
+/**
+ * This construct will swap between augmentation of the V1 and V2 API.
+ */
+if ( function_exists( 'register_rest_field' ) ) {
+ // The register_rest_field function was introduced in the v2 API.
+ // If that exists, then we call the function to augment that API.
+ add_action( 'rest_api_init', 'mitlib_api_v2_alter' );
+} else {
+ // If that function does not exist, then we call the old API augmentation.
+ if ( function_exists( 'get_fields' ) ) {
+ add_filter( 'json_prepare_post', 'mitlib_api_v1_alter', 10, 3 );
+ }
+}
+
+/**
+ * Get the value of a specified field for use in the API
+ *
+ * @param array $object Details of current post.
+ * @param string $field_name Name of field.
+ *
+ * @return mixed
+ */
+function mitlib_api_get_image( $object, $field_name ) {
+ $link = wp_get_attachment_image_src( $object[ $field_name ], 'thumbnail-size' );
+ return $link[0];
}
// Allows SVGs to be uploaded through media.
diff --git a/js/alerts.js b/js/alerts.js
index 11f27119..65ff8f94 100644
--- a/js/alerts.js
+++ b/js/alerts.js
@@ -1,118 +1,151 @@
// Loads alert-level posts on the top of all pages
-$(function mitlib_alerts(){
- var closable_alert = false,
- local_storage;
-
- // Check for localStorage
- if (Modernizr.localstorage) {
- local_storage = true;
- } else {
- local_storage = false;
- }
-
- $.ajax({
- cache: false,
- url: "/wp-json/posts",
- dataType: "json"
- })
- .done(function(json){
- var posts = json.length,
- post,
- alert_title,
- post_meta,
- is_alert,
- confirm,
- alert_posts_arr = [],
- alert_ID,
- alert_content,
- alert_template;
-
- for (var i = 0; i < posts; i++) {
- // Each post
- post = json[i];
- // Make sure the field exists
- if ($(post.meta).length) {
- // Post meta fields
- post_meta = post.meta;
- // Make sure the field exists
- if ($(post_meta.alert).length) {
- // Post alert field
- is_alert = post_meta.alert;
- // If an alert post
- if (is_alert === true) {
- // Confirm alert field
- confirm = post_meta.confirm_alert;
- if (confirm === true) {
- // Push alert posts to a unique array
- alert_posts_arr.push(post);
- }
- }
- }
- }
- };
- // If there is an alert post
- if (alert_posts_arr.length) {
- // The alert title
- alert_title = alert_posts_arr[0].title;
- // Check for empty title
- if (alert_title === '') {
- alert_title = 'Alert!'
- }
- // Alert post content
- alert_content = alert_posts_arr[0].content;
- // Alert post ID
- alert_ID = alert_posts_arr[0].ID;
-
- // Alert HTML template
- alert_template = '
' +
- '
' +
- '
' +
- '
' +
- '
' + alert_title + '
' + alert_content +
- '' +
- '
' +
- '
';
- // Closeable alert
- closable_alert = alert_posts_arr[0].meta.closable;
- // If localStorage
- if (local_storage === true) {
- // Check for the localStorage alert ID item
- if (localStorage.getItem('alert_closed-' + alert_ID) !== 'true') {
- // Append the template
- $(alert_template).prependTo('.wrap-page');
- $('.gldp-default').animate({"top":"292px"});
- // Remove the necessary transition class with a timeout, so that the animation shows.
- setTimeout(function() {
- $('.posts--preview--alerts').removeClass('transition-vertical--hide');
- }, 300);
- }
- } else { // No localStorage
- // Append the template, etc.
- $(alert_template).prependTo('.wrap-page');
- setTimeout(function() {
- $('.posts--preview--alerts').removeClass('transition-vertical--hide');
- }, 300);
- }
- // If this is a closable alert
- if (closable_alert === true) {
- // Add a Close icon/svg/button
- $('.posts--preview--alerts .post').append('');
- // On click
- $('#close').click(function(){
- // Add the necessary transition hide class
- $('.posts--preview--alerts').addClass('transition-vertical--hide');
- $('.gldp-default').css({"top":"105px"});
- // If localStorage
- if (local_storage === true) {
- // Set the localStorage item, using the post ID
- localStorage.setItem('alert_closed-' + alert_ID, 'true');
- }
- });
- }
+function filterAlerts(posts) {
+ // This processes an array of posts for valid, confirmed, alerts
+ var filtered = [],
+ post,
+ post_meta,
+ i;
+ for (i = 0; i < posts.length; i++) {
+ // Each post
+ post = posts[i];
+ // Make sure the field exists
+ if ($(post.meta).length) {
+ // Post meta fields
+ post_meta = post.meta;
+ // Make sure the field exists, is an alert, and is confirmed
+ if ($(post_meta.alert).length && true === post_meta.alert && true === post_meta.confirm_alert ) {
+ filtered.push(post);
}
+ }
+ };
- }).fail(function(){
- console.log('Alert posts failed to load');
+ return filtered;
+}
+
+function renderAlert(markup,id) {
+ // If localStorage
+ if (Modernizr.localstorage) {
+ // Check for the localStorage alert ID item
+ if (localStorage.getItem('alert_closed-' + id) !== 'true') {
+ // Append the template
+ $(markup).prependTo('.wrap-page');
+ $('.gldp-default').animate({"top":"292px"});
+ // Remove the necessary transition class with a timeout, so that the animation shows.
+ setTimeout(function() {
+ $('.posts--preview--alerts').removeClass('transition-vertical--hide');
+ }, 300);
+ }
+ } else { // No localStorage
+ // Append the template, etc.
+ $(markup).prependTo('.wrap-page');
+ setTimeout(function() {
+ $('.posts--preview--alerts').removeClass('transition-vertical--hide');
+ }, 300);
+ }
+}
+
+function setClosable(alert_ID) {
+ // Add a Close icon/svg/button
+ $('.posts--preview--alerts .post').append('');
+ // On click
+ $('#close').click(function(){
+ // Add the necessary transition hide class
+ $('.posts--preview--alerts').addClass('transition-vertical--hide');
+ $('.gldp-default').css({"top":"105px"});
+ // If localStorage
+ if (Modernizr.localstorage) {
+ // Set the localStorage item, using the post ID
+ localStorage.setItem('alert_closed-' + alert_ID, 'true');
+ }
+ });
+}
+
+function showAlertsV1(json) {
+ var alert_posts_arr = [],
+ alert_ID,
+ alert_template;
+
+ alert_posts_arr = filterAlerts(json)
+
+ // If there is an alert post
+ if (alert_posts_arr.length) {
+
+ // Check for empty title
+ if ('' === alert_posts_arr[0].title) {
+ alert_posts_arr[0].title = 'Alert!';
+ }
+
+ // Alert post ID
+ alert_ID = alert_posts_arr[0].id;
+
+ // Alert HTML template
+ alert_template = '' +
+ '
' +
+ '
' +
+ '
' +
+ '
' + alert_posts_arr[0].title + '
' + alert_posts_arr[0].content +
+ '' +
+ '
' +
+ '
';
+
+ renderAlert(alert_template,alert_ID);
+
+ // If this is a closable alert
+ if (true === alert_posts_arr[0].meta.closable) {
+ setClosable(alert_ID);
+ }
+ }
+}
+
+function showAlertsV2(json) {
+ var alert_posts_arr = [],
+ alert_ID,
+ alert_template;
+
+ alert_posts_arr = filterAlerts(json)
+
+ // If there is an alert post
+ if (alert_posts_arr.length) {
+
+ // Check for empty title
+ if ('' === alert_posts_arr[0].title.rendered) {
+ alert_posts_arr[0].title.rendered = 'Alert!';
+ }
+
+ // Alert HTML template
+ alert_template = '' +
+ '
' +
+ '
' +
+ '
' +
+ '
' + alert_posts_arr[0].title.rendered + '
' + alert_posts_arr[0].content.rendered +
+ '' +
+ '
' +
+ '
';
+
+ // Alert post ID
+ alert_ID = alert_posts_arr[0].id;
+
+ renderAlert(alert_template,alert_ID);
+
+ // If this is a closable alert
+ if (true === alert_posts_arr[0].meta.closable) {
+ setClosable(alert_ID);
+ }
+ }
+}
+
+$(function(){
+ // This is a temporary construct to make transitioning between API endpoints seamless.
+ // It tries the v1 endpoint first, and if that fails then falls back to the v2 endpoint.
+ $.getJSON('/wp-json/posts')
+ .done(function(data){
+ showAlertsV1(data);
+ })
+ .fail(function(){
+ $.getJSON('/wp-json/wp/v2/posts')
+ .done(function(data){
+ showAlertsV2(data);
+ });
});
});
diff --git a/js/experts-home.js b/js/experts-home.js
index b5bf00cc..d27e5aa7 100644
--- a/js/experts-home.js
+++ b/js/experts-home.js
@@ -2,86 +2,158 @@
// Experts
//
+// This implements a Fisher-Yates shuffle.
+// See also: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+function shuffleExperts(data) {
+ var m = data.length, t, i;
+
+ // While there remain elements to shuffle…
+ while (m) {
+
+ // Pick a remaining element…
+ i = Math.floor(Math.random() * m--);
+
+ // And swap it with the current element.
+ t = data[m];
+ data[m] = data[i];
+ data[i] = t;
+ }
+ return data;
+}
+
+// This parses the data structure returned by the V1 API
+function parseExpertsV1(data) {
+
+ // Expert names
+ var expertName1 = data[0].title;
+ var expertName2 = data[1].title;
+ var expertName3 = data[2].title;
+ var expertName4 = data[3].title;
+
+ // Expert images
+ var expertPhoto1 = data[0].featured_image.source;
+ var expertPhoto2 = data[1].featured_image.source;
+ var expertPhoto3 = data[2].featured_image.source;
+ var expertPhoto4 = data[3].featured_image.source;
+
+ // Expert job titles (post excerpts)
+ var expertExcerpt1 = data[0].excerpt;
+ var expertExcerpt2 = data[1].excerpt;
+ var expertExcerpt3 = data[2].excerpt;
+ var expertExcerpt4 = data[3].excerpt;
+
+ // Expert URL (currently an ACF field)
+ var expertURL1 = data[0].meta.expert_url;
+ var expertURL2 = data[1].meta.expert_url;
+ var expertURL3 = data[2].meta.expert_url;
+ var expertURL4 = data[3].meta.expert_url;
+
+ // Append extra markup only if JSON request successful
+ $('.expert').append('');
+ // Append expert image div
+ $('.expert .link-profile').append('
');
+ // Append empty spans for expert names
+ $('.expert .link-profile').append('');
+ // Append empty spans for expert titles
+ $('.expert .link-profile').append('');
+ // Add expert name to appropriate span
+ $('.expert .name:eq(0)').text(expertName1);
+ $('.expert .name:eq(1)').text(expertName2);
+ $('.expert .name:eq(2)').text(expertName3);
+ $('.expert .name:eq(3)').text(expertName4);
+ // Add image URL to src attribute
+ $('.expert .expert-photo:eq(0)').attr('src', expertPhoto1);
+ $('.expert .expert-photo:eq(1)').attr('src', expertPhoto2);
+ $('.expert .expert-photo:eq(2)').attr('src', expertPhoto3);
+ $('.expert .expert-photo:eq(3)').attr('src', expertPhoto4);
+ // Add expert excerpt
+ $('.expert .title-job:eq(0)').html(expertExcerpt1);
+ $('.expert .title-job:eq(1)').html(expertExcerpt2);
+ $('.expert .title-job:eq(2)').html(expertExcerpt3);
+ $('.expert .title-job:eq(3)').html(expertExcerpt4);
+ // Add expert URL
+ $('.expert .link-profile:eq(0)').attr('href', expertURL1);
+ $('.expert .link-profile:eq(1)').attr('href', expertURL2);
+ $('.expert .link-profile:eq(2)').attr('href', expertURL3);
+ $('.expert .link-profile:eq(3)').attr('href', expertURL4);
+ // Add the expert count to the "All Experts" button
+ $('.view-experts .count').text(data.length);
+}
+
+// This parses the data structure returned by the V2 API
+function parseExpertsV2(data) {
+
+ // Expert names
+ var expertName1 = data[0].title.rendered;
+ var expertName2 = data[1].title.rendered;
+ var expertName3 = data[2].title.rendered;
+ var expertName4 = data[3].title.rendered;
+
+ // Expert images
+ var expertPhoto1 = data[0].featured_media;
+ var expertPhoto2 = data[1].featured_media;
+ var expertPhoto3 = data[2].featured_media;
+ var expertPhoto4 = data[3].featured_media;
+
+ // Expert job titles (post excerpts)
+ var expertExcerpt1 = data[0].excerpt.rendered;
+ var expertExcerpt2 = data[1].excerpt.rendered;
+ var expertExcerpt3 = data[2].excerpt.rendered;
+ var expertExcerpt4 = data[3].excerpt.rendered;
+
+ // Expert URL (currently an ACF field)
+ var expertURL1 = data[0].meta.expert_url;
+ var expertURL2 = data[1].meta.expert_url;
+ var expertURL3 = data[2].meta.expert_url;
+ var expertURL4 = data[3].meta.expert_url;
+
+ // Append extra markup only if JSON request successful
+ $('.expert').append('');
+ // Append expert image div
+ $('.expert .link-profile').append('
');
+ // Append empty spans for expert names
+ $('.expert .link-profile').append('');
+ // Append empty spans for expert titles
+ $('.expert .link-profile').append('');
+ // Add expert name to appropriate span
+ $('.expert .name:eq(0)').text(expertName1);
+ $('.expert .name:eq(1)').text(expertName2);
+ $('.expert .name:eq(2)').text(expertName3);
+ $('.expert .name:eq(3)').text(expertName4);
+ // Add image URL to src attribute
+ $('.expert .expert-photo:eq(0)').attr('src', expertPhoto1);
+ $('.expert .expert-photo:eq(1)').attr('src', expertPhoto2);
+ $('.expert .expert-photo:eq(2)').attr('src', expertPhoto3);
+ $('.expert .expert-photo:eq(3)').attr('src', expertPhoto4);
+ // Add expert excerpt
+ $('.expert .title-job:eq(0)').html(expertExcerpt1);
+ $('.expert .title-job:eq(1)').html(expertExcerpt2);
+ $('.expert .title-job:eq(2)').html(expertExcerpt3);
+ $('.expert .title-job:eq(3)').html(expertExcerpt4);
+ // Add expert URL
+ $('.expert .link-profile:eq(0)').attr('href', expertURL1);
+ $('.expert .link-profile:eq(1)').attr('href', expertURL2);
+ $('.expert .link-profile:eq(2)').attr('href', expertURL3);
+ $('.expert .link-profile:eq(3)').attr('href', expertURL4);
+ // Add the expert count to the "All Experts" button
+ $('.view-experts .count').text(data.length);
+}
+
$(function(){
+ // This is a temporary construct to make transitioning between API endpoints seamless.
+ // It tries the v1 endpoint first, and if that fails then falls back to the v2 endpoint.
+ // Much of this could be eliminated by just loading this URL:
+ // /wp-json/wp/v2/experts?filter[orderby]=rand&filter[posts_per_page]=4
$.getJSON('/wp-json/posts?type=experts')
.done(function(data){
- // Count the objects
- var dataLength = data.length;
-
- // Fisher–Yates Shuffle
- function shuffle() {
- var m = dataLength, t, i;
-
- // While there remain elements to shuffle…
- while (m) {
-
- // Pick a remaining element…
- i = Math.floor(Math.random() * m--);
-
- // And swap it with the current element.
- t = data[m];
- data[m] = data[i];
- data[i] = t;
- }
- return data;
- }
- // Shuffle the array
- shuffle(data);
-
- // Expert names
- var expertName1 = data[0].title;
- var expertName2 = data[1].title;
- var expertName3 = data[2].title;
- var expertName4 = data[3].title;
-
- // Expert images
- var expertPhoto1 = data[0].featured_image.source;
- var expertPhoto2 = data[1].featured_image.source;
- var expertPhoto3 = data[2].featured_image.source;
- var expertPhoto4 = data[3].featured_image.source;
-
- // Expert job titles (post excerpts)
- var expertExcerpt1 = data[0].excerpt;
- var expertExcerpt2 = data[1].excerpt;
- var expertExcerpt3 = data[2].excerpt;
- var expertExcerpt4 = data[3].excerpt;
-
- // Expert URL (currently an ACF field)
- var expertURL1 = data[0].meta.expert_url;
- var expertURL2 = data[1].meta.expert_url;
- var expertURL3 = data[2].meta.expert_url;
- var expertURL4 = data[3].meta.expert_url;
-
- // Append extra markup only if JSON request successful
- $('.expert').append('');
- // Append expert image div
- $('.expert .link-profile').append('
');
- // Append empty spans for expert names
- $('.expert .link-profile').append('');
- // Append empty spans for expert titles
- $('.expert .link-profile').append('');
- // Add expert name to appropriate span
- $('.expert .name:eq(0)').text(expertName1);
- $('.expert .name:eq(1)').text(expertName2);
- $('.expert .name:eq(2)').text(expertName3);
- $('.expert .name:eq(3)').text(expertName4);
- // Add image URL to src attribute
- $('.expert .expert-photo:eq(0)').attr('src', expertPhoto1);
- $('.expert .expert-photo:eq(1)').attr('src', expertPhoto2);
- $('.expert .expert-photo:eq(2)').attr('src', expertPhoto3);
- $('.expert .expert-photo:eq(3)').attr('src', expertPhoto4);
- // Add expert excerpt
- $('.expert .title-job:eq(0)').html(expertExcerpt1);
- $('.expert .title-job:eq(1)').html(expertExcerpt2);
- $('.expert .title-job:eq(2)').html(expertExcerpt3);
- $('.expert .title-job:eq(3)').html(expertExcerpt4);
- // Add expert URL
- $('.expert .link-profile:eq(0)').attr('href', expertURL1);
- $('.expert .link-profile:eq(1)').attr('href', expertURL2);
- $('.expert .link-profile:eq(2)').attr('href', expertURL3);
- $('.expert .link-profile:eq(3)').attr('href', expertURL4);
- // Add the expert count to the "All Experts" button
- $('.view-experts .count').text(dataLength);
+ parseExpertsV1(shuffleExperts(data));
+ })
+ .fail(function(){
+ $.getJSON('/wp-json/wp/v2/experts?per_page=99')
+ .done(function(data){
+ parseExpertsV2(shuffleExperts(data));
+ });
});
+
});