1/* jshint onevar: false */ 2 3/** 4 * Load related posts 5 */ 6(function($) { 7 var jprp = { 8 response: null, 9 10 /** 11 * Utility get related posts JSON endpoint from URLs 12 * 13 * @param string URL (optional) 14 * @return string endpoint URL 15 */ 16 getEndpointURL: function( URL ) { 17 var locationObject = document.location; 18 19 if ( 'string' === typeof( URL ) && URL.match( /^https?:\/\// ) ) { 20 locationObject = document.createElement( 'a' ); 21 locationObject.href = URL; 22 } 23 24 var args = 'relatedposts=1'; 25 if ( ! $( '#jp-relatedposts' ).data( 'exclude' ) ) { 26 args += '&relatedposts_exclude=' + $( '#jp-relatedposts' ).data( 'exclude' ); 27 } 28 29 var pathname = locationObject.pathname; 30 if ( '/' !== pathname[0] ) { 31 pathname = '/' + pathname; 32 } 33 34 if ( '' === locationObject.search ) { 35 return pathname + '?' + args; 36 } else { 37 return pathname + locationObject.search + '&' + args; 38 } 39 }, 40 41 getAnchor: function( post, classNames ) { 42 var anchor_title = post.title; 43 if ( '' !== ( '' + post.excerpt ) ) { 44 anchor_title += '\n\n' + post.excerpt; 45 } 46 47 var anchor = $( '<a>' ); 48 49 anchor.attr({ 50 'class': classNames, 51 'href': post.url, 52 'title': anchor_title, 53 'rel': 'nofollow', 54 'data-origin': post.url_meta.origin, 55 'data-position': post.url_meta.position 56 }); 57 58 var anchor_html = $( '<div>' ).append( anchor ).html(); 59 return [ 60 anchor_html.substring( 0, anchor_html.length-4 ), 61 '</a>' 62 ]; 63 }, 64 65 generateMinimalHtml: function( posts ) { 66 var self = this; 67 var html = ''; 68 69 $.each( posts, function( index, post ) { 70 var anchor = self.getAnchor( post, 'jp-relatedposts-post-a' ); 71 var classes = 'jp-relatedposts-post jp-relatedposts-post' + index; 72 73 html += '<p class="' + classes + '" data-post-id="' + post.id + '" data-post-format="' + post.format + '">'; 74 html += '<span class="jp-relatedposts-post-title">
74' + anchor[0] + post.title + anchor[1] + '</span>'; 75 html += '<span class="jp-relatedposts-post-date">' + post.date + '</span>'; 76 html += '<span class="jp-relatedposts-post-context">' + post.context + '</span>'; 77 html += '</p>'; 78 } ); 79 return '<div class="jp-relatedposts-items jp-relatedposts-items-minimal">' + html + '</div>'; 80 }, 81 82 generateVisualHtml: function( posts ) { 83 var self = this; 84 var html = ''; 85 86 $.each( posts, function( index, post ) { 87 var anchor = self.getAnchor( post, 'jp-relatedposts-post-a' ); 88 var classes = 'jp-relatedposts-post jp-relatedposts-post' + index; 89 if ( ! post.img.src ) { 90 classes += ' jp-relatedposts-post-nothumbs'; 91 } else { 92 classes += ' jp-relatedposts-post-thumbs'; 93 } 94 95 html += '<div class="' + classes + '" data-post-id="' + post.id + '" data-post-format="' + post.format + '">'; 96 if ( post.img.src ) { 97 html += anchor[0] + '<img class="jp-relatedposts-post-img" src="' + post.img.src + '" width="' + post.img.width + '" alt="' + post.title + '" />' + anchor[1]; 98 } else { 99 var anchor_overlay = self.getAnchor( post, 'jp-relatedposts-post-a jp-relatedposts-post-aoverlay' ); 100 html += anchor_overlay[0] + anchor_overlay[1]; 101 } 102 html += '<h4 class="jp-relatedposts-post-title">
102' + anchor[0] + post.title + anchor[1] + '</h4>'; 103 html += '<p class="jp-relatedposts-post-excerpt">' + $( '<p>' ).text( post.excerpt ).html() + '</p>'; 104 html += '<p class="jp-relatedposts-post-date">' + post.date + '</p>'; 105 html += '<p class="jp-relatedposts-post-context">' + post.context + '</p>'; 106 html += '</div>'; 107 } ); 108 return '<div class="jp-relatedposts-items jp-relatedposts-items-visual">' + html + '</div>'; 109 }, 110 111 /** 112 * We want to set a max height on the excerpt however we want to set 113 * this according to the natual pacing of the page as we never want to 114 * cut off a line of text in the middle so we need to do some detective 115 * work. 116 */ 117 setVisualExcerptHeights: function() { 118 var elements = $( '#jp-relatedposts .jp-relatedposts-post-nothumbs .jp-relatedposts-post-excerpt' ); 119 120 if ( 0 >= elements.length ) { 121 return; 122 } 123 124 var fontSize = parseInt( elements.first().css( 'font-size' ), 10 ), 125 lineHeight = parseInt( elements.first().css( 'line-height' ), 10 ); 126 127 // Show 5 lines of text 128 elements.css( 129 'max-height', 130 ( 5 * lineHeight / fontSize ) + 'em' 131 ); 132 }, 133 134 getTrackedUrl: function( anchor ) { 135 var args = 'relatedposts_hit=1'; 136 args += '&relatedposts_origin=' + $( anchor ).data( 'origin' ); 137 args += '&relatedposts_position=' + $( anchor ).data( 'position' ); 138 139 var pathname = anchor.pathname; 140 if ( '/' !== pathname[0] ) { 141 pathname = '/' + pathname; 142 } 143 144 if ( '' === anchor.search ) { 145 return pathname + '?' + args; 146 } else { 147 return pathname + anchor.search + '&' + args; 148 } 149 }, 150 151 cleanupTrackedUrl: function() { 152 if ( 'function' !== typeof history.replaceState ) { 153 return; 154 } 155 156 var cleaned_search = document.location.search.replace( /\brelatedposts_[a-z]+=[0-9]*&?\b/gi, '' ); 157 if ( '?' === cleaned_search ) { 158 cleaned_search = ''; 159 } 160 if ( document.location.search !== cleaned_search ) { 161 history.replaceState( {}, document.title, document.location.pathname + cleaned_search ); 162 } 163 } 164 }; 165 166 $( function() { 167 jprp.cleanupTrackedUrl(); 168 169 $.getJSON( jprp.getEndpointURL(), function( response ) { 170 if ( 0 === response.items.length || 0 === $( '#jp-relatedposts' ).length ) { 171 return; 172 } 173 174 jprp.response = response; 175 176 var html = ''; 177 if ( !response.show_thumbnails ) { 178 html = jprp.generateMinimalHtml( response.items ); 179 } else { 180 html = jprp.generateVisualHtml( response.items ); 181 } 182 183 $( '#jp-relatedposts' ).append( html ); 184 jprp.setVisualExcerptHeights(); 185 $( '#jp-relatedposts' ).show(); 186 187 $( '#jp-relatedposts a.jp-relatedposts-post-a' ).click(function() { 188 this.href = jprp.getTrackedUrl( this ); 189 }); 190 } ); 191 } ); 192})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.