Add golden-layout as an alternative to splithandler
This commit is contained in:
parent
d94566ef20
commit
8b08d41038
4 changed files with 518 additions and 2 deletions
106
evennia/web/webclient/static/webclient/css/goldenlayout.css
Normal file
106
evennia/web/webclient/static/webclient/css/goldenlayout.css
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#clientwrapper #main {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#clientwrapper #main #main-sub {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#optionsbutton {
|
||||||
|
font-size: .9rem;
|
||||||
|
width: .9rem;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body .lm_popout {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lm_title {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#typelist {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typelistsub {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 5px;
|
||||||
|
width: max-content;
|
||||||
|
background-color: #333333;
|
||||||
|
line-height: .5em;
|
||||||
|
padding: .3em;
|
||||||
|
font-size: .9em;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#renamebox {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#renameboxin {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#updatelist {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.updatelistsub {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 5px;
|
||||||
|
width: max-content;
|
||||||
|
background-color: #333333;
|
||||||
|
line-height: .5em;
|
||||||
|
padding: .3em;
|
||||||
|
font-size: .9em;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inputcontrol {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputwrap {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inputsend {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inputfield {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glbutton {
|
||||||
|
font-size: 0.6em;
|
||||||
|
line-height: 1.3em;
|
||||||
|
padding: .5em;
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,6 @@ let defaultin_plugin = (function () {
|
||||||
//
|
//
|
||||||
// handle the default <enter> key triggering onSend()
|
// handle the default <enter> key triggering onSend()
|
||||||
var onKeydown = function (event) {
|
var onKeydown = function (event) {
|
||||||
$("#inputfield").focus();
|
|
||||||
if ( (event.which === 13) && (!event.shiftKey) ) { // Enter Key without shift
|
if ( (event.which === 13) && (!event.shiftKey) ) { // Enter Key without shift
|
||||||
var inputfield = $("#inputfield");
|
var inputfield = $("#inputfield");
|
||||||
var outtext = inputfield.val();
|
var outtext = inputfield.val();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,403 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Golden Layout plugin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
plugin_handler.add('goldenlayout', (function () {
|
||||||
|
|
||||||
|
var myLayout;
|
||||||
|
var input_component = null;
|
||||||
|
var known_types = ['all', 'untagged'];
|
||||||
|
var untagged = [];
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
content: [{
|
||||||
|
type: 'column',
|
||||||
|
content: [{
|
||||||
|
type: 'component',
|
||||||
|
componentName: 'Main',
|
||||||
|
isClosable: false,
|
||||||
|
componentState: {
|
||||||
|
types: 'untagged',
|
||||||
|
update_method: 'newlines',
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
type: 'component',
|
||||||
|
componentName: 'input',
|
||||||
|
id: 'inputComponent',
|
||||||
|
height: 15,
|
||||||
|
isClosable: false,
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var newDragConfig = {
|
||||||
|
title: 'Untitled',
|
||||||
|
type: 'component',
|
||||||
|
componentName: 'evennia',
|
||||||
|
componentState: {
|
||||||
|
types: 'all',
|
||||||
|
update_method: 'newlines',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// helper function: filter vals out of array
|
||||||
|
function filter (vals, array) {
|
||||||
|
let tmp = array.slice();
|
||||||
|
for (i=0; i<vals.length; i++) {
|
||||||
|
let val = vals[i];
|
||||||
|
while( tmp.indexOf(val) > -1 ) {
|
||||||
|
tmp.splice( tmp.indexOf(val), 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Calculate all known_types minus the 'all' type,
|
||||||
|
// then filter out all types that have been mapped to a pane.
|
||||||
|
var calculate_untagged_types = function () {
|
||||||
|
// set initial untagged list
|
||||||
|
untagged = filter( ['all', 'untagged'], known_types);
|
||||||
|
// for each .content pane
|
||||||
|
$('.content').each( function () {
|
||||||
|
let types = $(this).attr('types');
|
||||||
|
if ( typeof types !== "undefined" ) {
|
||||||
|
untagged = filter( types.split(' '), untagged );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Save the GoldenLayout state to localstorage whenever it changes.
|
||||||
|
var onStateChanged = function () {
|
||||||
|
let components = myLayout.root.getItemsByType('component');
|
||||||
|
components.forEach( function (component) {
|
||||||
|
if( component.hasId('inputComponent') ) { return; } // ignore input components
|
||||||
|
|
||||||
|
let text_div = component.container.getElement().children('.content');
|
||||||
|
let types = text_div.attr('types');
|
||||||
|
let update_method = text_div.attr('update_method');
|
||||||
|
component.container.extendState({ 'types': types, 'update_method': update_method });
|
||||||
|
});
|
||||||
|
|
||||||
|
var state = JSON.stringify( myLayout.toConfig() );
|
||||||
|
localStorage.setItem( 'evenniaGoldenLayoutSavedState', state );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Handle the renamePopup
|
||||||
|
var renamePopup = function (evnt) {
|
||||||
|
let element = $(evnt.data.contentItem.element);
|
||||||
|
let content = element.find('.content');
|
||||||
|
let title = evnt.data.contentItem.config.title;
|
||||||
|
let renamebox = document.getElementById('renamebox');
|
||||||
|
if( !renamebox ) {
|
||||||
|
renamebox = $('<div id="renamebox">');
|
||||||
|
renamebox.append('<input type="textbox" id="renameboxin" value="'+title+'">');
|
||||||
|
renamebox.insertBefore( content );
|
||||||
|
} else {
|
||||||
|
let title = $('#renameboxin').val();
|
||||||
|
evnt.data.setTitle( title );
|
||||||
|
evnt.data.contentItem.setTitle( title );
|
||||||
|
myLayout.emit('stateChanged');
|
||||||
|
$('#renamebox').remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
var onSelectTypesClicked = function (evnt) {
|
||||||
|
let element = $(evnt.data.contentItem.element);
|
||||||
|
let content = element.find('.content');
|
||||||
|
let selected_types = content.attr('types');
|
||||||
|
let menu = $('<div id="typelist">');
|
||||||
|
let div = $('<div class="typelistsub">');
|
||||||
|
|
||||||
|
if( selected_types ) {
|
||||||
|
selected_types = selected_types.split(' ');
|
||||||
|
}
|
||||||
|
for (i=0; i<known_types.length;i++) {
|
||||||
|
let type = known_types[i];
|
||||||
|
let choice;
|
||||||
|
if( selected_types && selected_types.includes(type) ) {
|
||||||
|
choice = $('<label><input type="checkbox" value="'+type+'" checked="checked"/>'+type+'</label>');
|
||||||
|
} else {
|
||||||
|
choice = $('<label><input type="checkbox" value="'+type+'"/>'+type+'</label>');
|
||||||
|
}
|
||||||
|
choice.appendTo(div);
|
||||||
|
}
|
||||||
|
div.appendTo(menu);
|
||||||
|
|
||||||
|
element.prepend(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var commitCheckboxes = function (evnt) {
|
||||||
|
let element = $(evnt.data.contentItem.element);
|
||||||
|
let content = element.find('.content');
|
||||||
|
let checkboxes = $('#typelist :input');
|
||||||
|
let types = [];
|
||||||
|
for (i=0; i<checkboxes.length; i++ ) {
|
||||||
|
let box = checkboxes[i];
|
||||||
|
if( $(box).prop('checked') ) {
|
||||||
|
types.push( $(box).val() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
content.attr('types', types.join(' '));
|
||||||
|
myLayout.emit('stateChanged');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle the typePopup
|
||||||
|
var typePopup = function (evnt) {
|
||||||
|
let typelist = document.getElementById('typelist');
|
||||||
|
if( !typelist ) {
|
||||||
|
onSelectTypesClicked(evnt);
|
||||||
|
} else {
|
||||||
|
commitCheckboxes(evnt);
|
||||||
|
calculate_untagged_types();
|
||||||
|
$('#typelist').remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var onUpdateMethodClicked = function (evnt) {
|
||||||
|
let element = $(evnt.data.contentItem.element);
|
||||||
|
let content = element.find('.content');
|
||||||
|
let update_method = content.attr('update_method');
|
||||||
|
let nlchecked = (update_method == 'newlines') ? 'checked="checked"' : '';
|
||||||
|
let apchecked = (update_method == 'append') ? 'checked="checked"' : '';
|
||||||
|
let rpchecked = (update_method == 'replace') ? 'checked="checked"' : '';
|
||||||
|
|
||||||
|
let menu = $('<div id="updatelist">');
|
||||||
|
let div = $('<div class="updatelistsub">');
|
||||||
|
|
||||||
|
let newlines = $('<label><input type="radio" name="update_method" value="newlines" '+nlchecked+'/>Newlines</label>');
|
||||||
|
let append = $('<label><input type="radio" name="update_method" value="append" '+apchecked+'/>Append</label>');
|
||||||
|
let replace = $('<label><input type="radio" name="update_method" value="replace" '+rpchecked+'/>Replace</label>');
|
||||||
|
|
||||||
|
newlines.appendTo(div);
|
||||||
|
append.appendTo(div);
|
||||||
|
replace.appendTo(div);
|
||||||
|
|
||||||
|
div.appendTo(menu);
|
||||||
|
|
||||||
|
element.prepend(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle the updatePopup
|
||||||
|
var updatePopup = function (evnt) {
|
||||||
|
let updatelist = document.getElementById('updatelist');
|
||||||
|
if( !updatelist ) {
|
||||||
|
onUpdateMethodClicked(evnt);
|
||||||
|
} else {
|
||||||
|
let element = $(evnt.data.contentItem.element);
|
||||||
|
let content = element.find('.content');
|
||||||
|
content.attr('update_method', $('input[name=update_method]:checked').val() );
|
||||||
|
myLayout.emit('stateChanged');
|
||||||
|
$('#updatelist').remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var onTabCreate = function (tab) {
|
||||||
|
//HTML for the typeDropdown
|
||||||
|
let tabRenameControl = $('<span class="lm_title" style="font-size: 1em;width: 1.5em;">\u2B57</span>');
|
||||||
|
let typePopupControl = $('<span class="lm_title" style="font-size: 1.5em;width: 1em;">⮛</span>');
|
||||||
|
let updatePopupControl = $('<span class="lm_title" style="font-size: 1.5em;width: 1em;">⮛</span>');
|
||||||
|
let splitControl = $('<span class="lm_title" style="font-size: 2em;width: 1em;">+</span>');
|
||||||
|
|
||||||
|
// track popups when the associated control is clicked
|
||||||
|
tabRenameControl.click( tab, renamePopup );
|
||||||
|
|
||||||
|
typePopupControl.click( tab, typePopup );
|
||||||
|
|
||||||
|
updatePopupControl.click( tab, updatePopup );
|
||||||
|
|
||||||
|
splitControl.click( tab, function (evnt) {
|
||||||
|
evnt.data.header.parent.addChild( newDragConfig );
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add the typeDropdown to the header
|
||||||
|
tab.element.prepend( tabRenameControl );
|
||||||
|
tab.element.append( typePopupControl );
|
||||||
|
tab.element.append( updatePopupControl );
|
||||||
|
tab.element.append( splitControl );
|
||||||
|
|
||||||
|
if( tab.contentItem.config.componentName == "Main" ) {
|
||||||
|
tab.element.prepend( $('#optionsbutton').clone(true).addClass('lm_title') );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var scrollAll = function () {
|
||||||
|
let components = myLayout.root.getItemsByType('component');
|
||||||
|
components.forEach( function (component) {
|
||||||
|
if( component.hasId('inputComponent') ) { return; } // ignore input components
|
||||||
|
|
||||||
|
let text_div = component.container.getElement().children('.content');
|
||||||
|
let scrollHeight = text_div.prop('scrollHeight');
|
||||||
|
let clientHeight = text_div.prop('clientHeight');
|
||||||
|
text_div.scrollTop( scrollHeight - clientHeight );
|
||||||
|
});
|
||||||
|
myLayout.updateSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var route_msg = function (text_div, txt, update_method) {
|
||||||
|
if ( update_method == 'replace' ) {
|
||||||
|
text_div.html(txt)
|
||||||
|
} else if ( update_method == 'append' ) {
|
||||||
|
text_div.append(txt);
|
||||||
|
} else { // line feed
|
||||||
|
text_div.append('<div class="out">' + txt + '</div>');
|
||||||
|
}
|
||||||
|
let scrollHeight = text_div.prop('scrollHeight');
|
||||||
|
let clientHeight = text_div.prop('clientHeight');
|
||||||
|
text_div.scrollTop( scrollHeight - clientHeight );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Public
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var initComponent = function (div, container, state, default_types, update_method) {
|
||||||
|
// set this container's content div types attribute
|
||||||
|
if( state ) {
|
||||||
|
div.attr('types', state.types);
|
||||||
|
div.attr('update_method', state.update_method);
|
||||||
|
} else {
|
||||||
|
div.attr('types', default_types);
|
||||||
|
div.attr('update_method', update_method);
|
||||||
|
}
|
||||||
|
div.appendTo( container.getElement() );
|
||||||
|
container.on('tab', onTabCreate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var onText = function (args, kwargs) {
|
||||||
|
// If the message is not itself tagged, we'll assume it
|
||||||
|
// should go into any panes with 'all' and 'untagged' set
|
||||||
|
var msgtype = 'untagged';
|
||||||
|
|
||||||
|
if ( kwargs && 'type' in kwargs ) {
|
||||||
|
msgtype = kwargs['type'];
|
||||||
|
if ( ! known_types.includes(msgtype) ) {
|
||||||
|
// this is a new output type that can be mapped to panes
|
||||||
|
console.log('detected new output type: ' + msgtype)
|
||||||
|
known_types.push(msgtype);
|
||||||
|
untagged.push(msgtype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let message_delivered = false;
|
||||||
|
let components = myLayout.root.getItemsByType('component');
|
||||||
|
|
||||||
|
components.forEach( function (component) {
|
||||||
|
if( component.hasId('inputComponent') ) { return; } // ignore the input component
|
||||||
|
|
||||||
|
let text_div = component.container.getElement().children('.content');
|
||||||
|
let attr_types = text_div.attr('types');
|
||||||
|
let pane_types = attr_types ? attr_types.split(' ') : [];
|
||||||
|
let update_method = text_div.attr('update_method');
|
||||||
|
let txt = args[0];
|
||||||
|
|
||||||
|
// is this message type listed in this pane's types (or is this pane catching 'all')
|
||||||
|
if( pane_types.includes(msgtype) || pane_types.includes('all') ) {
|
||||||
|
route_msg( text_div, txt, update_method );
|
||||||
|
message_delivered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is this pane catching 'upmapped' messages?
|
||||||
|
// And is this message type listed in the untagged types array?
|
||||||
|
if( pane_types.includes("untagged") && untagged.includes(msgtype) ) {
|
||||||
|
route_msg( text_div, txt, update_method );
|
||||||
|
message_delivered = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if ( message_delivered ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// unhandled message
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// required Init me
|
||||||
|
var init = function (options) {
|
||||||
|
// Set up our GoldenLayout instance built off of the default main-sub div
|
||||||
|
var savedState = localStorage.getItem( 'evenniaGoldenLayoutSavedState' );
|
||||||
|
var mainsub = document.getElementById('main-sub');
|
||||||
|
|
||||||
|
if( savedState !== null ) {
|
||||||
|
myLayout = new GoldenLayout( JSON.parse( savedState ), mainsub );
|
||||||
|
} else {
|
||||||
|
myLayout = new GoldenLayout( config, mainsub );
|
||||||
|
}
|
||||||
|
|
||||||
|
// register our component and replace the default messagewindow with the Main component element
|
||||||
|
myLayout.registerComponent( 'Main', function (container, componentState) {
|
||||||
|
let main = $('#messagewindow').addClass('content');
|
||||||
|
initComponent(main, container, componentState, 'untagged', 'newlines' );
|
||||||
|
});
|
||||||
|
|
||||||
|
myLayout.registerComponent( 'input', function (container, componentState) {
|
||||||
|
$('#inputcontrol').remove(); // remove the cluttered, HTML-defined input divs
|
||||||
|
$('<div id="inputcontrol">')
|
||||||
|
.append( '<div class="inputwrap"><button id="inputsend" type="button"">></button></div>' )
|
||||||
|
.append( '<textarea id="inputfield" type="text" class="form-control"></textarea>' )
|
||||||
|
.appendTo( container.getElement() );
|
||||||
|
});
|
||||||
|
|
||||||
|
myLayout.registerComponent( 'evennia', function (container, componentState) {
|
||||||
|
let div = $('<div class="content"></div>');
|
||||||
|
initComponent(div, container, componentState, 'all', 'newlines');
|
||||||
|
container.on('destroy', calculate_untagged_types);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make it go.
|
||||||
|
myLayout.init();
|
||||||
|
|
||||||
|
// Event when client window changes
|
||||||
|
$(window).bind("resize", scrollAll);
|
||||||
|
|
||||||
|
// Set Save State callback
|
||||||
|
myLayout.on( 'stateChanged', onStateChanged );
|
||||||
|
|
||||||
|
console.log('Golden Layout Plugin Initialized.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
init: init,
|
||||||
|
onText: onText,
|
||||||
|
getGL: function () { return myLayout },
|
||||||
|
initComponent: initComponent,
|
||||||
|
}
|
||||||
|
})());
|
||||||
|
|
@ -17,7 +17,6 @@ JQuery available.
|
||||||
|
|
||||||
<!-- Bootstrap CSS -->
|
<!-- Bootstrap CSS -->
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
||||||
|
|
||||||
<link rel='stylesheet' type="text/css" media="screen" href={% static "webclient/css/webclient.css" %}>
|
<link rel='stylesheet' type="text/css" media="screen" href={% static "webclient/css/webclient.css" %}>
|
||||||
|
|
||||||
<link rel="icon" type="image/x-icon" href="/static/website/images/evennia_logo.png" />
|
<link rel="icon" type="image/x-icon" href="/static/website/images/evennia_logo.png" />
|
||||||
|
|
@ -64,8 +63,14 @@ JQuery available.
|
||||||
<script src={% static "webclient/js/evennia.js" %} language="javascript" type="text/javascript" charset="utf-8"/></script>
|
<script src={% static "webclient/js/evennia.js" %} language="javascript" type="text/javascript" charset="utf-8"/></script>
|
||||||
|
|
||||||
<!-- set up splits before loading the GUI -->
|
<!-- set up splits before loading the GUI -->
|
||||||
|
<!--
|
||||||
<script src="https://unpkg.com/split.js@1.5.9/dist/split.min.js"></script>
|
<script src="https://unpkg.com/split.js@1.5.9/dist/split.min.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
|
||||||
|
-->
|
||||||
|
<script type="text/javascript" src="https://golden-layout.com/files/latest/js/goldenlayout.min.js"></script>
|
||||||
|
<link type="text/css" rel="stylesheet" href="https://golden-layout.com/files/latest/css/goldenlayout-base.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="https://golden-layout.com/files/latest/css/goldenlayout-dark-theme.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href={% static "webclient/css/goldenlayout.css" %} />
|
||||||
|
|
||||||
<!-- Load gui library -->
|
<!-- Load gui library -->
|
||||||
{% block guilib_import %}
|
{% block guilib_import %}
|
||||||
|
|
@ -73,10 +78,13 @@ JQuery available.
|
||||||
<script src={% static "webclient/js/plugins/popups.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/popups.js" %} language="javascript" type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/options.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/options.js" %} language="javascript" type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/history.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/history.js" %} language="javascript" type="text/javascript"></script>
|
||||||
|
<!--
|
||||||
<script src={% static "webclient/js/plugins/splithandler.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/splithandler.js" %} language="javascript" type="text/javascript"></script>
|
||||||
|
-->
|
||||||
<script src={% static "webclient/js/plugins/default_in.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/default_in.js" %} language="javascript" type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/oob.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/oob.js" %} language="javascript" type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/notifications.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/notifications.js" %} language="javascript" type="text/javascript"></script>
|
||||||
|
<script src={% static "webclient/js/plugins/goldenlayout.js" %} language="javascript" type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/default_out.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/default_out.js" %} language="javascript" type="text/javascript"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue