|
|
| Line 1: |
Line 1: |
| // Twinkle mobile TEST adapter v5 - personal test only | | // Twinkle mobile support is now site-wide via the Twinkle gadget (MediaWiki:Gadget-TwinkleMobile.js). This personal test page is no longer needed. |
| // Page: User:Bharatwiki Socrates/minerva.js (Minerva skin only)
| |
| // v4 worked (Twinkle item + inline sub-list inside the More menu),
| |
| // but the user wants the English Wikipedia behaviour: tap "Twinkle"
| |
| // and the options open as a panel ON the screen, not buried inside
| |
| // the scrolling menu.
| |
| // v5 change: the #p-cactions portlet Twinkle needs is now a floating
| |
| // panel (fixed position, hidden). The "Twinkle" entry in the More
| |
| // menu only toggles that panel: tapping it closes the menu and opens
| |
| // the panel with all Twinkle options. Tapping an option closes the
| |
| // panel and opens that module's dialog.
| |
| // All user-facing strings in English.
| |
| | |
| ( function () {
| |
| if ( mw.config.get( 'skin' ) !== 'minerva' ) {
| |
| return;
| |
| }
| |
| if ( window.twinkleMobileTestLoaded ) {
| |
| return;
| |
| }
| |
| window.twinkleMobileTestLoaded = true;
| |
| | |
| 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; }' +
| |
| '#p-cactions.twinkle-mobile-panel { position: fixed;' +
| |
| ' top: 52px; left: 2vw; width: 96vw; max-height: 72vh;' +
| |
| ' overflow-y: auto; z-index: 999; background: #fff;' +
| |
| ' border: 1px solid #a2a9b1; border-radius: 4px;' +
| |
| ' box-shadow: 0 4px 16px rgba(0,0,0,0.35); padding: 0 0 6px; }' +
| |
| '#p-cactions.twinkle-mobile-panel ul { list-style: none;' +
| |
| ' margin: 0; padding: 0; }' +
| |
| '#p-cactions.twinkle-mobile-panel li a { display: block;' +
| |
| ' padding: 12px 16px; color: #202122; text-decoration: none;' +
| |
| ' font-size: 1em; border-top: 1px solid #eaecf0; }' +
| |
| '#p-cactions.twinkle-mobile-panel li a:active {' +
| |
| ' background: #eaecf0; }' +
| |
| '.twinkle-panel-head { display: flex;' +
| |
| ' justify-content: space-between; align-items: center;' +
| |
| ' padding: 10px 16px; font-weight: bold; }' +
| |
| '.twinkle-panel-close { background: none; border: 0;' +
| |
| ' font-size: 20px; line-height: 1; padding: 4px 8px;' +
| |
| ' cursor: pointer; }'
| |
| );
| |
| rawCss( 'MediaWiki:Gadget-Twinkle.css' );
| |
| rawCss( 'MediaWiki:Gadget-morebits.css' );
| |
| rawCss( 'MediaWiki:Gadget-select2.min.css' );
| |
| | |
| var panel = null;
| |
| function togglePanel( show ) {
| |
| if ( !panel ) {
| |
| return;
| |
| }
| |
| panel.style.display = show ? 'block' : 'none';
| |
| }
| |
| function closeOverflow() {
| |
| var cb = document.getElementById(
| |
| 'page-actions-overflow-checkbox' );
| |
| if ( cb ) {
| |
| cb.checked = false;
| |
| }
| |
| }
| |
| | |
| function createPortlet() {
| |
| if ( document.getElementById( 'p-cactions' ) ) {
| |
| panel = document.getElementById( 'p-cactions' );
| |
| return true;
| |
| }
| |
| // The floating panel IS the p-cactions portlet.
| |
| panel = document.createElement( 'div' );
| |
| panel.id = 'p-cactions';
| |
| panel.className = 'twinkle-mobile-panel';
| |
| panel.style.display = 'none';
| |
| var head = document.createElement( 'div' );
| |
| head.className = 'twinkle-panel-head';
| |
| var title = document.createElement( 'span' );
| |
| title.textContent = 'Twinkle';
| |
| var closeBtn = document.createElement( 'button' );
| |
| closeBtn.className = 'twinkle-panel-close';
| |
| closeBtn.textContent = '×';
| |
| closeBtn.addEventListener( 'click', function () {
| |
| togglePanel( false );
| |
| } );
| |
| head.appendChild( title );
| |
| head.appendChild( closeBtn );
| |
| panel.appendChild( head );
| |
| var list = document.createElement( 'ul' );
| |
| panel.appendChild( list );
| |
| document.body.appendChild( panel );
| |
| // Any tap on a module link closes the panel (dialog opens).
| |
| panel.addEventListener( 'click', function ( e ) {
| |
| if ( e.target.closest( 'li a' ) &&
| |
| !e.target.closest( '.twinkle-panel-head' ) ) {
| |
| togglePanel( false );
| |
| }
| |
| } );
| |
| | |
| // Entry inside the More (overflow) menu toggles the panel.
| |
| var overflow = document.querySelector( 'ul#p-tb' ) ||
| |
| document.querySelector( '.page-actions-overflow-list' );
| |
| if ( overflow ) {
| |
| var li = document.createElement( 'li' );
| |
| li.className = 'toggle-list-item';
| |
| var a = document.createElement( 'a' );
| |
| a.className = 'toggle-list-item__anchor';
| |
| a.href = '#';
| |
| var label = document.createElement( 'span' );
| |
| label.className = 'toggle-list-item__label';
| |
| label.textContent = 'Twinkle';
| |
| a.appendChild( label );
| |
| a.addEventListener( 'click', function ( e ) {
| |
| e.preventDefault();
| |
| closeOverflow();
| |
| togglePanel( true );
| |
| } );
| |
| li.appendChild( a );
| |
| overflow.appendChild( li );
| |
| } else {
| |
| // Fallback: floating TW button toggles the panel.
| |
| var btn = document.createElement( 'button' );
| |
| btn.textContent = 'TW';
| |
| btn.style.cssText = 'position:fixed;right:12px;' +
| |
| 'bottom:64px;z-index:998;padding:10px 14px;' +
| |
| 'border-radius:20px;background:#202122;color:#fff;' +
| |
| 'border:0;';
| |
| btn.addEventListener( 'click', function () {
| |
| togglePanel( panel.style.display === 'none' );
| |
| } );
| |
| document.body.appendChild( btn );
| |
| }
| |
| return true;
| |
| }
| |
| | |
| function checkResult( tries ) {
| |
| var landed = document.querySelectorAll(
| |
| '#p-cactions li[id^="twinkle-"]' ).length;
| |
| if ( landed ) {
| |
| mw.notify( 'Twinkle is ready: open the More menu and tap ' +
| |
| 'Twinkle (' + landed + ' options)', { type: 'info' } );
| |
| return;
| |
| }
| |
| if ( tries > 0 ) {
| |
| setTimeout( function () { checkResult( tries - 1 ); }, 2000 );
| |
| return;
| |
| }
| |
| mw.notify( 'Twinkle loaded but its links did not arrive (v5)',
| |
| { type: 'error' } );
| |
| }
| |
| | |
| function start() {
| |
| createPortlet();
| |
| mw.loader.using( [
| |
| 'mediawiki.util', 'mediawiki.api', 'mediawiki.storage',
| |
| 'mediawiki.Title', 'mediawiki.user', 'jquery.ui'
| |
| ] ).then( function () {
| |
| return loadScript( 'MediaWiki:Gadget-select2.min.js' );
| |
| } ).then( function () {
| |
| return loadScript( 'MediaWiki:Gadget-morebits.js' );
| |
| } ).then( function () {
| |
| return loadScript( 'MediaWiki:Gadget-Twinkle.js' );
| |
| } ).then( function () {
| |
| checkResult( 10 );
| |
| } ).catch( function ( err ) {
| |
| mw.notify( 'Twinkle mobile test load failed: ' + err,
| |
| { type: 'error' } );
| |
| } );
| |
| }
| |
| | |
| if ( document.readyState === 'loading' ) {
| |
| document.addEventListener( 'DOMContentLoaded', start );
| |
| } else {
| |
| start();
| |
| }
| |
| }() );
| |