fix: elementor-youtube-widget (per JS gebaut) zuverlaessig erkennen
Nach dem script-blocking blieb ein per YouTube-iframe_api gebautes
Elementor-video leer: die API wird blockiert, also baut Elementor kein
iframe -> mein iframe-basierter platzhalter griff nicht, und das
data-settings enthielt nur {"video_type":"youtube"} (keine URL).
videoUrlForWidget() findet die video-URL jetzt aus mehreren quellen:
- explizite keys (youtube_url/vimeo_url/...) im data-settings
- beliebige youtube/vimeo-URL im data-settings (regex, escaped slashes)
- bereits server-gerendertes iframe im widget
- YouTube-thumbnail (i.ytimg.com/vi/ID/) bei lazyload/overlay-modus
Greift auch fuer .elementor-widget[data-widget_type^="video"] und ueberspringt
widgets, die der server-autodetect schon zum platzhalter gemacht hat.
Extraktions-logik isoliert getestet (thumbnail, escaped-json, vimeo).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -261,17 +261,61 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Elementor video widgets store the URL in data-settings and build the
|
/** Reconstruct a YouTube watch URL from a thumbnail (i.ytimg.com/vi/ID/…). */
|
||||||
* player via JS — handle them before that happens. */
|
function ytIdFromThumb( s ) {
|
||||||
|
const m = String( s || '' ).match( /(?:i\.ytimg\.com|img\.youtube\.com)\/vi\/([\w-]{6,})\// );
|
||||||
|
return m ? m[ 1 ] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the embedded video URL of an Elementor video widget. Elementor often
|
||||||
|
* does NOT put the URL in data-settings (only {"video_type":"youtube"}) and
|
||||||
|
* builds the player via the JS API — so we look in several places.
|
||||||
|
*/
|
||||||
|
function videoUrlForWidget( widget ) {
|
||||||
|
const ds = widget.getAttribute( 'data-settings' ) || '';
|
||||||
|
|
||||||
|
// 1) Explicit URL keys in data-settings (older/other Elementor versions).
|
||||||
|
try {
|
||||||
|
const s = JSON.parse( ds || '{}' );
|
||||||
|
const u = s.youtube_url || s.vimeo_url || s.video_url || s.external_url
|
||||||
|
|| s.hosted_url || ( s.link && s.link.url ) || '';
|
||||||
|
if ( u ) return u;
|
||||||
|
} catch ( e ) { /* not JSON / no keys */ }
|
||||||
|
|
||||||
|
// 2) Any youtube/vimeo URL anywhere in the data-settings string (JSON values
|
||||||
|
// are quoted, so stop at a quote/space; tolerate escaped slashes \/).
|
||||||
|
const m = ds.match( /https?:[^"\s]*?(?:youtube\.com|youtu\.be|vimeo\.com)[^"\s]*/i );
|
||||||
|
if ( m ) return m[ 0 ].replace( /\\\//g, '/' ).replace( /\\/g, '' );
|
||||||
|
|
||||||
|
// 3) A server-rendered iframe already inside the widget.
|
||||||
|
const ifr = widget.querySelector( 'iframe[src]' );
|
||||||
|
if ( ifr ) return ifr.getAttribute( 'src' );
|
||||||
|
|
||||||
|
// 4) A YouTube thumbnail (lazyload / image-overlay mode) → rebuild the URL.
|
||||||
|
const thumb = widget.querySelector(
|
||||||
|
'img[src*="ytimg.com/vi/"], img[src*="img.youtube.com/vi/"], [style*="ytimg.com/vi/"]'
|
||||||
|
);
|
||||||
|
if ( thumb ) {
|
||||||
|
const id = ytIdFromThumb( thumb.getAttribute( 'src' ) || thumb.getAttribute( 'style' ) || '' );
|
||||||
|
if ( id ) return 'https://www.youtube.com/watch?v=' + id;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Elementor video widgets build the player via JS — replace them with our
|
||||||
|
* consent placeholder before that happens. */
|
||||||
function handleElementorVideos() {
|
function handleElementorVideos() {
|
||||||
document.querySelectorAll( '.elementor-widget-video[data-settings]' ).forEach( function ( widget ) {
|
const widgets = document.querySelectorAll(
|
||||||
let settings;
|
'.elementor-widget-video, .elementor-widget[data-widget_type^="video"]'
|
||||||
try {
|
);
|
||||||
settings = JSON.parse( widget.dataset.settings );
|
widgets.forEach( function ( widget ) {
|
||||||
} catch ( e ) {
|
const container = widget.querySelector( '.elementor-widget-container' ) || widget;
|
||||||
return;
|
// Already turned into a placeholder (e.g. by the server-side autodetect
|
||||||
}
|
// catching a rendered iframe) → leave it.
|
||||||
const raw = settings.youtube_url || settings.vimeo_url || settings.external_url || '';
|
if ( container.querySelector( '.cb-blocker' ) ) return;
|
||||||
|
|
||||||
|
const raw = videoUrlForWidget( widget );
|
||||||
if ( ! raw ) return;
|
if ( ! raw ) return;
|
||||||
|
|
||||||
const embed = toEmbedUrl( raw );
|
const embed = toEmbedUrl( raw );
|
||||||
@@ -282,7 +326,6 @@
|
|||||||
|
|
||||||
// Neutralise Elementor so it won't build the player / load the overlay.
|
// Neutralise Elementor so it won't build the player / load the overlay.
|
||||||
widget.removeAttribute( 'data-settings' );
|
widget.removeAttribute( 'data-settings' );
|
||||||
const container = widget.querySelector( '.elementor-widget-container' ) || widget;
|
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
container.appendChild( buildPlaceholder( svc, embed, {} ) );
|
container.appendChild( buildPlaceholder( svc, embed, {} ) );
|
||||||
} );
|
} );
|
||||||
|
|||||||
Reference in New Issue
Block a user