mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 02:16:05 +00:00
quick temporary UI for the web client.
This commit is contained in:
@@ -1650,6 +1650,8 @@
|
||||
#include "code\ZAS\Zone.dm"
|
||||
#include "interface\interface.dm"
|
||||
#include "interface\skin.dmf"
|
||||
#include "interface\web\info.dms"
|
||||
#include "interface\web\interface.dms"
|
||||
#include "maps\_map.dm"
|
||||
#include "maps\tgstation.dm"
|
||||
#include "maps\RandomZLevels\Academy.dm"
|
||||
|
||||
316
interface/web/info.dms
Normal file
316
interface/web/info.dms
Normal file
@@ -0,0 +1,316 @@
|
||||
<byondclass name="info">
|
||||
<style type="text/css">
|
||||
.byond_info {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
.byond_info_tabbar {
|
||||
max-width: 80% !important;
|
||||
}
|
||||
.byond_info_tab {
|
||||
border-top-left-radius: 0px !important;
|
||||
border-top-right-radius: 0px !important;
|
||||
border-bottom-right-radius: 0px !important;
|
||||
border-bottom-left-radius: 0px !important;
|
||||
border: 1px solid #000000;
|
||||
margin-top: 0;
|
||||
margin-right: 5px;
|
||||
margin-bottom: -1px;
|
||||
margin-left: -2px;
|
||||
width: 85px;
|
||||
height: 21px;
|
||||
text-align: center;
|
||||
}
|
||||
.byond_info_tab.selected {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
.byond_info_contents {
|
||||
|
||||
}
|
||||
.byond_info table {
|
||||
|
||||
}
|
||||
.byond_info td {vertical-align: top;}
|
||||
.byond_info td img {vertical-align: middle;}
|
||||
.byond_info table td {
|
||||
cursor: default;
|
||||
}
|
||||
.byond_info table.verbs {
|
||||
table-layout: fixed;
|
||||
}
|
||||
.byond_info table.verbs td[verb]:hover {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
{
|
||||
config: {
|
||||
onShow: '',
|
||||
onHide: '',
|
||||
onTab: '',
|
||||
rightClick: false,
|
||||
_tabNames: [],
|
||||
_tabs: {},
|
||||
_tabInfo: {},
|
||||
_tabInfoPending: {},
|
||||
_curTab: null,
|
||||
_updateTimer: {},
|
||||
_clicked: false
|
||||
},
|
||||
fn: {
|
||||
content: function() {return this.top;},
|
||||
create: function() {
|
||||
this.top.removeChild(this.ui.tab);
|
||||
byond.css(this.ui.tabbar,'display','none');
|
||||
},
|
||||
stats: function(stats, verbs) {
|
||||
var t=this, tb=t.ui.tabbar, tbc=tb.childNodes, e=t.ui.contents, c=t.config, tabs=c._tabs, tabNames=c._tabNames, info=c._tabInfo, pending=c._tabInfoPending;
|
||||
if(!stats || !stats.length) stats = verbs;
|
||||
else if(verbs) stats = stats.concat(verbs);
|
||||
if(!stats || !(np=stats.length)) {
|
||||
if(tabs.length) {tb.innerHTML = ''; tabs.splice(0,tabs.length); c._tabInfo={};}
|
||||
if(this.shown) {this.shown=false; this.onhide();}
|
||||
return;
|
||||
}
|
||||
if(!this.shown) {this.shown=true; this.onshow();}
|
||||
var ih=byond.innerSize(e).height;
|
||||
|
||||
var i,j,l=stats.length,change,n,panel,curIdx=-1,tab,newIdx=-1;
|
||||
|
||||
for(i=0,l=stats.length; i<l; ++i) {
|
||||
panel = stats[i];
|
||||
panel.type = panel.items?'stats':'verbs';
|
||||
n = panel.type+':'+panel.name;
|
||||
if(c._curTab == n) {
|
||||
curIdx = i;
|
||||
delete pending[n];
|
||||
if(panel.changed!=false) {panel.changed=false; t._updatePanel(panel, n);}
|
||||
}
|
||||
else if(panel.changed!=false) {pending[n] = panel; panel.changed=false;}
|
||||
if(c._pendingTab == panel.name.toLowerCase()) {delete c._pendingTab; newIdx=i;}
|
||||
if(i>=tabNames.length || n!=tabNames[i]) {
|
||||
// prefer stats panel if nothing was clicked yet
|
||||
if(!c._clicked && newIdx<0 && c._curTab && n.match(/^stats/) && c._curTab.match(/^verbs/)) newIdx = i;
|
||||
change = true;
|
||||
tab = tabs[n];
|
||||
if(!tab) {
|
||||
tabs[n] = tab = t.ui.tab.cloneNode();
|
||||
tab.innerHTML = byond.htmlEncode(panel.name);
|
||||
tab.onclick = t._tabClick.bind(t,n);
|
||||
}
|
||||
if(i >= tbc.length) tb.appendChild(tab);
|
||||
else tb.insertBefore(tab,tbc[i]);
|
||||
j = tabNames.indexOf(n);
|
||||
if(j>=0) tabNames.splice(j,1);
|
||||
tabNames.splice(i,0,n);
|
||||
}
|
||||
}
|
||||
|
||||
while(tabNames.length > l) {
|
||||
change = true;
|
||||
n = tabNames.pop();
|
||||
tab = tabs[n];
|
||||
tab.onclick = null;
|
||||
if(tab.parentNode) tab.parentNode.removeChild(tab);
|
||||
delete tabs[n];
|
||||
if(tabInfo[n] && (j=tabInfo[n].table)) {
|
||||
if(j.parentNode) j.parentNode.removeChild(j);
|
||||
}
|
||||
if(n == c._curTab && newIdx < 0) {
|
||||
curIdx = Math.min(curIdx,l-1);
|
||||
if(curIdx >= 0) setTimeout(t._tabClick.bind(t,tabNames[curIdx]),100);
|
||||
}
|
||||
}
|
||||
if(change) t._recalcTabs();
|
||||
if(curIdx < 0 && l) newIdx = 0;
|
||||
if(newIdx >= 0) setTimeout(t._tabClick.bind(t,tabNames[newIdx]),100);
|
||||
delete c._pendingTab;
|
||||
|
||||
e.scrollTop = Math.max(0, Math.min(e.scrollTop,e.scrollHeight-ih));
|
||||
},
|
||||
postLoad: function() {
|
||||
byond.css(this.ui.tabbar,'display','');
|
||||
if(!this.shown) this.onhide();
|
||||
else this._recalcTabs();
|
||||
},
|
||||
_mouse: function(p,e) {
|
||||
// call preventDefault() to stop browser's normal drag behavior (which we don't handle)
|
||||
if(e) {
|
||||
if(e.type.match(/(down|start)$/i)) {this.captureMouse(e); e.preventDefault();}
|
||||
if(e.type.match(/(down|start|click)$/i)) {
|
||||
var m = byond(':map');
|
||||
if(m) m._getCoords(e);
|
||||
}
|
||||
if(e.type.match(/menu$/i)) e.preventDefault();
|
||||
}
|
||||
this.mouse(p,e);
|
||||
},
|
||||
dragTarget: function(e) {
|
||||
// this will fail to get a panel name if dragging between cells, but it isn't a big deal
|
||||
var t=this, c=t.config, i=c._tabInfo[c._curTab];
|
||||
return (i && i.panel && i.panel.items) ? {panel:i.panel.name} : {};
|
||||
},
|
||||
_innerHeight: function(e) {
|
||||
var bh=0, n, pads=['paddingTop','paddingBottom','borderTopWidth','borderBottomWidth'];
|
||||
for(var j=0,l=pads.length; j<l; ++j) {
|
||||
n=byond.cssPx(e,pads[j]); if(!isNaN(n)) bh += n;
|
||||
}
|
||||
return e.offsetHeight-bh;
|
||||
},
|
||||
_tabClick: function(n, ev) {
|
||||
var t=this, c=t.config, tb=t.ui.tabbar, e=t.ui.contents, tab, conts, i, l, a, pend;
|
||||
if(ev) c._clicked = true;
|
||||
try {
|
||||
c._curTab = n;
|
||||
tab = c._tabs[n];
|
||||
pend = c._tabInfoPending[n];
|
||||
if(pend) {pend.now=true; t._updatePanel(pend,n);}
|
||||
conts = c._tabInfo[n].table;
|
||||
for(i=0,a=tb.querySelectorAll('.selected'),l=a.length; i<l; ++i) {
|
||||
if(a[i] == tab) continue;
|
||||
a[i].classList.remove('selected');
|
||||
}
|
||||
tab.classList.add('selected');
|
||||
while(e.firstChild && e.firstChild != conts) e.removeChild(e.firstChild);
|
||||
if(!e.firstChild) e.appendChild(conts);
|
||||
t._recalcTabs();
|
||||
} catch(_){console.log(''+_);}
|
||||
if(c.onTab) t.input(c.onTab.replace(/\[\[\*\]\]/g, (c._curTab||'').replace(/^\w+:/,'')));
|
||||
},
|
||||
_recalcTabs: function(timed) {
|
||||
var t=this, tb=t.ui.tabbar, e=t.ui.contents, c=t.config, tm;
|
||||
byond.css(e,'height',t.loading?'100%':'calc(100% - '+tb.offsetHeight+'px)');
|
||||
if(!timed) {
|
||||
if((tm=c._tabTimer)) clearTimeout(tm);
|
||||
c._tabTimer = setTimeout(t._recalcTabs.bind(t,1), 100);
|
||||
}
|
||||
else c._tabTimer = 0;
|
||||
},
|
||||
onsize: function() {
|
||||
this._recalcTabs();
|
||||
return byond.fn.onsize.call(this);
|
||||
},
|
||||
_sameItem: function(o1, o2) {
|
||||
if(!o1) return !o2 || o2.null;
|
||||
if(!o2) return o1.null;
|
||||
return (o1.text == o2.text && o1.atom == o2.atom && o1.null == o2.null && o1.icon == o2.icon);
|
||||
},
|
||||
_sameAtom: function(o1, o2) {return o1.atom == o2.atom;},
|
||||
_updatePanel: function(p, n) {
|
||||
var t=this, oldp, cf=t.config, ti, newp, table, lst, oldlst, i, j, l, c, r, nc, nr, oldrows, obj, oldobj, re, ce, html, newrow, hasAtom;
|
||||
if(typeof p == 'string') { // timer fired
|
||||
ti = cf._updateTimer[n=p];
|
||||
p = ti.info;
|
||||
p.now = true;
|
||||
ti = null;
|
||||
delete cf._updateTimer[n];
|
||||
}
|
||||
else ti=cf._updateTimer[n];
|
||||
oldp = cf._tabInfo[n];
|
||||
if(!oldp) {
|
||||
table = document.createElement('table');
|
||||
byond.backstage().appendChild(table);
|
||||
table.className=p.items?'stats':'verbs';
|
||||
}
|
||||
else {
|
||||
if(!p.now) {
|
||||
if(!ti) cf._updateTimer[n] = ti = {timer:setTimeout(t._updatePanel.bind(t, n), 500)};
|
||||
ti.info = p;
|
||||
return oldp;
|
||||
}
|
||||
table = oldp.table;
|
||||
oldp = oldp.panel;
|
||||
}
|
||||
if(ti) {clearTimeout(ti.timer); delete cf._updateTimer[n];}
|
||||
oldrows = table.rows.length;
|
||||
newp = {table:table, panel:p};
|
||||
if(lst=p.items) {
|
||||
oldlst = oldp ? (oldp.items||[]) : [];
|
||||
nr = p.rows;
|
||||
newrow = '<td class=prefix></td><td></td><td class=suffix></td>';
|
||||
while(oldrows > nr) table.deleteRow(--oldrows);
|
||||
while(oldrows < nr) {
|
||||
re = table.insertRow(oldrows++);
|
||||
re.innerHTML = newrow;
|
||||
}
|
||||
for(i=r=0; r<nr; ++r) {
|
||||
re = table.rows[r];
|
||||
for(c=0; c<3; ++i,++c) {
|
||||
if(t._sameItem(obj=lst[i], oldlst[i])) continue;
|
||||
ce = re.cells[c];
|
||||
html = '';
|
||||
if(obj && obj.null) obj = null;
|
||||
if(obj) {
|
||||
if(obj.icon!=null && obj.icon!=undefined) {
|
||||
hasAtom = typeof obj.atom == 'number';
|
||||
html = '<img'+(hasAtom?' atom='+obj.atom:'')+' src="'+(hasAtom?t.atomIcon(obj.atom):byond.iconUrl(obj.icon))+'" />';
|
||||
if(obj.text) html += ' '+byond.htmlEncode(obj.text);
|
||||
if(hasAtom) byond.fillAtomIcons();
|
||||
}
|
||||
else if(obj.text) html = byond.htmlEncode(obj.text);
|
||||
byond.attr(ce,'title',obj.text||'');
|
||||
byond.attr(ce,'atom',obj.atom);
|
||||
ce.onclick = ce.ondblclick = ce.onmouseover = ce.onmouseout = ce.onmousemove = ce.onmousedown = ce.onmouseup = ce.oncontextmenu = (typeof obj.atom == 'number') && c==1 && t._mouse.bind(t,{element:ce,atom:obj.atom,panel:p.name,id:t.id});
|
||||
}
|
||||
else {
|
||||
ce.onclick = ce.ondblclick = ce.onmouseover = ce.onmouseout = ce.onmousemove = ce.onmousedown = ce.onmouseup = ce.oncontextmenu = null;
|
||||
byond.attr(ce,'atom',null);
|
||||
byond.attr(ce,'title','');
|
||||
}
|
||||
ce.innerHTML = html;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(lst=p.verbs) {
|
||||
oldlst = oldp ? (oldp.verbs||[]) : [];
|
||||
nc = 4; // eventually add more nuance
|
||||
nr = Math.ceil((l = lst.length) / nc);
|
||||
nc = Math.ceil(l / nr);
|
||||
newp.cols = nc;
|
||||
html = '';
|
||||
for(c=r=j=0,i=nc*nr; i--;) {
|
||||
if(!c) html += '<tr>';
|
||||
obj = lst[j];
|
||||
html += obj ? '<td title="'+byond.htmlEncode(obj.desc||'')+'" verb="'+byond.htmlEncode(obj.name)+'" onclick="byond(\''+t.id+'\').input(\''+byond.htmlEncode(obj.name.trim().replace(/\s+/g,'-'))+'\');return false">'+byond.htmlEncode(obj.name)+'</td>' : '<td></td>';
|
||||
if(++c>=nc) {c=0; html += '</tr>'; j=++r;}
|
||||
else j += nr;
|
||||
}
|
||||
table.innerHTML = html;
|
||||
}
|
||||
cf._tabInfo[n] = newp;
|
||||
return newp;
|
||||
}
|
||||
},
|
||||
winsetfn: {
|
||||
onTab: function(v) {
|
||||
var t=this,c=t.config;
|
||||
if(typeof v == 'string') c.onTab = v;
|
||||
else return c.onTab;
|
||||
},
|
||||
currentTab: function(v) {
|
||||
var t=this,c=t.config,ct,a,i,l,n;
|
||||
if(typeof v == 'string') {
|
||||
v = v.toLowerCase();
|
||||
for(a=c._tabNames,l=a.length,i=0; i<l; ++i) {
|
||||
n = a[i].replace(/^\w+:/i,'').toLowerCase();
|
||||
if(n == v) {t._tabClick(a[i],true); return;}
|
||||
}
|
||||
c._pendingTab = v; // can't find it; look in the next update
|
||||
return;
|
||||
}
|
||||
if(!c._curTab) return null;
|
||||
return c._curTab.replace(/^\w+:/i,'');
|
||||
},
|
||||
rightClick: function(v) {
|
||||
var c=this.config;
|
||||
v = byond.winset2bool(v);
|
||||
if(v===undefined || v==null) return c.rightClick;
|
||||
c.rightClick = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<div id=tabbar class="byond_info_tabbar"></div><div id=tab class="byond_info_tab byond_border byond_buttonbk"></div><div id=contents class="byond_info_contents byond_border1"></div>
|
||||
</byondclass>
|
||||
94
interface/web/interface.dms
Normal file
94
interface/web/interface.dms
Normal file
@@ -0,0 +1,94 @@
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
* {
|
||||
border-color: currentColor;
|
||||
}
|
||||
#skin {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
#mainvsplit {
|
||||
width: 100%;
|
||||
height: calc(100% - 1.5em);
|
||||
}
|
||||
.byond_map canvas {
|
||||
color: black;
|
||||
}
|
||||
#input {
|
||||
width: 100%;
|
||||
height: 1.5em;
|
||||
}
|
||||
.byond_input input {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
#rbuttons {
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
}
|
||||
#rbuttons div[byondclass=button] {
|
||||
display: inline-block;
|
||||
margin: 5px; 10px;
|
||||
background-color:#000000;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
var defaultSkin = (function(){
|
||||
var panesShown = {};
|
||||
var npanes = 0;
|
||||
return {
|
||||
show: function(id) {
|
||||
if(panesShown[id]) return;
|
||||
panesShown[id] = true;
|
||||
byond('rbutton_'+id).winset({'isVisible':true,'isChecked':true});
|
||||
++npanes;
|
||||
byond('rside').winset({left:'rbuttons'});
|
||||
byond('rpane').winset({left:id});
|
||||
},
|
||||
hide: function(id) {
|
||||
if(!panesShown[id]) return;
|
||||
delete panesShown[id];
|
||||
var button = byond('rbutton_'+id);
|
||||
button.winset({'isVisible':false});
|
||||
if(''+button.winget('isChecked') ==' true') byond('rbutton_text').winset({isChecked:true});
|
||||
var rpane = byond('rpane');
|
||||
if(rpane.winget('left') == id) rpane.winset({left:''});
|
||||
if(!--npanes) byond('rside').winset({left:''});
|
||||
}
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
<body>
|
||||
<div id="mainvsplit" byondclass="child" skinparams="is-vertical=true">
|
||||
<div id="map" byondclass='map'></div>
|
||||
<div id="rside" byondclass="child" skinparams="right=rpane;fit=left">
|
||||
<div id="rpane" byondclass="child" style="width:100%;height:100%;" skinparams="right=output">
|
||||
<div id="output" byondclass='output' isdefault=1></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="input" byondclass='input' isdefault=1></div>
|
||||
<div id="rbuttons" byondclass="pane">
|
||||
<div id="rbutton_text" byondclass="button" skinparams="text=Text;command='.skin byond(\'rpane\').winset({left:\'\'})';group=rbutton;isChecked=true"></div>
|
||||
<div id="rbutton_browser" byondclass="button" skinparams="text=Browser;command='.skin byond(\'rpane\').winset({left:\'browser\'})';group=rbutton" style="display:none"></div>
|
||||
<div id="rbutton_info" byondclass="button" skinparams="text=Info;command='.skin byond(\'rpane\').winset({left:\'info\'})';group=rbutton" style="display:none"></div>
|
||||
<div id="rbutton_special" byondclass="button" skinparams="text=Special;command='.skin byond(\'rpane\').winset({left:\'window1\'})';group=rbutton" style="display:none"></div>
|
||||
</div>
|
||||
<div byondclass="pane">
|
||||
<div id="browser" byondclass='browser' isdefault=1 skinparams="on-show='.skin defaultSkin.show(\'browser\')';on-hide='.skin defaultSkin.hide(\'browser\')'"></div>
|
||||
<div id="info" byondclass='info' isdefault=1 skinparams="on-show='.skin defaultSkin.show(\'info\')';on-hide='.skin defaultSkin.show(\'info\')'"></div>
|
||||
</div>
|
||||
<div byondclass="status" id="status" isdefault=1></div>
|
||||
<div byondclass="dpad" id="dpad" isdefault=1></div>
|
||||
<div byondclass="hotbar" id="hotbar" isdefault=1></div>
|
||||
</body>
|
||||
Reference in New Issue
Block a user