diff options
Diffstat (limited to 'resources/js/youtube.js.bak')
| -rw-r--r-- | resources/js/youtube.js.bak | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/resources/js/youtube.js.bak b/resources/js/youtube.js.bak new file mode 100644 index 0000000..6aa2ca8 --- /dev/null +++ b/resources/js/youtube.js.bak @@ -0,0 +1,227 @@ +// YouTube Player - Client-side JavaScript +// Following standard site.js pattern + +let env = {}; // Set by blade template +let cfg = {}; // User config from localStorage +let dom = { + input: {}, + button: {}, + section: {}, + video: {}, + info: {} +}; + +let selectedFormat = 'best'; + +// APP START HERE +$(document).ready(async function() { + console.log('YouTube Player Init'); + + // Core loop of the client application + // 1. Setup relationship with DOM and grab references to its elements + log('init DOM'); + await initDOM(); + + log('init cfg'); + await initCfg(); + + log('init services'); + await initServices(); + + log('YouTube Player Ready'); +}); + +// Gets user config from local storage if there is any +function initCfg() { + let localCfg = localStorage.getItem('youtube_cfg'); + if (localCfg) { + try { + cfg = JSON.parse(localCfg); + // Restore last used format if available + if (cfg.lastFormat) { + selectedFormat = cfg.lastFormat; + updateFormatButtons(); + } + } catch (e) { + cfg = {}; + } + } else { + cfg = {}; + } +} + +function initServices() { + // Attach event listeners + dom.button.load.addEventListener('click', loadVideo); + dom.input.videoUrl.addEventListener('keypress', function(e) { + if (e.key === 'Enter') { + loadVideo(); + } + }); + + // Format selector buttons + dom.button.formatBtns.forEach(btn => { + btn.addEventListener('click', function() { + selectFormat(this); + }); + }); +} + +function initDOM() { + dom.body = $('body')[0]; + + // Input elements + dom.input.videoUrl = $('#videoUrl')[0]; + + // Buttons + dom.button.load = $('#loadBtn')[0]; + dom.button.formatBtns = $('.format-btn').toArray(); + + // Sections + dom.section.error = $('#errorMsg')[0]; + dom.section.loading = $('#loadingMsg')[0]; + dom.section.videoSection = $('#videoSection')[0]; + dom.section.videoInfo = $('#videoInfo')[0]; + + // Video elements + dom.video.player = $('#videoPlayer')[0]; + + // Info elements + dom.info.title = $('#videoTitle')[0]; + dom.info.description = $('#videoDescription')[0]; +} + +function selectFormat(btn) { + // Remove active class from all buttons + dom.button.formatBtns.forEach(b => b.classList.remove('active')); + + // Add active class to clicked button + btn.classList.add('active'); + + // Store selected format + selectedFormat = btn.dataset.format; + + // Save to config + cfg.lastFormat = selectedFormat; + localStorage.setItem('youtube_cfg', JSON.stringify(cfg)); +} + +function updateFormatButtons() { + dom.button.formatBtns.forEach(btn => { + if (btn.dataset.format === selectedFormat) { + btn.classList.add('active'); + } else { + btn.classList.remove('active'); + } + }); +} + +async function loadVideo() { + const videoUrl = dom.input.videoUrl.value.trim(); + + if (!videoUrl) { + showError('Please enter a YouTube URL'); + return; + } + + // Validate YouTube URL + if (!isValidYouTubeUrl(videoUrl)) { + showError('Please enter a valid YouTube URL'); + return; + } + + hideError(); + showLoading(); + hideVideo(); + + try { + // Get video info and stream URL + const response = await axios.post('/yt/info', { + url: videoUrl, + format: selectedFormat + }); + + const data = response.data; + + if (data.error) { + throw new Error(data.error); + } + + // Display video + displayVideo(data); + + // Save to recent videos in config + saveToRecent(videoUrl, data.title); + + } catch (error) { + console.error('Error:', error); + showError(`Failed to load video: ${error.message}`); + } finally { + hideLoading(); + } +} + +function displayVideo(data) { + // Set video source + dom.video.player.src = data.stream_url; + + // Display video info + dom.info.title.textContent = data.title || 'Untitled Video'; + dom.info.description.textContent = data.description || 'No description available'; + + // Show elements + dom.section.videoSection.hidden = false; + dom.section.videoInfo.hidden = false; + + // Auto-play + dom.video.player.play().catch(e => { + log('Auto-play prevented: ' + e.message); + }); +} + +function isValidYouTubeUrl(url) { + const patterns = [ + /^(https?:\/\/)?(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)[\w-]+/, + /^(https?:\/\/)?(www\.)?youtube\.com\/embed\/[\w-]+/ + ]; + return patterns.some(pattern => pattern.test(url)); +} + +function saveToRecent(url, title) { + if (!cfg.recentVideos) { + cfg.recentVideos = []; + } + + // Add to beginning of array, limit to 10 recent + cfg.recentVideos.unshift({ url, title, timestamp: Date.now() }); + cfg.recentVideos = cfg.recentVideos.slice(0, 10); + + localStorage.setItem('youtube_cfg', JSON.stringify(cfg)); +} + +// UI Helper functions +function showError(message) { + dom.section.error.textContent = message; + dom.section.error.hidden = false; +} + +function hideError() { + dom.section.error.hidden = true; +} + +function showLoading() { + dom.section.loading.hidden = false; +} + +function hideLoading() { + dom.section.loading.hidden = true; +} + +function hideVideo() { + dom.section.videoSection.hidden = true; + dom.section.videoInfo.hidden = true; +} + +function log(msg, lvl = 1) { + console.log(msg); +} |
