summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/jetpack/modules/related-posts/related-posts.js')
-rw-r--r--plugins/jetpack/modules/related-posts/related-posts.js331
1 files changed, 331 insertions, 0 deletions
diff --git a/plugins/jetpack/modules/related-posts/related-posts.js b/plugins/jetpack/modules/related-posts/related-posts.js
new file mode 100644
index 00000000..f8fa781b
--- /dev/null
+++ b/plugins/jetpack/modules/related-posts/related-posts.js
@@ -0,0 +1,331 @@
+/* jshint onevar: false */
+/* globals related_posts_js_options */
+
+/**
+ * Load related posts
+ */
+( function( $ ) {
+ var jprp = {
+ response: null,
+
+ /**
+ * Utility get related posts JSON endpoint from URLs
+ *
+ * @param {string} URL (optional)
+ * @return {string} Endpoint URL
+ */
+ getEndpointURL: function( URL ) {
+ var locationObject,
+ is_customizer =
+ 'undefined' !== typeof wp &&
+ wp.customize &&
+ wp.customize.settings &&
+ wp.customize.settings.url &&
+ wp.customize.settings.url.self;
+
+ // If we're in Customizer, write the correct URL.
+ if ( is_customizer ) {
+ locationObject = document.createElement( 'a' );
+ locationObject.href = wp.customize.settings.url.self;
+ } else {
+ locationObject = document.location;
+ }
+
+ if ( 'string' === typeof URL && URL.match( /^https?:\/\// ) ) {
+ locationObject = document.createElement( 'a' );
+ locationObject.href = URL;
+ }
+
+ var args = 'relatedposts=1';
+ if ( $( '#jp-relatedposts' ).data( 'exclude' ) ) {
+ args += '&relatedposts_exclude=' + $( '#jp-relatedposts' ).data( 'exclude' );
+ }
+
+ if ( is_customizer ) {
+ args += '&jetpackrpcustomize=1';
+ }
+
+ var pathname = locationObject.pathname;
+ if ( '/' !== pathname[ 0 ] ) {
+ pathname = '/' + pathname;
+ }
+
+ if ( '' === locationObject.search ) {
+ return pathname + '?' + args;
+ } else {
+ return pathname + locationObject.search + '&' + args;
+ }
+ },
+
+ getAnchor: function( post, classNames ) {
+ var anchor_title = post.title;
+ if ( '' !== '' + post.excerpt ) {
+ anchor_title += '\n\n' + post.excerpt;
+ }
+
+ var anchor = $( '<a>' );
+
+ anchor.attr( {
+ class: classNames,
+ href: post.url,
+ title: anchor_title,
+ rel: post.rel,
+ 'data-origin': post.url_meta.origin,
+ 'data-position': post.url_meta.position,
+ } );
+
+ var anchor_html = $( '<div>' )
+ .append( anchor )
+ .html();
+ return [ anchor_html.substring( 0, anchor_html.length - 4 ), '</a>' ];
+ },
+
+ generateMinimalHtml: function( posts, options ) {
+ var self = this;
+ var html = '';
+
+ $.each( posts, function( index, post ) {
+ var anchor = self.getAnchor( post, 'jp-relatedposts-post-a' );
+ var classes = 'jp-relatedposts-post jp-relatedposts-post' + index;
+
+ if ( post.classes.length > 0 ) {
+ classes += ' ' + post.classes.join( ' ' );
+ }
+
+ html +=
+ '<p class="' +
+ classes +
+ '" data-post-id="' +
+ post.id +
+ '" data-post-format="' +
+ post.format +
+ '">';
+ html +=
+ '<span class="jp-relatedposts-post-title">' +
+ anchor[ 0 ] +
+ post.title +
+ anchor[ 1 ] +
+ '</span>';
+ if ( options.showDate ) {
+ html += '<span class="jp-relatedposts-post-date">' + post.date + '</span>';
+ }
+ if ( options.showContext ) {
+ html += '<span class="jp-relatedposts-post-context">' + post.context + '</span>';
+ }
+ html += '</p>';
+ } );
+ return (
+ '<div class="jp-relatedposts-items jp-relatedposts-items-minimal jp-relatedposts-' +
+ options.layout +
+ ' ">' +
+ html +
+ '</div>'
+ );
+ },
+
+ generateVisualHtml: function( posts, options ) {
+ var self = this;
+ var html = '';
+
+ $.each( posts, function( index, post ) {
+ var anchor = self.getAnchor( post, 'jp-relatedposts-post-a' );
+ var classes = 'jp-relatedposts-post jp-relatedposts-post' + index;
+
+ if ( post.classes.length > 0 ) {
+ classes += ' ' + post.classes.join( ' ' );
+ }
+
+ if ( ! post.img.src ) {
+ classes += ' jp-relatedposts-post-nothumbs';
+ } else {
+ classes += ' jp-relatedposts-post-thumbs';
+ }
+
+ html +=
+ '<div class="' +
+ classes +
+ '" data-post-id="' +
+ post.id +
+ '" data-post-format="' +
+ post.format +
+ '">';
+ if ( post.img.src ) {
+ html +=
+ anchor[ 0 ] +
+ '<img class="jp-relatedposts-post-img" src="' +
+ post.img.src +
+ '" width="' +
+ post.img.width +
+ '" alt="' +
+ post.title +
+ '" />' +
+ anchor[ 1 ];
+ } else {
+ var anchor_overlay = self.getAnchor(
+ post,
+ 'jp-relatedposts-post-a jp-relatedposts-post-aoverlay'
+ );
+ html += anchor_overlay[ 0 ] + anchor_overlay[ 1 ];
+ }
+ html +=
+ '<' +
+ related_posts_js_options.post_heading +
+ ' class="jp-relatedposts-post-title">' +
+ anchor[ 0 ] +
+ post.title +
+ anchor[ 1 ] +
+ '</' +
+ related_posts_js_options.post_heading +
+ '>';
+ html +=
+ '<p class="jp-relatedposts-post-excerpt">' +
+ $( '<p>' )
+ .text( post.excerpt )
+ .html() +
+ '</p>';
+ if ( options.showDate ) {
+ html += '<p class="jp-relatedposts-post-date">' + post.date + '</p>';
+ }
+ if ( options.showContext ) {
+ html += '<p class="jp-relatedposts-post-context">' + post.context + '</p>';
+ }
+ html += '</div>';
+ } );
+ return (
+ '<div class="jp-relatedposts-items jp-relatedposts-items-visual jp-relatedposts-' +
+ options.layout +
+ ' ">' +
+ html +
+ '</div>'
+ );
+ },
+
+ /**
+ * We want to set a max height on the excerpt however we want to set
+ * this according to the natual pacing of the page as we never want to
+ * cut off a line of text in the middle so we need to do some detective
+ * work.
+ */
+ setVisualExcerptHeights: function() {
+ var elements = $(
+ '#jp-relatedposts .jp-relatedposts-post-nothumbs .jp-relatedposts-post-excerpt'
+ );
+
+ if ( 0 >= elements.length ) {
+ return;
+ }
+
+ var fontSize = parseInt( elements.first().css( 'font-size' ), 10 ),
+ lineHeight = parseInt( elements.first().css( 'line-height' ), 10 );
+
+ // Show 5 lines of text
+ elements.css( 'max-height', ( 5 * lineHeight ) / fontSize + 'em' );
+ },
+
+ getTrackedUrl: function( anchor ) {
+ var args = 'relatedposts_hit=1';
+ args += '&relatedposts_origin=' + $( anchor ).data( 'origin' );
+ args += '&relatedposts_position=' + $( anchor ).data( 'position' );
+
+ var pathname = anchor.pathname;
+ if ( '/' !== pathname[ 0 ] ) {
+ pathname = '/' + pathname;
+ }
+
+ if ( '' === anchor.search ) {
+ return pathname + '?' + args;
+ } else {
+ return pathname + anchor.search + '&' + args;
+ }
+ },
+
+ cleanupTrackedUrl: function() {
+ if ( 'function' !== typeof history.replaceState ) {
+ return;
+ }
+
+ var cleaned_search = document.location.search.replace(
+ /\brelatedposts_[a-z]+=[0-9]*&?\b/gi,
+ ''
+ );
+ if ( '?' === cleaned_search ) {
+ cleaned_search = '';
+ }
+ if ( document.location.search !== cleaned_search ) {
+ history.replaceState( {}, document.title, document.location.pathname + cleaned_search );
+ }
+ },
+ };
+
+ function afterPostsHaveLoaded() {
+ jprp.setVisualExcerptHeights();
+ $( '#jp-relatedposts a.jp-relatedposts-post-a' ).click( function() {
+ this.href = jprp.getTrackedUrl( this );
+ } );
+ }
+
+ /**
+ * Initialize Related Posts.
+ */
+ function startRelatedPosts() {
+ jprp.cleanupTrackedUrl();
+
+ var endpointURL = jprp.getEndpointURL(),
+ $relatedPosts = $( '#jp-relatedposts' );
+
+ if ( $( '#jp-relatedposts .jp-relatedposts-post' ).length ) {
+ afterPostsHaveLoaded();
+ return;
+ }
+
+ $.getJSON( endpointURL, function( response ) {
+ if ( 0 === response.items.length || 0 === $relatedPosts.length ) {
+ return;
+ }
+
+ jprp.response = response;
+
+ var html,
+ showThumbnails,
+ options = {};
+
+ if ( 'undefined' !== typeof wp && wp.customize ) {
+ showThumbnails = wp.customize.instance( 'jetpack_relatedposts[show_thumbnails]' ).get();
+ options.showDate = wp.customize.instance( 'jetpack_relatedposts[show_date]' ).get();
+ options.showContext = wp.customize.instance( 'jetpack_relatedposts[show_context]' ).get();
+ options.layout = wp.customize.instance( 'jetpack_relatedposts[layout]' ).get();
+ } else {
+ showThumbnails = response.show_thumbnails;
+ options.showDate = response.show_date;
+ options.showContext = response.show_context;
+ options.layout = response.layout;
+ }
+
+ html = ! showThumbnails
+ ? jprp.generateMinimalHtml( response.items, options )
+ : jprp.generateVisualHtml( response.items, options );
+
+ $relatedPosts.append( html );
+ if ( options.showDate ) {
+ $relatedPosts.find( '.jp-relatedposts-post-date' ).show();
+ }
+ $relatedPosts.show();
+ afterPostsHaveLoaded();
+ } );
+ }
+
+ $( function() {
+ if ( 'undefined' !== typeof wp && wp.customize ) {
+ if ( wp.customize.selectiveRefresh ) {
+ wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
+ if ( 'jetpack_relatedposts' === placement.partial.id ) {
+ startRelatedPosts();
+ }
+ } );
+ }
+ wp.customize.bind( 'preview-ready', startRelatedPosts );
+ } else {
+ startRelatedPosts();
+ }
+ } );
+} )( jQuery );