<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://dunedb.com/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-VideoGallery.js</id>
	<title>MediaWiki:Gadget-VideoGallery.js - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://dunedb.com/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-VideoGallery.js"/>
	<link rel="alternate" type="text/html" href="https://dunedb.com/index.php?title=MediaWiki:Gadget-VideoGallery.js&amp;action=history"/>
	<updated>2026-05-23T18:05:18Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://dunedb.com/index.php?title=MediaWiki:Gadget-VideoGallery.js&amp;diff=822&amp;oldid=prev</id>
		<title>Operator: Created page with &quot;/* Video Gallery – Common.js / Gadget    Loads only when .video-gallery-main-container exists  */  mw.loader.using( [ &#039;jquery&#039;, &#039;mediawiki.util&#039; ] ).then( function () { 	&#039;use strict&#039;;  	// Avoid double-init if RL bundles it twice 	if ( window.DuneVideoGalleryLoaded ) { return; } 	window.DuneVideoGalleryLoaded = true;  	// Bail out on pages without a gallery 	if ( !$( &#039;.video-gallery-main-container&#039; ).length ) { return; }  	/* -------------------------------------------...&quot;</title>
		<link rel="alternate" type="text/html" href="https://dunedb.com/index.php?title=MediaWiki:Gadget-VideoGallery.js&amp;diff=822&amp;oldid=prev"/>
		<updated>2025-06-02T03:26:24Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;&lt;span class=&quot;autocomment&quot;&gt;Video Gallery – Common.js / Gadget    Loads only when .video-gallery-main-container exists: &lt;/span&gt;  mw.loader.using( [ &amp;#039;jquery&amp;#039;, &amp;#039;mediawiki.util&amp;#039; ] ).then( function () { 	&amp;#039;use strict&amp;#039;;  	// Avoid double-init if RL bundles it twice 	if ( window.DuneVideoGalleryLoaded ) { return; } 	window.DuneVideoGalleryLoaded = true;  	// Bail out on pages without a gallery 	if ( !$( &amp;#039;.video-gallery-main-container&amp;#039; ).length ) { return; }  	/* -------------------------------------------...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;/* Video Gallery – Common.js / Gadget&lt;br /&gt;
   Loads only when .video-gallery-main-container exists  */&lt;br /&gt;
&lt;br /&gt;
mw.loader.using( [ &amp;#039;jquery&amp;#039;, &amp;#039;mediawiki.util&amp;#039; ] ).then( function () {&lt;br /&gt;
	&amp;#039;use strict&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
	// Avoid double-init if RL bundles it twice&lt;br /&gt;
	if ( window.DuneVideoGalleryLoaded ) { return; }&lt;br /&gt;
	window.DuneVideoGalleryLoaded = true;&lt;br /&gt;
&lt;br /&gt;
	// Bail out on pages without a gallery&lt;br /&gt;
	if ( !$( &amp;#039;.video-gallery-main-container&amp;#039; ).length ) { return; }&lt;br /&gt;
&lt;br /&gt;
	/* -------------------------------------------------&lt;br /&gt;
	   DuneVideoGallery object (your original code)&lt;br /&gt;
	--------------------------------------------------*/&lt;br /&gt;
	window.DuneVideoGallery = {&lt;br /&gt;
		videoData: {},&lt;br /&gt;
		currentVideo: null,&lt;br /&gt;
&lt;br /&gt;
		init: function () {&lt;br /&gt;
			this.parseVideoData();&lt;br /&gt;
			this.setupEventListeners();&lt;br /&gt;
			this.checkUrlParams();&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		parseVideoData: function () {&lt;br /&gt;
			var dataElement = $( &amp;#039;#video-gallery-data&amp;#039; );&lt;br /&gt;
			if ( dataElement.length ) {&lt;br /&gt;
				try {&lt;br /&gt;
					this.videoData = JSON.parse( dataElement.text() );&lt;br /&gt;
				} catch ( e ) {&lt;br /&gt;
					console.error( &amp;#039;Failed to parse video data:&amp;#039;, e );&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		setupEventListeners: function () {&lt;br /&gt;
			var self = this;&lt;br /&gt;
&lt;br /&gt;
			$( document )&lt;br /&gt;
				.on( &amp;#039;click&amp;#039;, &amp;#039;.video-tab&amp;#039;, function ( e ) {&lt;br /&gt;
					e.preventDefault();&lt;br /&gt;
					self.switchTab( $( this ).data( &amp;#039;tab&amp;#039; ) );&lt;br /&gt;
				} )&lt;br /&gt;
				.on( &amp;#039;click&amp;#039;, &amp;#039;.video-card&amp;#039;, function ( e ) {&lt;br /&gt;
					e.preventDefault();&lt;br /&gt;
					self.loadVideo( $( this ).data( &amp;#039;video-id&amp;#039; ) );&lt;br /&gt;
				} )&lt;br /&gt;
				.on( &amp;#039;input&amp;#039;, &amp;#039;.video-search-input&amp;#039;, function () {&lt;br /&gt;
					self.searchVideos( $( this ).val() );&lt;br /&gt;
				} )&lt;br /&gt;
				.on( &amp;#039;click&amp;#039;, &amp;#039;.video-search-button&amp;#039;, function ( e ) {&lt;br /&gt;
					e.preventDefault();&lt;br /&gt;
					self.searchVideos( $( &amp;#039;.video-search-input&amp;#039; ).val() );&lt;br /&gt;
				} );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		switchTab: function ( tabName ) {&lt;br /&gt;
			$( &amp;#039;.video-tab, .video-tab-content&amp;#039; ).removeClass( &amp;#039;active&amp;#039; );&lt;br /&gt;
			$( &amp;#039;.video-tab[data-tab=&amp;quot;&amp;#039; + tabName + &amp;#039;&amp;quot;]&amp;#039; ).addClass( &amp;#039;active&amp;#039; );&lt;br /&gt;
			$( &amp;#039;.video-tab-content[data-content=&amp;quot;&amp;#039; + tabName + &amp;#039;&amp;quot;]&amp;#039; ).addClass( &amp;#039;active&amp;#039; );&lt;br /&gt;
&lt;br /&gt;
			var url = new URL( window.location );&lt;br /&gt;
			url.searchParams.set( &amp;#039;tab&amp;#039;, tabName );&lt;br /&gt;
			window.history.pushState( {}, &amp;#039;&amp;#039;, url );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		loadVideo: function ( videoId ) {&lt;br /&gt;
			var video = this.videoData[ videoId ];&lt;br /&gt;
			if ( !video ) { console.error( &amp;#039;Video not found:&amp;#039;, videoId ); return; }&lt;br /&gt;
&lt;br /&gt;
			$( &amp;#039;.video-card&amp;#039; ).removeClass( &amp;#039;active&amp;#039; )&lt;br /&gt;
				.filter( &amp;#039;[data-video-id=&amp;quot;&amp;#039; + videoId + &amp;#039;&amp;quot;]&amp;#039; ).addClass( &amp;#039;active&amp;#039; );&lt;br /&gt;
&lt;br /&gt;
			this.currentVideo = video;&lt;br /&gt;
			$( &amp;#039;#videoPlayerPanel&amp;#039; ).html( this.buildPlayerHTML( video ) );&lt;br /&gt;
&lt;br /&gt;
			var url = new URL( window.location );&lt;br /&gt;
			url.searchParams.set( &amp;#039;video&amp;#039;, videoId );&lt;br /&gt;
			window.history.pushState( {}, &amp;#039;&amp;#039;, url );&lt;br /&gt;
&lt;br /&gt;
			if ( window.innerWidth &amp;lt;= 1200 ) {&lt;br /&gt;
				document.getElementById( &amp;#039;videoPlayerPanel&amp;#039; )&lt;br /&gt;
					.scrollIntoView( { behavior: &amp;#039;smooth&amp;#039;, block: &amp;#039;start&amp;#039; } );&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		buildPlayerHTML: function ( v ) {&lt;br /&gt;
			var published = v.published_at ? v.published_at.slice( 0, 10 ) : &amp;#039;&amp;#039;;&lt;br /&gt;
			return (&lt;br /&gt;
				&amp;#039;&amp;lt;div class=&amp;quot;video-embed-container&amp;quot;&amp;gt;&amp;#039; +&lt;br /&gt;
					&amp;#039;&amp;lt;iframe src=&amp;quot;https://www.youtube.com/embed/&amp;#039; + v.youtube_id +&lt;br /&gt;
					&amp;#039;?rel=0&amp;amp;modestbranding=1&amp;quot; frameborder=&amp;quot;0&amp;quot; allow=&amp;quot;accelerometer; autoplay; &amp;#039; +&lt;br /&gt;
					&amp;#039;clipboard-write; encrypted-media; gyroscope; picture-in-picture&amp;quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&amp;#039; +&lt;br /&gt;
				&amp;#039;&amp;lt;/div&amp;gt;&amp;#039; +&lt;br /&gt;
				&amp;#039;&amp;lt;div class=&amp;quot;video-details-header&amp;quot;&amp;gt;&amp;#039; +&lt;br /&gt;
					&amp;#039;&amp;lt;h2 class=&amp;quot;video-main-title&amp;quot;&amp;gt;&amp;#039; + this.escapeHtml( v.title ) + &amp;#039;&amp;lt;/h2&amp;gt;&amp;#039; +&lt;br /&gt;
					&amp;#039;&amp;lt;div class=&amp;quot;video-meta&amp;quot;&amp;gt;&amp;#039; +&lt;br /&gt;
						&amp;#039;&amp;lt;span class=&amp;quot;video-author&amp;quot;&amp;gt;👤 &amp;#039; + this.escapeHtml( v.author || v.channel_title ) + &amp;#039;&amp;lt;/span&amp;gt;&amp;#039; +&lt;br /&gt;
						&amp;#039;&amp;lt;span class=&amp;quot;video-date&amp;quot;&amp;gt;📅 &amp;#039; + published + &amp;#039;&amp;lt;/span&amp;gt;&amp;#039; +&lt;br /&gt;
					&amp;#039;&amp;lt;/div&amp;gt;&amp;#039; +&lt;br /&gt;
				&amp;#039;&amp;lt;/div&amp;gt;&amp;#039; +&lt;br /&gt;
				&amp;#039;&amp;lt;div class=&amp;quot;video-notes-section&amp;quot;&amp;gt;&amp;#039; +&lt;br /&gt;
					&amp;#039;&amp;lt;div class=&amp;quot;notes-header&amp;quot;&amp;gt;Video Notes&amp;lt;/div&amp;gt;&amp;#039; +&lt;br /&gt;
					&amp;#039;&amp;lt;div class=&amp;quot;notes-content&amp;quot;&amp;gt;&amp;#039; +&lt;br /&gt;
						( v.video_notes || &amp;#039;&amp;lt;p&amp;gt;No notes available for this video.&amp;lt;/p&amp;gt;&amp;#039; ) +&lt;br /&gt;
					&amp;#039;&amp;lt;/div&amp;gt;&amp;#039; +&lt;br /&gt;
				&amp;#039;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
			);&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		escapeHtml: function ( txt ) {&lt;br /&gt;
			return txt.replace( /[&amp;amp;&amp;lt;&amp;gt;&amp;quot;&amp;#039;]/g, function ( ch ) {&lt;br /&gt;
				return { &amp;#039;&amp;amp;&amp;#039;: &amp;#039;&amp;amp;amp;&amp;#039;, &amp;#039;&amp;lt;&amp;#039;: &amp;#039;&amp;amp;lt;&amp;#039;, &amp;#039;&amp;gt;&amp;#039;: &amp;#039;&amp;amp;gt;&amp;#039;, &amp;#039;&amp;quot;&amp;#039;: &amp;#039;&amp;amp;quot;&amp;#039;, &amp;quot;&amp;#039;&amp;quot;: &amp;#039;&amp;amp;#039;&amp;#039; }[ ch ];&lt;br /&gt;
			} );&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		checkUrlParams: function () {&lt;br /&gt;
			var params   = new URLSearchParams( window.location.search );&lt;br /&gt;
			var tab      = params.get( &amp;#039;tab&amp;#039; );&lt;br /&gt;
			var videoId  = params.get( &amp;#039;video&amp;#039; );&lt;br /&gt;
&lt;br /&gt;
			if ( tab &amp;amp;&amp;amp; $( &amp;#039;.video-tab[data-tab=&amp;quot;&amp;#039; + tab + &amp;#039;&amp;quot;]&amp;#039; ).length ) {&lt;br /&gt;
				this.switchTab( tab );&lt;br /&gt;
			}&lt;br /&gt;
			if ( videoId &amp;amp;&amp;amp; this.videoData[ videoId ] ) {&lt;br /&gt;
				var self = this;&lt;br /&gt;
				setTimeout( function () { self.loadVideo( videoId ); }, 100 );&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		searchVideos: function ( q ) {&lt;br /&gt;
			q = ( q || &amp;#039;&amp;#039; ).toLowerCase();&lt;br /&gt;
			if ( !q ) {&lt;br /&gt;
				$( &amp;#039;.video-card, .video-section&amp;#039; ).show();&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			var self = this;&lt;br /&gt;
			$( &amp;#039;.video-card&amp;#039; ).each( function () {&lt;br /&gt;
				var id   = $( this ).data( &amp;#039;video-id&amp;#039; );&lt;br /&gt;
				var v    = self.videoData[ id ] || {};&lt;br /&gt;
				var blob = ( v.title + &amp;#039; &amp;#039; + v.channel_title + &amp;#039; &amp;#039; + ( v.description || &amp;#039;&amp;#039; ) +&lt;br /&gt;
					&amp;#039; &amp;#039; + ( ( v.tags || [] ).join( &amp;#039; &amp;#039; ) ) ).toLowerCase();&lt;br /&gt;
&lt;br /&gt;
				$( this ).toggle( blob.includes( q ) );&lt;br /&gt;
			} );&lt;br /&gt;
&lt;br /&gt;
			$( &amp;#039;.video-section&amp;#039; ).each( function () {&lt;br /&gt;
				$( this ).toggle( $( this ).find( &amp;#039;.video-card:visible&amp;#039; ).length &amp;gt; 0 );&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	// Boot once DOM ready&lt;br /&gt;
	$( function () {&lt;br /&gt;
		window.DuneVideoGallery.init();&lt;br /&gt;
	} );&lt;br /&gt;
} );&lt;/div&gt;</summary>
		<author><name>Operator</name></author>
	</entry>
</feed>