Jump to content

User:Udays108/common.js: Difference between revisions

From BioMicro Center
Udays108 (talk | contribs)
No edit summary
Udays108 (talk | contribs)
No edit summary
Line 1: Line 1:
/**
/**
  * BioMicro Center Wiki — Modern UI JavaScript
  * BioMicro Center Wiki — Full DOM Replacement
  * Paste into: User:USERNAME/common.js
  * Paste into: User:USERNAME/common.js
* Promoted to: MediaWiki:Common.js (by sysop)
  *
  *
  * Injects: topbar, page-hero, horizontal nav w/ dropdowns.
  * Strategy:
  * Enhances: TOC styling, smooth scroll, table auto-class.
* 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';
  'use strict';


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


/* ── Helper: create element with attrs & children ──────────── */
  /* ── Build topbar HTML ─────────────────────────────────────── */
function el( tag, attrs, children ) {
  function buildTopbar() {
var node = document.createElement( tag );
    var d = document.createElement( 'div' );
Object.keys( attrs || {} ).forEach( function ( k ) {
    d.className = 'bmc-topbar';
if ( k === 'className' ) {
    d.innerHTML =
node.className = attrs[ k ];
      '<div class="inner">' +
} else if ( k === 'textContent' ) {
        '<a href="mailto:biomicro@mit.edu">biomicro@mit.edu</a>' +
node.textContent = attrs[ k ];
        '<span>|</span>' +
} else if ( k === 'innerHTML' ) {
        '617-715-4533' +
node.innerHTML = attrs[ k ];
        '<span>|</span>' +
} else {
        'Building 68-322' +
node.setAttribute( k, attrs[ k ] );
      '</div>';
}
    return d;
} );
  }
( children || [] ).forEach( function ( c ) {
if ( c ) node.appendChild( c );
} );
return node;
}


/* ── 1. Inject Topbar ───────────────────────────────────────── */
  /* ── Build nav dropdown item ───────────────────────────────── */
function injectTopbar() {
  function buildDropdownMenu( items ) {
var topbar = el( 'div', { className: 'bmc-topbar' }, [
    var menu = document.createElement( 'div' );
el( 'div', { className: 'bmc-topbar-inner' }, [
    menu.className = 'bmc-dropdown-menu';
el( 'a', { href: 'mailto:biomicro@mit.edu', textContent: 'biomicro@mit.edu' } ),
    items.forEach( function ( item ) {
el( 'span', { textContent: '|' } ),
      if ( item.divider ) {
document.createTextNode( '617-715-4533' ),
        var div = document.createElement( 'div' );
el( 'span', { textContent: '|' } ),
        div.className = 'bmc-divider';
document.createTextNode( 'Building 68-322' )
        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;
  }


// Insert before the MediaWiki header element
  /* ── Build full header ─────────────────────────────────────── */
var mwHead = document.getElementById( 'mw-head' ) ||
  function buildHeader( currentPage ) {
document.querySelector( '.vector-header' );
    /* Logo */
if ( mwHead && mwHead.parentNode ) {
    var logo = document.createElement( 'a' );
mwHead.parentNode.insertBefore( topbar, mwHead );
    logo.href = 'https://bmcwiki.mit.edu/index.php/BioMicroCenter';
} else {
    logo.className = 'bmc-logo';
document.body.insertBefore( topbar, document.body.firstChild );
    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>';


// Adjust sticky header top offset to account for topbar height
    /* Nav */
var topbarH = topbar.offsetHeight;
    var ul = document.createElement( 'ul' );
var style = document.createElement( 'style' );
    NAV.forEach( function ( item ) {
style.textContent =
      var li = document.createElement( 'li' );
'#mw-head, .vector-header, .vector-header-container { top: ' + topbarH + 'px !important; }' +
      var isActive = ( item.match || [] ).some( function ( m ) {
'.bmc-page-hero { margin-top: 0; }';
        return currentPage.indexOf( m ) !== -1;
document.head.appendChild( style );
      } );
}
      if ( isActive ) li.classList.add( 'bmc-active' );
      if ( item.items ) li.classList.add( 'bmc-dropdown' );


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


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


var link = el( 'a', { href: item.href, textContent: item.label } );
    var nav = document.createElement( 'nav' );
li.appendChild( link );
    nav.className = 'bmc-nav';
    nav.appendChild( ul );


if ( item.dropdown && item.dropdown.length ) {
    /* Search */
li.classList.add( 'bmc-dropdown' );
    var searchForm = document.createElement( 'form' );
var menu = el( 'div', { className: 'bmc-dropdown-menu' } );
    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">&#9906;</button>';


item.dropdown.forEach( function ( d ) {
    var right = document.createElement( 'div' );
if ( d.divider ) {
    right.className = 'bmc-header-right';
menu.appendChild( el( 'div', { className: 'bmc-divider' } ) );
    right.appendChild( nav );
} else if ( d.groupLabel ) {
    right.appendChild( searchForm );
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 );
    /* Inner wrapper */
}
    var inner = document.createElement( 'div' );
    inner.className = 'bmc-header-inner';
    inner.appendChild( logo );
    inner.appendChild( right );


return li;
    var header = document.createElement( 'header' );
}
    header.className = 'bmc-header';
    header.appendChild( inner );
    return header;
  }


function injectHorizontalNav() {
  /* ── Build page hero ───────────────────────────────────────── */
var currentPage = mw.config.get( 'wgPageName' ) || '';
  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 ul = document.createElement( 'ul' );
    var h1 = document.createElement( 'h1' );
NAV_ITEMS.forEach( function ( item ) {
    h1.textContent = titleText;
ul.appendChild( buildNavItem( item, currentPage ) );
} );


var nav = el( 'nav', { className: 'bmc-hnav' }, [ ul ] );
    var inner = document.createElement( 'div' );
    inner.className = 'inner';
    inner.appendChild( crumb );
    inner.appendChild( h1 );


// Find or create the header inner wrapper
    var hero = document.createElement( 'div' );
var mwHead = document.getElementById( 'mw-head' ) ||
    hero.className = 'bmc-page-hero';
document.querySelector( '.vector-header' );
    hero.appendChild( inner );
if ( !mwHead ) return;
    return hero;
  }


// Find or create a flex inner container
  /* ── Build sidebar TOC from MediaWiki #toc ─────────────────── */
var inner = mwHead.querySelector( '.bmc-header-inner' );
  function buildSidebarToc( mwToc ) {
if ( !inner ) {
    var toc = document.createElement( 'div' );
inner = el( 'div', { className: 'bmc-header-inner' } );
    toc.className = 'bmc-toc';
// Move existing header children into inner (except topbar)
Array.from( mwHead.childNodes ).forEach( function ( child ) {
inner.appendChild( child );
} );
mwHead.appendChild( inner );
}


// Build logo
    var h3 = document.createElement( 'h3' );
var logoLink = el( 'a', {
    h3.textContent = 'On this page';
href: 'https://bmcwiki.mit.edu/index.php/BioMicroCenter',
    toc.appendChild( h3 );
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
    if ( mwToc ) {
inner.innerHTML = '';
      /* Clone only the list from the MediaWiki TOC */
inner.appendChild( logoLink );
      var mwList = mwToc.querySelector( 'ul' );
inner.appendChild( nav );
      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;
    }


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


// Build breadcrumb
  /* ── Build footer ──────────────────────────────────────────── */
var crumb = el( 'div', { className: 'bmc-breadcrumb' }, [
  function buildFooter() {
el( 'a', { href: 'http://biomicro.mit.edu', textContent: 'Home' } ),
    var inner = document.createElement( 'div' );
el( 'span', { textContent: '' } ),
    inner.className = 'bmc-footer-inner';
document.createTextNode( titleText )
    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 &amp; Pricing</a></li>' +
          '<li><a href="https://bmcwiki.mit.edu/index.php/BioMicroCenter:Acknowledgement">Acknowledgements</a></li>' +
        '</ul>' +
      '</div>';


var heroH1 = el( 'h1', { textContent: titleText } );
    var bottom = document.createElement( 'div' );
    bottom.className = 'bmc-footer-bottom';
    bottom.innerHTML =
      '<span>&copy; ' + new Date().getFullYear() + ' MIT BioMicro Center</span>' +
      '<span>' +
        '<a href="https://bmcwiki.mit.edu/index.php/Special:UserLogin">Log in</a>' +
        ' &nbsp;|&nbsp; ' +
        '<a href="https://accessibility.mit.edu" target="_blank">Accessibility</a>' +
      '</span>';


var heroInner = el( 'div', { className: 'bmc-hero-inner' }, [ crumb, heroH1 ] );
    var footer = document.createElement( 'footer' );
var hero = el( 'div', { className: 'bmc-page-hero' }, [ heroInner ] );
    footer.className = 'bmc-footer';
    footer.appendChild( inner );
    footer.appendChild( bottom );
    return footer;
  }


// Insert hero between header and content
  /* ── Smooth scroll for anchor links ───────────────────────── */
var mwHead = document.getElementById( 'mw-head' ) ||
  function initSmoothScroll( container ) {
document.querySelector( '.vector-header' );
    container.addEventListener( 'click', function ( e ) {
var content = document.getElementById( 'content' ) ||
      var a = e.target.closest( 'a[href^="#"]' );
document.querySelector( '.mw-body' ) ||
      if ( !a ) return;
document.querySelector( '.vector-body' );
      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 );
      }
    } );
  }


if ( mwHead && mwHead.parentNode ) {
  /* ── Main: build and inject the shell ─────────────────────── */
var ref = mwHead.nextSibling;
  function buildShell() {
mwHead.parentNode.insertBefore( hero, ref );
    var currentPage = mw.config.get( 'wgPageName' ) || '';
} else if ( content && content.parentNode ) {
content.parentNode.insertBefore( hero, content );
}
}


/* ── 4. Rewrite Footer ──────────────────────────────────────── */
    /* 1. Extract wiki content BEFORE any DOM manipulation */
function rewriteFooter() {
    var mwContentText = document.getElementById( 'mw-content-text' );
var footer = document.getElementById( 'footer' ) ||
    if ( !mwContentText ) return; /* not a content page, bail */
document.querySelector( '.mw-footer' );
if ( !footer ) return;


var inner = el( 'div', { className: 'bmc-footer-inner' }, [
    var contentClone = mwContentText.cloneNode( true );
// 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' }, [
    /* 2. Extract page title */
el( 'span', { textContent: '© ' + new Date().getFullYear() + ' MIT BioMicro Center' } ),
    var titleEl = document.getElementById( 'firstHeading' ) ||
el( 'span', {}, [
      document.querySelector( '.mw-first-heading' );
el( 'a', {
    var titleText = titleEl
href: 'https://accessibility.mit.edu',
      ? titleEl.textContent.trim()
target: '_blank',
      : ( mw.config.get( 'wgTitle' ) || 'BioMicro Center' );
textContent: 'Accessibility'
} )
] )
] );


footer.innerHTML = '';
    /* 3. Extract MediaWiki TOC from the cloned content */
footer.appendChild( inner );
    var mwToc = contentClone.querySelector( '#toc, .toc' );
footer.appendChild( bottom );
    if ( mwToc ) mwToc.parentNode.removeChild( mwToc ); /* remove from content body */
}


/* ── 5. Smooth Scroll ───────────────────────────────────────── */
    /* 4. Build shell elements */
function initSmoothScroll() {
    var topbar = buildTopbar();
var content = document.querySelector( '.mw-parser-output' );
    var header = buildHeader( currentPage );
if ( !content ) return;
    var hero  = buildHero( titleText );
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 ─────────────────────────────── */
    /* Page layout grid */
function styleUnstyledTables() {
    var layout = document.createElement( 'div' );
var tables = document.querySelectorAll(
    layout.className = 'bmc-page-layout';
'.mw-parser-output table:not(.wikitable):not(.infobox):not(.navbox):not(.toc)'
);
tables.forEach( function ( t ) { t.classList.add( 'wikitable' ); } );
}


/* ── Entry point ────────────────────────────────────────────── */
    /* Sidebar */
mw.hook( 'wikipage.content' ).add( function () {
    var sidebar = buildSidebarToc( mwToc );
injectTopbar();
    if ( sidebar ) {
injectHorizontalNav();
      layout.appendChild( sidebar );
injectPageHero();
    } else {
rewriteFooter();
      /* No TOC — collapse to single-column via inline style */
initSmoothScroll();
      layout.style.gridTemplateColumns = '1fr';
styleUnstyledTables();
    }
} );
 
    /* 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();
  } );


} )();
} )();

Revision as of 22:39, 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">&#9906;</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 &amp; 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>&copy; ' + new Date().getFullYear() + ' MIT BioMicro Center</span>' +
      '<span>' +
        '<a href="https://bmcwiki.mit.edu/index.php/Special:UserLogin">Log in</a>' +
        ' &nbsp;|&nbsp; ' +
        '<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();
  } );

} )();