User:Udays108/common.js: Difference between revisions
Appearance
No edit summary |
No edit summary Tag: Manual revert |
||
| (3 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
/** | /** | ||
* BioMicro Center Wiki — | * BioMicro Center Wiki — Full DOM Replacement | ||
* Paste into: User:USERNAME/common.js | * Paste into: User:USERNAME/common.js | ||
* | * | ||
* | * Strategy: | ||
* | * 1. Extract wiki article content from MediaWiki's DOM | ||
* 2. Inject the complete about.html shell structure | |||
* 3. Place article content inside the shell | |||
* MediaWiki still runs underneath for editing, search, login, etc. | |||
*/ | */ | ||
( function () { | ( function () { | ||
'use strict'; | |||
/* ── Nav definition (matches about.html exactly) ──────────── */ | |||
var NAV = [ | |||
{ | |||
label: 'About', | |||
href: 'http://biomicro.mit.edu/about.html', | |||
match: [ 'BioMicroCenter', 'Main_Page' ] | |||
}, | |||
{ | |||
label: 'News', | |||
href: 'http://biomicro.mit.edu/news.html', | |||
match: [ 'News', 'Seminar' ], | |||
items: [ | |||
{ 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', ext: true } | |||
] | |||
}, | |||
{ | |||
label: 'Services', | |||
href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:Assisted_Services', | |||
match: [ 'Assisted_Services', 'Walkup', 'Service', 'Consumable' ], | |||
items: [ | |||
{ 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', ext: true }, | |||
{ label: 'Informatics', href: 'https://igb.mit.edu/', ext: true } | |||
] | |||
}, | |||
{ | |||
label: 'Submission', | |||
href: 'http://biomicro.mit.edu/submit.html', | |||
match: [ 'Submission', 'Submit', 'Pricing' ], | |||
items: [ | |||
{ 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', 'Resource', 'Form', 'Acknowledgement' ], | |||
items: [ | |||
{ 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' } | |||
] | |||
} | |||
]; | |||
/* ── Build topbar HTML ─────────────────────────────────────── */ | |||
function buildTopbar() { | |||
var d = document.createElement( 'div' ); | |||
d.className = 'bmc-topbar'; | |||
d.innerHTML = | |||
'<div class="inner">' + | |||
'<a href="mailto:biomicro@mit.edu">biomicro@mit.edu</a>' + | |||
'<span>|</span>' + | |||
'617-715-4533' + | |||
'<span>|</span>' + | |||
'Building 68-322' + | |||
'</div>'; | |||
return d; | |||
} | |||
/* ── Build nav dropdown item ───────────────────────────────── */ | |||
function buildDropdownMenu( items ) { | |||
var menu = document.createElement( 'div' ); | |||
menu.className = 'bmc-dropdown-menu'; | |||
items.forEach( function ( item ) { | |||
if ( item.divider ) { | |||
var div = document.createElement( 'div' ); | |||
div.className = 'bmc-divider'; | |||
menu.appendChild( div ); | |||
} else if ( item.groupLabel ) { | |||
var gl = document.createElement( 'div' ); | |||
gl.className = 'bmc-group-label'; | |||
gl.textContent = item.groupLabel; | |||
menu.appendChild( gl ); | |||
} else { | |||
var a = document.createElement( 'a' ); | |||
a.href = item.href; | |||
a.textContent = item.label; | |||
if ( item.ext ) a.target = '_blank'; | |||
menu.appendChild( a ); | |||
} | |||
} ); | |||
return menu; | |||
} | |||
/* ── Build full header ─────────────────────────────────────── */ | |||
function buildHeader( currentPage ) { | |||
/* Logo */ | |||
var logo = document.createElement( 'a' ); | |||
logo.href = 'https://bmcwiki.mit.edu/index.php/BioMicroCenter'; | |||
logo.className = 'bmc-logo'; | |||
logo.innerHTML = | |||
'<div class="bmc-logo-mark">BMC</div>' + | |||
'<div class="bmc-logo-text">' + | |||
'<span class="bmc-logo-name">MIT BioMicro Center</span>' + | |||
'<span class="bmc-logo-sub">Integrated Genomics Core Facility</span>' + | |||
'</div>'; | |||
/* Nav */ | |||
var ul = document.createElement( 'ul' ); | |||
NAV.forEach( function ( item ) { | |||
var li = document.createElement( 'li' ); | |||
var isActive = ( item.match || [] ).some( function ( m ) { | |||
return currentPage.indexOf( m ) !== -1; | |||
} ); | |||
if ( isActive ) li.classList.add( 'bmc-active' ); | |||
if ( item.items ) li.classList.add( 'bmc-dropdown' ); | |||
var a = document.createElement( 'a' ); | |||
a.href = item.href; | |||
a.textContent = item.label; | |||
li.appendChild( a ); | |||
if ( item.items ) { | |||
li.appendChild( buildDropdownMenu( item.items ) ); | |||
} | |||
ul.appendChild( li ); | |||
} ); | |||
var nav = document.createElement( 'nav' ); | |||
nav.className = 'bmc-nav'; | |||
nav.appendChild( ul ); | |||
/* Search */ | |||
var searchForm = document.createElement( 'form' ); | |||
searchForm.className = 'bmc-search-form'; | |||
searchForm.method = 'get'; | |||
searchForm.action = '/index.php'; | |||
searchForm.innerHTML = | |||
'<input type="hidden" name="title" value="Special:Search">' + | |||
'<input type="search" name="search" placeholder="Search wiki…" aria-label="Search">' + | |||
'<button type="submit">⚲</button>'; | |||
var right = document.createElement( 'div' ); | |||
right.className = 'bmc-header-right'; | |||
right.appendChild( nav ); | |||
right.appendChild( searchForm ); | |||
/* Inner wrapper */ | |||
var inner = document.createElement( 'div' ); | |||
inner.className = 'bmc-header-inner'; | |||
inner.appendChild( logo ); | |||
inner.appendChild( right ); | |||
var header = document.createElement( 'header' ); | |||
header.className = 'bmc-header'; | |||
header.appendChild( inner ); | |||
return header; | |||
} | |||
/* ── Build page hero ───────────────────────────────────────── */ | |||
function buildHero( titleText ) { | |||
var crumb = document.createElement( 'div' ); | |||
crumb.className = 'bmc-breadcrumb'; | |||
crumb.innerHTML = | |||
'<a href="http://biomicro.mit.edu">Home</a>' + | |||
'<span class="sep">›</span>' + | |||
document.createTextNode( titleText ).textContent; // plain text, no XSS | |||
var h1 = document.createElement( 'h1' ); | |||
h1.textContent = titleText; | |||
var inner = document.createElement( 'div' ); | |||
inner.className = 'inner'; | |||
inner.appendChild( crumb ); | |||
inner.appendChild( h1 ); | |||
var hero = document.createElement( 'div' ); | |||
hero.className = 'bmc-page-hero'; | |||
hero.appendChild( inner ); | |||
return hero; | |||
} | |||
/* ── Build sidebar TOC from MediaWiki #toc ─────────────────── */ | |||
function buildSidebarToc( mwToc ) { | |||
var toc = document.createElement( 'div' ); | |||
toc.className = 'bmc-toc'; | |||
var h3 = document.createElement( 'h3' ); | |||
h3.textContent = 'On this page'; | |||
toc.appendChild( h3 ); | |||
if ( mwToc ) { | |||
/* Clone only the list from the MediaWiki TOC */ | |||
var mwList = mwToc.querySelector( 'ul' ); | |||
if ( mwList ) { | |||
var cloned = mwList.cloneNode( true ); | |||
/* Mark sub-items */ | |||
cloned.querySelectorAll( 'li li' ).forEach( function ( li ) { | |||
li.classList.add( 'bmc-sub' ); | |||
} ); | |||
toc.appendChild( cloned ); | |||
} | |||
} else { | |||
/* No TOC generated — leave the sidebar empty or show nothing */ | |||
return null; | |||
} | |||
var aside = document.createElement( 'aside' ); | |||
aside.className = 'bmc-sidebar'; | |||
aside.appendChild( toc ); | |||
return aside; | |||
} | |||
/* ── Build footer ──────────────────────────────────────────── */ | |||
function buildFooter() { | |||
var inner = document.createElement( 'div' ); | |||
inner.className = 'bmc-footer-inner'; | |||
inner.innerHTML = | |||
'<div>' + | |||
'<h4>MIT BioMicro Center</h4>' + | |||
'<ul>' + | |||
'<li>Building 68-322</li>' + | |||
'<li>Cambridge, MA 02139</li>' + | |||
'<li><a href="mailto:biomicro@mit.edu">biomicro@mit.edu</a></li>' + | |||
'<li>617-715-4533</li>' + | |||
'</ul>' + | |||
'</div>' + | |||
'<div>' + | |||
'<h4>Services</h4>' + | |||
'<ul>' + | |||
'<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:Assisted_Services">Bulk Sequencing</a></li>' + | |||
'<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:Assisted_Services">Single Cell</a></li>' + | |||
'<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:Walkup_Instrumentation">Spatial Genomics</a></li>' + | |||
'<li><a href="https://igb.mit.edu/" target="_blank">Informatics</a></li>' + | |||
'</ul>' + | |||
'</div>' + | |||
'<div>' + | |||
'<h4>Resources</h4>' + | |||
'<ul>' + | |||
'<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:FAQ">FAQs</a></li>' + | |||
'<li><a href="http://biomicro.mit.edu/forms.html">Forms</a></li>' + | |||
'<li><a href="http://biomicro.mit.edu/pricing_v2.html">Grant Support & Pricing</a></li>' + | |||
'<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:Acknowledgement">Acknowledgements</a></li>' + | |||
'</ul>' + | |||
'</div>'; | |||
var bottom = document.createElement( 'div' ); | |||
bottom.className = 'bmc-footer-bottom'; | |||
bottom.innerHTML = | |||
'<span>© ' + new Date().getFullYear() + ' MIT BioMicro Center</span>' + | |||
'<span>' + | |||
'<a href="https://bmcwiki.mit.edu/index.php/Special:UserLogin">Log in</a>' + | |||
' | ' + | |||
'<a href="https://accessibility.mit.edu" target="_blank">Accessibility</a>' + | |||
'</span>'; | |||
var footer = document.createElement( 'footer' ); | |||
footer.className = 'bmc-footer'; | |||
footer.appendChild( inner ); | |||
footer.appendChild( bottom ); | |||
return footer; | |||
} | |||
/* ── Smooth scroll for anchor links ───────────────────────── */ | |||
function initSmoothScroll( container ) { | |||
container.addEventListener( 'click', function ( e ) { | |||
var a = e.target.closest( 'a[href^="#"]' ); | |||
if ( !a ) return; | |||
var id = decodeURIComponent( a.getAttribute( 'href' ).slice( 1 ) ); | |||
var target = document.getElementById( id ); | |||
if ( target ) { | |||
e.preventDefault(); | |||
target.scrollIntoView( { behavior: 'smooth', block: 'start' } ); | |||
history.pushState( null, '', '#' + id ); | |||
} | |||
} ); | |||
} | |||
/* ── Main: build and inject the shell ─────────────────────── */ | |||
function buildShell() { | |||
var currentPage = mw.config.get( 'wgPageName' ) || ''; | |||
/* 1. Extract wiki content BEFORE any DOM manipulation */ | |||
var mwContentText = document.getElementById( 'mw-content-text' ); | |||
if ( !mwContentText ) return; /* not a content page, bail */ | |||
var contentClone = mwContentText.cloneNode( true ); | |||
/* 2. Extract page title */ | |||
var titleEl = document.getElementById( 'firstHeading' ) || | |||
document.querySelector( '.mw-first-heading' ); | |||
var titleText = titleEl | |||
? titleEl.textContent.trim() | |||
: ( mw.config.get( 'wgTitle' ) || 'BioMicro Center' ); | |||
/* 3. Extract MediaWiki TOC from the cloned content */ | |||
var mwToc = contentClone.querySelector( '#toc, .toc' ); | |||
if ( mwToc ) mwToc.parentNode.removeChild( mwToc ); /* remove from content body */ | |||
/* 4. Build shell elements */ | |||
var topbar = buildTopbar(); | |||
var header = buildHeader( currentPage ); | |||
var hero = buildHero( titleText ); | |||
/* Page layout grid */ | |||
var layout = document.createElement( 'div' ); | |||
layout.className = 'bmc-page-layout'; | |||
/* Sidebar */ | |||
var sidebar = buildSidebarToc( mwToc ); | |||
if ( sidebar ) { | |||
layout.appendChild( sidebar ); | |||
} else { | |||
/* No TOC — collapse to single-column via inline style */ | |||
layout.style.gridTemplateColumns = '1fr'; | |||
} | |||
/* Main content area */ | |||
var main = document.createElement( 'main' ); | |||
main.className = 'bmc-content'; | |||
main.appendChild( contentClone ); | |||
layout.appendChild( main ); | |||
var footer = buildFooter(); | |||
/* 5. Build wrapper */ | |||
var wrapper = document.createElement( 'div' ); | |||
wrapper.id = 'bmc-wrapper'; | |||
wrapper.appendChild( topbar ); | |||
wrapper.appendChild( header ); | |||
wrapper.appendChild( hero ); | |||
wrapper.appendChild( layout ); | |||
wrapper.appendChild( footer ); | |||
/* 6. Inject into body (prepend so it appears first) */ | |||
document.body.insertBefore( wrapper, document.body.firstChild ); | |||
/* 7. Smooth scroll */ | |||
initSmoothScroll( main ); | |||
initSmoothScroll( sidebar || main ); | |||
/* 8. Auto-style plain tables in content */ | |||
main.querySelectorAll( | |||
'.mw-parser-output table:not(.wikitable):not(.infobox):not(.navbox)' | |||
).forEach( function ( t ) { | |||
t.classList.add( 'wikitable' ); | |||
} ); | |||
} | |||
/* ── Entry point ───────────────────────────────────────────── */ | |||
mw.hook( 'wikipage.content' ).add( function () { | |||
/* Skip special pages (edit forms, history, etc.) to not break them */ | |||
var ns = mw.config.get( 'wgNamespaceNumber' ); | |||
var action = mw.config.get( 'wgAction' ); | |||
if ( action !== 'view' ) return; | |||
if ( ns < 0 ) return; /* Special: pages */ | |||
buildShell(); | |||
} ); | |||
} )(); | } )(); | ||
Latest revision as of 23:19, 8 May 2026
/**
* BioMicro Center Wiki — Full DOM Replacement
* Paste into: User:USERNAME/common.js
*
* Strategy:
* 1. Extract wiki article content from MediaWiki's DOM
* 2. Inject the complete about.html shell structure
* 3. Place article content inside the shell
* MediaWiki still runs underneath for editing, search, login, etc.
*/
( function () {
'use strict';
/* ── Nav definition (matches about.html exactly) ──────────── */
var NAV = [
{
label: 'About',
href: 'http://biomicro.mit.edu/about.html',
match: [ 'BioMicroCenter', 'Main_Page' ]
},
{
label: 'News',
href: 'http://biomicro.mit.edu/news.html',
match: [ 'News', 'Seminar' ],
items: [
{ 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', ext: true }
]
},
{
label: 'Services',
href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter:Assisted_Services',
match: [ 'Assisted_Services', 'Walkup', 'Service', 'Consumable' ],
items: [
{ 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', ext: true },
{ label: 'Informatics', href: 'https://igb.mit.edu/', ext: true }
]
},
{
label: 'Submission',
href: 'http://biomicro.mit.edu/submit.html',
match: [ 'Submission', 'Submit', 'Pricing' ],
items: [
{ 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', 'Resource', 'Form', 'Acknowledgement' ],
items: [
{ 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' }
]
}
];
/* ── Build topbar HTML ─────────────────────────────────────── */
function buildTopbar() {
var d = document.createElement( 'div' );
d.className = 'bmc-topbar';
d.innerHTML =
'<div class="inner">' +
'<a href="mailto:biomicro@mit.edu">biomicro@mit.edu</a>' +
'<span>|</span>' +
'617-715-4533' +
'<span>|</span>' +
'Building 68-322' +
'</div>';
return d;
}
/* ── Build nav dropdown item ───────────────────────────────── */
function buildDropdownMenu( items ) {
var menu = document.createElement( 'div' );
menu.className = 'bmc-dropdown-menu';
items.forEach( function ( item ) {
if ( item.divider ) {
var div = document.createElement( 'div' );
div.className = 'bmc-divider';
menu.appendChild( div );
} else if ( item.groupLabel ) {
var gl = document.createElement( 'div' );
gl.className = 'bmc-group-label';
gl.textContent = item.groupLabel;
menu.appendChild( gl );
} else {
var a = document.createElement( 'a' );
a.href = item.href;
a.textContent = item.label;
if ( item.ext ) a.target = '_blank';
menu.appendChild( a );
}
} );
return menu;
}
/* ── Build full header ─────────────────────────────────────── */
function buildHeader( currentPage ) {
/* Logo */
var logo = document.createElement( 'a' );
logo.href = 'https://bmcwiki.mit.edu/index.php/BioMicroCenter';
logo.className = 'bmc-logo';
logo.innerHTML =
'<div class="bmc-logo-mark">BMC</div>' +
'<div class="bmc-logo-text">' +
'<span class="bmc-logo-name">MIT BioMicro Center</span>' +
'<span class="bmc-logo-sub">Integrated Genomics Core Facility</span>' +
'</div>';
/* Nav */
var ul = document.createElement( 'ul' );
NAV.forEach( function ( item ) {
var li = document.createElement( 'li' );
var isActive = ( item.match || [] ).some( function ( m ) {
return currentPage.indexOf( m ) !== -1;
} );
if ( isActive ) li.classList.add( 'bmc-active' );
if ( item.items ) li.classList.add( 'bmc-dropdown' );
var a = document.createElement( 'a' );
a.href = item.href;
a.textContent = item.label;
li.appendChild( a );
if ( item.items ) {
li.appendChild( buildDropdownMenu( item.items ) );
}
ul.appendChild( li );
} );
var nav = document.createElement( 'nav' );
nav.className = 'bmc-nav';
nav.appendChild( ul );
/* Search */
var searchForm = document.createElement( 'form' );
searchForm.className = 'bmc-search-form';
searchForm.method = 'get';
searchForm.action = '/index.php';
searchForm.innerHTML =
'<input type="hidden" name="title" value="Special:Search">' +
'<input type="search" name="search" placeholder="Search wiki…" aria-label="Search">' +
'<button type="submit">⚲</button>';
var right = document.createElement( 'div' );
right.className = 'bmc-header-right';
right.appendChild( nav );
right.appendChild( searchForm );
/* Inner wrapper */
var inner = document.createElement( 'div' );
inner.className = 'bmc-header-inner';
inner.appendChild( logo );
inner.appendChild( right );
var header = document.createElement( 'header' );
header.className = 'bmc-header';
header.appendChild( inner );
return header;
}
/* ── Build page hero ───────────────────────────────────────── */
function buildHero( titleText ) {
var crumb = document.createElement( 'div' );
crumb.className = 'bmc-breadcrumb';
crumb.innerHTML =
'<a href="http://biomicro.mit.edu">Home</a>' +
'<span class="sep">›</span>' +
document.createTextNode( titleText ).textContent; // plain text, no XSS
var h1 = document.createElement( 'h1' );
h1.textContent = titleText;
var inner = document.createElement( 'div' );
inner.className = 'inner';
inner.appendChild( crumb );
inner.appendChild( h1 );
var hero = document.createElement( 'div' );
hero.className = 'bmc-page-hero';
hero.appendChild( inner );
return hero;
}
/* ── Build sidebar TOC from MediaWiki #toc ─────────────────── */
function buildSidebarToc( mwToc ) {
var toc = document.createElement( 'div' );
toc.className = 'bmc-toc';
var h3 = document.createElement( 'h3' );
h3.textContent = 'On this page';
toc.appendChild( h3 );
if ( mwToc ) {
/* Clone only the list from the MediaWiki TOC */
var mwList = mwToc.querySelector( 'ul' );
if ( mwList ) {
var cloned = mwList.cloneNode( true );
/* Mark sub-items */
cloned.querySelectorAll( 'li li' ).forEach( function ( li ) {
li.classList.add( 'bmc-sub' );
} );
toc.appendChild( cloned );
}
} else {
/* No TOC generated — leave the sidebar empty or show nothing */
return null;
}
var aside = document.createElement( 'aside' );
aside.className = 'bmc-sidebar';
aside.appendChild( toc );
return aside;
}
/* ── Build footer ──────────────────────────────────────────── */
function buildFooter() {
var inner = document.createElement( 'div' );
inner.className = 'bmc-footer-inner';
inner.innerHTML =
'<div>' +
'<h4>MIT BioMicro Center</h4>' +
'<ul>' +
'<li>Building 68-322</li>' +
'<li>Cambridge, MA 02139</li>' +
'<li><a href="mailto:biomicro@mit.edu">biomicro@mit.edu</a></li>' +
'<li>617-715-4533</li>' +
'</ul>' +
'</div>' +
'<div>' +
'<h4>Services</h4>' +
'<ul>' +
'<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:Assisted_Services">Bulk Sequencing</a></li>' +
'<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:Assisted_Services">Single Cell</a></li>' +
'<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:Walkup_Instrumentation">Spatial Genomics</a></li>' +
'<li><a href="https://igb.mit.edu/" target="_blank">Informatics</a></li>' +
'</ul>' +
'</div>' +
'<div>' +
'<h4>Resources</h4>' +
'<ul>' +
'<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:FAQ">FAQs</a></li>' +
'<li><a href="http://biomicro.mit.edu/forms.html">Forms</a></li>' +
'<li><a href="http://biomicro.mit.edu/pricing_v2.html">Grant Support & Pricing</a></li>' +
'<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:Acknowledgement">Acknowledgements</a></li>' +
'</ul>' +
'</div>';
var bottom = document.createElement( 'div' );
bottom.className = 'bmc-footer-bottom';
bottom.innerHTML =
'<span>© ' + new Date().getFullYear() + ' MIT BioMicro Center</span>' +
'<span>' +
'<a href="https://bmcwiki.mit.edu/index.php/Special:UserLogin">Log in</a>' +
' | ' +
'<a href="https://accessibility.mit.edu" target="_blank">Accessibility</a>' +
'</span>';
var footer = document.createElement( 'footer' );
footer.className = 'bmc-footer';
footer.appendChild( inner );
footer.appendChild( bottom );
return footer;
}
/* ── Smooth scroll for anchor links ───────────────────────── */
function initSmoothScroll( container ) {
container.addEventListener( 'click', function ( e ) {
var a = e.target.closest( 'a[href^="#"]' );
if ( !a ) return;
var id = decodeURIComponent( a.getAttribute( 'href' ).slice( 1 ) );
var target = document.getElementById( id );
if ( target ) {
e.preventDefault();
target.scrollIntoView( { behavior: 'smooth', block: 'start' } );
history.pushState( null, '', '#' + id );
}
} );
}
/* ── Main: build and inject the shell ─────────────────────── */
function buildShell() {
var currentPage = mw.config.get( 'wgPageName' ) || '';
/* 1. Extract wiki content BEFORE any DOM manipulation */
var mwContentText = document.getElementById( 'mw-content-text' );
if ( !mwContentText ) return; /* not a content page, bail */
var contentClone = mwContentText.cloneNode( true );
/* 2. Extract page title */
var titleEl = document.getElementById( 'firstHeading' ) ||
document.querySelector( '.mw-first-heading' );
var titleText = titleEl
? titleEl.textContent.trim()
: ( mw.config.get( 'wgTitle' ) || 'BioMicro Center' );
/* 3. Extract MediaWiki TOC from the cloned content */
var mwToc = contentClone.querySelector( '#toc, .toc' );
if ( mwToc ) mwToc.parentNode.removeChild( mwToc ); /* remove from content body */
/* 4. Build shell elements */
var topbar = buildTopbar();
var header = buildHeader( currentPage );
var hero = buildHero( titleText );
/* Page layout grid */
var layout = document.createElement( 'div' );
layout.className = 'bmc-page-layout';
/* Sidebar */
var sidebar = buildSidebarToc( mwToc );
if ( sidebar ) {
layout.appendChild( sidebar );
} else {
/* No TOC — collapse to single-column via inline style */
layout.style.gridTemplateColumns = '1fr';
}
/* Main content area */
var main = document.createElement( 'main' );
main.className = 'bmc-content';
main.appendChild( contentClone );
layout.appendChild( main );
var footer = buildFooter();
/* 5. Build wrapper */
var wrapper = document.createElement( 'div' );
wrapper.id = 'bmc-wrapper';
wrapper.appendChild( topbar );
wrapper.appendChild( header );
wrapper.appendChild( hero );
wrapper.appendChild( layout );
wrapper.appendChild( footer );
/* 6. Inject into body (prepend so it appears first) */
document.body.insertBefore( wrapper, document.body.firstChild );
/* 7. Smooth scroll */
initSmoothScroll( main );
initSmoothScroll( sidebar || main );
/* 8. Auto-style plain tables in content */
main.querySelectorAll(
'.mw-parser-output table:not(.wikitable):not(.infobox):not(.navbox)'
).forEach( function ( t ) {
t.classList.add( 'wikitable' );
} );
}
/* ── Entry point ───────────────────────────────────────────── */
mw.hook( 'wikipage.content' ).add( function () {
/* Skip special pages (edit forms, history, etc.) to not break them */
var ns = mw.config.get( 'wgNamespaceNumber' );
var action = mw.config.get( 'wgAction' );
if ( action !== 'view' ) return;
if ( ns < 0 ) return; /* Special: pages */
buildShell();
} );
} )();