mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
* Add the system for managed global variables * Travis ban old globals * So you CAN inline proccall, that's neat * Fix that * master.dm * Remove the hack procs * Move InitGlobals to the proper spot * configuration.dm * Fix the missing pre-slash * clockcult.dm * This is probably for the best * Doy * Fix shit * Rest of the DEFINES tree * Fix * Use global. for access * Update find_references_in_globals Always hated that proc Whoever made it must've bee a r e a l idiot... * __HELPERS tree * Move global initialization to master. Fix the declaration * database.dm * Dat newline * I said DECLARATIVE order! * Here's something you can chew on @Iamgoofball * game_modes.dm * Fix this * genetics.dm * flavor_misc.dm * More stuff * Do it mso's way. Keep the controllers as global * Make master actually see it * Fix * Finish _globalvars/lists * Finish the rest of the _globalvars tree * This is weird * Migrate the controllers * SLOTH -> GLOB * Lighting globals * round_start_time -> ticker * PAI card list -> pai SS * record_id_num -> static * Diseases list -> SSdisease * More disease globals to the SS * More disease stuff * Emote list * Better and better * Bluh * So much stuff * Ahh * Wires * dview * station_areas * Teleportlocs * blood_splatter_icons * Stuff and such * More stuff * RAD IO * More stuff and such * Blob shit * Changeling stuff * Add "Balance" to changelogs * Balance for changelog compiler + Auto Tagging * Update the PR template * hivemind_bank * Bip * sacrificed * Good shit * Better define * More cult shit * Devil shit * Gang shit * > borers Fix shit * Rename the define * Nuke * Objectives * Sandbox * Multiverse sword * Announce systems * Stuff and such * TC con * Airlock * doppllllerrrrrr * holopads * Shut up byond you inconsistent fuck * Sneaky fuck * Burp * Bip * Fixnshit * Port without regard * askdlfjs; * asdfjasoidojfi * Protected globals and more * SO MANY * ajsimkvahsaoisd * akfdsiaopwimfeoiwafaw * gsdfigjosidjfgiosdg * AHHHHHHHHHHHHHHHHHHHHHHH!!!!! * facerolll * ASDFASDFASDF * Removes the unused parts of dmm_suite * WIP * Fix quote * asdfjauwfnkjs * afwlunhskjfda * asfjlaiwuefhaf * SO CLOSE * wwwweeeeeewwwww * agdgmoewranwg * HOLY MOTHER OF FUCK AND THATS JUST HALF THE JOB?!? * Fix syntax errors * 100 errors * Another 100 * So many... * Ugh * More shit * kilme * Stuuuuuufffff * ajrgmrlshio;djfa;sdkl * jkbhkhjbmjvjmh * soi soi soi * butt * TODAY WE LEARNED THAT GLOBAL AND STATIC ARE THE EXACT SAME FUCKING THING * lllllllllllllllllllllllllllllllllllllllllll * afsdijfiawhnflnjhnwsdfs * yugykihlugk,kj * time to go * STUFFF!!! * AAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHHHHHHHHHH!!!!!!!!!!!!!!!!!!!!!!! * ngoaijdjlfkamsdlkf * Break time * aufjsdklfalsjfi * CONTROL KAY AND PRAY * IT COMPILEELEELELAKLJFKLDAFJLKFDJLADKJHFLJKAJGAHIEJALDFJ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * Goteem * Fix testing mode * This does not belong in this PR * Convert it to a controller * Eh, fuck this option * Revert controllerization Ill do it some other time * Fix * Working controllerization * FOR THE LOVE OF CHRIST PROTECT THE LOGS * Protect admins and deadmins * Use the inbuilt proc
368 lines
12 KiB
Plaintext
368 lines
12 KiB
Plaintext
/*
|
|
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)
|
|
|
|
*/
|
|
|
|
GLOBAL_LIST_EMPTY(html_interfaces)
|
|
|
|
/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 = "")
|
|
GLOB.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()
|
|
|
|
GLOB.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) |