PageSourceSearch

https://owcltd.com/wp-content/plugins,_ultimate-post,_assets,_js,_…==1.2.2.pagespeed.jc.w_7SYvbcDx.js

js owcltd.com collected 2026-10-09 21:57:57 UTC 21,608 bytes, 2 lines download raw bytes

1var mod_pagespeed_77Guht9mQf = "(function ($) {\n	(\"use strict\");\n\n	$(document).ready(function () {\n		initYouTubeGallery();\n	});\n\n	function initYouTubeGallery() {\n		// Helper for parsing JSON data\n		function parseMaybeJSON(val, fallback) {\n			if (typeof val === \"string\") {\n				try {\n					return JSON.parse(val);\n				} catch (e) {\n					return fallback;\n				}\n			}\n			return typeof val === \"object\" && val !== null ? val : fallback;\n		}\n\n		// Helper to truncate text responsively\n		function truncateText(text, length) {\n			if (!text) return \"\";\n			const width = $(window).width();\n			let maxLength;\n			if (width < 600) {\n				maxLength = length.sm || length.lg;\n			} else if (width < 900) {\n				maxLength = length.md || length.lg;\n			} else {\n				maxLength = length.lg;\n			}\n			return text.length > maxLength\n				? text.substring(0, maxLength) + \"...\"\n				: text;\n		}\n\n		// Helper to sort videos\n		function sortVideos(videos, sortBy) {\n			const sorted = [...videos];\n			switch (sortBy) {\n				case \"title\":\n					return sorted.sort((a, b) =>\n						a.title.localeCompare(b.title, undefined, {\n							sensitivity: \"base\",\n						})\n					);\n				case \"latest\":\n					return sorted.sort(\n						(a, b) =>\n							new Date(b.publishedAt).getTime() -\n							new Date(a.publishedAt).getTime()\n					);\n				case \"date\":\n					return sorted.sort(\n						(a, b) =>\n							new Date(a.publishedAt).getTime() -\n							new Date(b.publishedAt).getTime()\n					);\n				case \"popular\":\n					return sorted.sort((a, b) => (b.viewCount || 0) - (a.viewCount || 0));\n				default:\n					return videos;\n			}\n		}\n\n		// Extract playlist ID from URL or direct ID, and handle channel URLs/handles\n		function getPlaylistId(input) {\n			if (!input) return \"\";\n			try {\n				const url = new URL(input);\n				if (url.hostname === \"www.youtube.com\") {\n					if (url.pathname.startsWith(\"/channel/\")) {\n						return url.pathname.split(\"/channel/\")[1];\n					} else if (url.pathname.startsWith(\"/@\")) {\n						return url.pathname.substring(2); // Return handle for later resolution\n					} else if (url.searchParams.get(\"list\")) {\n						return url.searchParams.get(\"list\");\n					}\n				}\n				return input;\n			} catch (e) {\n				return input;\n			}\n		}\n\n		// Resolve handle to channel ID using YouTube API\n		function resolveHandleToChannelId(handle, apiKey, callback) {\n			$.get(\n				`https://www.googleapis.com/youtube/v3/search?part=snippet&q=${encodeURIComponent(\n					handle\n				)}&type=channel&key=${apiKey}
1`\n			)\n				.done(function (data) {\n					if (data.items && data.items.length > 0) {\n						callback(data.items[0].snippet.channelId);\n					} else {\n						callback(null);\n					}\n				})\n				.fail(function () {\n					callback(null);\n				});\n		}\n\n		// Helper function to generate video player iframe\n		function generatePlayerIframe(videoId, config) {\n			const params = [\n				`autoplay=${config.autoplay ? \"1\" : \"0\"}`,\n				`loop=${config.loop ? \"1\" : \"0\"}`,\n				`mute=${config.mute ? \"1\" : \"0\"}`,\n				`controls=${config.showPlayerControl ? \"1\" : \"0\"}`,\n				`modestbranding=${config.hideYoutubeLogo ? \"1\" : \"0\"}`,\n				config.loop ? `playlist=${videoId}` : null,\n			]\n				.filter(Boolean)\n				.join(\"&\");\n\n			return `\n				<div class=\"ultp-ytg-video-wrapper\">\n					<iframe \n						src=\"https://www.youtube.com/embed/${videoId}?${params}\"\n						title=\"YouTube Video\"\n						frameborder=\"0\"\n						allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n						allowfullscreen\n					></iframe>\n				</div>\n			`;\n		}\n\n		// Generate text content (title and description)\n		function getYoutubeTextContent(\n			enableTitle,\n			title,\n			titleLength,\n			enableDesc,\n			description,\n			descriptionLength,\n			videoId\n		) {\n			let html = '<div class=\"ultp-ytg-content\">';\n			if (enableTitle) {\n				html += `<div class=\"ultp-ytg-title\"><a href=\"https://www.youtube.com/watch?v=${videoId}\" target=\"_blank\" rel=\"noopener noreferrer\">${truncateText(\n					title,\n					titleLength\n				)}</a></div>`;\n			}\n			if (enableDesc) {\n				html += `<div class=\"ultp-ytg-description\">${truncateText(\n					description,\n					descriptionLength\n				)}</div>`;\n			}\n			html += \"</div>\";\n			return html;\n		}\n\n		// Initialize YouTube Gallery\n		$(\".wp-block-ultimate-post-youtube-gallery\").each(function () {\n			const $block = $(this);\n			const $wrapper = $block.find(\".ultp-block-wrapper\");\n			let $container = $block.find(\".ultp-ytg-view-grid, .ultp-ytg-container\");\n			const $loadMoreBtn = $block.find(\".ultp-ytg-loadmore-btn\");\n\n			// Get configuration from data attributes\n			const config = {\n				playlistIdOrUrl: $block.data(\"playlist\") || \"\",\n				apiKey: $block.data(\"api-key\") || \"\",\n				cacheDuration: parseInt($block.data(\"cache-duration\")) || 0,\n				sortBy: $block.data(\"sort-by\") || \"date\",\n				galleryLayout: $block.data(\"gallery-layout\") || \"grid\",\n				videosPerPage: parseMaybeJSON($block.data(\"videos-per-page\"), {\n					lg: 9,\n					md: 6,\n					sm: 3,\n				}),\n				showVideoTitle: $block.data(\"show-video-title\") == \"1\",\n				videoTitleLength: parseMaybeJSON($block.data(\"video-title-length\"), {\n					lg: 50,\n					md: 50,\n					sm: 50,\n				}),\n				loadMoreEnable: $block.data(\"load-more-enable\") == \"1\",\n				moreButtonLabel: $block.data(\"more-button-label\") || \"More Videos\",\n				autoplay: $block.data(\"autoplay\") == \"1\",\n				loop: $block.data(\"loop\") == \"1\",\n				mute: $block.data(\"mute\") == \"1\",\n				showPlayerControl: $block.data(\"show-player-control\") == \"1\",\n				hideYoutubeLogo: $block.data(\"hide-youtube-logo\") == \"1\",\n				showDescription: $block.data(\"show-description\") == \"1\",\n				videoDescriptionLength: parseMaybeJSON(\n					$block.data(\"video-description-length\"),\n					{\n						lg: 100,\n						md: 100,\n						sm: 100,\n					}\n				),\n				imageHeightRatio: $block.data(\"image-height-ratio\") || \"16-9\",\n				galleryColumn: parseMaybeJSON($block.data(\"gallery-column\"), {\n					lg: 3,\n					md: 2,\n					sm: 1,\n				}),\n				displayType: $block.data(\"display-type\") || \"grid\",\n				enableListView: $block.data(\"enable-list-view\") == \"1\",\n				enableIconAnimation: $block.data(\"enable-icon-animation\") == \"1\",\n				defaultYoutubeIcon: $block.data(\"enable-youtube-icon\") == \"1\",\n				imgHeight: $block.data(\"img-height\"),\n			};\n\n			let playlistId = getPlaylistId(config.playlistIdOrUrl);\n\n			// If it's a handle (starts with @), resolve to channel ID\n			if (playlistId.startsWith(\"@\")) {\n				const handle = playlistId.substring(1);\n				resolveHandleToChannelId(handle, config.apiKey, function (channelId) {\n					if (channelId) {\n						playlistId = channelId;\n						proceedWithPlaylist(playlistId);\n					} else {\n						$wrapper.html(\n							'<p style=\"color:#888\">Invalid handle or API key.</p>'\n						);\n					}\n				});\n			} else {\n				proceedWithPlaylist(playlistId);\n			}\n\n			function proceedWithPlaylist(playlistId) {\n				// Convert channel ID to uploads playlist ID\n				if (playlistId.startsWith(\"UC\")) {\n					playlistId = \"UU\" + playlistId.substring(2);\n				}\n\n				if (!playlistId || !config.apiKey) {\n					$wrapper.html(\n						'<p style=\"color:#888\">Please provide both YouTube playlist ID/URL and API key.</p>'\n					);\n					return;\n				}\n\n				// State management\n				let allVideos = [];\n				let shownCount = config.videosPerPage.lg || 9;\n				let activeVideo = null;\n				let playingId = null;\n\n				// Update responsive counts\n				function updateResponsiveCounts() {\n					const width = $(window).width();\n					if (width < 600) {\n						shownCount = Math.max(shownCount, config.videosPerPage.sm || 3);\n					} else if (width < 900) {\n						shownCount = Math.max(shownCount, config.videosPerPage.md || 6);\n					} else {\n						shownCount = Math.max(shownCount, config.videosPerPage.lg || 9);\n					}\n				}\n\n				// Render videos for playlist layout\n				function renderPlaylistLayout(videos) {\n					if (!videos.length) {\n						$container.html(\"<p>No videos found in this playlist.</p>\");\n						return;\n					}\n\n					if (!activeVideo) {\n						activeVideo = videos[0];\n					}\n\n					let html = '<div class=\"ultp-ytg-main\">';\n					// Generate player iframe and place .ultp-ytg-content inside .ultp-ytg-video-wrapper\n					const playerWrapper = `\n						<div class=\"ultp-ytg-video-wrapper\">\n							<iframe \n								src=\"https://www.youtube.com/embed/${activeVideo.videoId}
1?${[\n						`autoplay=${config.autoplay ? \"1\" : \"0\"}`,\n						`loop=${config.loop ? \"1\" : \"0\"}`,\n						`mute=${config.mute ? \"1\" : \"0\"}`,\n						`controls=${config.showPlayerControl ? \"1\" : \"0\"}`,\n						`modestbranding=${config.hideYoutubeLogo ? \"1\" : \"0\"}`,\n						config.loop ? `playlist=${activeVideo.videoId}` : null,\n					]\n						.filter(Boolean)\n						.join(\"&\")}\"\n								title=\"YouTube Video\"\n								frameborder=\"0\"\n								allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n								allowfullscreen\n							></iframe>\n							${getYoutubeTextContent(\n								config.showVideoTitle,\n								activeVideo.title,\n								config.videoTitleLength,\n								config.showDescription,\n								activeVideo.description,\n								config.videoDescriptionLength,\n								activeVideo.videoId\n							)}\n						</div>\n					`;\n					html += playerWrapper;\n					html += \"</div>\";\n\n					html += '<div class=\"ultp-ytg-playlist-sidebar\">';\n					html += '<div class=\"ultp-ytg-playlist-items\">';\n					videos.forEach(function (video) {\n						const isActive = video.videoId === activeVideo.videoId;\n						html += `\n							<div class=\"ultp-ytg-playlist-item ${\n								isActive ? \"active\" : \"\"\n							}\" data-video-id=\"${video.videoId}\">\n								<img src=\"${video.thumbnail}\" alt=\"${video.title}\" loading=\"lazy\" />\n								<div class=\"ultp-ytg-playlist-item-content\">\n									<div class=\"ultp-ytg-playlist-item-title\">\n										${truncateText(video.title, config.videoTitleLength)}\n									</div>\n								</div>\n							</div>\n						`;\n					});\n					html += \"</div></div>\";\n\n					$container.html(html);\n				}\n\n				// Render videos for grid/list layout\n				function renderGridLayout(videos, count) {\n					if (!videos.length) {\n						$container.html(\"<p>No videos found in this playlist.</p>\");\n						return;\n					}\n\n					const displayedVideos = videos.slice(0, count);\n					let html = \"\";\n					displayedVideos.forEach(function (video) {\n						const isPlaying = playingId === video.videoId;\n						html += `<div class=\"ultp-ytg-item${isPlaying ? \" active\" : \"\"}\">`;\n						html += `<div class=\"ultp-ytg-video\">`;\n\n						if (isPlaying) {\n							html += generatePlayerIframe(video.videoId, config);\n						} else {\n							// enableIconAnimation\n							const getSvgIcon = $(\".ultp-ytg-play__icon\").html();\n							html += `\n								<img src=\"${video.thumbnail}\" alt=\"${\n								video.title\n							}\" loading=\"lazy\" data-video-id=\"${\n								video.videoId\n							}\" style=\"cursor:pointer;\" />\n								<div class=\"ultp-ytg-play__icon${\n									config.enableIconAnimation ? \" ytg-icon-animation\" : \"\"\n								}\">\n									${getSvgIcon}\n								</div>\n							`;\n						}\n\n						html += `</div>`;\n						html += `<div class=\"ultp-ytg-inside\">`;\n						html += getYoutubeTextContent(\n							config.showVideoTitle,\n							video.title,\n							config.videoTitleLength,\n							config.showDescription,\n							video.description,\n							config.videoDescriptionLength,\n							video.videoId\n						);\n						html += `</div></div>`;\n					});\n\n					$container.html(html);\n\n					// Update load more button visibility\n					if (config.loadMoreEnable && count < videos.length) {\n						$loadMoreBtn.show();\n					} else {\n						$loadMoreBtn.hide();\n					}\n				}\n\n				// Render based on layout type\n				function renderVideos(videos, count) {\n					if (config.galleryLayout === \"playlist\") {\n						renderPlaylistLayout(videos);\n					} else {\n						renderGridLayout(videos, count);\n					}\n				}\n\n				// Fetch videos from YouTube API\n				const cacheKey = `ultp_youtube_gallery_${playlistId}_${config.apiKey}_${config.sortBy}_${config.imgHeight}`;\n				const duration = config.cacheDuration;\n				let cached = null;\n\n				try {\n					cached = JSON.parse(localStorage.getItem(cacheKey));\n				} catch (e) {\n					cached = null;\n				}\n\n				const now = Date.now();\n				if (\n					cached &&\n					cached.data &&\n					cached.timestamp &&\n					duration > 0 &&\n					now - cached.timestamp < duration * 1000\n				) {\n					allVideos = sortVideos(cached.data, config.sortBy);\n					renderVideos(allVideos, shownCount);\n				} else {\n					// Only show loading skeleton for grid/list layouts, not for playlist layout\n					if (config.galleryLayout !== \"playlist\") {\n						$container.html(`\n							<div class=\"ultp-ytg-loading gallery-postx gallery-active\">\n								<div class=\"skeleton-box\"></div>\n								<div class=\"skeleton-box\"></div>\n								<div class=\"skeleton-box\"></div>\n								<div class=\"skeleton-box\"></div>\n								<div class=\"skeleton-box\"></div>\n								<div class=\"skeleton-box\"></div>\n							</div>\n						`);\n					} else {\n						$container.html(`\n							<div class=\"ultp-ytg-loading ultp-ytg-playlist-loading\">
1\n								<div class=\"ytg-loader\"></div>\n							</div>`);\n					}\n\n					$.get(\"https://www.googleapis.com/youtube/v3/playlistItems\", {\n						part: \"snippet\",\n						maxResults: 50,\n						playlistId: playlistId,\n						key: config.apiKey,\n					})\n						.done(function (data) {\n							setTimeout(function () {\n								$container.empty(); // Remove loading after 3s\n								if (data.error) {\n									$container.html(\n										`<div class=\"ultp-ytg-error\">${\n											data.error.message || \"Failed to fetch playlist.\"\n										}</div>`\n									);\n									return;\n								}\n\n								const videos = (data.items || [])\n									.filter(function (item) {\n										return (\n											item.snippet.title !== \"Private video\" &&\n											item.snippet.title !== \"Deleted video\"\n										);\n									})\n									.map(function (item) {\n										return {\n											videoId: item.snippet.resourceId.videoId,\n											title: item.snippet.title,\n											thumbnail:\n												(item.snippet.thumbnails &&\n													item.snippet.thumbnails[config.imgHeight] &&\n													item.snippet.thumbnails[config.imgHeight].url) ||\n												item.snippet.thumbnails[config.imgHeight].url ||\n												item.snippet.thumbnails?.medium?.url ||\n												\"\",\n											publishedAt: item.snippet.publishedAt || \"\",\n											description: item.snippet.description || \"\",\n											viewCount: 0, // Initialize for popular sorting\n										};\n									}); // If sorting by popular, fetch view counts\n								if (config.sortBy === \"popular\") {\n									const videoIds = videos.map((v) => v.videoId).join(\",\");\n									$.get(\n										`https://www.googleapis.com/youtube/v3/videos?part=statistics&id=${videoIds}&key=${config.apiKey}`\n									)\n										.done(function (statsData) {\n											if (statsData.items) {\n												const statsMap = {};\n												statsData.items.forEach(function (item) {\n													statsMap[item.id] = item.statistics.viewCount;\n												});\n												videos.forEach(function (v) {\n													v.viewCount = parseInt(statsMap[v.videoId] || 0);\n												});\n											}\n											allVideos = sortVideos(videos, config.sortBy);\n											if (duration > 0) {\n												try {\n													localStorage.setItem(\n														cacheKey,\n														JSON.stringify({\n															data: videos,\n															timestamp: now,\n														})\n													);\n												} catch (e) {\n													console.warn(\"Failed to cache videos:\", e);\n												}\n											}\n											renderVideos(allVideos, shownCount);\n										})\n										.fail(function () {\n											console.warn(\n												\"Failed to fetch video statistics for popular sorting.\"\n											);\n											allVideos = sortVideos(videos, config.sortBy);\n											renderVideos(allVideos, shownCount);\n										});\n								} else {\n									allVideos = sortVideos(videos, config.sortBy);\n									if (duration > 0) {\n										try {\n											localStorage.setItem(\n												cacheKey,\n												JSON.stringify({\n													data: videos,\n													timestamp: now,\n												})\n											);\n										} catch (e) {\n											console.warn(\"Failed to cache videos:\", e);\n										}\n									}\n									renderVideos(allVideos, shownCount);\n								}\n							}, 2000);\n						})\n						.fail(function () {\n							setTimeout(function () {\n								$container.empty();\n								$container.html(\n									'<div class=\"ultp-ytg-error\">Failed to fetch videos. Please try again.</div>'\n								);\n							}, 3000);\n						});\n				}\n\n				// Event handlers\n				$block.on(\"click\", \".ultp-ytg-playlist-item\", function () {\n					const videoId = $(this).data(\"video-id\");\n					if (!videoId) return;\n\n					activeVideo = allVideos.find(function (v) {\n						return v.videoId === videoId;\n					});\n\n					if (activeVideo) {\n						renderPlaylistLayout(allVideos);\n					}\n				});\n				// Make clicking the play icon also start the video with loader fallback (per item)\n				$block.on(\"click\", \".ultp-ytg-play__icon\", function () {\n					// Find the previous img[data-vi
1deo-id] sibling to get the videoId\n					const $img = $(this).siblings(\"img[data-video-id]\");\n					const videoId = $img.data(\"video-id\");\n					if (!videoId) return;\n					// Find the closest .ultp-ytg-item and its .ultp-ytg-video\n					const $item = $(this).closest(\".ultp-ytg-item\");\n					const $videoDiv = $item.find(\".ultp-ytg-video\");\n					// Show loader only in this video area\n					$videoDiv.html(\n						'<div class=\"ultp-ytg-loading\"><div class=\"ytg-loader\"></div></div>'\n					);\n					// Add active class to this item, remove from others\n					$item\n						.addClass(\"active\")\n						.siblings(\".ultp-ytg-item\")\n						.removeClass(\"active\");\n					setTimeout(function () {\n						playingId = videoId;\n						renderGridLayout(allVideos, shownCount);\n					}, 1000);\n				});\n\n				$block.on(\"click\", \".ultp-ytg-video img[data-video-id]\", function () {\n					const videoId = $(this).data(\"video-id\");\n					if (!videoId) return;\n\n					playingId = videoId;\n					renderGridLayout(allVideos, shownCount);\n				});\n\n				$loadMoreBtn.on(\"click\", function () {\n					shownCount += config.videosPerPage.lg;\n					renderGridLayout(allVideos, shownCount);\n				});\n				// Responsive handling\n				$(window).on(\"resize\", function () {\n					if (allVideos.length) {\n						updateResponsiveCounts();\n						renderVideos(allVideos, shownCount);\n					}\n				});\n			}\n		});\n	}\n})(jQuery);\n";
2var mod_pagespeed_h9MJ$SlQTp = "(function(){const siteNavigation=document.getElementById('site-navigation');if(!siteNavigation){return;}const button=siteNavigation.getElementsByTagName('button')[0];if('undefined'===typeof button){return;}const menu=siteNavigation.getElementsByTagName('ul')[0];if('undefined'===typeof menu){button.style.display='none';return;}if(!menu.classList.contains('nav-menu')){menu.classList.add('nav-menu');}button.addEventListener('click',function(){siteNavigation.classList.toggle('toggled');if(button.getAttribute('aria-expanded')==='true'){button.setAttribute('aria-expanded','false');}else{button.setAttribute('aria-expanded','true');}});let textnode=document.createTextNode('\\u2716');let linkItem=document.createElement('a');linkItem.href='#';linkItem.classList.add('dismiss-menu');linkItem.appendChild(textnode);linkItem.addEventListener('click',function(event){event.preventDefault;siteNavigation.classList.toggle('toggled');if(button.getAttribute('aria-expanded')==='true'){button.setAttribute('aria-expanded','false');}else{button.setAttribute('aria-expanded','true');}});let listItem=document.createElement('li');listItem.classList.add('dismiss-menu-item');listItem.appendChild(linkItem);const mainMenu=document.getElementById('primary-menu');mainMenu.prepend(listItem);document.addEventListener('click',function(event){const isClickInside=siteNavigation.contains(event.target);if(!isClickInside){siteNavigation.classList.remove('toggled');button.setAttribute('aria-expanded','false');}});const links=menu.getElementsByTagName('a');const linksWithChildren=menu.querySelectorAll('.menu-item-has-children > a, .page_item_has_children > a');for(const link of links){link.addEventListener('focus',toggleFocus,true);link.addEventListener('blur',toggleFocus,true);}for(const link of linksWithChildren){link.addEventListener('touchstart',toggleFocus,false);link.addEventListener('click',toggleFocus,false);}function toggleFocus(){if(event.type==='touchstart'||event.type==='click'){const menuItem=this.parentNode;if(siteNavigation.classList.contains('toggled')&&(!menuItem.classList.contains('focus')||this.getAttribute('href')==='#')){event.preventDefault();for(const link of menuItem.parentNode.children){if(menuItem!==link){link.classList.remove('focus');}}menuItem.classList.toggle('focus');}}}}());";

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.