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.
// Twinkle mobile TEST adapter v3 - DIAGNOSTIC version, personal test only
// Page: User:Bharatwiki Socrates/minerva.js (Minerva skin only)
// Purpose: v1 loaded the files but no menu was visible; v2 could not find
// any Twinkle menu. v3 does not guess: it shows a fixed on-screen log
// banner that records every stage and, after Twinkle initializes, a DOM
// census (does #p-cactions exist? does #p-twinkle exist? how many
// twinkle-* items are in the page, and are they visible?).
// The banner stays until tapped. All strings in English.

( function () {
	if ( mw.config.get( 'skin' ) !== 'minerva' ) {
		return;
	}
	if ( window.twinkleMobileTestLoaded ) {
		return;
	}
	window.twinkleMobileTestLoaded = true;

	var banner = document.createElement( 'div' );
	banner.id = 'twinkle-diag-banner';
	banner.style.cssText = 'position:fixed;left:0;right:0;bottom:0;' +
		'z-index:99999;background:#202122;color:#fff;font-size:12px;' +
		'font-family:monospace;padding:8px;max-height:45vh;overflow:auto;';
	banner.title = 'Tap to close';
	banner.addEventListener( 'click', function () {
		banner.remove();
	} );
	function log( msg ) {
		var line = document.createElement( 'div' );
		line.textContent = msg;
		banner.appendChild( line );
	}
	function mountBanner() {
		if ( document.body && !banner.parentNode ) {
			document.body.appendChild( banner );
		}
	}
	if ( document.body ) {
		mountBanner();
	} else {
		document.addEventListener( 'DOMContentLoaded', mountBanner );
	}
	log( '[v3] adapter start, skin=' + mw.config.get( 'skin' ) );

	var indexPhp = mw.util.wikiScript( 'index' );
	function rawUrl( title ) {
		return indexPhp + '?title=' + encodeURIComponent( title ) +
			'&action=raw&ctype=text/javascript';
	}
	function rawCss( title ) {
		var link = document.createElement( 'link' );
		link.rel = 'stylesheet';
		link.href = indexPhp + '?title=' + encodeURIComponent( title ) +
			'&action=raw&ctype=text/css';
		document.head.appendChild( link );
	}
	function loadScript( title ) {
		return $.getScript( rawUrl( title ) );
	}

	mw.util.addCSS(
		'.ui-dialog { max-width: 96vw !important; left: 2vw !important; }' +
		'.morebits-dialog { max-width: 96vw !important; }' +
		'.morebits-dialog-content { overflow-x: auto; }' +
		'.select2-container { max-width: 90vw; }'
	);
	rawCss( 'MediaWiki:Gadget-Twinkle.css' );
	rawCss( 'MediaWiki:Gadget-morebits.css' );
	rawCss( 'MediaWiki:Gadget-select2.min.css' );

	function describe( el ) {
		if ( !el ) {
			return 'ABSENT';
		}
		var cs = window.getComputedStyle( el );
		var r = el.getBoundingClientRect();
		return 'present, tag=' + el.tagName +
			', li=' + el.querySelectorAll( 'li' ).length +
			', display=' + cs.display +
			', visibility=' + cs.visibility +
			', size=' + Math.round( r.width ) + 'x' +
			Math.round( r.height ) +
			', parent=' + ( el.parentNode ? ( el.parentNode.id ||
				el.parentNode.className || el.parentNode.tagName ) : '?' );
	}
	function census( tag ) {
		log( '--- census ' + tag + ' ---' );
		log( 'window.Twinkle: ' + typeof window.Twinkle );
		log( '#p-cactions: ' +
			describe( document.getElementById( 'p-cactions' ) ) );
		log( '#p-twinkle: ' +
			describe( document.getElementById( 'p-twinkle' ) ) );
		log( '[id^="twinkle-"] count: ' +
			document.querySelectorAll( '[id^="twinkle-"]' ).length );
		log( 'li[id^="ca-"] twinkle-ish: ' +
			document.querySelectorAll( 'li[id^="ca-twinkle"]' ).length );
		var items = document.querySelectorAll( '[id^="twinkle-"]' );
		var names = [];
		for ( var i = 0; i < items.length && i < 8; i++ ) {
			names.push( items[ i ].id );
		}
		if ( names.length ) {
			log( 'sample ids: ' + names.join( ', ' ) );
		}
	}

	mw.loader.using( [
		'mediawiki.util', 'mediawiki.api', 'mediawiki.storage',
		'mediawiki.Title', 'mediawiki.user', 'jquery.ui'
	] ).then( function () {
		log( '[v3] core modules loaded (incl. jquery.ui)' );
		return loadScript( 'MediaWiki:Gadget-select2.min.js' );
	} ).then( function () {
		log( '[v3] select2 loaded' );
		return loadScript( 'MediaWiki:Gadget-morebits.js' );
	} ).then( function () {
		log( '[v3] morebits loaded' );
		return loadScript( 'MediaWiki:Gadget-Twinkle.js' );
	} ).then( function () {
		log( '[v3] Twinkle.js loaded, waiting for its init...' );
		var n = 0;
		var timer = setInterval( function () {
			n++;
			census( 't+' + ( n * 3 ) + 's' );
			if ( document.querySelectorAll( '[id^="twinkle-"]' ).length ||
				n >= 5 ) {
				clearInterval( timer );
				log( '[v3] census done' );
			}
		}, 3000 );
	} ).catch( function ( err ) {
		log( '[v3] LOAD FAILED: ' + err );
	} );
}() );