|
|
| class YoutubeModal extends HTMLElement { |
| constructor() { |
| super(); |
| this.modal = null; |
| this.closeBtn = null; |
| this.activeVideoId = null; |
| this.isOpen = false; |
| } |
|
|
| connectedCallback() { |
| this.attachShadow({ mode: 'open' }); |
| this.render(); |
| this.setupEventListeners(); |
| } |
| render() { |
| this.shadowRoot.innerHTML = ` |
| <style> |
| :host { |
| --vlc-navy: #002060; |
| --vlc-sky: #00A0E9; |
| --vlc-leaf: #8DC63F; |
| } |
| :host { |
| display: contents; |
| } |
| |
| .modal { |
| position: fixed; |
| inset: 0; |
| z-index: 1000; |
| display: none; |
| align-items: center; |
| justify-content: center; |
| padding: 1rem; |
| } |
| .modal.active { |
| display: flex; |
| } |
| .backdrop { |
| position: absolute; |
| inset: 0; |
| background: rgba(0, 0, 0, 0.8); |
| } |
| .panel { |
| position: relative; |
| width: 100%; |
| max-width: 56rem; |
| background: transparent; |
| border-radius: 0.75rem; |
| overflow: hidden; |
| } |
| .header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| background: var(--vlc-navy); |
| color: white; |
| padding: 1rem; |
| } |
| .title { |
| font-size: 1.125rem; |
| font-weight: 600; |
| } |
| .close-btn { |
| padding: 0.25rem; |
| border-radius: 0.375rem; |
| background: transparent; |
| color: white; |
| border: none; |
| cursor: pointer; |
| } |
| .close-btn:hover { |
| background: rgba(255, 255, 255, 0.1); |
| } |
| .iframe-container { |
| position: relative; |
| width: 100%; |
| height: 0; |
| padding-bottom: 56.25%; /* 16:9 aspect ratio */ |
| } |
| iframe { |
| position: absolute; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| border: none; |
| } |
| </style> |
| <div class="modal" id="youtube-modal"> |
| <div class="backdrop" id="youtube-modal-backdrop"></div> |
| <div class="panel"> |
| <div class="header"> |
| <h4 class="title">Watch Demo</h4> |
| <button class="close-btn" id="modal-close-btn" aria-label="Close"> |
| <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| <line x1="18" y1="6" x2="6" y2="18"></line> |
| <line x1="6" y1="6" x2="18" y2="18"></line> |
| </svg> |
| </button> |
| </div> |
| <div class="iframe-container"> |
| <iframe id="youtube-iframe" |
| frameborder="0" |
| allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" |
| allowfullscreen |
| loading="lazy"></iframe> |
| </div> |
| </div> |
| </div> |
| `; |
| } |
| setupEventListeners() { |
| this.modal = this.shadowRoot.getElementById('youtube-modal'); |
| this.closeBtn = this.shadowRoot.getElementById('modal-close-btn'); |
| this.backdrop = this.shadowRoot.getElementById('youtube-modal-backdrop'); |
|
|
| if (this.closeBtn) { |
| this.closeBtn.addEventListener('click', () => this.close()); |
| } |
| |
| if (this.backdrop) { |
| this.backdrop.addEventListener('click', (e) => { |
| if (e.target === this.backdrop) { |
| this.close(); |
| } |
| }); |
| } |
| |
| document.addEventListener('keydown', (e) => { |
| if (e.key === 'Escape' && this.isOpen) { |
| e.preventDefault(); |
| this.close(); |
| } |
| }); |
| } |
| static get observedAttributes() { |
| return ['video-id']; |
| } |
|
|
| attributeChangedCallback(name, oldValue, newValue) { |
| if (name === 'video-id' && oldValue !== newValue) { |
| this.activeVideoId = newValue; |
| if (this.isOpen) { |
| this.open(newValue); |
| } |
| } |
| } |
| open(videoId) { |
| if (!videoId) return; |
| |
| this.activeVideoId = videoId; |
| const iframe = this.shadowRoot.getElementById('youtube-iframe'); |
| if (iframe) { |
| iframe.src = `https://www.youtube.com/embed/${videoId}?autoplay=1&rel=0&modestbranding=1`; |
| } |
| |
| this.modal.classList.add('active'); |
| document.body.style.overflow = 'hidden'; |
| document.documentElement.style.overflow = 'hidden'; |
| this.isOpen = true; |
| } |
|
|
| close() { |
| if (!this.isOpen) return; |
| |
| const iframe = this.shadowRoot.getElementById('youtube-iframe'); |
| if (iframe) { |
| iframe.src = ''; |
| } |
| |
| this.modal.classList.remove('active'); |
| document.body.style.overflow = ''; |
| document.documentElement.style.overflow = ''; |
| this.isOpen = false; |
| } |
| } |
|
|
| customElements.define('youtube-modal', YoutubeModal); |
|
|