| @@ -170,8 +170,51 @@ | ||
| 170 | 170 | return $markup; |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | 173 | /** |
| 174 | + * Build the facade markup for one self-hosted <video>. (#309) | |
| 175 | + * | |
| 176 | + * Same contract as render(): a focusable <button>, the original | |
| 177 | + * element preserved whole inside <noscript>, the swap done by | |
| 178 | + * facade_script(). Differences that matter: | |
| 179 | + * | |
| 180 | + * - the poster comes from the element's own poster attribute, never | |
| 181 | + * derived — the caller has already refused to build a facade | |
| 182 | + * without one, because a blank black box is worse than the video. | |
| 183 | + * - the source URL travels in data-xspeed-video-native, a separate | |
| 184 | + * attribute from the iframe player URL, so the click handler knows | |
| 185 | + * to build a <video controls autoplay> rather than an <iframe>. | |
| 186 | + * | |
| 187 | + * @param string $original_markup The untouched <video …>…</video> element. | |
| 188 | + * @param string $src The video file URL to load on click. | |
| 189 | + * @param string $poster The element's own poster URL. | |
| 190 | + * @param string $title Accessible label for the play button. | |
| 191 | + */ | |
| 192 | + public static function render_native( string $original_markup, string $src, string $poster, string $title = '' ): string { | |
| 193 | + $label = '' !== $title | |
| 194 | + ? sprintf( | |
| 195 | + /* translators: %s: video title. */ | |
| 196 | + __( 'Play video: %s', 'xspeed' ), | |
| 197 | + $title | |
| 198 | + ) | |
| 199 | + : __( 'Play video', 'xspeed' ); | |
| 200 | + | |
| 201 | + $style = 'position:relative;display:block;width:100%;padding:0;border:0;cursor:pointer;background:#000;aspect-ratio:16/9;'; | |
| 202 | + $style .= 'background-image:url(' . esc_url( $poster ) . ');background-size:cover;background-position:center;'; | |
| 203 | + | |
| 204 | + $markup = '<button type="button" class="xspeed-video-facade" data-xspeed-video-native="' . esc_url( $src ) . '"'; | |
| 205 | + $markup .= ' data-xspeed-poster="' . esc_url( $poster ) . '"'; | |
| 206 | + $markup .= ' aria-label="' . esc_attr( $label ) . '" style="' . esc_attr( $style ) . '">'; | |
| 207 | + $markup .= '<span class="xspeed-video-facade__play" aria-hidden="true" style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:68px;height:48px;border-radius:14px;background:rgba(0,0,0,.7);display:flex;align-items:center;justify-content:center;">'; | |
| 208 | + $markup .= '<svg width="24" height="24" viewBox="0 0 24 24" fill="#fff" focusable="false"><path d="M8 5v14l11-7z"/></svg>'; | |
| 209 | + $markup .= '</span>'; | |
| 210 | + $markup .= '</button>'; | |
| 211 | + $markup .= '<noscript>' . $original_markup . '</noscript>'; | |
| 212 | + | |
| 213 | + return $markup; | |
| 214 | + } | |
| 215 | + | |
| 216 | + /** | |
| 174 | 217 | * The one CSS rule the facade can't express as an inline style. |
| 175 | 218 | * |
| 176 | 219 | * Gutenberg wraps an embed in |
| 177 | 220 | * `figure.wp-has-aspect-ratio > div.wp-block-embed__wrapper`, gives the |
| @@ -202,8 +245,21 @@ | ||
| 202 | 245 | return <<<'JS' |
| 203 | 246 | document.addEventListener('click',function(e){ |
| 204 | 247 | var b=e.target.closest&&e.target.closest('.xspeed-video-facade'); |
| 205 | 248 | if(!b)return; |
| 249 | +var n=b.getAttribute('data-xspeed-video-native'); | |
| 250 | +if(n){ | |
| 251 | +var v=document.createElement('video'); | |
| 252 | +v.setAttribute('src',n); | |
| 253 | +var p=b.getAttribute('data-xspeed-poster');if(p)v.setAttribute('poster',p); | |
| 254 | +v.setAttribute('controls',''); | |
| 255 | +v.setAttribute('autoplay',''); | |
| 256 | +v.setAttribute('playsinline',''); | |
| 257 | +v.setAttribute('style','width:100%;aspect-ratio:16/9;background:#000;'); | |
| 258 | +var nt=b.getAttribute('aria-label');if(nt)v.setAttribute('title',nt); | |
| 259 | +b.parentNode.replaceChild(v,b); | |
| 260 | +return; | |
| 261 | +} | |
| 206 | 262 | var u=b.getAttribute('data-xspeed-video');if(!u)return; |
| 207 | 263 | var f=document.createElement('iframe'); |
| 208 | 264 | f.setAttribute('src',u); |
| 209 | 265 | f.setAttribute('frameborder','0'); |