diff --git a/evennia/web/webclient/static/webclient/js/plugins/default_in.js b/evennia/web/webclient/static/webclient/js/plugins/default_in.js index 044e4e7ec8..d5996685cb 100644 --- a/evennia/web/webclient/static/webclient/js/plugins/default_in.js +++ b/evennia/web/webclient/static/webclient/js/plugins/default_in.js @@ -3,7 +3,9 @@ * Evennia Webclient default "send-text-on-enter-key" IO plugin * */ -let defaultin_plugin = (function () { +let defaultInPlugin = (function () { + + var focusOnKeydown = true; // // handle the default key triggering onSend() @@ -50,14 +52,17 @@ let defaultin_plugin = (function () { // Anything else, focus() a textarea if needed, and allow the default event default: - // is an inputfield actually focused? - if( inputfield.length < 1 ) { - // Nope, focus the last .inputfield found in the DOM (or #inputfield) - // :last only matters if multi-input plugins are in use - inputfield = $(".inputfield:last"); - inputfield.focus(); - if( inputfield.length < 1 ) { // non-goldenlayout backwards compatibility - $("#inputfield").focus(); + // has some other UI element turned off this behavior temporarily? + if( focusOnKeydown ) { + // is an inputfield actually focused? + if( inputfield.length < 1 ) { + // Nope, focus the last .inputfield found in the DOM (or #inputfield) + // :last only matters if multi-input plugins are in use + inputfield = $(".inputfield:last"); + inputfield.focus(); + if( inputfield.length < 1 ) { // non-goldenlayout backwards compatibility + $("#inputfield").focus(); + } } } } @@ -65,6 +70,13 @@ let defaultin_plugin = (function () { return true; } + // + // allow other UI elements to toggle this focus behavior on/off + var setKeydownFocus = function (bool) { + console.log("Focus = " + bool); + focusOnKeydown = bool; + } + // // Mandatory plugin init function var init = function () { @@ -81,6 +93,7 @@ let defaultin_plugin = (function () { return { init: init, onKeydown: onKeydown, + setKeydownFocus: setKeydownFocus, } })(); -window.plugin_handler.add("defaultin", defaultin_plugin); +window.plugin_handler.add("default_in", defaultInPlugin); diff --git a/evennia/web/webclient/static/webclient/js/plugins/goldenlayout.js b/evennia/web/webclient/static/webclient/js/plugins/goldenlayout.js index 4e21265f42..29dd136b77 100644 --- a/evennia/web/webclient/static/webclient/js/plugins/goldenlayout.js +++ b/evennia/web/webclient/static/webclient/js/plugins/goldenlayout.js @@ -5,7 +5,11 @@ */ let goldenlayout = (function () { - var myLayout; + var myLayout; // The actively used GoldenLayout API object. + + var evenniaGoldenLayouts = {}; // key/value storage Object for each selectable layout. + var activeLayoutName = "default"; // The object key of the active evenniaGoldenLayout + var knownTypes = ["all", "untagged", "testing"]; var untagged = []; @@ -80,6 +84,7 @@ let goldenlayout = (function () { myLayout.emit("stateChanged"); $("#renamebox").remove(); + window.plugins["default_in"].setKeydownFocus(true); } @@ -137,6 +142,7 @@ let goldenlayout = (function () { renamebox = $("
"); renamebox.append(""); renamebox.insertBefore( content ); + window.plugins["default_in"].setKeydownFocus(false); } else { closeRenameDropdown(); } @@ -262,6 +268,94 @@ let goldenlayout = (function () { } + // + // + var resetUI = function (newLayout) { + var mainsub = document.getElementById("main-sub"); + + // rebuild the original HTML stacking + var messageDiv = $("#messagewindow").detach(); + messageDiv.prependTo( mainsub ); + + // out with the old + myLayout.destroy(); + + // in with the new + myLayout = new GoldenLayout( newLayout, mainsub ); + + // re-register our main, input and generic evennia components. + registerComponents( myLayout ); + + // call all other plugins to give them a chance to registerComponents. + for( let plugin in window.plugins ) { + if( "onLayoutChanged" in window.plugins[plugin] ) { + window.plugins[plugin].onLayoutChanged(); + } + } + + // finish the setup and actually start GoldenLayout + myLayout.init(); + + // work out which types are untagged based on our pre-configured layout + calculateUntaggedTypes(); + + // Set the Event handler for when the client window changes size + $(window).bind("resize", scrollAll); + + // Set Save State callback + myLayout.on( "stateChanged", onStateChanged ); + } + + + // + // + var onSwitchLayout = function (evnt) { + // get the new layout name from the select box + var name = $('#layoutInput').val(); + + // check to see if the layout is in the list of known layouts + if( name in evenniaGoldenLayouts ) { + console.log( evenniaGoldenLayouts ); + + var newLayout = evenniaGoldenLayouts[name]; + activeLayoutName = name; + + // pull the trigger + resetUI( newLayout ); + } + } + + + // + // + var onSaveLayout = function (evnt) { + // get the name from the select box + var name = $('#layoutName').val(); + var input = $('#layoutInput'); + + if( name === "" ) { return; } // Can't save without a valid name + + // Is this name new or pre-existing? + if( !(name in evenniaGoldenLayouts) ) { + // add the new evenniaGoldenLayout to the listed dropdown options + var option = $(''); + input.append(option); + } + + // store the current layout to the local list of layouts + evenniaGoldenLayouts[ name ] = myLayout.toConfig(); + activeLayoutName = name; + + // upload it to the server + if( Evennia.isConnected() && myLayout.isInitialised ) { + window.options["webclientActiveLayout"] = name; + window.options["webclientLayouts"] = JSON.stringify( evenniaGoldenLayouts ); + console.log("Saving layout to server..."); + Evennia.msg("webclient_options", [], window.options); + } + } + + // // Save the GoldenLayout state to localstorage whenever it changes. var onStateChanged = function () { @@ -275,18 +369,9 @@ let goldenlayout = (function () { component.container.extendState({ "types": types, "updateMethod": updateMethod }); }); - // update the layout options when the stat changes from our previous stored state. - var state = JSON.stringify( myLayout.toConfig() ); - - if( state !== window.options["webclientLayout"] ) { - localStorage.setItem( "evenniaGoldenLayoutSavedState", state ); - - // Also update the server-side options, if the connection is ready to go. - if( Evennia.isConnected() && myLayout.isInitialised ) { - window.options["webclientLayout"] = state; - Evennia.msg("webclient_options", [], window.options); - } - } + // update localstorage + localStorage.setItem( "evenniaGoldenLayoutSavedState", JSON.stringify(myLayout.toConfig()) ); + localStorage.getItem( "evenniaGoldenLayoutSavedStateName", JSON.stringify( activeLayoutName ) ); } @@ -418,6 +503,7 @@ let goldenlayout = (function () { }); } + // // Public // @@ -431,17 +517,6 @@ let goldenlayout = (function () { } - // - // - var onKeydown = function(evnt) { - var renamebox = document.getElementById("renamebox"); - if( renamebox ) { - return true; - } - return false; - } - - // // Add new HTML message to an existing Div pane, while // honoring the pane's updateMethod and scroll state, etc. @@ -524,45 +599,42 @@ let goldenlayout = (function () { // var onGotOptions = function (args, kwargs) { // Reset the UI if the JSON layout sent from the server doesn't match the client's current JSON - if( ("webclientLayout" in kwargs) && (kwargs["webclientLayout"] !== window.options["webclientLayout"]) ) { - var mainsub = document.getElementById("main-sub"); + if( "webclientLayouts" in kwargs ) { + console.log("Got evennia GoldenLayouts"); - // rebuild the original HTML stacking - var messageDiv = $("#messagewindow").detach(); - messageDiv.prependTo( mainsub ); - - // out with the old - myLayout.destroy(); - - // in with the new - myLayout = new GoldenLayout( JSON.parse( kwargs["webclientLayout"] ), mainsub ); - - // re-register our main, input and generic evennia components. - registerComponents( myLayout ); - - // call all other plugins to give them a chance to registerComponents. - for( let plugin in window.plugins ) { - if( "onLayoutChange" in window.plugins[plugin] ) { - window.plugins[plugin].onLayoutChange(); - } - } - - // finish the setup and actually start GoldenLayout - myLayout.init(); - - // work out which types are untagged based on our pre-configured layout - calculateUntaggedTypes(); - - // Set the Event handler for when the client window changes size - $(window).bind("resize", scrollAll); - - // Set Save State callback - myLayout.on( "stateChanged", onStateChanged ); - - return true; + evenniaGoldenLayouts = JSON.parse( kwargs["webclientLayouts"] ); } } + + // + // + var onOptionsUI = function (parentdiv) { + var layoutInput = $(''); + var saveButton = $(''); + + var layouts = Object.keys( evenniaGoldenLayouts ); + for (var x = 0; x < layouts.length; x++) { + var option = $(''); + layoutInput.append(option); + } + + layoutInput.val( activeLayoutName ); // current selection + layoutName.val( activeLayoutName ); + + // Layout selection on-change callback + layoutInput.on('change', onSwitchLayout); + saveButton.on('click', onSaveLayout); + + // add the selection dialog control to our parentdiv + parentdiv.append('
UI Layout Selection (This list may be longer after login):
'); + parentdiv.append(layoutInput); + parentdiv.append(layoutName); + parentdiv.append(saveButton); + } + + // // var onText = function (args, kwargs) { @@ -603,16 +675,24 @@ let goldenlayout = (function () { var init = function (options) { // Set up our GoldenLayout instance built off of the default main-sub div var savedState = localStorage.getItem( "evenniaGoldenLayoutSavedState" ); + var activeName = localStorage.getItem( "evenniaGoldenLayoutSavedStateName" ); var mainsub = document.getElementById("main-sub"); + // pre-load the evenniaGoldenLayouts with the hard-coded default + evenniaGoldenLayouts[ "default" ] = window.goldenlayout_config; + + if( activeName !== null ) { + activeLayoutName = activeName; + } + if( savedState !== null ) { // Overwrite the global-variable configuration from // webclient/js/plugins/goldenlayout_default_config.js // with the version from localstorage - window.goldenlayout_config = JSON.parse( savedState ); + evenniaGoldenLayouts[ activeLayoutName ] = JSON.parse( savedState ); } - myLayout = new GoldenLayout( window.goldenlayout_config, mainsub ); + myLayout = new GoldenLayout( evenniaGoldenLayouts[activeLayoutName], mainsub ); $("#prompt").remove(); // remove the HTML-defined prompt div $("#inputcontrol").remove(); // remove the cluttered, HTML-defined input divs @@ -623,8 +703,8 @@ let goldenlayout = (function () { return { init: init, postInit: postInit, - onKeydown: onKeydown, onGotOptions: onGotOptions, + onOptionsUI: onOptionsUI, onText: onText, getGL: function () { return myLayout; }, addKnownType: addKnownType, diff --git a/evennia/web/webclient/static/webclient/js/plugins/message_routing.js b/evennia/web/webclient/static/webclient/js/plugins/message_routing.js index 1279126b39..e051c12fae 100644 --- a/evennia/web/webclient/static/webclient/js/plugins/message_routing.js +++ b/evennia/web/webclient/static/webclient/js/plugins/message_routing.js @@ -4,8 +4,6 @@ */ let spawns = (function () { - var ignoreDefaultKeydown = false; - var spawnmap = {}; // { id1: { r:regex, t:tag } } pseudo-array of regex-tag pairs // @@ -42,12 +40,12 @@ let spawns = (function () { // var onFocusIn = function (evnt) { - ignoreDefaultKeydown = true; + window.plugins["default_in"].setKeydownFocus(false); } // var onFocusOut = function (evnt) { - ignoreDefaultKeydown = false; + window.plugins["default_in"].setKeydownFocus(true); onAlterTag(evnt); // percolate event so closing the pane, etc saves any last changes. } @@ -121,14 +119,6 @@ let spawns = (function () { } - // - // OnKeydown -- if the Options window is open, capture focus - // - var onKeydown = function(evnt) { - return ignoreDefaultKeydown; - } - - // // init // @@ -148,7 +138,6 @@ let spawns = (function () { init: init, onOptionsUI: onOptionsUI, onText: onText, - onKeydown: onKeydown, } })(); window.plugin_handler.add("spawns", spawns); diff --git a/evennia/web/webclient/static/webclient/js/plugins/options2.js b/evennia/web/webclient/static/webclient/js/plugins/options2.js index 14063c7c85..01eba285c8 100644 --- a/evennia/web/webclient/static/webclient/js/plugins/options2.js +++ b/evennia/web/webclient/static/webclient/js/plugins/options2.js @@ -75,11 +75,14 @@ let options2 = (function () { .click( function () { optionsContainer = null; tab.contentItem.remove(); + window.plugins["default_in"].setKeydownFocus(true); }); optionsContainer = tab.contentItem; } }); main.parent.addChild( optionsComponent ); + + window.plugins["default_in"].setKeydownFocus(false); } else { optionsContainer.remove(); optionsContainer = null;