No edit summary
Twinkle mobile test adapter v3: diagnostic banner
Line 1: Line 1:
// Twinkle mobile TEST adapter - for personal testing only
// Twinkle mobile TEST adapter v3 - DIAGNOSTIC version, personal test only
 
// Page: User:Bharatwiki Socrates/minerva.js (Minerva skin only)
// Location: User:Bharatwiki Socrates/minerva.js (runs only on the Minerva skin)
// 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
// Purpose: Without modifying the gadget definitions, load Twinkle's raw files on
// banner that records every stage and, after Twinkle initializes, a DOM
 
// census (does #p-cactions exist? does #p-twinkle exist? how many
// mobile to test whether the menus and dialogs work in Minerva.
// twinkle-* items are in the page, and are they visible?).
 
// The banner stays until tapped. All strings in English.
// Once the test passes, this file will be removed, and the actual fix will be made
 
// through the gadget definitions and a small mobile CSS gadget.


( function () {
( function () {
Line 19: Line 16:
}
}
window.twinkleMobileTestLoaded = true;
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' );
var indexPhp = mw.util.wikiScript( 'index' );
Line 36: Line 59:
}
}


// Mobile par dialog screen ke andar rahe, iske liye CSS fitting
mw.util.addCSS(
mw.util.addCSS(
'.ui-dialog { max-width: 96vw !important; left: 2vw !important; }' +
'.ui-dialog { max-width: 96vw !important; left: 2vw !important; }' +
'.morebits-dialog { max-width: 96vw !important; }' +
'.morebits-dialog { max-width: 96vw !important; }' +
'.morebits-dialog-content { overflow-x: auto; }' +
'.morebits-dialog-content { overflow-x: auto; }' +
'.select2-container { max-width: 90vw; }' +
'.select2-container { max-width: 90vw; }'
'#p-twinkle, .twinkle-menu { font-size: 100%; }'
);
);
rawCss( 'MediaWiki:Gadget-Twinkle.css' );
rawCss( 'MediaWiki:Gadget-Twinkle.css' );
rawCss( 'MediaWiki:Gadget-morebits.css' );
rawCss( 'MediaWiki:Gadget-morebits.css' );
rawCss( 'MediaWiki:Gadget-select2.min.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( [
mw.loader.using( [
Line 52: Line 109:
'mediawiki.Title', 'mediawiki.user', 'jquery.ui'
'mediawiki.Title', 'mediawiki.user', 'jquery.ui'
] ).then( function () {
] ).then( function () {
log( '[v3] core modules loaded (incl. jquery.ui)' );
return loadScript( 'MediaWiki:Gadget-select2.min.js' );
return loadScript( 'MediaWiki:Gadget-select2.min.js' );
} ).then( function () {
} ).then( function () {
log( '[v3] select2 loaded' );
return loadScript( 'MediaWiki:Gadget-morebits.js' );
return loadScript( 'MediaWiki:Gadget-morebits.js' );
} ).then( function () {
} ).then( function () {
log( '[v3] morebits loaded' );
return loadScript( 'MediaWiki:Gadget-Twinkle.js' );
return loadScript( 'MediaWiki:Gadget-Twinkle.js' );
} ).then( function () {
} ).then( function () {
mw.notify( 'Twinkle mobile test load ho gaya', { type: 'info' } );
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 ) {
} ).catch( function ( err ) {
mw.notify( 'Twinkle mobile test load FAIL: ' + err, { type: 'error' } );
log( '[v3] LOAD FAILED: ' + err );
} );
} );
}() );
}() );

Revision as of 05:05, 1 November 2026

// 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 );
	} );
}() );