// vim: ts=4 sw=4 et ai// <nowiki>( function () { // sample value: {"a": {"b": "WP:RFA", "c": {"d": "WP:ANI"}}} var gMenuJson = null; // sample value: ["a", "b"] var gPressedKeys = []; var gGeneralKeyListener = null; // GUI components var gBackBtn; //var gBreadcrumb; var SUPERJUMP_PANEL_ID = "superjump-container-panel"; var SUPERJUMP_TABLE_ID = "superjump-keys-table"; var MENU_JSON_LOCALSTORAGE_KEY = "enwp_superjump_menu_json"; var MENU_JSON_LOCALSTORAGE_SEPARATOR = "|"; function initAccessKeyListeners() { for( var key in gMenuJson ) { initAccessKeyListener( key, function () { handleKey( key, gMenuJson, /* accessKey */ true ); } ); } } function navigateToPath( keys ) { var menu = gMenuJson; for( var i = 0; i < keys.length - 1; i++ ) { menu = menu[ keys[i] ]; } gPressedKeys = keys.slice( 0, keys.length - 1 ); var lastKey = keys[ keys.length - 1 ]; handleKey( lastKey, menu ); } function handleKey( key, menu, accessKey ) { if( key == "Escape" ) { closeInterface(); gPressedKeys = []; return; } else if( key == "Backspace" ) { if( gPressedKeys.length > 1 ) { navigateToPath( gPressedKeys.slice( 0, gPressedKeys.length - 1 ) ); } return; } var submenu = menu[ key ]; if( typeof submenu === typeof "" ) { window.location.href = mw.util.getUrl( submenu ); } else if( submenu ) { gPressedKeys.push( key ); displayOrUpdateInterface( makePanel( submenu ) ); if( gGeneralKeyListener ) { document.removeEventListener( "keydown", gGeneralKeyListener ); gGeneralKeyListener = null; } gGeneralKeyListener = function ( event ) { handleKey( event.key, submenu ); }; document.addEventListener( "keydown", gGeneralKeyListener ); } } function displayOrUpdateInterface( panel ) { panel.id = SUPERJUMP_TABLE_ID; var containerPanel = document.getElementById( SUPERJUMP_PANEL_ID ); if( !containerPanel ) { containerPanel = createInterface(); document.body.appendChild( containerPanel ); } containerPanel.replaceChild( panel, document.getElementById( SUPERJUMP_TABLE_ID ) ); gBackBtn.disabled = gPressedKeys.length < 2; //gBreadcrumb.textContent = "Pressed: " + gPressedKeys.map( function ( x ) { return "[" + x + "]"; } ).join( " > " ); } function createInterface() { containerPanel = document.createElement( "div" ); containerPanel.id = SUPERJUMP_PANEL_ID; var topBar = document.createElement( "div" ); gBackBtn = document.createElement( "button" ); gBackBtn.textContent = "Back [Backspace]"; gBackBtn.addEventListener( "click", function () { navigateToPath( gPressedKeys.slice( 0, gPressedKeys.length - 1 ) ); } ); topBar.appendChild( gBackBtn ); var closeBtn = document.createElement( "button" ); closeBtn.textContent = "Close [Esc]"; closeBtn.addEventListener( "click", closeInterface ); topBar.appendChild( closeBtn ); containerPanel.appendChild( topBar ); var startingPanel = document.createElement( "div" ); startingPanel.id = SUPERJUMP_TABLE_ID; containerPanel.appendChild( startingPanel ); //var bottomBar = document.createElement( "div" ); //gBreadcrumb = document.createElement( "span" ); //bottomBar.appendChild( gBreadcrumb ); //var editConfigBtn = document.createElement( "button" ); //editConfigBtn.textContent = "Edit configuration"; //editConfigBtn.addEventListener( "click", function () { // window.location.href = mw.util.getUrl( getMenuJsonPageTitle(), { action: "edit" } ); //} ); //bottomBar.appendChild( editConfigBtn ); //containerPanel.appendChild( bottomBar ); return containerPanel; } function closeInterface() { var panel = document.getElementById( SUPERJUMP_PANEL_ID ); panel.parentNode.removeChild( panel ); if( gGeneralKeyListener ) { document.removeEventListener( "keydown", gGeneralKeyListener ); } } function makePanel( menu ) { var table = document.createElement( "table" ); var keys = Object.keys( menu ); var numItems = keys.length; var tds = new Array( numItems ); for( var i = 0; i < numItems; i++ ) { var td = document.createElement( "td" ); var keySpan = document.createElement( "span" ); keySpan.className = "key-span"; keySpan.textContent = "[" + keys[i] + "]"; td.appendChild( keySpan ); var actionSpan = document.createElement( "span" ); var menuItem = menu[ keys[i] ]; if( typeof menuItem === typeof "" ) { actionSpan.textContent = menuItem; } else { var numChoices = Object.keys( menuItem ).length; actionSpan.textContent = numChoices + " choice" + ( numChoices !== 1 ? "s" : "" ); } td.appendChild( actionSpan ); tds[i] = td; } var numRows = Math.max( 2, Math.ceil( Math.sqrt( numItems ) ) ); var numCols = numRows; for( var i = 0; i < numRows; i++ ) { var tr = document.createElement( "tr" ); for( var j = 0; j < numCols; j++ ) { var cell = tds[ i * numCols + j ]; if( cell ) { tr.appendChild( cell ); } } table.appendChild( tr ); } return table; } function initAccessKeyListener( key, listener ) { var hasOurAccessKey = document.querySelectorAll( "a[accesskey=" + key + "]" ); if( hasOurAccessKey.length ) { for( var i = 0; i < hasOurAccessKey.length; i++ ) { hasOurAccessKey[i].setAttribute( "accesskey", "" ); $( hasOurAccessKey[i] ).updateTooltipAccessKeys(); } } $( "body" ).append( $( "<a>" ) .attr( { href: "#", accesskey: key } ) .css( { position: "fixed", opacity: "0" } ) .text( "superjump-link-" + key ) .addClass( "superjump-accesskey-sink" ) .click( listener ) ); } function setMenuJson() { var reqParams = { format: "json", action: "query", prop: "revisions", titles: getMenuJsonPageTitle(), rvprop: "content|ids", rvslots: "main" }; var storedRevidAndMenuJson = getStoredRevidAndMenuJson(); var storedRevid, storedMenuJson; if( storedRevidAndMenuJson ) { storedRevid = storedRevidAndMenuJson[0]; storedMenuJson = storedRevidAndMenuJson[1]; reqParams.rvstartid = parseInt( storedRevid ) + 1; reqParams.rvdir = "newer"; } return $.getJSON( mw.util.wikiScript( "api" ), reqParams ).then( function ( data ) { if( !data || !data.query || !data.query.pages ) { mw.notify( "Error loading menu JSON page!" ); return; } var pageId = Object.keys( data.query.pages )[0]; var pageObj = data.query.pages[pageId]; if( pageObj.missing ) { mw.notify( "Error! You'll need to create " + getMenuJsonPageTitle() + " to use superjump." ); return; } var revs = pageObj.revisions; if( !revs ) { gMenuJson = JSON.parse(storedMenuJson); return; } var mostRecentRev = revs[ revs.length - 1 ]; var apiRevid = mostRecentRev.revid; var apiJson = mostRecentRev.slots.main["*"]; if( isLocalStorageAvailable() ) { var storageValue = apiRevid + MENU_JSON_LOCALSTORAGE_SEPARATOR + apiJson; window.localStorage.setItem( MENU_JSON_LOCALSTORAGE_KEY, storageValue ); } gMenuJson = JSON.parse(apiJson); } ); } function getMenuJsonPageTitle() { return "User:" + mw.config.get( "wgUserName" ) + "/superjump-config.json"; } function getStoredRevidAndMenuJson() { var localStorageAvailable = isLocalStorageAvailable(); if( localStorageAvailable ) { var storedRevidAndMenuJson = window.localStorage.getItem( MENU_JSON_LOCALSTORAGE_KEY ); if( storedRevidAndMenuJson && storedRevidAndMenuJson.indexOf( MENU_JSON_LOCALSTORAGE_SEPARATOR ) >= 0 ) { return storedRevidAndMenuJson.split( MENU_JSON_LOCALSTORAGE_SEPARATOR ); } } return null; } function isLocalStorageAvailable() { try { var storage = window.localStorage, x = '__storage_test__'; storage.setItem( x, x ); storage.removeItem( x ); return true; } catch( e ) { return false; } } $.when( $.ready, mw.loader.using( "mediawiki.util" ) ) .then( setMenuJson ) .then( function () { mw.util.addCSS( "#" + SUPERJUMP_PANEL_ID + "{ position: fixed; "+ "top: 50%; left: 50%; margin-right: -50%; transform: translate(-50%, -50%); " + "background-color:white; padding: 1em; border:thin solid gray;" + "box-shadow:0px 7px 7px 0px rgba(0,0,0,0.3)}"+ "#" + SUPERJUMP_PANEL_ID + " > div * { margin-left: 0.75em; }"+ "#" + SUPERJUMP_TABLE_ID + " td{padding: 0.5em;}"+ "#" + SUPERJUMP_TABLE_ID + " .key-span{font-family:monospace; cursor:default; padding-right: 0.1em; font-size: 200%}"+ "#" + SUPERJUMP_TABLE_ID + " span{vertical-align:middle;}"); initAccessKeyListeners(); } );} )();// </nowiki>