initial commit - cross reference with 5th port - obviously has compile errors
@@ -0,0 +1,112 @@
|
||||
html, body, div.wrapper > table
|
||||
{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
background-color: #EAEAEA;
|
||||
font-family: verdana,Geneva,sans-serif;
|
||||
font-size: 12px;
|
||||
color: #272727;
|
||||
}
|
||||
|
||||
a
|
||||
{
|
||||
color: #5353B1;
|
||||
}
|
||||
|
||||
div.wrapper
|
||||
{
|
||||
position: absolute; top: 24px; left: 0px; right: 0px; bottom: 0px;
|
||||
}
|
||||
|
||||
div#headbar
|
||||
{
|
||||
background-color: #B2B2B2;
|
||||
border-bottom: 1px solid #C2C2C2;
|
||||
height: 24px;
|
||||
padding: 4px 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
div#hand
|
||||
{
|
||||
padding: 8px 8px;
|
||||
padding-bottom: 4px;
|
||||
background-color: #EAEAEA;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a.card
|
||||
{
|
||||
display: inline-block;
|
||||
margin: 0px 2px;
|
||||
|
||||
background-image: url(cards.png);
|
||||
background-repeat: no-repeat;
|
||||
width: 94px;
|
||||
height: 129px;
|
||||
|
||||
box-sizing: border-box;
|
||||
background-position: 0px 0px;
|
||||
background-origin: border-box;
|
||||
|
||||
text-decoration: none;
|
||||
font-size: 0px;
|
||||
}
|
||||
|
||||
a.card.clubs.ten { background-position: -5px -5px; }
|
||||
a.card.diamonds.ten { background-position: -109px -5px; }
|
||||
a.card.hearts.ten { background-position: -213px -5px; }
|
||||
a.card.spades.ten { background-position: -317px -5px; }
|
||||
a.card.clubs.two { background-position: -421px -5px; }
|
||||
a.card.diamonds.two { background-position: -525px -5px; }
|
||||
a.card.hearts.two { background-position: -629px -5px; }
|
||||
a.card.spades.two { background-position: -733px -5px; }
|
||||
a.card.clubs.three { background-position: -5px -144px; }
|
||||
a.card.diamonds.three { background-position: -109px -144px; }
|
||||
a.card.hearts.three { background-position: -213px -144px; }
|
||||
a.card.spades.three { background-position: -317px -144px; }
|
||||
a.card.clubs.four { background-position: -421px -144px; }
|
||||
a.card.diamonds.four { background-position: -525px -144px; }
|
||||
a.card.hearts.four { background-position: -629px -144px; }
|
||||
a.card.spades.four { background-position: -733px -144px; }
|
||||
a.card.clubs.five { background-position: -5px -283px; }
|
||||
a.card.diamonds.five { background-position: -109px -283px; }
|
||||
a.card.hearts.five { background-position: -213px -283px; }
|
||||
a.card.spades.five { background-position: -317px -283px; }
|
||||
a.card.clubs.six { background-position: -421px -283px; }
|
||||
a.card.diamonds.six { background-position: -525px -283px; }
|
||||
a.card.hearts.six { background-position: -629px -283px; }
|
||||
a.card.spades.six { background-position: -733px -283px; }
|
||||
a.card.clubs.seven { background-position: -5px -422px; }
|
||||
a.card.diamonds.seven { background-position: -109px -422px; }
|
||||
a.card.hearts.seven { background-position: -213px -422px; }
|
||||
a.card.spades.seven { background-position: -317px -422px; }
|
||||
a.card.clubs.eight { background-position: -421px -422px; }
|
||||
a.card.diamonds.eight { background-position: -525px -422px; }
|
||||
a.card.hearts.eight { background-position: -629px -422px; }
|
||||
a.card.spades.eight { background-position: -733px -422px; }
|
||||
a.card.clubs.nine { background-position: -5px -561px; }
|
||||
a.card.diamonds.nine { background-position: -109px -561px; }
|
||||
a.card.hearts.nine { background-position: -213px -561px; }
|
||||
a.card.spades.nine { background-position: -317px -561px; }
|
||||
a.card.clubs.ace { background-position: -421px -561px; }
|
||||
a.card.diamonds.ace { background-position: -525px -561px; }
|
||||
a.card.hearts.ace { background-position: -629px -561px; }
|
||||
a.card.spades.ace { background-position: -733px -561px; }
|
||||
a.card.clubs.jack { background-position: -5px -700px; }
|
||||
a.card.diamonds.jack { background-position: -109px -700px; }
|
||||
a.card.hearts.jack { background-position: -213px -700px; }
|
||||
a.card.spades.jack { background-position: -317px -700px; }
|
||||
a.card.clubs.king { background-position: -421px -700px; }
|
||||
a.card.diamonds.king { background-position: -525px -700px; }
|
||||
a.card.hearts.king { background-position: -629px -700px; }
|
||||
a.card.spades.king { background-position: -733px -700px; }
|
||||
a.card.clubs.queen { background-position: -837px -5px; }
|
||||
a.card.diamonds.queen { background-position: -837px -144px; }
|
||||
a.card.hearts.queen { background-position: -837px -283px; }
|
||||
a.card.spades.queen { background-position: -837px -422px; }
|
||||
a.card.joker { background-position: -837px -561px; }
|
||||
@@ -0,0 +1,13 @@
|
||||
// Used by playing cards; /obj/item/weapon/hand
|
||||
// Subtype exists because of sendResources; these must be sent when the client connects.
|
||||
|
||||
/datum/html_interface/cards/New()
|
||||
. = ..()
|
||||
|
||||
src.head = src.head + "<link rel=\"stylesheet\" type=\"text/css\" href=\"cards.css\" />"
|
||||
src.updateLayout("<div id=\"headbar\"></div><div class=\"wrapper\"><table><tr><td style=\"vertical-align: middle;\"><div id=\"hand\"></div></td></tr></table></div>")
|
||||
|
||||
/datum/html_interface/cards/registerResources(var/list/resources = list())
|
||||
resources["cards.css"] = 'cards.css'
|
||||
resources["cards.png"] = 'cards.png'
|
||||
..(resources)
|
||||
|
After Width: | Height: | Size: 277 KiB |
@@ -0,0 +1,11 @@
|
||||
html
|
||||
{
|
||||
-ms-overflow-style: scrollbar;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
font-family: Arial;
|
||||
overflow-y: scroll;
|
||||
overflow-x: auto;
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
Author: NullQuery
|
||||
Created on: 2014-09-24
|
||||
|
||||
** CAUTION - A WORD OF WARNING **
|
||||
|
||||
If there is no getter or setter available and you aren't extending my code with a sub-type, DO NOT ACCESS VARIABLES DIRECTLY!
|
||||
|
||||
Add a getter/setter instead, even if it does nothing but return or set the variable. Thank you for your patience with me. -NQ
|
||||
|
||||
** Public API **
|
||||
|
||||
var/datum/html_interface/hi = new/datum/html_interface(ref, title, width = 700, height = 480, head = "")
|
||||
|
||||
Creates a new HTML interface object with [ref] as the object and [title] as the initial title of the page. [width] and [height] is the initial width and height
|
||||
of the window. The text in [head] is added just before the end </head> tag.
|
||||
|
||||
hi.setTitle(title)
|
||||
|
||||
Changes the title of the page.
|
||||
|
||||
hi.getTitle()
|
||||
|
||||
Returns the current title of the page.
|
||||
|
||||
hi.updateLayout(layout)
|
||||
|
||||
Updates the overall layout of the page (the HTML code between the body tags).
|
||||
|
||||
This should be used sparingly.
|
||||
|
||||
hi.updateContent(id, content, ignore_cache = FALSE)
|
||||
|
||||
Updates a portion of the page, i.e., the DOM element with the appropriate ID. The contents of the element are replaced with the provided HTML.
|
||||
|
||||
The content is cached on the server-side to minimize network traffic when the client "should have" the same HTML. The client may not have
|
||||
the same HTML if scripts cause the content to change. In this case set the ignore_cache parameter.
|
||||
|
||||
hi.executeJavaScript(jscript, client = null)
|
||||
|
||||
Executes Javascript on the browser.
|
||||
|
||||
The client is optional and may be a /mob, /client or /html_interface_client object. If not specified the code is executed on all clients.
|
||||
|
||||
hi.show(client)
|
||||
|
||||
Shows the HTML interface to the provided client. This will create a window, apply the current layout and contents. It will then wait for events.
|
||||
|
||||
hi.hide(client)
|
||||
|
||||
Hides the HTML interface from the provided client. This will close the browser window.
|
||||
|
||||
hi.isUsed()
|
||||
|
||||
Returns TRUE if the interface is being used (has an active client) or FALSE if not.
|
||||
|
||||
hi.closeAll()
|
||||
|
||||
Closes the interface on all clients.
|
||||
|
||||
** Additional notes **
|
||||
|
||||
When working with byond:// links make sure to reference the HTML interface object and NOT the original object. Topic() will still be called on
|
||||
your object, but it will pass through the HTML interface first allowing interception at a higher level.
|
||||
|
||||
If you want to use custom resources(images/css/js) with an existing interface:
|
||||
You have to use modules/client/asset_cache to ensure they get sent BEFORE the interface opens
|
||||
|
||||
** Sample code **
|
||||
|
||||
mob/var/datum/html_interface/hi
|
||||
|
||||
mob/verb/test()
|
||||
if (!hi) hi = new/datum/html_interface(src, "[src.key]")
|
||||
|
||||
hi.updateLayout("<div id=\"content\"></div>")
|
||||
hi.updateContent("content", "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>")
|
||||
|
||||
hi.show(src)
|
||||
|
||||
*/
|
||||
|
||||
/var/list/html_interfaces = new/list()
|
||||
|
||||
/datum/html_interface
|
||||
// The atom we should report to.
|
||||
var/atom/ref
|
||||
|
||||
// The current title of the browser window.
|
||||
var/title
|
||||
|
||||
// A list of content elements that have been changed. This is necessary when showing the browser control to new clients.
|
||||
var/list/content_elements = new/list()
|
||||
|
||||
// The HTML layout, typically what's in-between the <body></body> tag. May be overridden by extensions.
|
||||
var/layout
|
||||
|
||||
// An associative list of clients currently viewing this screen. The key is the /client object, the value is the /datum/html_interface_client object.
|
||||
var/list/clients
|
||||
|
||||
// This goes just before the closing HEAD tag. I haven't exposed any getters/setters for it because it's only being used by extensions.
|
||||
var/head = ""
|
||||
|
||||
// The initial width of the browser control, used when the window is first shown to a client.
|
||||
var/width
|
||||
|
||||
// The initial height of the browser control, used when the window is first shown to a client.
|
||||
var/height
|
||||
|
||||
// A type associated list of assets the interface needs.
|
||||
//Sent to the client when the interface opens on the client for the first time.
|
||||
var/static/list/asset_list
|
||||
|
||||
/datum/html_interface/New(atom/ref, title, width = 700, height = 480, head = "")
|
||||
html_interfaces.Add(src)
|
||||
|
||||
. = ..()
|
||||
|
||||
src.ref = ref
|
||||
src.title = title
|
||||
src.width = width
|
||||
src.height = height
|
||||
src.head = head
|
||||
|
||||
/datum/html_interface/Destroy()
|
||||
src.closeAll()
|
||||
|
||||
html_interfaces.Remove(src)
|
||||
|
||||
return ..()
|
||||
|
||||
/* * Hooks */
|
||||
/datum/html_interface/proc/specificRenderTitle(datum/html_interface_client/hclient, ignore_cache = FALSE)
|
||||
|
||||
//if you need to override this, either call ..() or add your resources to asset_list
|
||||
/datum/html_interface/proc/registerResources(var/list/resources = list())
|
||||
resources["jquery.min.js"] = 'js/jquery.min.js'
|
||||
resources["bootstrap.min.js"] = 'js/bootstrap.min.js'
|
||||
resources["bootstrap.min.css"] = 'css/bootstrap.min.css'
|
||||
resources["html_interface.css"] = 'css/html_interface.css'
|
||||
resources["html_interface.js"] = 'js/html_interface.js'
|
||||
var/assetlist = list()
|
||||
for (var/R in resources)
|
||||
register_asset(R,resources[R])
|
||||
assetlist += R
|
||||
if (!asset_list)
|
||||
asset_list = list()
|
||||
asset_list[type] = assetlist
|
||||
|
||||
/datum/html_interface/proc/createWindow(datum/html_interface_client/hclient)
|
||||
winclone(hclient.client, "window", "browser_\ref[src]")
|
||||
|
||||
var/list/params = list(
|
||||
"size" = "[width]x[height]",
|
||||
"statusbar" = "false",
|
||||
"on-close" = "byond://?src=\ref[src]&html_interface_action=onclose"
|
||||
)
|
||||
|
||||
if (hclient.client.hi_last_pos) params["pos"] = "[hclient.client.hi_last_pos]"
|
||||
|
||||
winset(hclient.client, "browser_\ref[src]", list2params(params))
|
||||
|
||||
winset(hclient.client, "browser_\ref[src].browser", list2params(list("parent" = "browser_\ref[src]", "type" = "browser", "pos" = "0,0", "size" = "[width]x[height]", "anchor1" = "0,0", "anchor2" = "100,100", "use-title" = "true", "auto-format" = "false")))
|
||||
|
||||
/* * Public API */
|
||||
/datum/html_interface/proc/getTitle() return src.title
|
||||
|
||||
/datum/html_interface/proc/setTitle(title, ignore_cache = FALSE)
|
||||
src.title = title
|
||||
|
||||
var/datum/html_interface_client/hclient
|
||||
|
||||
for (var/client in src.clients)
|
||||
hclient = src._getClient(src.clients[client])
|
||||
|
||||
if (hclient && hclient.active) src._renderTitle(src.clients[client], ignore_cache)
|
||||
|
||||
/datum/html_interface/proc/executeJavaScript(jscript, datum/html_interface_client/hclient = null)
|
||||
if (hclient)
|
||||
hclient = getClient(hclient)
|
||||
|
||||
if (istype(hclient))
|
||||
if (hclient.is_loaded) hclient.client << output(list2params(list(jscript)), "browser_\ref[src].browser:eval")
|
||||
else
|
||||
for (var/client in src.clients) if(src.clients[client]) src.executeJavaScript(jscript, src.clients[client])
|
||||
|
||||
/datum/html_interface/proc/callJavaScript(func, list/arguments, datum/html_interface_client/hclient = null)
|
||||
if (!arguments) arguments = new/list()
|
||||
|
||||
if (hclient)
|
||||
hclient = getClient(hclient)
|
||||
|
||||
if (istype(hclient))
|
||||
if (hclient.is_loaded)
|
||||
hclient.client << output(list2params(arguments), "browser_\ref[src].browser:[func]")
|
||||
else
|
||||
for (var/client in src.clients) if (src.clients[client]) src.callJavaScript(func, arguments, src.clients[client])
|
||||
|
||||
/datum/html_interface/proc/updateLayout(layout)
|
||||
src.layout = layout
|
||||
|
||||
var/datum/html_interface_client/hclient
|
||||
|
||||
for (var/client in src.clients)
|
||||
hclient = src._getClient(src.clients[client])
|
||||
|
||||
if (hclient && hclient.active) src._renderLayout(hclient)
|
||||
|
||||
/datum/html_interface/proc/updateContent(id, content, ignore_cache = FALSE)
|
||||
src.content_elements[id] = content
|
||||
|
||||
var/datum/html_interface_client/hclient
|
||||
|
||||
for (var/client in src.clients)
|
||||
hclient = src._getClient(src.clients[client])
|
||||
|
||||
if (hclient && hclient.active)
|
||||
spawn (-1) src._renderContent(id, hclient, ignore_cache)
|
||||
|
||||
/datum/html_interface/proc/show(datum/html_interface_client/hclient)
|
||||
hclient = getClient(hclient, TRUE)
|
||||
|
||||
if (istype(hclient))
|
||||
if ((type in asset_list) && islist(asset_list[type]))
|
||||
send_asset_list(hclient.client, asset_list[type], TRUE)
|
||||
|
||||
if (!winexists(hclient.client, "browser_\ref[src]"))
|
||||
src.createWindow(hclient)
|
||||
//src._renderTitle(hclient, TRUE)
|
||||
//src._renderLayout(hclient)
|
||||
|
||||
hclient.is_loaded = FALSE
|
||||
hclient.client << output(replacetextEx(replacetextEx(file2text('html_interface.html'), "\[hsrc\]", "\ref[src]"), "</head>", "[head]</head>"), "browser_\ref[src].browser")
|
||||
|
||||
winshow(hclient.client, "browser_\ref[src]", TRUE)
|
||||
|
||||
while (hclient.client && hclient.active && !hclient.is_loaded) sleep(2)
|
||||
|
||||
/datum/html_interface/proc/hide(datum/html_interface_client/hclient)
|
||||
hclient = getClient(hclient)
|
||||
|
||||
if (istype(hclient))
|
||||
if (src.clients)
|
||||
src.clients.Remove(hclient.client)
|
||||
|
||||
if (!src.clients.len) src.clients = null
|
||||
|
||||
hclient.client.hi_last_pos = winget(hclient.client, "browser_\ref[src]" ,"pos")
|
||||
|
||||
winshow(hclient.client, "browser_\ref[src]", FALSE)
|
||||
winset(hclient.client, "browser_\ref[src]", "parent=none")
|
||||
|
||||
if (hascall(src.ref, "hiOnHide")) call(src.ref, "hiOnHide")(hclient)
|
||||
|
||||
// Convert a /mob to /client, and /client to /datum/html_interface_client
|
||||
/datum/html_interface/proc/getClient(client, create_if_not_exist = FALSE)
|
||||
if (istype(client, /datum/html_interface_client)) return src._getClient(client)
|
||||
else if (ismob(client))
|
||||
var/mob/mob = client
|
||||
client = mob.client
|
||||
|
||||
if (istype(client, /client))
|
||||
if (create_if_not_exist && (!src.clients || !(client in src.clients)))
|
||||
if (!src.clients) src.clients = new/list()
|
||||
if (!(client in src.clients)) src.clients[client] = new/datum/html_interface_client(client)
|
||||
|
||||
if (src.clients && (client in src.clients)) return src._getClient(src.clients[client])
|
||||
else return null
|
||||
else return null
|
||||
|
||||
/datum/html_interface/proc/enableFor(datum/html_interface_client/hclient)
|
||||
hclient.active = TRUE
|
||||
|
||||
src.show(hclient)
|
||||
|
||||
/datum/html_interface/proc/disableFor(datum/html_interface_client/hclient)
|
||||
hclient.active = FALSE
|
||||
|
||||
/datum/html_interface/proc/isUsed()
|
||||
if (src.clients && src.clients.len > 0)
|
||||
var/datum/html_interface_client/hclient
|
||||
|
||||
for (var/key in clients)
|
||||
hclient = _getClient(clients[key])
|
||||
|
||||
if (hclient)
|
||||
if (hclient.active) return TRUE
|
||||
else
|
||||
clients.Remove(key)
|
||||
|
||||
return FALSE
|
||||
|
||||
/datum/html_interface/proc/closeAll()
|
||||
if (src.clients)
|
||||
for (var/client in src.clients)
|
||||
src.hide(src.clients[client])
|
||||
|
||||
/* * Danger Zone */
|
||||
|
||||
/datum/html_interface/proc/_getClient(datum/html_interface_client/hclient)
|
||||
if (hclient)
|
||||
if (hclient.client)
|
||||
// res = if the client has been active in the past 10 minutes and the client is allowed to view the object (context-sensitive).
|
||||
var/res = hclient.client.inactivity <= 6000 && (hascall(src.ref, "hiIsValidClient") ? call(src.ref, "hiIsValidClient")(hclient, src) : TRUE)
|
||||
|
||||
if (res)
|
||||
if (!hclient.active) src.enableFor(hclient)
|
||||
else
|
||||
if (hclient.active) src.disableFor(hclient)
|
||||
|
||||
return hclient
|
||||
else
|
||||
return null
|
||||
else
|
||||
return null
|
||||
|
||||
/datum/html_interface/proc/_renderTitle(datum/html_interface_client/hclient, ignore_cache = FALSE, ignore_loaded = FALSE)
|
||||
if (hclient && (ignore_loaded || hclient.is_loaded))
|
||||
// Only render if we have new content.
|
||||
|
||||
if (ignore_cache || src.title != hclient.title)
|
||||
hclient.title = title
|
||||
|
||||
src.specificRenderTitle(hclient)
|
||||
|
||||
hclient.client << output(list2params(list(title)), "browser_\ref[src].browser:setTitle")
|
||||
|
||||
/datum/html_interface/proc/_renderLayout(datum/html_interface_client/hclient, ignore_loaded = FALSE)
|
||||
if (hclient && (ignore_loaded || hclient.is_loaded))
|
||||
var/html = src.layout
|
||||
|
||||
// Only render if we have new content.
|
||||
if (html != hclient.layout)
|
||||
hclient.layout = html
|
||||
|
||||
hclient.client << output(list2params(list(html)), "browser_\ref[src].browser:updateLayout")
|
||||
|
||||
for (var/id in src.content_elements) src._renderContent(id, hclient, ignore_loaded = ignore_loaded)
|
||||
|
||||
/datum/html_interface/proc/_renderContent(id, datum/html_interface_client/hclient, ignore_cache = FALSE, ignore_loaded = FALSE)
|
||||
if (hclient && (ignore_loaded || hclient.is_loaded))
|
||||
var/html = src.content_elements[id]
|
||||
|
||||
// Only render if we have new content.
|
||||
if (ignore_cache || !(id in hclient.content_elements) || html != hclient.content_elements[id])
|
||||
hclient.content_elements[id] = html
|
||||
|
||||
hclient.client << output(list2params(list(id, html)), "browser_\ref[src].browser:updateContent")
|
||||
|
||||
/datum/html_interface/Topic(href, href_list[])
|
||||
var/datum/html_interface_client/hclient = getClient(usr.client)
|
||||
|
||||
if (istype(hclient))
|
||||
if ("html_interface_action" in href_list)
|
||||
switch (href_list["html_interface_action"])
|
||||
|
||||
if ("onload")
|
||||
hclient.layout = null
|
||||
hclient.content_elements.len = 0
|
||||
|
||||
src._renderTitle(hclient, TRUE, TRUE)
|
||||
src._renderLayout(hclient, TRUE)
|
||||
|
||||
hclient.is_loaded = TRUE
|
||||
|
||||
if ("onclose")
|
||||
src.hide(hclient)
|
||||
else if (src.ref && hclient.active) src.ref.Topic(href, href_list, hclient)
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta charset="UTF-8" />
|
||||
<title></title>
|
||||
<link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
|
||||
<link rel="stylesheet" type="text/css" href="html_interface.css" />
|
||||
<script type="text/javascript">var hSrc = "[hsrc]";</script>
|
||||
<script type="text/javascript" src="jquery.min.js"></script>
|
||||
<script type="text/javascript" src="jquery.mousewheel.min.js"></script>
|
||||
<script type="text/javascript" src="bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="html_interface.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,43 @@
|
||||
/datum/html_interface_client
|
||||
// The /client object represented by this model.
|
||||
var/client/client
|
||||
|
||||
// The layout currently visible to the client.
|
||||
var/layout
|
||||
|
||||
// The content elements (mirrored from /datum/html_interface) currently visible to the client.
|
||||
var/list/content_elements = new/list()
|
||||
|
||||
// The current title for this client
|
||||
var/title
|
||||
|
||||
// TRUE if the browser control has loaded and will accept input, FALSE if not.
|
||||
var/is_loaded = FALSE
|
||||
|
||||
// TRUE if this client should receive updates, FALSE if not.
|
||||
var/active = TRUE
|
||||
|
||||
// A list of extra variables, for use by extensions.
|
||||
var/list/extra_vars
|
||||
|
||||
/datum/html_interface_client/New(client/client)
|
||||
. = ..()
|
||||
|
||||
src.client = client
|
||||
|
||||
/datum/html_interface_client/proc/putExtraVar(key, value)
|
||||
if (!src.extra_vars) src.extra_vars = new/list()
|
||||
src.extra_vars[key] = value
|
||||
|
||||
/datum/html_interface_client/proc/removeExtraVar(key)
|
||||
if (src.extra_vars)
|
||||
. = src.extra_vars[key]
|
||||
|
||||
src.extra_vars.Remove(key)
|
||||
|
||||
if (!src.extra_vars.len) src.extra_vars = null
|
||||
|
||||
return .
|
||||
|
||||
/datum/html_interface_client/proc/getExtraVar(key)
|
||||
if (src.extra_vars) return src.extra_vars[key]
|
||||
@@ -0,0 +1,45 @@
|
||||
var is_loading = false;
|
||||
var load_count = 0;
|
||||
|
||||
function onload()
|
||||
{
|
||||
if (!is_loading)
|
||||
{
|
||||
var count = ++load_count;
|
||||
is_loading = true;
|
||||
$("body").html("");
|
||||
|
||||
window.location.href = "byond://?src=" + hSrc + "&html_interface_action=onload";
|
||||
|
||||
// The request may fail which would prevent the player from refreshing the screen again. Try to detect this retry.
|
||||
setTimeout(function()
|
||||
{
|
||||
if (count == load_count && is_loading && $("body").html() == "")
|
||||
{
|
||||
is_loading = false;
|
||||
onload();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
$(document).on("keydown", function(e)
|
||||
{
|
||||
if (!e.ctrlKey && e.which == 116)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
onload();
|
||||
}
|
||||
});
|
||||
|
||||
onload();
|
||||
});
|
||||
|
||||
function fixText(text) { return text.replace(/ÿ/g, ""); }
|
||||
|
||||
function setTitle(new_title) { $("title").html(fixText(new_title)); $(window).trigger("onUpdateTitle"); }
|
||||
function updateLayout(new_html) { $("body").html(fixText(new_html)); $(window).trigger("onUpdateLayout"); setTimeout(function(){ is_loading = false; }, 200); }
|
||||
function updateContent(id, new_html) { $("#" + id).html(fixText(new_html)); $(window).trigger("onUpdateContent"); }
|
||||
@@ -0,0 +1,321 @@
|
||||
body
|
||||
{
|
||||
background-color: #272727;
|
||||
background-image: url(uiBg.png);
|
||||
background-repeat: repeat-x;
|
||||
background-position: center top;
|
||||
|
||||
font-family: verdana,Geneva,sans-serif;
|
||||
font-size: 12px;
|
||||
color: #FFFFFF;
|
||||
line-height: 170%; /* NullQuery: 170% of what? */
|
||||
}
|
||||
|
||||
/* Fix for IE8 */
|
||||
body
|
||||
{
|
||||
background-color: #1F1F1F\9 !important;
|
||||
}
|
||||
|
||||
#ntbgcenter
|
||||
{
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 246px;
|
||||
|
||||
background-image: url(uiBgcenter.png);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
#content
|
||||
{
|
||||
padding: 8px;
|
||||
font-family: Verdana, Geneva, sans-serif;
|
||||
}
|
||||
|
||||
hr
|
||||
{
|
||||
background-color: #40628a;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
a, a:link, a:visited, a:active, .linkOn, .linkOff
|
||||
{
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
background: #40628a;
|
||||
border: 1px solid #161616;
|
||||
padding: 1px 4px 1px 4px;
|
||||
margin: 0 2px 0 0;
|
||||
cursor:default;
|
||||
}
|
||||
|
||||
a.nobg, a.nobg:link, a.nobg:visited, a.nobg:active
|
||||
{
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
cursor:default;
|
||||
font-weight:bold;
|
||||
}
|
||||
a.nobg:hover
|
||||
{
|
||||
color:#40628a;
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
color: #40628a;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
a.white, a.white:link, a.white:visited, a.white:active
|
||||
{
|
||||
color: #40628a;
|
||||
text-decoration: none;
|
||||
background: #ffffff;
|
||||
border: 1px solid #161616;
|
||||
padding: 1px 4px 1px 4px;
|
||||
margin: 0 2px 0 0;
|
||||
cursor:default;
|
||||
}
|
||||
|
||||
a.white:hover
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #40628a;
|
||||
}
|
||||
|
||||
.linkOn, a.linkOn:link, a.linkOn:visited, a.linkOn:active, a.linkOn:hover
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #2f943c;
|
||||
border-color: #24722e;
|
||||
}
|
||||
|
||||
.linkOff, a.linkOff:link, a.linkOff:visited, a.linkOff:active, a.linkOff:hover
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #999999;
|
||||
border-color: #666666;
|
||||
}
|
||||
|
||||
a.icon, .linkOn.icon, .linkOff.icon
|
||||
{
|
||||
position: relative;
|
||||
padding: 1px 4px 2px 20px;
|
||||
}
|
||||
|
||||
a.icon img, .linkOn.icon img
|
||||
{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
ul
|
||||
{
|
||||
padding: 4px 0 0 10px;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
li
|
||||
{
|
||||
padding: 0 0 2px 0;
|
||||
}
|
||||
|
||||
img, a img
|
||||
{
|
||||
border-style:none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{
|
||||
margin: 0;
|
||||
padding: 16px 0 8px 0;
|
||||
color: #517087;
|
||||
}
|
||||
|
||||
h1
|
||||
{
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
h2
|
||||
{
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h3
|
||||
{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
h4
|
||||
{
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.good
|
||||
{
|
||||
color: #00ff00;
|
||||
}
|
||||
|
||||
.average
|
||||
{
|
||||
color: #d09000;
|
||||
}
|
||||
|
||||
.bad
|
||||
{
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.highlight
|
||||
{
|
||||
color: #8BA5C4;
|
||||
}
|
||||
|
||||
.dark
|
||||
{
|
||||
color: #272727;
|
||||
}
|
||||
|
||||
.notice
|
||||
{
|
||||
position: relative;
|
||||
background: #E9C183;
|
||||
color: #15345A;
|
||||
font-size: 10px;
|
||||
font-style: italic;
|
||||
padding: 2px 4px 0 4px;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.notice.icon
|
||||
{
|
||||
padding: 2px 4px 0 20px;
|
||||
}
|
||||
|
||||
.notice img
|
||||
{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
div.notice
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.statusDisplay
|
||||
{
|
||||
background: #000000;
|
||||
color: #ffffff;
|
||||
border: 1px solid #40628a;
|
||||
padding: 4px;
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.statusLabel
|
||||
{
|
||||
width: 138px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
color: #98B0C3;
|
||||
}
|
||||
|
||||
.statusValue
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
.block
|
||||
{
|
||||
padding: 8px;
|
||||
margin: 10px 4px 4px 4px;
|
||||
border: 1px solid #40628a;
|
||||
background-color: #202020;
|
||||
}
|
||||
|
||||
.block h3
|
||||
{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.progressBar
|
||||
{
|
||||
width: 240px;
|
||||
height: 14px;
|
||||
border: 1px solid #666666;
|
||||
float: left;
|
||||
margin: 0 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progressFill
|
||||
{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #40628a;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progressFill.good
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #00ff00;
|
||||
}
|
||||
|
||||
.progressFill.average
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #d09000;
|
||||
}
|
||||
|
||||
.progressFill.bad
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #ff0000;
|
||||
}
|
||||
|
||||
.progressFill.highlight
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #8BA5C4;
|
||||
}
|
||||
|
||||
.clearBoth
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.clearLeft
|
||||
{
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.clearRight
|
||||
{
|
||||
clear: right;
|
||||
}
|
||||
|
||||
.line
|
||||
{
|
||||
width: 100%;
|
||||
clear: both;
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Author: NullQuery
|
||||
Created on: 2014-09-25
|
||||
|
||||
Extension to implement Nanotrasen styled windows.
|
||||
|
||||
Additional procs:
|
||||
|
||||
hi.setEyeColor(color, client)
|
||||
|
||||
Use this to set the color of the 'eye' in the top-left corner of the window.
|
||||
|
||||
The client is optional and may be a /mob, /client or /html_interface_client object. It must be specified, since the eye icon is specific to a client.
|
||||
|
||||
*/
|
||||
|
||||
/datum/html_interface/nanotrasen/New()
|
||||
. = ..()
|
||||
|
||||
// Add appropriate CSS and set the default layout.
|
||||
src.head = src.head + "<link rel=\"stylesheet\" type=\"text/css\" href=\"hi-nanotrasen.css\" />"
|
||||
src.updateLayout("")
|
||||
|
||||
/datum/html_interface/nanotrasen/updateLayout(layout)
|
||||
// Wrap the layout in our custom HTML
|
||||
return ..("<div id=\"ntbgcenter\"></div><div id=\"content\">[layout]</div>")
|
||||
|
||||
/datum/html_interface/specificRenderTitle(datum/html_interface_client/hclient, ignore_cache = FALSE)
|
||||
// Update the title in our custom header (in addition to default functionality)
|
||||
winset(hclient.client, "browser_\ref[src].uiTitle", list2params(list("text" = "[src.title]")))
|
||||
|
||||
/datum/html_interface/nanotrasen/registerResources(var/list/resources = list())
|
||||
resources["uiBg.png"] = 'uiBg.png'
|
||||
resources["uiBgcenter.png"] = 'uiBgcenter.png'
|
||||
resources["hi-nanotrasen.css"] = 'hi-nanotrasen.css'
|
||||
..(resources)
|
||||
|
||||
/datum/html_interface/nanotrasen/createWindow(datum/html_interface_client/hclient)
|
||||
. = ..() // we want the default window
|
||||
|
||||
// Remove the titlebar
|
||||
winset(hclient.client, "browser_\ref[src]", list2params(list(
|
||||
"titlebar" = "false"
|
||||
)))
|
||||
|
||||
// Reposition the browser
|
||||
winset(hclient.client, "browser_\ref[src].browser", list2params(list(
|
||||
"pos" = "0,35",
|
||||
"size" = "[width]x[height - 35]"
|
||||
)))
|
||||
|
||||
// Add top background image
|
||||
winset(hclient.client, "browser_\ref[src].topbg", list2params(list(
|
||||
"parent" = "browser_\ref[src]",
|
||||
"type" = "label",
|
||||
"pos" = "0,0",
|
||||
"size" = "[width]x35",
|
||||
"anchor1" = "0,0",
|
||||
"anchor2" = "100,0",
|
||||
"image" = "['uiBgtop.png']",
|
||||
"image-mode" = "tile",
|
||||
"is-disabled" = "true"
|
||||
)))
|
||||
|
||||
// Add Nanotrasen logo
|
||||
winset(hclient.client, "browser_\ref[src].uiTitleFluff", list2params(list(
|
||||
"parent" = "browser_\ref[src]",
|
||||
"type" = "label",
|
||||
"pos" = "[width - 42 - 4 - 24 - 4 - 24 - 4],5",
|
||||
"size" = "42x24",
|
||||
"anchor1" = "100,0",
|
||||
"anchor2" = "100,0",
|
||||
"image" = "['uiTitleFluff.png']",
|
||||
"image-mode" = "tile",
|
||||
"is-disabled" = "true"
|
||||
)))
|
||||
|
||||
// Add Eye picture
|
||||
winset(hclient.client, "browser_\ref[src].uiTitleEye", list2params(list(
|
||||
"parent" = "browser_\ref[src]",
|
||||
"type" = "label",
|
||||
"pos" = "8,5",
|
||||
"size" = "42x24",
|
||||
"anchor1" = "0,0",
|
||||
"anchor2" = "0,0",
|
||||
"image" = "['uiEyeGreen.png']",
|
||||
"image-mode" = "tile",
|
||||
"is-disabled" = "true"
|
||||
)))
|
||||
|
||||
// Add title text
|
||||
winset(hclient.client, "browser_\ref[src].uiTitle", list2params(list(
|
||||
"parent" = "browser_\ref[src]",
|
||||
"type" = "label",
|
||||
"is-transparent" = "true",
|
||||
"pos" = "64,0",
|
||||
"size" = "580x35",
|
||||
"anchor1" = "0,0",
|
||||
"anchor2" = "100,0",
|
||||
"is-disabled" = "true",
|
||||
"text" = "[src.title]",
|
||||
"align" = "left",
|
||||
"font-family" = "verdana,Geneva,sans-serif",
|
||||
"font-size" = "12", // ~ 16px
|
||||
"text-color" = "#E9C183"
|
||||
)))
|
||||
|
||||
// Add minimize button
|
||||
// TODO: Style the button (add image)
|
||||
winset(hclient.client, "browser_\ref[src].uiTitleMinimize", list2params(list(
|
||||
"parent" = "browser_\ref[src]",
|
||||
"type" = "button",
|
||||
"is-flat" = "true",
|
||||
"background-color"="#383838", // should be unnecessary if image is used
|
||||
"text-color" = "#FFFFFF", // should be unnecessary if image is used
|
||||
"is-transparent" = "true",
|
||||
"pos" = "[width - 24 - 4 - 24 - 4],5",
|
||||
"size" = "24x24",
|
||||
"anchor1" = "100,0",
|
||||
"anchor2" = "100,0",
|
||||
"text" = "-",
|
||||
"font-family" = "verdana,Geneva,sans-serif", // should be unnecessary if image is used
|
||||
"font-size" = "12", // ~ 16px - should be unnecessary if image is used
|
||||
|
||||
// Disable resizing (disables maximizing), minimize window, bind window.on-size to catch 'restore window' button to enable resizing if restored.
|
||||
"command" = ".winset \"browser_\ref[src].can-resize=false;browser_\ref[src].is-minimized=true;browser_\ref[src].on-size=\".swinset \\\"browser_\ref[src].can-resize=true;browser_\ref[src].on-size=\\\"\"\""
|
||||
)))
|
||||
|
||||
// Add close button
|
||||
// TODO: Style the button (add image)
|
||||
winset(hclient.client, "browser_\ref[src].uiTitleClose", list2params(list(
|
||||
"parent" = "browser_\ref[src]",
|
||||
"type" = "button",
|
||||
"is-flat" = "true",
|
||||
"background-color"="#383838", // should be unnecessary if image is used
|
||||
"text-color" = "#FFFFFF", // should be unnecessary if image is used
|
||||
"command" = "byond://?src=\ref[src];html_interface_action=onclose",
|
||||
"is-transparent" = "true",
|
||||
"pos" = "[width - 24 - 4],5",
|
||||
"size" = "24x24",
|
||||
"anchor1" = "100,0",
|
||||
"anchor2" = "100,0",
|
||||
"text" = "X",
|
||||
"font-family" = "verdana,Geneva,sans-serif", // should be unnecessary if image is used
|
||||
"font-size" = "12" // ~ 16px - should be unnecessary if image is used
|
||||
)))
|
||||
|
||||
/datum/html_interface/nanotrasen/enableFor(datum/html_interface_client/hclient)
|
||||
. = ..()
|
||||
|
||||
src.setEyeColor("green", hclient)
|
||||
|
||||
/datum/html_interface/nanotrasen/disableFor(datum/html_interface_client/hclient)
|
||||
hclient.active = FALSE
|
||||
|
||||
src.setEyeColor("red", hclient)
|
||||
|
||||
/datum/html_interface/nanotrasen/proc/setEyeColor(color, datum/html_interface_client/hclient)
|
||||
hclient = getClient(hclient)
|
||||
|
||||
if (istype(hclient))
|
||||
var/resource
|
||||
switch (color)
|
||||
if ("green") resource = 'uiEyeGreen.png'
|
||||
if ("orange") resource = 'uiEyeOrange.png'
|
||||
if ("red") resource = 'uiEyeRed.png'
|
||||
else CRASH("Invalid color: [color]")
|
||||
|
||||
if (hclient.getExtraVar("eye_color") != color)
|
||||
hclient.putExtraVar("eye_color", color)
|
||||
|
||||
winset(hclient.client, "browser_\ref[src].uiTitleEye", list2params(list("image" = "[resource]")))
|
||||
else
|
||||
WARNING("Invalid object passed to /datum/html_interface/nanotrasen/proc/setEyeColor")
|
||||
|
After Width: | Height: | Size: 257 B |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 912 B |
|
After Width: | Height: | Size: 985 B |
|
After Width: | Height: | Size: 946 B |
|
After Width: | Height: | Size: 946 B |