first commit
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
{% if settings.source is not empty %}
|
||||
{% set classes = settings.classes | merge( [ base_styles.base ] ) | join(' ') %}
|
||||
{% set data_settings = {
|
||||
'source': settings.source,
|
||||
'autoplay': settings.autoplay,
|
||||
'mute': settings.mute,
|
||||
'controls': settings.player_controls,
|
||||
'cc_load_policy': settings.captions,
|
||||
'loop': settings.loop,
|
||||
'rel': settings.rel,
|
||||
'start': settings.start,
|
||||
'end': settings.end,
|
||||
'privacy': settings.privacy_mode,
|
||||
'lazyload': settings.lazyload,
|
||||
} %}
|
||||
<div data-id="{{ id }}" data-e-type="{{ type }}" class="{{ classes }}" data-settings="{{ data_settings|json_encode|e('html_attr') }}"></div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\AtomicWidgets\Elements\Atomic_Youtube;
|
||||
|
||||
use Elementor\Modules\AtomicWidgets\Controls\Section;
|
||||
use Elementor\Modules\AtomicWidgets\Controls\Types\Switch_Control;
|
||||
use Elementor\Modules\AtomicWidgets\Controls\Types\Text_Control;
|
||||
use Elementor\Modules\AtomicWidgets\Elements\Atomic_Widget_Base;
|
||||
use Elementor\Modules\AtomicWidgets\Elements\Has_Template;
|
||||
use Elementor\Modules\AtomicWidgets\PropTypes\Classes_Prop_Type;
|
||||
use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\Boolean_Prop_Type;
|
||||
use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\String_Prop_Type;
|
||||
use Elementor\Modules\AtomicWidgets\PropTypes\Size_Prop_Type;
|
||||
use Elementor\Modules\AtomicWidgets\Styles\Style_Definition;
|
||||
use Elementor\Modules\AtomicWidgets\Styles\Style_Variant;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Atomic_Youtube extends Atomic_Widget_Base {
|
||||
use Has_Template;
|
||||
|
||||
public static function get_element_type(): string {
|
||||
return 'e-youtube';
|
||||
}
|
||||
|
||||
public function get_title() {
|
||||
return esc_html__( 'YouTube', 'elementor' );
|
||||
}
|
||||
|
||||
public function get_keywords() {
|
||||
return [ 'ato', 'atom', 'atoms', 'atomic' ];
|
||||
}
|
||||
|
||||
public function get_icon() {
|
||||
return 'eicon-e-youtube';
|
||||
}
|
||||
|
||||
protected static function define_props_schema(): array {
|
||||
return [
|
||||
'classes' => Classes_Prop_Type::make()
|
||||
->default( [] ),
|
||||
|
||||
'source' => String_Prop_Type::make()
|
||||
->default( 'https://www.youtube.com/watch?v=XHOmBV4js_E' ),
|
||||
|
||||
'start' => String_Prop_Type::make(),
|
||||
'end' => String_Prop_Type::make(),
|
||||
'autoplay' => Boolean_Prop_Type::make()->default( false ),
|
||||
'mute' => Boolean_Prop_Type::make()->default( false ),
|
||||
'loop' => Boolean_Prop_Type::make()->default( false ),
|
||||
'lazyload' => Boolean_Prop_Type::make()->default( false ),
|
||||
'player_controls' => Boolean_Prop_Type::make()->default( true ),
|
||||
'captions' => Boolean_Prop_Type::make()->default( false ),
|
||||
'privacy_mode' => Boolean_Prop_Type::make()->default( false ),
|
||||
'rel' => Boolean_Prop_Type::make()->default( true ),
|
||||
];
|
||||
}
|
||||
|
||||
protected function define_atomic_controls(): array {
|
||||
return [
|
||||
Section::make()
|
||||
->set_label( __( 'Content', 'elementor' ) )
|
||||
->set_items( [
|
||||
Text_Control::bind_to( 'source' )
|
||||
->set_label( esc_html__( 'YouTube URL', 'elementor' ) )
|
||||
->set_placeholder( esc_html__( 'Type or paste your URL', 'elementor' ) ),
|
||||
|
||||
Text_Control::bind_to( 'start' )->set_label( esc_html__( 'Start time', 'elementor' ) ),
|
||||
Text_Control::bind_to( 'end' )->set_label( esc_html__( 'End time', 'elementor' ) ),
|
||||
Switch_Control::bind_to( 'autoplay' )->set_label( esc_html__( 'Autoplay', 'elementor' ) ),
|
||||
Switch_Control::bind_to( 'mute' )->set_label( esc_html__( 'Mute', 'elementor' ) ),
|
||||
Switch_Control::bind_to( 'loop' )->set_label( esc_html__( 'Loop', 'elementor' ) ),
|
||||
Switch_Control::bind_to( 'lazyload' )->set_label( esc_html__( 'Lazy load', 'elementor' ) ),
|
||||
Switch_Control::bind_to( 'player_controls' )->set_label( esc_html__( 'Player controls', 'elementor' ) ),
|
||||
Switch_Control::bind_to( 'captions' )->set_label( esc_html__( 'Captions', 'elementor' ) ),
|
||||
Switch_Control::bind_to( 'privacy_mode' )->set_label( esc_html__( 'Privacy mode', 'elementor' ) ),
|
||||
Switch_Control::bind_to( 'rel' )->set_label( esc_html__( 'Related videos', 'elementor' ) ),
|
||||
] ),
|
||||
];
|
||||
}
|
||||
|
||||
protected function define_base_styles(): array {
|
||||
return [
|
||||
'base' => Style_Definition::make()
|
||||
->add_variant(
|
||||
Style_Variant::make()
|
||||
->add_prop( 'aspect-ratio', String_Prop_Type::generate( '16/9' ) )
|
||||
->add_prop( 'overflow', String_Prop_Type::generate( 'hidden' ) )
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public function get_script_depends() {
|
||||
return [ 'elementor-youtube-handler' ];
|
||||
}
|
||||
|
||||
protected function get_templates(): array {
|
||||
return [
|
||||
'elementor/elements/atomic-youtube' => __DIR__ . '/atomic-youtube.html.twig',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
import { register } from '@elementor/frontend-handlers';
|
||||
|
||||
const getYoutubeVideoIdFromUrl = ( url ) => {
|
||||
const regex = /^(?:https?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?vi?=|(?:embed|v|vi|user|shorts)\/))([^?&"'>]+)/;
|
||||
const match = url.match( regex );
|
||||
return match ? match[ 1 ] : null;
|
||||
};
|
||||
|
||||
const loadYouTubeAPI = () => {
|
||||
return new Promise( ( resolve ) => {
|
||||
if ( window.YT && window.YT.loaded ) {
|
||||
resolve( window.YT );
|
||||
return;
|
||||
}
|
||||
|
||||
const YOUTUBE_IFRAME_API_URL = 'https://www.youtube.com/iframe_api';
|
||||
if ( ! document.querySelector( `script[src="${ YOUTUBE_IFRAME_API_URL }"]` ) ) {
|
||||
const tag = document.createElement( 'script' );
|
||||
tag.src = YOUTUBE_IFRAME_API_URL;
|
||||
const firstScriptTag = document.getElementsByTagName( 'script' )[ 0 ];
|
||||
firstScriptTag.parentNode.insertBefore( tag, firstScriptTag );
|
||||
}
|
||||
|
||||
const checkYT = () => {
|
||||
if ( window.YT && window.YT.loaded ) {
|
||||
resolve( window.YT );
|
||||
} else {
|
||||
setTimeout( checkYT, 350 );
|
||||
}
|
||||
};
|
||||
checkYT();
|
||||
} );
|
||||
};
|
||||
|
||||
register( {
|
||||
elementType: 'e-youtube',
|
||||
uniqueId: 'e-youtube-handler',
|
||||
callback: ( { element } ) => {
|
||||
const youtubeElement = document.createElement( 'div' );
|
||||
youtubeElement.style.height = '100%';
|
||||
element.appendChild( youtubeElement );
|
||||
|
||||
const settingsAttr = element.getAttribute( 'data-settings' );
|
||||
const parsedSettings = settingsAttr ? JSON.parse( settingsAttr ) : {};
|
||||
|
||||
const videoId = getYoutubeVideoIdFromUrl( parsedSettings.source );
|
||||
|
||||
if ( ! videoId ) {
|
||||
return;
|
||||
}
|
||||
|
||||
let player;
|
||||
let observer;
|
||||
|
||||
const prepareYTVideo = ( YT ) => {
|
||||
const playerOptions = {
|
||||
videoId,
|
||||
events: {
|
||||
onReady: () => {
|
||||
if ( parsedSettings.mute ) {
|
||||
player.mute();
|
||||
}
|
||||
|
||||
if ( parsedSettings.autoplay ) {
|
||||
player.playVideo();
|
||||
}
|
||||
},
|
||||
onStateChange: ( event ) => {
|
||||
if ( event.data === YT.PlayerState.ENDED && parsedSettings.loop ) {
|
||||
player.seekTo( parsedSettings.start || 0 );
|
||||
}
|
||||
},
|
||||
},
|
||||
playerVars: {
|
||||
controls: parsedSettings.controls ? 1 : 0,
|
||||
rel: parsedSettings.rel ? 0 : 1,
|
||||
cc_load_policy: parsedSettings.cc_load_policy ? 1 : 0,
|
||||
autoplay: parsedSettings.autoplay ? 1 : 0,
|
||||
start: parsedSettings.start,
|
||||
end: parsedSettings.end,
|
||||
},
|
||||
};
|
||||
|
||||
// To handle CORS issues, when the default host is changed, the origin parameter has to be set.
|
||||
if ( parsedSettings.privacy ) {
|
||||
playerOptions.host = 'https://www.youtube-nocookie.com';
|
||||
playerOptions.origin = window.location.hostname;
|
||||
}
|
||||
|
||||
player = new YT.Player( youtubeElement, playerOptions );
|
||||
|
||||
return player;
|
||||
};
|
||||
|
||||
if ( parsedSettings.lazyload ) {
|
||||
observer = new IntersectionObserver(
|
||||
( entries ) => {
|
||||
if ( entries[ 0 ].isIntersecting ) {
|
||||
loadYouTubeAPI().then( ( apiObject ) => prepareYTVideo( apiObject ) );
|
||||
observer.unobserve( element );
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
observer.observe( element );
|
||||
} else {
|
||||
loadYouTubeAPI().then( ( apiObject ) => prepareYTVideo( apiObject ) );
|
||||
}
|
||||
|
||||
return () => {
|
||||
if ( player && 'function' === typeof player.destroy ) {
|
||||
player.destroy();
|
||||
player = null;
|
||||
}
|
||||
|
||||
if ( element.contains( youtubeElement ) ) {
|
||||
element.removeChild( youtubeElement );
|
||||
}
|
||||
|
||||
if ( observer && 'function' === typeof observer.disconnect ) {
|
||||
observer.disconnect();
|
||||
observer = null;
|
||||
}
|
||||
};
|
||||
},
|
||||
} );
|
||||
Reference in New Issue
Block a user