Jump to content

User:Udays108/common.js

From BioMicro Center
Revision as of 21:53, 8 May 2026 by Udays108 (talk | contribs)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
 * BioMicro Center Wiki — Modern UI JavaScript
 * Paste into: User:USERNAME/common.js
 * Promoted to: MediaWiki:Common.js (by sysop)
 *
 * Injects: topbar, page-hero, horizontal nav w/ dropdowns.
 * Enhances: TOC styling, smooth scroll, table auto-class.
 */

( function () {
	'use strict';

	/* ── Nav definition (mirrors about.html) ───────────────────── */
	var NAV_ITEMS = [
		{
			label: 'About',
			href: 'http://biomicro.mit.edu/about.html',
			match: [ 'BioMicroCenter', 'About' ]
		},
		{
			label: 'News',
			href: 'http://biomicro.mit.edu/news.html',
			match: [ 'News' ],
			dropdown: [
				{ label: 'Latest News', href: 'http://biomicro.mit.edu/news.html' },
				{ label: 'Seminars', href: 'http://biomicro.mit.edu/seminars.html' },
				{ label: 'Classes & Training', href: 'https://igb.mit.edu/mini-courses', external: true }
			]
		},
		{
			label: 'Services',
			href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:Assisted_Services',
			match: [ 'Assisted_Services', 'Walkup', 'Services' ],
			dropdown: [
				{ label: 'Walkup', href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:Walkup_Instrumentation' },
				{ label: 'Assisted', href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:Assisted_Services' },
				{ label: 'Consumables', href: 'http://biomicro.mit.edu/consumables.html' },
				{ label: 'Training', href: 'https://igb.mit.edu/mini-courses', external: true },
				{ label: 'Informatics', href: 'https://igb.mit.edu/', external: true }
			]
		},
		{
			label: 'Submission',
			href: 'http://biomicro.mit.edu/submit.html',
			match: [ 'Submission', 'Submit' ],
			dropdown: [
				{ groupLabel: 'MIT Users' },
				{ label: 'Submit a Sample', href: 'http://biomicro.mit.edu/submit.html' },
				{ label: 'MIT Pricing', href: 'https://bmcwiki.mit.edu/index.php/MIT:Pricing' },
				{ divider: true },
				{ groupLabel: 'Non-MIT Users' },
				{ label: 'External Submission', href: 'http://biomicro.mit.edu/submit.html' },
				{ label: 'External Pricing', href: 'http://biomicro.mit.edu/pricing_v2.html' }
			]
		},
		{
			label: 'Staff',
			href: 'http://biomicro.mit.edu/staff.html',
			match: [ 'Staff' ]
		},
		{
			label: 'Resources',
			href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:FAQ',
			match: [ 'FAQ', 'Resources', 'Forms', 'Acknowledgement' ],
			dropdown: [
				{ label: 'FAQs', href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:FAQ' },
				{ label: 'Forms', href: 'http://biomicro.mit.edu/forms.html' },
				{ label: 'Grant Support & Pricing', href: 'http://biomicro.mit.edu/pricing_v2.html' },
				{ label: 'Acknowledgements', href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:Acknowledgement' }
			]
		}
	];

	/* ── Helper: create element with attrs & children ──────────── */
	function el( tag, attrs, children ) {
		var node = document.createElement( tag );
		Object.keys( attrs || {} ).forEach( function ( k ) {
			if ( k === 'className' ) {
				node.className = attrs[ k ];
			} else if ( k === 'textContent' ) {
				node.textContent = attrs[ k ];
			} else if ( k === 'innerHTML' ) {
				node.innerHTML = attrs[ k ];
			} else {
				node.setAttribute( k, attrs[ k ] );
			}
		} );
		( children || [] ).forEach( function ( c ) {
			if ( c ) node.appendChild( c );
		} );
		return node;
	}

	/* ── 1. Inject Topbar ───────────────────────────────────────── */
	function injectTopbar() {
		var topbar = el( 'div', { className: 'bmc-topbar' }, [
			el( 'div', { className: 'bmc-topbar-inner' }, [
				el( 'a', { href: 'mailto:biomicro@mit.edu', textContent: 'biomicro@mit.edu' } ),
				el( 'span', { textContent: '|' } ),
				document.createTextNode( '617-715-4533' ),
				el( 'span', { textContent: '|' } ),
				document.createTextNode( 'Building 68-322' )
			] )
		] );

		// Insert before the MediaWiki header element
		var mwHead = document.getElementById( 'mw-head' ) ||
			document.querySelector( '.vector-header' );
		if ( mwHead && mwHead.parentNode ) {
			mwHead.parentNode.insertBefore( topbar, mwHead );
		} else {
			document.body.insertBefore( topbar, document.body.firstChild );
		}

		// Adjust sticky header top offset to account for topbar height
		var topbarH = topbar.offsetHeight;
		var style = document.createElement( 'style' );
		style.textContent =
			'#mw-head, .vector-header, .vector-header-container { top: ' + topbarH + 'px !important; }' +
			'.bmc-page-hero { margin-top: 0; }';
		document.head.appendChild( style );
	}

	/* ── 2. Inject Horizontal Nav ───────────────────────────────── */
	function buildNavItem( item, currentPage ) {
		var li = document.createElement( 'li' );

		// Check if this nav item is active
		var isActive = ( item.match || [] ).some( function ( m ) {
			return currentPage.indexOf( m ) !== -1;
		} );
		if ( isActive ) li.classList.add( 'bmc-active' );

		var link = el( 'a', { href: item.href, textContent: item.label } );
		li.appendChild( link );

		if ( item.dropdown && item.dropdown.length ) {
			li.classList.add( 'bmc-dropdown' );
			var menu = el( 'div', { className: 'bmc-dropdown-menu' } );

			item.dropdown.forEach( function ( d ) {
				if ( d.divider ) {
					menu.appendChild( el( 'div', { className: 'bmc-divider' } ) );
				} else if ( d.groupLabel ) {
					menu.appendChild( el( 'div', {
						className: 'bmc-group-label',
						textContent: d.groupLabel
					} ) );
				} else {
					var a = el( 'a', { href: d.href, textContent: d.label } );
					if ( d.external ) a.setAttribute( 'target', '_blank' );
					menu.appendChild( a );
				}
			} );

			li.appendChild( menu );
		}

		return li;
	}

	function injectHorizontalNav() {
		var currentPage = mw.config.get( 'wgPageName' ) || '';

		var ul = document.createElement( 'ul' );
		NAV_ITEMS.forEach( function ( item ) {
			ul.appendChild( buildNavItem( item, currentPage ) );
		} );

		var nav = el( 'nav', { className: 'bmc-hnav' }, [ ul ] );

		// Find or create the header inner wrapper
		var mwHead = document.getElementById( 'mw-head' ) ||
			document.querySelector( '.vector-header' );
		if ( !mwHead ) return;

		// Find or create a flex inner container
		var inner = mwHead.querySelector( '.bmc-header-inner' );
		if ( !inner ) {
			inner = el( 'div', { className: 'bmc-header-inner' } );
			// Move existing header children into inner (except topbar)
			Array.from( mwHead.childNodes ).forEach( function ( child ) {
				inner.appendChild( child );
			} );
			mwHead.appendChild( inner );
		}

		// Build logo
		var logoLink = el( 'a', {
			href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter',
			className: 'bmc-logo'
		}, [
			el( 'div', { className: 'bmc-logo-mark', textContent: 'BMC' } ),
			el( 'div', { className: 'bmc-logo-text' }, [
				el( 'span', { className: 'bmc-logo-name', textContent: 'MIT BioMicro Center' } ),
				el( 'span', { className: 'bmc-logo-sub', textContent: 'Integrated Genomics Core Facility' } )
			] )
		] );

		// Clear inner and rebuild with logo + nav
		inner.innerHTML = '';
		inner.appendChild( logoLink );
		inner.appendChild( nav );
	}

	/* ── 3. Inject Page Hero ────────────────────────────────────── */
	function injectPageHero() {
		// Get page title from MediaWiki's firstHeading
		var titleEl = document.getElementById( 'firstHeading' ) ||
			document.querySelector( '.mw-first-heading' );
		var titleText = titleEl ? titleEl.textContent.trim() : mw.config.get( 'wgTitle' );

		// Build breadcrumb
		var crumb = el( 'div', { className: 'bmc-breadcrumb' }, [
			el( 'a', { href: 'http://biomicro.mit.edu', textContent: 'Home' } ),
			el( 'span', { textContent: '›' } ),
			document.createTextNode( titleText )
		] );

		var heroH1 = el( 'h1', { textContent: titleText } );

		var heroInner = el( 'div', { className: 'bmc-hero-inner' }, [ crumb, heroH1 ] );
		var hero = el( 'div', { className: 'bmc-page-hero' }, [ heroInner ] );

		// Insert hero between header and content
		var mwHead = document.getElementById( 'mw-head' ) ||
			document.querySelector( '.vector-header' );
		var content = document.getElementById( 'content' ) ||
			document.querySelector( '.mw-body' ) ||
			document.querySelector( '.vector-body' );

		if ( mwHead && mwHead.parentNode ) {
			var ref = mwHead.nextSibling;
			mwHead.parentNode.insertBefore( hero, ref );
		} else if ( content && content.parentNode ) {
			content.parentNode.insertBefore( hero, content );
		}
	}

	/* ── 4. Rewrite Footer ──────────────────────────────────────── */
	function rewriteFooter() {
		var footer = document.getElementById( 'footer' ) ||
			document.querySelector( '.mw-footer' );
		if ( !footer ) return;

		var inner = el( 'div', { className: 'bmc-footer-inner' }, [
			// Col 1: address
			el( 'div', {}, [
				el( 'h4', { textContent: 'MIT BioMicro Center' } ),
				( function () {
					var ul = document.createElement( 'ul' );
					[ 'Building 68-322', 'Cambridge, MA 02139' ].forEach( function ( t ) {
						ul.appendChild( el( 'li', { textContent: t } ) );
					} );
					var emailLi = document.createElement( 'li' );
					emailLi.appendChild( el( 'a', {
						href: 'mailto:biomicro@mit.edu',
						textContent: 'biomicro@mit.edu'
					} ) );
					ul.appendChild( emailLi );
					ul.appendChild( el( 'li', { textContent: '617-715-4533' } ) );
					return ul;
				} )()
			] ),
			// Col 2: services
			el( 'div', {}, [
				el( 'h4', { textContent: 'Services' } ),
				( function () {
					var ul = document.createElement( 'ul' );
					[
						{ label: 'Bulk Sequencing', href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:Assisted_Services' },
						{ label: 'Single Cell', href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:Assisted_Services' },
						{ label: 'Spatial Genomics', href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:Walkup_Instrumentation' },
						{ label: 'Informatics', href: 'https://igb.mit.edu/' }
					].forEach( function ( item ) {
						var li = document.createElement( 'li' );
						li.appendChild( el( 'a', { href: item.href, textContent: item.label } ) );
						ul.appendChild( li );
					} );
					return ul;
				} )()
			] ),
			// Col 3: resources
			el( 'div', {}, [
				el( 'h4', { textContent: 'Resources' } ),
				( function () {
					var ul = document.createElement( 'ul' );
					[
						{ label: 'FAQs', href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:FAQ' },
						{ label: 'Forms', href: 'http://biomicro.mit.edu/forms.html' },
						{ label: 'Grant Support & Pricing', href: 'http://biomicro.mit.edu/pricing_v2.html' },
						{ label: 'Acknowledgements', href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:Acknowledgement' }
					].forEach( function ( item ) {
						var li = document.createElement( 'li' );
						li.appendChild( el( 'a', { href: item.href, textContent: item.label } ) );
						ul.appendChild( li );
					} );
					return ul;
				} )()
			] )
		] );

		var bottom = el( 'div', { className: 'bmc-footer-bottom' }, [
			el( 'span', { textContent: '© ' + new Date().getFullYear() + ' MIT BioMicro Center' } ),
			el( 'span', {}, [
				el( 'a', {
					href: 'https://accessibility.mit.edu',
					target: '_blank',
					textContent: 'Accessibility'
				} )
			] )
		] );

		footer.innerHTML = '';
		footer.appendChild( inner );
		footer.appendChild( bottom );
	}

	/* ── 5. Smooth Scroll ───────────────────────────────────────── */
	function initSmoothScroll() {
		var content = document.querySelector( '.mw-parser-output' );
		if ( !content ) return;
		content.addEventListener( 'click', function ( e ) {
			var a = e.target.closest( 'a[href^="#"]' );
			if ( !a ) return;
			var target = document.getElementById(
				decodeURIComponent( a.getAttribute( 'href' ).slice( 1 ) )
			);
			if ( target ) {
				e.preventDefault();
				target.scrollIntoView( { behavior: 'smooth', block: 'start' } );
				history.pushState( null, '', a.getAttribute( 'href' ) );
			}
		} );
	}

	/* ── 6. Auto-style plain tables ─────────────────────────────── */
	function styleUnstyledTables() {
		var tables = document.querySelectorAll(
			'.mw-parser-output table:not(.wikitable):not(.infobox):not(.navbox):not(.toc)'
		);
		tables.forEach( function ( t ) { t.classList.add( 'wikitable' ); } );
	}

	/* ── Entry point ────────────────────────────────────────────── */
	mw.hook( 'wikipage.content' ).add( function () {
		injectTopbar();
		injectHorizontalNav();
		injectPageHero();
		rewriteFooter();
		initSmoothScroll();
		styleUnstyledTables();
	} );

} )();