| @@ -11,9 +11,9 @@ | ||
| 11 | 11 | |
| 12 | 12 | /** |
| 13 | 13 | * Utility get related posts JSON endpoint from URLs |
| 14 | 14 | * |
| 15 | - * @param {string} URL (optional) | |
| 15 | + * @param {string} URL (optional) | |
| 16 | 16 | * @return {string} Endpoint URL |
| 17 | 17 | */ |
| 18 | 18 | getEndpointURL: function ( URL ) { |
| 19 | 19 | var locationObject, |
| @@ -58,11 +58,10 @@ | ||
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | if ( '' === locationObject.search ) { |
| 61 | 61 | return pathname + '?' + args; |
| 62 | - } else { | |
| 63 | - return pathname + locationObject.search + '&' + args; | |
| 64 | 62 | } |
| 63 | + return pathname + locationObject.search + '&' + args; | |
| 65 | 64 | }, |
| 66 | 65 | |
| 67 | 66 | getAnchor: function ( post, classNames ) { |
| 68 | 67 | var anchorTitle = post.title; |
| @@ -76,21 +75,26 @@ | ||
| 76 | 75 | if ( '' !== post.rel ) { |
| 77 | 76 | anchor.setAttribute( 'rel', post.rel ); |
| 78 | 77 | } |
| 79 | 78 | |
| 79 | + return anchor; | |
| 80 | + }, | |
| 81 | + | |
| 82 | + cleanHtml: function ( str ) { | |
| 80 | 83 | var div = document.createElement( 'div' ); |
| 81 | - div.appendChild( anchor ); | |
| 82 | - | |
| 83 | - var anchorHTML = div.innerHTML; | |
| 84 | - return [ anchorHTML.substring( 0, anchorHTML.length - 4 ), '</a>' ]; | |
| 84 | + div.innerHTML = str; | |
| 85 | + return div.textContent || div.innerText || ''; | |
| 85 | 86 | }, |
| 86 | 87 | |
| 87 | - generateMinimalHtml: function ( posts, options ) { | |
| 88 | + generateMinimalDiv: function ( posts, options ) { | |
| 88 | 89 | var self = this; |
| 89 | - var html = ''; | |
| 90 | + var div = document.createElement( 'div' ); | |
| 91 | + div.setAttribute( | |
| 92 | + 'class', | |
| 93 | + 'jp-relatedposts-items jp-relatedposts-items-minimal jp-relatedposts-' + options.layout | |
| 94 | + ); | |
| 90 | 95 | |
| 91 | 96 | posts.forEach( function ( post, index ) { |
| 92 | - var anchor = self.getAnchor( post, 'jp-relatedposts-post-a' ); | |
| 93 | 97 | var classes = 'jp-relatedposts-post jp-relatedposts-post' + index; |
| 94 | 98 | |
| 95 | 99 | if ( post.classes.length > 0 ) { |
| 96 | 100 | classes += ' ' + post.classes.join( ' ' ); |
| @@ -95,50 +99,48 @@ | ||
| 95 | 99 | if ( post.classes.length > 0 ) { |
| 96 | 100 | classes += ' ' + post.classes.join( ' ' ); |
| 97 | 101 | } |
| 98 | 102 | |
| 99 | - html += | |
| 100 | - '<p class="' + | |
| 101 | - classes + | |
| 102 | - '" data-post-id="' + | |
| 103 | - post.id + | |
| 104 | - '" data-post-format="' + | |
| 105 | - post.format + | |
| 106 | - '">'; | |
| 107 | - html += | |
| 108 | - '<span class="jp-relatedposts-post-title">' + | |
| 109 | - anchor[ 0 ] + | |
| 110 | - post.title + | |
| 111 | - anchor[ 1 ] + | |
| 112 | - '</span>'; | |
| 103 | + var p = document.createElement( 'p' ); | |
| 104 | + p.setAttribute( 'class', classes ); | |
| 105 | + p.setAttribute( 'data-post-id', post.id ); | |
| 106 | + p.setAttribute( 'data-post-format', post.format ); | |
| 107 | + div.appendChild( p ); | |
| 108 | + | |
| 109 | + var titleSpan = document.createElement( 'span' ); | |
| 110 | + titleSpan.setAttribute( 'class', 'jp-relatedposts-post-title' ); | |
| 111 | + p.appendChild( titleSpan ); | |
| 112 | + | |
| 113 | + var anchor = self.getAnchor( post, 'jp-relatedposts-post-a' ); | |
| 114 | + titleSpan.appendChild( anchor ); | |
| 115 | + anchor.textContent = self.cleanHtml( post.title ); | |
| 116 | + | |
| 113 | 117 | if ( options.showDate ) { |
| 114 | - html += | |
| 115 | - '<time class="jp-relatedposts-post-date" datetime="' + | |
| 116 | - post.date + | |
| 117 | - '">' + | |
| 118 | - post.date + | |
| 119 | - '</time>'; | |
| 118 | + var timeElt = document.createElement( 'time' ); | |
| 119 | + timeElt.setAttribute( 'class', 'jp-relatedposts-post-date' ); | |
| 120 | + timeElt.setAttribute( 'datetime', post.date ); | |
| 121 | + timeElt.textContent = post.date; | |
| 122 | + p.appendChild( timeElt ); | |
| 120 | 123 | } |
| 121 | 124 | if ( options.showContext ) { |
| 122 | - html += '<span class="jp-relatedposts-post-context">' + post.context + '</span>'; | |
| 125 | + var contextSpan = document.createElement( 'span' ); | |
| 126 | + contextSpan.setAttribute( 'class', 'jp-relatedposts-post-context' ); | |
| 127 | + contextSpan.textContent = self.cleanHtml( post.context ); | |
| 128 | + p.appendChild( contextSpan ); | |
| 123 | 129 | } |
| 124 | - html += '</p>'; | |
| 125 | 130 | } ); |
| 126 | - return ( | |
| 127 | - '<div class="jp-relatedposts-items jp-relatedposts-items-minimal jp-relatedposts-' + | |
| 128 | - options.layout + | |
| 129 | - ' ">' + | |
| 130 | - html + | |
| 131 | - '</div>' | |
| 132 | - ); | |
| 131 | + return div; | |
| 133 | 132 | }, |
| 134 | 133 | |
| 135 | - generateVisualHtml: function ( posts, options ) { | |
| 134 | + generateVisualDiv: function ( posts, options ) { | |
| 136 | 135 | var self = this; |
| 137 | - var html = ''; | |
| 136 | + var div = document.createElement( 'div' ); | |
| 137 | + div.setAttribute( | |
| 138 | + 'class', | |
| 139 | + 'jp-relatedposts-items jp-relatedposts-items-visual jp-relatedposts-' + options.layout | |
| 140 | + ); | |
| 138 | 141 | |
| 139 | 142 | posts.forEach( function ( post, index ) { |
| 140 | - var anchor = self.getAnchor( post, 'jp-relatedposts-post-a' ); | |
| 141 | 143 | var classes = 'jp-relatedposts-post jp-relatedposts-post' + index; |
| 142 | 144 | |
| 143 | 145 | if ( post.classes.length > 0 ) { |
| 144 | 146 | classes += ' ' + post.classes.join( ' ' ); |
| @@ -149,73 +151,67 @@ | ||
| 149 | 151 | } else { |
| 150 | 152 | classes += ' jp-relatedposts-post-thumbs'; |
| 151 | 153 | } |
| 152 | 154 | |
| 153 | - var dummyContainer = document.createElement( 'p' ); | |
| 154 | - dummyContainer.innerHTML = post.excerpt; | |
| 155 | - var excerpt = dummyContainer.textContent; | |
| 155 | + var innerDiv = document.createElement( 'div' ); | |
| 156 | + innerDiv.setAttribute( 'class', classes ); | |
| 157 | + innerDiv.setAttribute( 'data-post-id', post.id ); | |
| 158 | + innerDiv.setAttribute( 'data-post-format', post.format ); | |
| 159 | + div.appendChild( innerDiv ); | |
| 156 | 160 | |
| 157 | - html += | |
| 158 | - '<div class="' + | |
| 159 | - classes + | |
| 160 | - '" data-post-id="' + | |
| 161 | - post.id + | |
| 162 | - '" data-post-format="' + | |
| 163 | - post.format + | |
| 164 | - '">'; | |
| 165 | 161 | if ( post.img.src ) { |
| 166 | - html += | |
| 167 | - anchor[ 0 ] + | |
| 168 | - '<img class="jp-relatedposts-post-img" loading="lazy" src="' + | |
| 169 | - post.img.src + | |
| 170 | - '" width="' + | |
| 171 | - post.img.width + | |
| 172 | - '" height="' + | |
| 173 | - post.img.height + | |
| 174 | - ( post.img.srcset ? '" srcset="' + post.img.srcset : '' ) + | |
| 175 | - ( post.img.sizes ? '" sizes="' + post.img.sizes : '' ) + | |
| 176 | - '" alt="' + | |
| 177 | - post.img.alt_text + | |
| 178 | - '" />' + | |
| 179 | - anchor[ 1 ]; | |
| 162 | + var imgAnchor = self.getAnchor( post, 'jp-relatedposts-post-a' ); | |
| 163 | + innerDiv.appendChild( imgAnchor ); | |
| 164 | + | |
| 165 | + var img = document.createElement( 'img' ); | |
| 166 | + img.setAttribute( 'class', 'jp-relatedposts-post-img' ); | |
| 167 | + img.setAttribute( 'loading', 'lazy' ); | |
| 168 | + img.setAttribute( 'src', post.img.src ); | |
| 169 | + img.setAttribute( 'width', post.img.width ); | |
| 170 | + img.setAttribute( 'height', post.img.height ); | |
| 171 | + if ( post.img.srcset ) { | |
| 172 | + img.setAttribute( 'srcset', post.img.srcset ); | |
| 173 | + } | |
| 174 | + if ( post.img.sizes ) { | |
| 175 | + img.setAttribute( 'sizes', post.img.sizes ); | |
| 176 | + } | |
| 177 | + img.setAttribute( 'alt', post.img.alt_text ); | |
| 178 | + imgAnchor.appendChild( img ); | |
| 180 | 179 | } else { |
| 181 | 180 | var anchor_overlay = self.getAnchor( |
| 182 | 181 | post, |
| 183 | 182 | 'jp-relatedposts-post-a jp-relatedposts-post-aoverlay' |
| 184 | 183 | ); |
| 185 | - html += anchor_overlay[ 0 ] + anchor_overlay[ 1 ]; | |
| 184 | + innerDiv.appendChild( anchor_overlay ); | |
| 186 | 185 | } |
| 187 | - html += | |
| 188 | - '<' + | |
| 189 | - related_posts_js_options.post_heading + | |
| 190 | - ' class="jp-relatedposts-post-title">' + | |
| 191 | - anchor[ 0 ] + | |
| 192 | - post.title + | |
| 193 | - anchor[ 1 ] + | |
| 194 | - '</' + | |
| 195 | - related_posts_js_options.post_heading + | |
| 196 | - '>'; | |
| 197 | - html += '<p class="jp-relatedposts-post-excerpt">' + excerpt + '</p>'; | |
| 186 | + var heading = document.createElement( related_posts_js_options.post_heading ); | |
| 187 | + heading.setAttribute( 'class', 'jp-relatedposts-post-title' ); | |
| 188 | + innerDiv.appendChild( heading ); | |
| 189 | + | |
| 190 | + var headingAnchor = self.getAnchor( post, 'jp-relatedposts-post-a' ); | |
| 191 | + headingAnchor.textContent = self.cleanHtml( post.title ); | |
| 192 | + heading.appendChild( headingAnchor ); | |
| 193 | + | |
| 194 | + var p = document.createElement( 'p' ); | |
| 195 | + p.setAttribute( 'class', 'jp-relatedposts-post-excerpt' ); | |
| 196 | + p.textContent = self.cleanHtml( post.excerpt ); | |
| 197 | + innerDiv.appendChild( p ); | |
| 198 | + | |
| 198 | 199 | if ( options.showDate ) { |
| 199 | - html += | |
| 200 | - '<time class="jp-relatedposts-post-date" datetime="' + | |
| 201 | - post.date + | |
| 202 | - '">' + | |
| 203 | - post.date + | |
| 204 | - '</time>'; | |
| 200 | + var timeElt = document.createElement( 'time' ); | |
| 201 | + timeElt.setAttribute( 'class', 'jp-relatedposts-post-date' ); | |
| 202 | + timeElt.setAttribute( 'datetime', post.date ); | |
| 203 | + timeElt.textContent = post.date; | |
| 204 | + innerDiv.appendChild( timeElt ); | |
| 205 | 205 | } |
| 206 | 206 | if ( options.showContext ) { |
| 207 | - html += '<p class="jp-relatedposts-post-context">' + post.context + '</p>'; | |
| 207 | + var contextP = document.createElement( 'p' ); | |
| 208 | + contextP.setAttribute( 'class', 'jp-relatedposts-post-context' ); | |
| 209 | + contextP.textContent = self.cleanHtml( post.context ); | |
| 210 | + innerDiv.appendChild( contextP ); | |
| 208 | 211 | } |
| 209 | - html += '</div>'; | |
| 210 | 212 | } ); |
| 211 | - return ( | |
| 212 | - '<div class="jp-relatedposts-items jp-relatedposts-items-visual jp-relatedposts-' + | |
| 213 | - options.layout + | |
| 214 | - ' ">' + | |
| 215 | - html + | |
| 216 | - '</div>' | |
| 217 | - ); | |
| 213 | + return div; | |
| 218 | 214 | }, |
| 219 | 215 | |
| 220 | 216 | /** |
| 221 | 217 | * We want to set a max height on the excerpt however we want to set |
| @@ -254,11 +250,10 @@ | ||
| 254 | 250 | } |
| 255 | 251 | |
| 256 | 252 | if ( '' === anchor.search ) { |
| 257 | 253 | return pathname + '?' + args; |
| 258 | - } else { | |
| 259 | - return pathname + anchor.search + '&' + args; | |
| 260 | 254 | } |
| 255 | + return pathname + anchor.search + '&' + args; | |
| 261 | 256 | }, |
| 262 | 257 | |
| 263 | 258 | cleanupTrackedUrl: function () { |
| 264 | 259 | if ( 'function' !== typeof history.replaceState ) { |
| @@ -295,9 +290,8 @@ | ||
| 295 | 290 | function startRelatedPosts() { |
| 296 | 291 | jprp.cleanupTrackedUrl(); |
| 297 | 292 | |
| 298 | 293 | var endpointURL = jprp.getEndpointURL(); |
| 299 | - var relatedPosts = document.querySelector( '#jp-relatedposts' ); | |
| 300 | 294 | |
| 301 | 295 | if ( ! endpointURL ) { |
| 302 | 296 | return; |
| 303 | 297 | } |
| @@ -306,8 +300,9 @@ | ||
| 306 | 300 | afterPostsHaveLoaded(); |
| 307 | 301 | return; |
| 308 | 302 | } |
| 309 | 303 | |
| 304 | + var relatedPosts = document.querySelector( '#jp-relatedposts' ); | |
| 310 | 305 | var request = new XMLHttpRequest(); |
| 311 | 306 | request.open( 'GET', endpointURL, true ); |
| 312 | 307 | request.setRequestHeader( 'x-requested-with', 'XMLHttpRequest' ); |
| 313 | 308 | |
| @@ -321,10 +316,9 @@ | ||
| 321 | 316 | } |
| 322 | 317 | |
| 323 | 318 | jprp.response = response; |
| 324 | 319 | |
| 325 | - var html, | |
| 326 | - showThumbnails, | |
| 320 | + var showThumbnails, | |
| 327 | 321 | options = {}; |
| 328 | 322 | |
| 329 | 323 | if ( 'undefined' !== typeof wp && wp.customize ) { |
| 330 | 324 | showThumbnails = wp.customize.instance( 'jetpack_relatedposts[show_thumbnails]' ).get(); |
| @@ -339,15 +333,13 @@ | ||
| 339 | 333 | options.showContext = response.show_context; |
| 340 | 334 | options.layout = response.layout; |
| 341 | 335 | } |
| 342 | 336 | |
| 343 | - html = ! showThumbnails | |
| 344 | - ? jprp.generateMinimalHtml( response.items, options ) | |
| 345 | - : jprp.generateVisualHtml( response.items, options ); | |
| 337 | + var div = ! showThumbnails | |
| 338 | + ? jprp.generateMinimalDiv( response.items, options ) | |
| 339 | + : jprp.generateVisualDiv( response.items, options ); | |
| 346 | 340 | |
| 347 | - var div = document.createElement( 'div' ); | |
| 348 | 341 | relatedPosts.appendChild( div ); |
| 349 | - div.outerHTML = html; | |
| 350 | 342 | |
| 351 | 343 | if ( options.showDate ) { |
| 352 | 344 | var dates = relatedPosts.querySelectorAll( '.jp-relatedposts-post-date' ); |
| 353 | 345 | |
| @@ -357,9 +349,9 @@ | ||
| 357 | 349 | } |
| 358 | 350 | |
| 359 | 351 | relatedPosts.style.display = 'block'; |
| 360 | 352 | afterPostsHaveLoaded(); |
| 361 | - } catch ( error ) { | |
| 353 | + } catch { | |
| 362 | 354 | // Do nothing |
| 363 | 355 | } |
| 364 | 356 | } |
| 365 | 357 | }; |