Nano Is Dead
@@ -19,7 +19,6 @@ data/
|
||||
/_maps/map_files/**/backup/*
|
||||
/_maps/map_files/**/*.dmm.backup
|
||||
/_maps/quicksave/*
|
||||
/nano/debug.html
|
||||
**/__pycache__/*
|
||||
*.db
|
||||
stddef.dm
|
||||
|
||||
@@ -20,7 +20,6 @@ jobs:
|
||||
script:
|
||||
- find . -name "*.php" -print0 | xargs -0 -n1 php -l
|
||||
- find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/travis/json_verifier.py
|
||||
- tools/travis/build_nanoui.sh
|
||||
- tools/travis/build_tgui.sh
|
||||
- tools/travis/check_grep.sh
|
||||
- python3 tools/travis/check_line_endings.py
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#define UNCONSCIOUS 1
|
||||
#define DEAD 2
|
||||
|
||||
// NanoUI & TGUI flags
|
||||
// TGUI flags
|
||||
#define STATUS_INTERACTIVE 2 // GREEN Visability
|
||||
#define STATUS_UPDATE 1 // ORANGE Visability
|
||||
#define STATUS_DISABLED 0 // RED Visability
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
#define FIRE_PRIORITY_PARALLAX 65
|
||||
#define FIRE_PRIORITY_FLIGHTPACKS 80
|
||||
#define FIRE_PRIORITY_MOBS 100
|
||||
#define FIRE_PRIORITY_NANOUI 110
|
||||
#define FIRE_PRIORITY_TGUI 110
|
||||
#define FIRE_PRIORITY_TICKER 200
|
||||
#define FIRE_PRIORITY_RUNECHAT 410 // I hate how high the fire priority on this is -aa
|
||||
#define FIRE_PRIORITY_OVERLAYS 500
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
SUBSYSTEM_DEF(nanoui)
|
||||
name = "Nanoui"
|
||||
wait = 9
|
||||
flags = SS_NO_INIT
|
||||
priority = FIRE_PRIORITY_NANOUI
|
||||
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
|
||||
offline_implications = "All NanoUIs will no longer process. Shuttle call recommended."
|
||||
|
||||
var/list/currentrun = list()
|
||||
var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key.
|
||||
var/list/processing_uis = list() // A list of processing UIs, ungrouped.
|
||||
|
||||
/datum/controller/subsystem/nanoui/Shutdown()
|
||||
close_all_uis()
|
||||
|
||||
/datum/controller/subsystem/nanoui/stat_entry()
|
||||
..("P:[processing_uis.len]")
|
||||
|
||||
/datum/controller/subsystem/nanoui/fire(resumed = 0)
|
||||
if(!resumed)
|
||||
src.currentrun = processing_uis.Copy()
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
|
||||
while(currentrun.len)
|
||||
var/datum/nanoui/ui = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(ui && ui.user && ui.src_object)
|
||||
ui.process()
|
||||
else
|
||||
processing_uis.Remove(ui)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
@@ -9,7 +9,7 @@ SUBSYSTEM_DEF(tgui)
|
||||
name = "TGUI"
|
||||
wait = 9
|
||||
flags = SS_NO_INIT
|
||||
priority = FIRE_PRIORITY_NANOUI // Yes I am aware that this is TGUI and I used the nanoUI fire priority. Dont @ me.
|
||||
priority = FIRE_PRIORITY_TGUI
|
||||
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
|
||||
offline_implications = "All TGUIs will no longer process. Shuttle call recommended."
|
||||
|
||||
|
||||
@@ -533,5 +533,5 @@
|
||||
/**
|
||||
* Return the object that is the host of any UI's that this component has
|
||||
*/
|
||||
/datum/component/nano_host()
|
||||
/datum/component/tgui_host(mob/user)
|
||||
return parent
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
|
||||
|
||||
/*
|
||||
We can't just insert in HTML into the nanoUI so we need the raw data to play with.
|
||||
We can't just insert in HTML into the TGUI so we need the raw data to play with.
|
||||
Instead of creating this list over and over when someone leaves their PDA open to the page
|
||||
we'll only update it when it changes. The PDA_Manifest global list is zeroed out upon any change
|
||||
using /datum/datacore/proc/manifest_inject(), or manifest_insert()
|
||||
|
||||
@@ -100,7 +100,6 @@
|
||||
current.mind = null
|
||||
leave_all_huds() //leave all the huds in the old body, so it won't get huds if somebody else enters it
|
||||
|
||||
SSnanoui.user_transferred(current, new_character)
|
||||
SStgui.on_transfer(current, new_character)
|
||||
|
||||
if(new_character.mind) //remove any mind currently in our new body's mind variable
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
ui.open()
|
||||
ui.set_autoupdate(TRUE)
|
||||
|
||||
/obj/machinery/portable_atmospherics/scrubber/tgui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.physical_state)
|
||||
/obj/machinery/portable_atmospherics/scrubber/tgui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"on" = on,
|
||||
"port_connected" = connected_port ? TRUE : FALSE,
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
ui.open()
|
||||
ui.set_autoupdate(FALSE)
|
||||
|
||||
/obj/machinery/computer/secure_data/tgui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/computer/secure_data/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["currentPage"] = current_page
|
||||
data["isPrinting"] = is_printing
|
||||
|
||||
@@ -315,7 +315,7 @@ Class Procs:
|
||||
update_multitool_menu(usr)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/Topic(href, href_list, var/nowindow = 0, var/datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
if(..(href, href_list, nowindow, state))
|
||||
return 1
|
||||
|
||||
@@ -329,7 +329,7 @@ Class Procs:
|
||||
/obj/machinery/proc/inoperable(var/additional_flags = 0)
|
||||
return (stat & (NOPOWER|BROKEN|additional_flags))
|
||||
|
||||
/obj/machinery/CanUseTopic(var/mob/user)
|
||||
/obj/machinery/tgui_status(mob/user, datum/tgui_state/state)
|
||||
if(!interact_offline && (stat & (NOPOWER|BROKEN)))
|
||||
return STATUS_CLOSE
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
ui.open()
|
||||
|
||||
|
||||
/obj/item/aicard/tgui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.inventory_state)
|
||||
/obj/item/aicard/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
|
||||
var/mob/living/silicon/ai/AI = locate() in src
|
||||
|
||||
@@ -50,14 +50,14 @@
|
||||
else if(!istype(armor, /datum/armor))
|
||||
stack_trace("Invalid type [armor.type] found in .armor during /obj Initialize()")
|
||||
|
||||
/obj/Topic(href, href_list, nowindow = FALSE, datum/topic_state/state = GLOB.default_state)
|
||||
/obj/Topic(href, href_list, nowindow = FALSE, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
// Calling Topic without a corresponding window open causes runtime errors
|
||||
if(!nowindow && ..())
|
||||
return TRUE
|
||||
|
||||
// In the far future no checks are made in an overriding Topic() beyond if(..()) return
|
||||
// Instead any such checks are made in CanUseTopic()
|
||||
if(CanUseTopic(usr, state, href_list) == STATUS_INTERACTIVE)
|
||||
if(tgui_status(usr, state, href_list) == STATUS_INTERACTIVE)
|
||||
CouldUseTopic(usr)
|
||||
return FALSE
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
return TRUE
|
||||
|
||||
/obj/proc/CouldUseTopic(mob/user)
|
||||
var/atom/host = nano_host()
|
||||
var/atom/host = tgui_host()
|
||||
host.add_fingerprint(user)
|
||||
|
||||
/obj/proc/CouldNotUseTopic(mob/user)
|
||||
@@ -77,7 +77,6 @@
|
||||
STOP_PROCESSING(SSobj, src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists
|
||||
else
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
SSnanoui.close_uis(src)
|
||||
SStgui.close_uis(src)
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
if(voice_choice)
|
||||
curse(user)
|
||||
|
||||
/obj/structure/mirror/magic/on_ui_close(mob/user)
|
||||
/obj/structure/mirror/magic/tgui_close(mob/user)
|
||||
curse(user)
|
||||
|
||||
/obj/structure/mirror/magic/attackby(obj/item/I, mob/living/user, params)
|
||||
|
||||
@@ -221,77 +221,10 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
"rook_white.png" = 'icons/chess_pieces/rook_white.png',
|
||||
"sprites.png" = 'icons/chess_pieces/sprites.png',
|
||||
"blank.gif" = 'icons/chess_pieces/blank.gif',
|
||||
"background.png" = 'nano/images/uiBackground.png',
|
||||
"garbochess.js" = 'html/browser/garbochess.js',
|
||||
"boardui.js" = 'html/browser/boardui.js'
|
||||
)
|
||||
|
||||
/datum/asset/simple/headers
|
||||
assets = list(
|
||||
"alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
|
||||
"alarm_red.gif" = 'icons/program_icons/alarm_red.gif',
|
||||
"batt_5.gif" = 'icons/program_icons/batt_5.gif',
|
||||
"batt_20.gif" = 'icons/program_icons/batt_20.gif',
|
||||
"batt_40.gif" = 'icons/program_icons/batt_40.gif',
|
||||
"batt_60.gif" = 'icons/program_icons/batt_60.gif',
|
||||
"batt_80.gif" = 'icons/program_icons/batt_80.gif',
|
||||
"batt_100.gif" = 'icons/program_icons/batt_100.gif',
|
||||
"charging.gif" = 'icons/program_icons/charging.gif',
|
||||
"downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif',
|
||||
"downloader_running.gif" = 'icons/program_icons/downloader_running.gif',
|
||||
"ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif',
|
||||
"ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif',
|
||||
"power_norm.gif" = 'icons/program_icons/power_norm.gif',
|
||||
"power_warn.gif" = 'icons/program_icons/power_warn.gif',
|
||||
"sig_high.gif" = 'icons/program_icons/sig_high.gif',
|
||||
"sig_low.gif" = 'icons/program_icons/sig_low.gif',
|
||||
"sig_lan.gif" = 'icons/program_icons/sig_lan.gif',
|
||||
"sig_none.gif" = 'icons/program_icons/sig_none.gif',
|
||||
"smmon_0.gif" = 'icons/program_icons/smmon_0.gif',
|
||||
"smmon_1.gif" = 'icons/program_icons/smmon_1.gif',
|
||||
"smmon_2.gif" = 'icons/program_icons/smmon_2.gif',
|
||||
"smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
|
||||
"smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
|
||||
"smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
|
||||
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
|
||||
)
|
||||
|
||||
/datum/asset/nanoui
|
||||
var/list/common = list()
|
||||
|
||||
var/list/common_dirs = list(
|
||||
"nano/assets/",
|
||||
"nano/codemirror/",
|
||||
"nano/layouts/"
|
||||
)
|
||||
var/list/uncommon_dirs = list(
|
||||
"nano/templates/"
|
||||
)
|
||||
|
||||
/datum/asset/nanoui/register()
|
||||
// Crawl the directories to find files.
|
||||
for(var/path in common_dirs)
|
||||
var/list/filenames = flist(path)
|
||||
for(var/filename in filenames)
|
||||
if(copytext(filename, length(filename)) != "/") // Ignore directories.
|
||||
if(fexists(path + filename))
|
||||
common[filename] = fcopy_rsc(path + filename)
|
||||
register_asset(filename, common[filename])
|
||||
for(var/path in uncommon_dirs)
|
||||
var/list/filenames = flist(path)
|
||||
for(var/filename in filenames)
|
||||
if(copytext(filename, length(filename)) != "/") // Ignore directories.
|
||||
if(fexists(path + filename))
|
||||
register_asset(filename, fcopy_rsc(path + filename))
|
||||
|
||||
/datum/asset/nanoui/send(client, uncommon)
|
||||
if(!islist(uncommon))
|
||||
uncommon = list(uncommon)
|
||||
|
||||
send_asset_list(client, uncommon)
|
||||
send_asset_list(client, common)
|
||||
|
||||
|
||||
//Pill sprites for UIs
|
||||
/datum/asset/chem_master
|
||||
var/assets = list()
|
||||
|
||||
@@ -60,8 +60,6 @@
|
||||
var/karma_spent = 0
|
||||
var/karma_tab = 0
|
||||
|
||||
var/topic_debugging = 0 //if set to true, allows client to see nanoUI errors -- yes i realize this is messy but it'll make live testing infinitely easier
|
||||
|
||||
control_freak = CONTROL_FREAK_ALL | CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS
|
||||
|
||||
var/ip_intel = "Disabled"
|
||||
|
||||
@@ -51,12 +51,6 @@
|
||||
to_chat(world, "[src]'s Topic: [href] destined for [hsrc].")
|
||||
#endif
|
||||
|
||||
if(href_list["nano_err"]) //nano throwing errors
|
||||
if(topic_debugging)
|
||||
to_chat(src, "## NanoUI: " + html_decode(href_list["nano_err"]))//NANO DEBUG HOOK
|
||||
|
||||
|
||||
|
||||
if(href_list["asset_cache_confirm_arrival"])
|
||||
// to_chat(src, "ASSET JOB [href_list["asset_cache_confirm_arrival"]] ARRIVED.")
|
||||
var/job = text2num(href_list["asset_cache_confirm_arrival"])
|
||||
@@ -834,7 +828,7 @@
|
||||
preload_rsc = 1 // If config.resource_urls is not set, preload like normal.
|
||||
// Most assets are now handled through global_cache.dm
|
||||
getFiles(
|
||||
'html/search.js', // Used in various non-NanoUI HTML windows for search functionality
|
||||
'html/search.js', // Used in various non-TGUI HTML windows for search functionality
|
||||
'html/panels.css' // Used for styling certain panels, such as in the new player panel
|
||||
)
|
||||
spawn (10) //removing this spawn causes all clients to not get verbs.
|
||||
@@ -955,18 +949,15 @@
|
||||
to_chat(usr, "<span class='warning'>You requested your UI resource files too quickly. Please try again in [(last_ui_resource_send - world.time)/10] seconds.</span>")
|
||||
return
|
||||
|
||||
var/choice = alert(usr, "This will reload your NanoUI and TGUI resources. If you have any open UIs this may break them. Are you sure?", "Resource Reloading", "Yes", "No")
|
||||
var/choice = alert(usr, "This will reload your TGUI resources. If you have any open UIs this may break them. Are you sure?", "Resource Reloading", "Yes", "No")
|
||||
if(choice == "Yes")
|
||||
// 600 deciseconds = 1 minute
|
||||
last_ui_resource_send = world.time + 60 SECONDS
|
||||
|
||||
// Close their open UIs
|
||||
SSnanoui.close_user_uis(usr)
|
||||
SStgui.close_user_uis(usr)
|
||||
|
||||
// Resend the resources
|
||||
var/datum/asset/nano_assets = get_asset_datum(/datum/asset/nanoui)
|
||||
nano_assets.register()
|
||||
|
||||
var/datum/asset/tgui_assets = get_asset_datum(/datum/asset/simple/tgui)
|
||||
tgui_assets.register()
|
||||
|
||||
@@ -450,7 +450,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
dat += "<b>Deadchat Anonymity:</b> <a href='?_src_=prefs;preference=ghost_anonsay'><b>[toggles2 & PREFTOGGLE_2_ANONDCHAT ? "Anonymous" : "Not Anonymous"]</b></a><br>"
|
||||
if(user.client.donator_level > 0)
|
||||
dat += "<b>Donator Publicity:</b> <a href='?_src_=prefs;preference=donor_public'><b>[(toggles & PREFTOGGLE_DONATOR_PUBLIC) ? "Public" : "Hidden"]</b></a><br>"
|
||||
dat += "<b>Fancy NanoUI:</b> <a href='?_src_=prefs;preference=nanoui'>[(toggles2 & PREFTOGGLE_2_FANCYUI) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Fancy TGUI:</b> <a href='?_src_=prefs;preference=tgui'>[(toggles2 & PREFTOGGLE_2_FANCYUI) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>FPS:</b> <a href='?_src_=prefs;preference=clientfps;task=input'>[clientfps]</a><br>"
|
||||
dat += "<b>Ghost Ears:</b> <a href='?_src_=prefs;preference=ghost_ears'><b>[(toggles & PREFTOGGLE_CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]</b></a><br>"
|
||||
dat += "<b>Ghost Radio:</b> <a href='?_src_=prefs;preference=ghost_radio'><b>[(toggles & PREFTOGGLE_CHAT_GHOSTRADIO) ? "All Chatter" : "Nearest Speakers"]</b></a><br>"
|
||||
@@ -2001,7 +2001,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
var/mob/living/carbon/human/H = usr
|
||||
H.remake_hud()
|
||||
|
||||
if("nanoui")
|
||||
if("tgui")
|
||||
toggles2 ^= PREFTOGGLE_2_FANCYUI
|
||||
|
||||
if("ghost_att_anim")
|
||||
|
||||
@@ -304,7 +304,7 @@
|
||||
ui.open()
|
||||
|
||||
/datum/personal_crafting/proc/close(mob/user)
|
||||
var/datum/nanoui/ui = SStgui.get_open_ui(user, src, "main")
|
||||
var/datum/tgui/ui = SStgui.get_open_ui(user, src, "main")
|
||||
if(ui)
|
||||
ui.close()
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ log transactions
|
||||
linked_db = null
|
||||
authenticated_account = null
|
||||
visible_message("[bicon(src)]<span class='warning'>[src] buzzes rudely, \"Connection to remote database lost.\"</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
if(ticks_left_timeout > 0)
|
||||
ticks_left_timeout--
|
||||
@@ -91,7 +91,7 @@ log transactions
|
||||
held_card = I
|
||||
if(authenticated_account && held_card.associated_account_number != authenticated_account.account_number)
|
||||
authenticated_account = null
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
else if(authenticated_account)
|
||||
if(istype(I, /obj/item/stack/spacecash))
|
||||
//consume the money
|
||||
@@ -103,7 +103,7 @@ log transactions
|
||||
authenticated_account.credit(C.amount, "Credit deposit", machine_id, authenticated_account.owner_name)
|
||||
|
||||
to_chat(user, "<span class='info'>You insert [C] into [src].</span>")
|
||||
SSnanoui.update_uis(src)
|
||||
SStgui.update_uis(src)
|
||||
C.use(C.amount)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -64,7 +64,7 @@ GLOBAL_VAR(current_date_string)
|
||||
ui = new(user, src, ui_key, "AccountsUplinkTerminal", name, 800, 600, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/account_database/tgui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
/obj/machinery/computer/account_database/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["currentPage"] = current_page
|
||||
data["is_printing"] = (next_print > world.time)
|
||||
|
||||
@@ -58,10 +58,10 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
|
||||
transfer_fingerprints_to(M)
|
||||
|
||||
/obj/item/stack/marker_beacon/AltClick(mob/living/user)
|
||||
if(!istype(user) || CanUseTopic(user, GLOB.physical_state) != STATUS_INTERACTIVE)
|
||||
if(!istype(user) || tgui_status(user, GLOB.tgui_physical_state) != STATUS_INTERACTIVE)
|
||||
return
|
||||
var/input_color = input(user, "Choose a color.", "Beacon Color") as null|anything in GLOB.marker_beacon_colors
|
||||
if(!istype(user) || CanUseTopic(user, GLOB.physical_state) != STATUS_INTERACTIVE)
|
||||
if(!istype(user) || tgui_status(user, GLOB.tgui_physical_state) != STATUS_INTERACTIVE)
|
||||
return
|
||||
if(input_color)
|
||||
picked_color = input_color
|
||||
@@ -130,10 +130,10 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
|
||||
|
||||
/obj/structure/marker_beacon/AltClick(mob/living/user)
|
||||
..()
|
||||
if(!istype(user) || CanUseTopic(user, GLOB.physical_state) != STATUS_INTERACTIVE)
|
||||
if(!istype(user) || tgui_status(user, GLOB.tgui_physical_state) != STATUS_INTERACTIVE)
|
||||
return
|
||||
var/input_color = input(user, "Choose a color.", "Beacon Color") as null|anything in GLOB.marker_beacon_colors
|
||||
if(!istype(user) || CanUseTopic(user, GLOB.physical_state) != STATUS_INTERACTIVE)
|
||||
if(!istype(user) || tgui_status(user, GLOB.tgui_physical_state) != STATUS_INTERACTIVE)
|
||||
return
|
||||
if(input_color)
|
||||
picked_color = input_color
|
||||
|
||||
@@ -31,16 +31,15 @@
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/machinery/mineral/processing_unit_console/attack_ghost(mob/user)
|
||||
return ui_interact(user)
|
||||
return open_ui(user)
|
||||
|
||||
/obj/machinery/mineral/processing_unit_console/attack_hand(mob/user)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
return ui_interact(user)
|
||||
return open_ui(user)
|
||||
|
||||
/obj/machinery/mineral/processing_unit_console/ui_interact(mob/user)
|
||||
. = ..()
|
||||
/obj/machinery/mineral/processing_unit_console/proc/open_ui(mob/user)
|
||||
if(!machine)
|
||||
return
|
||||
|
||||
|
||||
@@ -278,18 +278,8 @@
|
||||
return 1
|
||||
|
||||
// As a synthetic, the only limit on visibility is view range
|
||||
/obj/item/mmi/contents_nano_distance(var/src_object, var/mob/living/user)
|
||||
/obj/item/mmi/contents_tgui_distance(src_object, mob/living/user)
|
||||
. = ..()
|
||||
if((src_object in view(src)) && get_dist(src_object, src) <= user.client.view)
|
||||
return STATUS_INTERACTIVE // interactive (green visibility)
|
||||
return user.shared_living_nano_distance(src_object)
|
||||
|
||||
// For now the only thing that is helped by this is radio access
|
||||
// Later a more intricate system for MMI UI interaction can be established
|
||||
/obj/item/mmi/contents_nano_interact(var/src_object, var/mob/living/user)
|
||||
if(!istype(user, /mob/living/carbon/brain))
|
||||
log_runtime(EXCEPTION("Somehow a non-brain mob is inside an MMI!"), user)
|
||||
return ..()
|
||||
var/mob/living/carbon/brain/BM = user
|
||||
if(BM.container == src && src_object == radio)
|
||||
return STATUS_INTERACTIVE
|
||||
return ..()
|
||||
return user.shared_living_tgui_distance()
|
||||
|
||||
@@ -455,7 +455,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
notify_ai(2)
|
||||
|
||||
uneq_all()
|
||||
SSnanoui.close_user_uis(src)
|
||||
SStgui.close_user_uis(src)
|
||||
sight_mode = null
|
||||
update_sight()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/mob/Logout()
|
||||
SSnanoui.user_logout(src) // this is used to clean up (remove) this user's Nano UIs
|
||||
SStgui.on_logout(src) // Cleanup any TGUIs the user has open
|
||||
unset_machine()
|
||||
GLOB.player_list -= src
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/*
|
||||
This state checks that the user is an admin, end of story
|
||||
*/
|
||||
GLOBAL_DATUM_INIT(admin_state, /datum/topic_state/admin_state, new())
|
||||
|
||||
/datum/topic_state/admin_state/can_use_topic(var/src_object, var/mob/user)
|
||||
return check_rights(R_ADMIN, 0, user) ? STATUS_INTERACTIVE : STATUS_CLOSE
|
||||
@@ -1,41 +0,0 @@
|
||||
/datum/proc/nano_host()
|
||||
return src
|
||||
|
||||
/datum/proc/CanUseTopic(var/mob/user, var/datum/topic_state/state)
|
||||
var/src_object = nano_host()
|
||||
return state.can_use_topic(src_object, user)
|
||||
|
||||
/datum/topic_state/proc/href_list(var/mob/user)
|
||||
return list()
|
||||
|
||||
/datum/topic_state/proc/can_use_topic(var/src_object, var/mob/user)
|
||||
return STATUS_CLOSE
|
||||
|
||||
/mob/proc/shared_nano_interaction()
|
||||
if(stat || !client)
|
||||
return STATUS_CLOSE // no updates, close the interface
|
||||
else if(incapacitated())
|
||||
return STATUS_UPDATE // update only (orange visibility)
|
||||
return STATUS_INTERACTIVE
|
||||
|
||||
/mob/dead/observer/shared_nano_interaction()
|
||||
if(check_rights(R_ADMIN, 0, src))
|
||||
return STATUS_INTERACTIVE // Admins are more equal
|
||||
return STATUS_UPDATE // Ghosts can view updates
|
||||
|
||||
/mob/living/silicon/ai/shared_nano_interaction()
|
||||
if(apc_override)
|
||||
return STATUS_INTERACTIVE
|
||||
if(lacks_power())
|
||||
return STATUS_CLOSE
|
||||
if(check_unable(1, 0))
|
||||
return STATUS_CLOSE
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/shared_nano_interaction()
|
||||
. = STATUS_INTERACTIVE
|
||||
if(!cell || cell.charge <= 0)
|
||||
return STATUS_CLOSE
|
||||
if(lockcharge)
|
||||
. = STATUS_DISABLED
|
||||
return min(., ..())
|
||||
@@ -1,7 +0,0 @@
|
||||
/*
|
||||
This state only checks if user is conscious.
|
||||
*/
|
||||
GLOBAL_DATUM_INIT(conscious_state, /datum/topic_state/conscious_state, new())
|
||||
|
||||
/datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user)
|
||||
return user.stat == CONSCIOUS ? STATUS_INTERACTIVE : STATUS_CLOSE
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
This state checks if user is somewhere within src_object, as well as the default NanoUI interaction.
|
||||
*/
|
||||
GLOBAL_DATUM_INIT(contained_state, /datum/topic_state/contained_state, new())
|
||||
|
||||
/datum/topic_state/contained_state/can_use_topic(var/atom/src_object, var/mob/user)
|
||||
if(!src_object.contains(user))
|
||||
return STATUS_CLOSE
|
||||
|
||||
return user.shared_nano_interaction()
|
||||
|
||||
/atom/proc/contains(var/atom/location)
|
||||
if(!location)
|
||||
return 0
|
||||
if(location == src)
|
||||
return 1
|
||||
|
||||
return contains(location.loc)
|
||||
@@ -1,119 +0,0 @@
|
||||
GLOBAL_DATUM_INIT(default_state, /datum/topic_state/default, new())
|
||||
|
||||
/datum/topic_state/default/href_list(var/mob/user)
|
||||
return list()
|
||||
|
||||
/datum/topic_state/default/can_use_topic(var/src_object, var/mob/user)
|
||||
return user.default_can_use_topic(src_object)
|
||||
|
||||
/mob/proc/default_can_use_topic(var/src_object)
|
||||
return STATUS_CLOSE // By default no mob can do anything with NanoUI
|
||||
|
||||
/mob/dead/observer/default_can_use_topic()
|
||||
if(can_admin_interact())
|
||||
return STATUS_INTERACTIVE // Admins are more equal
|
||||
return STATUS_UPDATE // Ghosts can view updates
|
||||
|
||||
/mob/living/silicon/pai/default_can_use_topic(var/src_object)
|
||||
if((src_object == src || src_object == radio) && stat == CONSCIOUS)
|
||||
return STATUS_INTERACTIVE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/default_can_use_topic(var/src_object)
|
||||
. = shared_nano_interaction()
|
||||
if(. <= STATUS_DISABLED)
|
||||
return
|
||||
|
||||
// robots can interact with things they can see within their view range
|
||||
if((src_object in view(src)) && get_dist(src_object, src) <= src.client.view)
|
||||
return STATUS_INTERACTIVE // interactive (green visibility)
|
||||
return STATUS_DISABLED // no updates, completely disabled (red visibility)
|
||||
|
||||
/mob/living/silicon/ai/default_can_use_topic(var/src_object)
|
||||
. = shared_nano_interaction()
|
||||
// Fix the weird hacking blurb to actually let them restore power
|
||||
if(aiRestorePowerRoutine == 3 && istype(src_object, /obj/machinery/power/apc))
|
||||
return STATUS_INTERACTIVE
|
||||
if(. != STATUS_INTERACTIVE)
|
||||
return
|
||||
|
||||
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
|
||||
// unless it's on the same level as the object it's interacting with.
|
||||
var/turf/T = get_turf(src_object)
|
||||
if(!T || !(atoms_share_level(src,T) || is_level_reachable(T.z)))
|
||||
return STATUS_CLOSE
|
||||
|
||||
// If an object is in view then we can interact with it
|
||||
if(src_object in view(client.view, src))
|
||||
return STATUS_INTERACTIVE
|
||||
|
||||
// If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
|
||||
if(is_in_chassis())
|
||||
//stop AIs from leaving windows open and using then after they lose vision
|
||||
if(GLOB.cameranet && !GLOB.cameranet.checkTurfVis(get_turf(src_object)))
|
||||
return STATUS_CLOSE
|
||||
return STATUS_INTERACTIVE
|
||||
else if(get_dist(src_object, src) <= client.view) // View does not return what one would expect while installed in an inteliCard
|
||||
return STATUS_INTERACTIVE
|
||||
|
||||
return STATUS_CLOSE
|
||||
|
||||
//Some atoms such as vehicles might have special limitations for how mobs inside them interact with NanoUI.
|
||||
/atom/proc/contents_nano_distance(var/src_object, var/mob/living/user)
|
||||
return user.shared_living_nano_distance(src_object)
|
||||
|
||||
//Some atoms such as vehicles might have special benefits for how mobs inside them interact with NanoUI.
|
||||
/atom/proc/contents_nano_interact(var/src_object, var/mob/living/user)
|
||||
return STATUS_CLOSE // No help at all by default
|
||||
|
||||
/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
|
||||
if(!(src_object in view(4, src))) // If the src object is not in visable, disable updates
|
||||
return STATUS_CLOSE
|
||||
|
||||
var/dist = get_dist(src_object, src)
|
||||
if(dist <= 1)
|
||||
return STATUS_INTERACTIVE // interactive (green visibility)
|
||||
else if(dist <= 2)
|
||||
return STATUS_UPDATE // update only (orange visibility)
|
||||
else if(dist <= 4)
|
||||
return STATUS_DISABLED // no updates, completely disabled (red visibility)
|
||||
return STATUS_CLOSE
|
||||
|
||||
/mob/living/default_can_use_topic(var/src_object)
|
||||
. = shared_nano_interaction(src_object)
|
||||
if(. != STATUS_CLOSE)
|
||||
if(loc)
|
||||
. = min(., loc.contents_nano_distance(src_object, src))
|
||||
if(. == STATUS_INTERACTIVE)
|
||||
return STATUS_UPDATE
|
||||
|
||||
/mob/living/carbon/brain/default_can_use_topic(var/src_object)
|
||||
. = shared_nano_interaction(src_object)
|
||||
if(. <= STATUS_DISABLED)
|
||||
return
|
||||
// Maybe add a handler here to call an "interaction state" thing on the MMI,
|
||||
// later
|
||||
if(loc)
|
||||
. = max(., loc.contents_nano_interact(src_object, src)) // This is an "augment" on interaction
|
||||
. = min(., loc.contents_nano_distance(src_object, src)) // This is a "limit" on interaction
|
||||
|
||||
/mob/living/carbon/human/default_can_use_topic(var/src_object)
|
||||
. = shared_nano_interaction(src_object)
|
||||
if(. != STATUS_CLOSE)
|
||||
. = min(., shared_living_nano_distance(src_object))
|
||||
if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction.
|
||||
return STATUS_INTERACTIVE
|
||||
|
||||
/mob/living/carbon/alien/default_can_use_topic(var/src_object)
|
||||
. = shared_nano_interaction(src_object)
|
||||
if(. != STATUS_CLOSE)
|
||||
. = min(., shared_living_nano_distance(src_object))
|
||||
if(!IsAdvancedToolUser())
|
||||
. = STATUS_CLOSE
|
||||
|
||||
/mob/living/simple_animal/bot/default_can_use_topic(var/src_object)
|
||||
. = shared_nano_interaction(src_object)
|
||||
if(. != STATUS_CLOSE)
|
||||
if(!(src_object in contents))
|
||||
. = STATUS_CLOSE
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
This checks that the user is a ghost or alternatively an admin. Used for the mob spawner.
|
||||
We don't want any living people somehow getting the menu open and reincarnating while alive
|
||||
*/
|
||||
|
||||
GLOBAL_DATUM_INIT(ghost_state, /datum/topic_state/ghost_state, new())
|
||||
|
||||
/datum/topic_state/ghost_state/can_use_topic(var/src_object, var/mob/user)
|
||||
if(user.stat == DEAD)
|
||||
return STATUS_INTERACTIVE
|
||||
if(check_rights(R_ADMIN, 0, src))
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
This state checks that the src_object is somewhere in the user's first-level inventory (in hands, on ear, etc.), but not further down (such as in bags).
|
||||
*/
|
||||
GLOBAL_DATUM_INIT(inventory_state, /datum/topic_state/inventory_state, new())
|
||||
|
||||
/datum/topic_state/inventory_state/can_use_topic(var/src_object, var/mob/user)
|
||||
if(!((src_object in user) || user.is_in_active_hand(src_object) || user.is_in_inactive_hand(src_object)))
|
||||
return STATUS_CLOSE
|
||||
|
||||
return user.shared_nano_interaction()
|
||||
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
This state checks if src_object is contained anywhere in the user's inventory, including bags, etc.
|
||||
*/
|
||||
GLOBAL_DATUM_INIT(deep_inventory_state, /datum/topic_state/deep_inventory_state, new())
|
||||
|
||||
/datum/topic_state/deep_inventory_state/can_use_topic(var/src_object, var/mob/user)
|
||||
if(!user.contains(src_object))
|
||||
return STATUS_CLOSE
|
||||
|
||||
return user.shared_nano_interaction()
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* This state only checks if the user isn't incapacitated
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(not_incapacitated_state, /datum/topic_state/not_incapacitated_state, new())
|
||||
|
||||
/**
|
||||
* This state checks if the user isn't incapacitated and that their loc is a turf
|
||||
**/
|
||||
GLOBAL_DATUM_INIT(not_incapacitated_turf_state, /datum/topic_state/not_incapacitated_state, new(no_turfs = TRUE))
|
||||
|
||||
/datum/topic_state/not_incapacitated_state
|
||||
var/turf_check = FALSE
|
||||
|
||||
/datum/topic_state/not_incapacitated_state/New(loc, no_turfs = FALSE)
|
||||
..()
|
||||
turf_check = no_turfs
|
||||
|
||||
/datum/topic_state/not_incapacitated_state/can_use_topic(src_object, mob/user)
|
||||
if(user.stat)
|
||||
return STATUS_CLOSE
|
||||
if(user.incapacitated() || user.lying || (turf_check && !isturf(user.loc)))
|
||||
return STATUS_DISABLED
|
||||
return STATUS_INTERACTIVE
|
||||
@@ -1,18 +0,0 @@
|
||||
GLOBAL_DATUM_INIT(physical_state, /datum/topic_state/physical, new())
|
||||
|
||||
/datum/topic_state/physical/can_use_topic(var/src_object, var/mob/user)
|
||||
. = user.shared_nano_interaction(src_object)
|
||||
if(. > STATUS_CLOSE)
|
||||
return min(., user.check_physical_distance(src_object))
|
||||
|
||||
/mob/proc/check_physical_distance(var/src_object)
|
||||
return STATUS_CLOSE
|
||||
|
||||
/mob/dead/observer/check_physical_distance(var/src_object)
|
||||
return default_can_use_topic(src_object)
|
||||
|
||||
/mob/living/check_physical_distance(var/src_object)
|
||||
return shared_living_nano_distance(src_object)
|
||||
|
||||
/mob/living/silicon/check_physical_distance(var/src_object)
|
||||
return max(STATUS_UPDATE, shared_living_nano_distance(src_object))
|
||||
@@ -1,9 +0,0 @@
|
||||
/*
|
||||
This state checks that the src_object is the same the as user
|
||||
*/
|
||||
GLOBAL_DATUM_INIT(self_state, /datum/topic_state/self_state, new())
|
||||
|
||||
/datum/topic_state/self_state/can_use_topic(var/src_object, var/mob/user)
|
||||
if(src_object != user)
|
||||
return STATUS_CLOSE
|
||||
return user.shared_nano_interaction()
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
This state checks that the user is on the same Z-level as src_object
|
||||
*/
|
||||
|
||||
GLOBAL_DATUM_INIT(z_state, /datum/topic_state/z_state, new())
|
||||
|
||||
/datum/topic_state/z_state/can_use_topic(var/src_object, var/mob/user)
|
||||
var/turf/turf_obj = get_turf(src_object)
|
||||
var/turf/turf_usr = get_turf(user)
|
||||
if(!turf_obj || !turf_usr)
|
||||
return STATUS_CLOSE
|
||||
|
||||
return turf_obj.z == turf_usr.z ? STATUS_INTERACTIVE : STATUS_CLOSE
|
||||
@@ -1,16 +0,0 @@
|
||||
/datum/nano_module
|
||||
var/name
|
||||
var/datum/host
|
||||
|
||||
/datum/nano_module/New(var/host)
|
||||
src.host = host
|
||||
|
||||
/datum/nano_module/nano_host()
|
||||
return host ? host : src
|
||||
|
||||
/datum/nano_module/on_ui_close(mob/user)
|
||||
if(host)
|
||||
host.on_ui_close(user)
|
||||
|
||||
/datum/nano_module/proc/can_still_topic(var/datum/topic_state/state = GLOB.default_state)
|
||||
return CanUseTopic(usr, state) == STATUS_INTERACTIVE
|
||||
@@ -1,64 +0,0 @@
|
||||
// This file contains all Nano procs/definitions for external classes/objects
|
||||
|
||||
/**
|
||||
* Called when a Nano UI window is closed
|
||||
* This is how Nano handles closed windows
|
||||
* It must be a verb so that it can be called using winset
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/client/verb/nanoclose(var/uiref as text)
|
||||
set hidden = 1 // hide this verb from the user's panel
|
||||
set name = "nanoclose"
|
||||
|
||||
var/datum/nanoui/ui = locate(uiref)
|
||||
|
||||
if(istype(ui))
|
||||
ui.close()
|
||||
|
||||
if(ui.ref)
|
||||
var/href = "close=1"
|
||||
src.Topic(href, params2list(href), ui.ref) // this will direct to the atom's Topic() proc via client.Topic()
|
||||
else if(ui.on_close_logic)
|
||||
// no atomref specified (or not found)
|
||||
// so just reset the user mob's machine var
|
||||
if(src && src.mob)
|
||||
src.mob.unset_machine()
|
||||
|
||||
/**
|
||||
* The ui_interact proc is used to open and update Nano UIs
|
||||
* If ui_interact is not used then the UI will not update correctly
|
||||
* ui_interact is currently defined for /datum
|
||||
*
|
||||
* @param user /mob The mob who is interacting with this ui
|
||||
* @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main")
|
||||
* @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui
|
||||
* @param force_open boolean Force the UI to (re)open, even if it's already open
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
|
||||
return
|
||||
|
||||
/**
|
||||
* The UI-close proc is called when the UI is closed.
|
||||
*
|
||||
* @param user /mob The mob who was interacting with this UI.
|
||||
*/
|
||||
/datum/proc/on_ui_close(mob/user)
|
||||
return
|
||||
|
||||
/**
|
||||
* The ui_data proc is used to get data for the interface
|
||||
*
|
||||
* @param user /mob The mob who is viewing this ui
|
||||
* @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main")
|
||||
* @param state /datum/topic_state Current topic state of the UI
|
||||
*
|
||||
* @return list()
|
||||
*/
|
||||
/datum/proc/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
return list()
|
||||
|
||||
// Used by the Nano UI Manager (/datum/nanomanager) to track UIs opened by this mob
|
||||
/mob/var/list/open_uis = list()
|
||||
@@ -1,532 +0,0 @@
|
||||
/**********************************************************
|
||||
NANO UI FRAMEWORK
|
||||
|
||||
nanoui class (or whatever Byond calls classes)
|
||||
|
||||
nanoui is used to open and update nano browser uis
|
||||
**********************************************************/
|
||||
|
||||
/datum/nanoui
|
||||
// the user who opened this ui
|
||||
var/mob/user
|
||||
// the object this ui "belongs" to
|
||||
var/datum/src_object
|
||||
// the title of this ui
|
||||
var/title
|
||||
// the key of this ui, this is to allow multiple (different) uis for each src_object
|
||||
var/ui_key
|
||||
// window_id is used as the window name/identifier for browse and onclose
|
||||
var/window_id
|
||||
// the browser window width
|
||||
var/width = 0
|
||||
// the browser window height
|
||||
var/height = 0
|
||||
// whether to use extra logic when window closes
|
||||
var/on_close_logic = 1
|
||||
// an extra ref to use when the window is closed, usually null
|
||||
var/atom/ref = null
|
||||
// options for modifying window behaviour
|
||||
var/window_options = "focus=0;can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id
|
||||
// the list of stylesheets to apply to this ui
|
||||
var/list/stylesheets = list()
|
||||
// the list of javascript scripts to use for this ui
|
||||
var/list/scripts = list()
|
||||
// a list of templates which can be used with this ui
|
||||
var/templates[0]
|
||||
// the layout key for this ui (this is used on the frontend, leave it as "default" unless you know what you're doing)
|
||||
var/layout_key = "default"
|
||||
// this sets whether to re-render the ui layout with each update (default 0, turning on will break the map ui if it's in use)
|
||||
var/auto_update_layout = 0
|
||||
// this sets whether to re-render the ui content with each update (default 1)
|
||||
var/auto_update_content = 1
|
||||
// the default state to use for this ui (this is used on the frontend, leave it as "default" unless you know what you're doing)
|
||||
var/state_key = "default"
|
||||
// show the map ui, this is used by the default layout
|
||||
var/show_map = 0
|
||||
// the map z level to display
|
||||
var/map_z_level = 1
|
||||
// initial data, containing the full data structure, must be sent to the ui (the data structure cannot be extended later on)
|
||||
var/list/initial_data = null // Initialize as null for proper ! usage in initial set up
|
||||
// set to 1 to update the ui automatically every master_controller tick
|
||||
var/is_auto_updating = 0
|
||||
// the current status/visibility of the ui
|
||||
var/status = STATUS_INTERACTIVE
|
||||
|
||||
// Relationship between a master interface and its children. Used in update_status
|
||||
var/datum/nanoui/master_ui
|
||||
var/list/datum/nanoui/children = list()
|
||||
var/datum/topic_state/state = null
|
||||
|
||||
/**
|
||||
* Create a new nanoui instance.
|
||||
*
|
||||
* @param nuser /mob The mob who has opened/owns this ui
|
||||
* @param nsrc_object /obj|/mob The obj or mob which this ui belongs to
|
||||
* @param nui_key string A string key to use for this ui. Allows for multiple unique uis on one src_oject
|
||||
* @param ntemplate string The filename of the template file from /nano/templates (e.g. "my_template.tmpl")
|
||||
* @param ntitle string The title of this ui
|
||||
* @param nwidth int the width of the ui window
|
||||
* @param nheight int the height of the ui window
|
||||
* @param nref /atom A custom ref to use if "on_close_logic" is set to 1
|
||||
*
|
||||
* @return /nanoui new nanoui object
|
||||
*/
|
||||
/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = GLOB.default_state)
|
||||
user = nuser
|
||||
src_object = nsrc_object
|
||||
ui_key = nui_key
|
||||
window_id = "[ui_key]\ref[src_object]"
|
||||
|
||||
src.master_ui = master_ui
|
||||
if(master_ui)
|
||||
master_ui.children += src
|
||||
src.state = state
|
||||
|
||||
// add the passed template filename as the "main" template, this is required
|
||||
add_template("main", ntemplate_filename)
|
||||
|
||||
if(ntitle)
|
||||
title = ntitle
|
||||
if(nwidth)
|
||||
width = nwidth
|
||||
if(nheight)
|
||||
height = nheight
|
||||
if(nref)
|
||||
ref = nref
|
||||
|
||||
add_common_assets()
|
||||
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/nanoui)
|
||||
assets.send(user, ntemplate_filename)
|
||||
|
||||
/**
|
||||
* Use this proc to add assets which are common to (and required by) all nano uis
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/add_common_assets()
|
||||
add_script("libraries.min.js") // A JS file comprising of jQuery, doT.js and jQuery Timer libraries (compressed together)
|
||||
add_script("nano.js") // A JS file of the NanoUI JavaScript compressed into one file.
|
||||
add_stylesheet("nanoui.css") // Concatenated CSS sheet common to all UIs, contains all of the standard NanoUI styling.
|
||||
|
||||
// CodeMirror
|
||||
add_script("codemirror-compressed.js") // A custom minified JavaScript file of CodeMirror, with the following plugins: CSS Mode, NTSL Mode, CSS-hint addon, Search addon, Sublime Keymap.
|
||||
|
||||
/**
|
||||
* Set the current status (also known as visibility) of this ui.
|
||||
*
|
||||
* @param state int The status to set, see the defines at the top of this file
|
||||
* @param push_update int (bool) Push an update to the ui to update it's status (an update is always sent if the status has changed to red (0))
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/set_status(state, push_update)
|
||||
if(state != status) // Only update if it is different
|
||||
if(status == STATUS_DISABLED)
|
||||
status = state
|
||||
if(push_update)
|
||||
update()
|
||||
else
|
||||
status = state
|
||||
if(push_update || status == 0)
|
||||
push_data(null, 1) // Update the UI, force the update in case the status is 0, data is null so that previous data is used
|
||||
|
||||
/**
|
||||
* Update the status (visibility) of this ui based on the user's status
|
||||
*
|
||||
* @param push_update int (bool) Push an update to the ui to update it's status. This is set to 0/false if an update is going to be pushed anyway (to avoid unnessary updates)
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/update_status(var/push_update = 0)
|
||||
var/new_status = src_object.CanUseTopic(user, state)
|
||||
if(master_ui)
|
||||
new_status = min(new_status, master_ui.status)
|
||||
|
||||
set_status(new_status, push_update)
|
||||
if(new_status == STATUS_CLOSE)
|
||||
close()
|
||||
|
||||
/**
|
||||
* Set the ui to auto update (every master_controller tick)
|
||||
*
|
||||
* @param state int (bool) Set auto update to 1 or 0 (true/false)
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/set_auto_update(nstate = 1)
|
||||
is_auto_updating = nstate
|
||||
|
||||
/**
|
||||
* Set the initial data for the ui. This is vital as the data structure set here cannot be changed when pushing new updates.
|
||||
*
|
||||
* @param data /list The list of data for this ui
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/set_initial_data(list/data)
|
||||
initial_data = data
|
||||
|
||||
/**
|
||||
* Get config data to sent to the ui.
|
||||
*
|
||||
* @return /list config data
|
||||
*/
|
||||
/datum/nanoui/proc/get_config_data()
|
||||
var/name = "[src_object]"
|
||||
var/list/config_data = list(
|
||||
"title" = title,
|
||||
"map" = (GLOB.using_map && GLOB.using_map.name) ? GLOB.using_map.name : "Unknown",
|
||||
"srcObject" = list("name" = name),
|
||||
"stateKey" = state_key,
|
||||
"status" = status,
|
||||
"autoUpdateLayout" = auto_update_layout,
|
||||
"autoUpdateContent" = auto_update_content,
|
||||
"showMap" = show_map,
|
||||
"mapZLevel" = map_z_level,
|
||||
"user" = list(
|
||||
"name" = user.name,
|
||||
"fancy" = user.client.prefs.toggles2 & PREFTOGGLE_2_FANCYUI
|
||||
),
|
||||
"window" = list(
|
||||
"width" = width,
|
||||
"height" = height,
|
||||
"ref" = window_id
|
||||
)
|
||||
)
|
||||
return config_data
|
||||
|
||||
/**
|
||||
* Get data to sent to the ui.
|
||||
*
|
||||
* @param data /list The list of general data for this ui (can be null to use previous data sent)
|
||||
*
|
||||
* @return /list data to send to the ui
|
||||
*/
|
||||
/datum/nanoui/proc/get_send_data(var/list/data)
|
||||
var/list/config_data = get_config_data()
|
||||
|
||||
var/list/send_data = list("config" = config_data)
|
||||
|
||||
if(!isnull(data))
|
||||
send_data["data"] = data
|
||||
|
||||
return send_data
|
||||
|
||||
/**
|
||||
* Set the browser window options for this ui
|
||||
*
|
||||
* @param nwindow_options string The new window options
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/set_window_options(nwindow_options)
|
||||
window_options = nwindow_options
|
||||
|
||||
/**
|
||||
* Add a CSS stylesheet to this UI
|
||||
* These must be added before the UI has been opened, adding after that will have no effect
|
||||
*
|
||||
* @param file string The name of the CSS file from /nano/css (e.g. "my_style.css")
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/add_stylesheet(file)
|
||||
stylesheets.Add(file)
|
||||
|
||||
/**
|
||||
* Add a JavsScript script to this UI
|
||||
* These must be added before the UI has been opened, adding after that will have no effect
|
||||
*
|
||||
* @param file string The name of the JavaScript file from /nano/js (e.g. "my_script.js")
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/add_script(file)
|
||||
scripts.Add(file)
|
||||
|
||||
/**
|
||||
* Add a template for this UI
|
||||
* Templates are combined with the data sent to the UI to create the rendered view
|
||||
* These must be added before the UI has been opened, adding after that will have no effect
|
||||
*
|
||||
* @param key string The key which is used to reference this template in the frontend
|
||||
* @param filename string The name of the template file from /nano/templates (e.g. "my_template.tmpl")
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/add_template(key, filename)
|
||||
templates[key] = filename
|
||||
|
||||
/**
|
||||
* Set the layout key for use in the frontend Javascript
|
||||
* The layout key is the basic layout key for the page
|
||||
* Two files are loaded on the client based on the layout key varable:
|
||||
* -> a template in /nano/templates with the filename "layout_<layout_key>.tmpl
|
||||
* -> a CSS stylesheet in /nano/css with the filename "layout_<layout_key>.css
|
||||
*
|
||||
* @param nlayout string The layout key to use
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/set_layout_key(nlayout_key)
|
||||
layout_key = lowertext(nlayout_key)
|
||||
|
||||
/**
|
||||
* Set the ui to update the layout (re-render it) on each update, turning this on will break the map ui (if it's being used)
|
||||
*
|
||||
* @param state int (bool) Set update to 1 or 0 (true/false) (default 0)
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/set_auto_update_layout(nstate)
|
||||
auto_update_layout = nstate
|
||||
|
||||
/**
|
||||
* Set the ui to update the main content (re-render it) on each update
|
||||
*
|
||||
* @param state int (bool) Set update to 1 or 0 (true/false) (default 1)
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/set_auto_update_content(nstate)
|
||||
auto_update_content = nstate
|
||||
|
||||
/**
|
||||
* Set the state key for use in the frontend Javascript
|
||||
*
|
||||
* @param nstate_key string The key of the state to use
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/set_state_key(nstate_key)
|
||||
state_key = nstate_key
|
||||
|
||||
/**
|
||||
* Toggle showing the map ui
|
||||
*
|
||||
* @param nstate_key boolean 1 to show map, 0 to hide (default is 0)
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/set_show_map(nstate)
|
||||
show_map = nstate
|
||||
|
||||
/**
|
||||
* Toggle showing the map ui
|
||||
*
|
||||
* @param nstate_key boolean 1 to show map, 0 to hide (default is 0)
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/set_map_z_level(nz)
|
||||
map_z_level = nz
|
||||
|
||||
/**
|
||||
* Set whether or not to use the "old" on close logic (mainly unset_machine())
|
||||
*
|
||||
* @param state int (bool) Set on_close_logic to 1 or 0 (true/false)
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/use_on_close_logic(state)
|
||||
on_close_logic = state
|
||||
|
||||
/**
|
||||
* Return the HTML for this UI
|
||||
*
|
||||
* @return string HTML for the UI
|
||||
*/
|
||||
/datum/nanoui/proc/get_html()
|
||||
|
||||
// before the UI opens, add the layout files based on the layout key
|
||||
add_template("layout", "layout_[layout_key].tmpl")
|
||||
|
||||
var/head_content = ""
|
||||
|
||||
for(var/filename in scripts)
|
||||
head_content += "<script type='text/javascript' src='[filename]'></script> "
|
||||
|
||||
for(var/filename in stylesheets)
|
||||
head_content += "<link rel='stylesheet' type='text/css' href='[filename]'> "
|
||||
|
||||
var/template_data_json = "{}" // An empty JSON object
|
||||
if(templates.len > 0)
|
||||
template_data_json = json_encode(templates)
|
||||
|
||||
var/list/send_data = get_send_data(initial_data)
|
||||
var/initial_data_json = replacetext(replacetext(json_encode(send_data), """, "&#34;"), "'", "'")
|
||||
|
||||
var/url_parameters_json = json_encode(list("src" = UID()))
|
||||
|
||||
return {"
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<script type='text/javascript'>
|
||||
function receiveUpdateData(jsonString)
|
||||
{
|
||||
// We need both jQuery and NanoStateManager to be able to recieve data
|
||||
// At the moment any data received before those libraries are loaded will be lost
|
||||
if(typeof NanoStateManager != 'undefined' && typeof jQuery != 'undefined')
|
||||
{
|
||||
NanoStateManager.receiveUpdateData(jsonString);
|
||||
}
|
||||
else
|
||||
{
|
||||
alert('browser.recieveUpdateData failed due to jQuery or NanoStateManager being unavailiable.');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
[head_content]
|
||||
</head>
|
||||
<body scroll=auto data-template-data='[template_data_json]' data-url-parameters='[url_parameters_json]' data-initial-data='[initial_data_json]'>
|
||||
<div id='uiLayout'>
|
||||
</div>
|
||||
<noscript>
|
||||
<div id='uiNoScript'>
|
||||
<h1>Javascript Required</h1>
|
||||
<p>Javascript is required in order to use this NanoUI interface.</p>
|
||||
<p>Please enable Javascript in Internet Explorer, and restart your game.</p>
|
||||
</div>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
||||
"}
|
||||
|
||||
/**
|
||||
* Open this UI
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/open()
|
||||
if(!user.client)
|
||||
return
|
||||
|
||||
var/window_size = ""
|
||||
if(width && height)
|
||||
window_size = "size=[width]x[height];"
|
||||
|
||||
update_status(0)
|
||||
if(status == STATUS_CLOSE)
|
||||
return
|
||||
|
||||
if(!initial_data)
|
||||
set_initial_data(src_object.ui_data(user, ui_key, state)) // Get the UI data.
|
||||
|
||||
// Preset the can_rezie and titlebar values on uis if the user has fancy uis set
|
||||
// Prevents the ui from flickering when opened
|
||||
if(user.client.prefs.toggles2 & PREFTOGGLE_2_FANCYUI)
|
||||
set_window_options("focus=0;can_close=1;can_minimize=1;can_maximize=0;can_resize=0;titlebar=0;")
|
||||
|
||||
user << browse(get_html(), "window=[window_id];[window_size][window_options]")
|
||||
winset(user, "mapwindow.map", "focus=true") // return keyboard focus to map
|
||||
on_close_winset()
|
||||
//onclose(user, window_id)
|
||||
SSnanoui.ui_opened(src)
|
||||
|
||||
/**
|
||||
* Reinitialize the UI with
|
||||
*/
|
||||
/datum/nanoui/proc/reinitialize(template, list/data)
|
||||
if(template)
|
||||
add_template("main", template)
|
||||
if(data)
|
||||
set_initial_data(data)
|
||||
open()
|
||||
|
||||
/**
|
||||
* Close this UI
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/close()
|
||||
is_auto_updating = 0
|
||||
SSnanoui.ui_closed(src)
|
||||
user << browse(null, "window=[window_id]")
|
||||
for(var/datum/nanoui/child in children)
|
||||
child.close()
|
||||
|
||||
src_object.on_ui_close(user)
|
||||
|
||||
/**
|
||||
* Set the UI window to call the nanoclose verb when the window is closed
|
||||
* This allows Nano to handle closed windows
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/on_close_winset()
|
||||
if(!user.client)
|
||||
return
|
||||
var/params = "\ref[src]"
|
||||
|
||||
winset(user, window_id, "on-close=\"nanoclose [params]\"")
|
||||
|
||||
/**
|
||||
* Push data to an already open UI window
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/push_data(data, force_push = 0)
|
||||
update_status(0)
|
||||
if(status == STATUS_DISABLED && !force_push)
|
||||
return // Cannot update UI, no visibility
|
||||
|
||||
var/list/send_data = get_send_data(data)
|
||||
|
||||
// to_chat(user, list2json_usecache(send_data))// used for debugging //NANO DEBUG HOOK
|
||||
|
||||
user << output(list2params(list(json_encode(send_data))),"[window_id].browser:receiveUpdateData")
|
||||
|
||||
/**
|
||||
* This Topic() proc is called whenever a user clicks on a link within a Nano UI
|
||||
* If the UI status is currently STATUS_INTERACTIVE then call the src_object Topic()
|
||||
* If the src_object Topic() returns 1 (true) then update all UIs attached to src_object
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/Topic(href, href_list)
|
||||
update_status(0) // update the status
|
||||
if(status != STATUS_INTERACTIVE || user != usr) // If UI is not interactive or usr calling Topic is not the UI user
|
||||
return
|
||||
|
||||
// This is used to toggle the nano map ui
|
||||
var/map_update = 0
|
||||
if(href_list["showMap"])
|
||||
set_show_map(text2num(href_list["showMap"]))
|
||||
map_update = 1
|
||||
|
||||
if(href_list["mapZLevel"])
|
||||
set_map_z_level(text2num(href_list["mapZLevel"]))
|
||||
map_update = 1
|
||||
|
||||
if((src_object && src_object.Topic(href, href_list, 0, state)) || map_update)
|
||||
SSnanoui.update_uis(src_object) // update all UIs attached to src_object
|
||||
|
||||
/**
|
||||
* Process this UI, updating the entire UI or just the status (aka visibility)
|
||||
* This process proc is called by the master_controller
|
||||
*
|
||||
* @param update string For this UI to update
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/process(update = 0)
|
||||
if(!src_object || !user)
|
||||
close()
|
||||
return
|
||||
|
||||
if(status && (update || is_auto_updating))
|
||||
update() // Update the UI (update_status() is called whenever a UI is updated)
|
||||
else
|
||||
update_status(1) // Not updating UI, so lets check here if status has changed
|
||||
|
||||
/**
|
||||
* Update the UI
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/update(var/force_open = 0)
|
||||
src_object.ui_interact(user, ui_key, src, force_open, master_ui, state)
|
||||
@@ -1,237 +0,0 @@
|
||||
/**
|
||||
* Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data
|
||||
*
|
||||
* @param user /mob The mob who opened/owns the ui
|
||||
* @param src_object /datum The datum which the ui belongs to
|
||||
* @param ui_key string A string key used for the ui
|
||||
* @param ui /datum/nanoui An existing instance of the ui (can be null)
|
||||
* @param data list The data to be passed to the ui, if it exists
|
||||
* @param force_open boolean The ui is being forced to (re)open, so close ui if it exists (instead of updating)
|
||||
*
|
||||
* @return /nanoui Returns the found ui, for null if none exists
|
||||
*/
|
||||
/datum/controller/subsystem/nanoui/proc/try_update_ui(var/mob/user, var/datum/src_object, ui_key, var/datum/nanoui/ui, var/force_open = 0)
|
||||
if(isnull(ui)) // no ui has been passed, so we'll search for one
|
||||
ui = get_open_ui(user, src_object, ui_key)
|
||||
|
||||
if(!isnull(ui))
|
||||
var/data = src_object.ui_data(user, ui_key, ui.state) // Get data from src_object.
|
||||
if(!force_open)
|
||||
ui.push_data(data)
|
||||
else
|
||||
ui.reinitialize(null, data)
|
||||
return ui
|
||||
return null
|
||||
|
||||
/**
|
||||
* Get an open /nanoui ui for the current user, src_object and ui_key
|
||||
*
|
||||
* @param user /mob The mob who opened/owns the ui
|
||||
* @param src_object /obj|/mob The obj or mob which the ui belongs to
|
||||
* @param ui_key string A string key used for the ui
|
||||
*
|
||||
* @return /nanoui Returns the found ui, or null if none exists
|
||||
*/
|
||||
/datum/controller/subsystem/nanoui/proc/get_open_ui(var/mob/user, src_object, ui_key)
|
||||
var/src_object_key = "\ref[src_object]"
|
||||
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open")
|
||||
return null
|
||||
else if(isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list))
|
||||
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open for this object")
|
||||
return null
|
||||
|
||||
for(var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
|
||||
if(ui.user == user)
|
||||
return ui
|
||||
|
||||
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - ui not found")
|
||||
return null
|
||||
|
||||
/**
|
||||
* Update all /nanoui uis attached to src_object
|
||||
*
|
||||
* @param src_object /obj|/mob The obj or mob which the uis are attached to
|
||||
*
|
||||
* @return int The number of uis updated
|
||||
*/
|
||||
/datum/controller/subsystem/nanoui/proc/update_uis(src_object)
|
||||
var/src_object_key = "\ref[src_object]"
|
||||
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
return 0
|
||||
|
||||
var/update_count = 0
|
||||
for(var/ui_key in open_uis[src_object_key])
|
||||
for(var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.nano_host())
|
||||
ui.process(1)
|
||||
update_count++
|
||||
return update_count
|
||||
|
||||
/**
|
||||
* Close all /nanoui uis attached to src_object
|
||||
*
|
||||
* @param src_object /obj|/mob The obj or mob which the uis are attached to
|
||||
*
|
||||
* @return int The number of uis close
|
||||
*/
|
||||
/datum/controller/subsystem/nanoui/proc/close_uis(src_object)
|
||||
var/src_object_key = "\ref[src_object]"
|
||||
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
return 0
|
||||
|
||||
var/close_count = 0
|
||||
for(var/ui_key in open_uis[src_object_key])
|
||||
for(var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.nano_host())
|
||||
ui.close()
|
||||
close_count++
|
||||
return close_count
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Close *ALL* UIs
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
**/
|
||||
/datum/controller/subsystem/nanoui/proc/close_all_uis()
|
||||
var/close_count = 0
|
||||
for(var/src_object_key in open_uis)
|
||||
for(var/ui_key in open_uis[src_object_key])
|
||||
for(var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.nano_host()) // Check the UI is valid.
|
||||
ui.close() // Close the UI.
|
||||
close_count++ // Count each UI we close.
|
||||
return close_count
|
||||
|
||||
/**
|
||||
* Update /nanoui uis belonging to user
|
||||
*
|
||||
* @param user /mob The mob who owns the uis
|
||||
* @param src_object /obj|/mob If src_object is provided, only update uis which are attached to src_object (optional)
|
||||
* @param ui_key string If ui_key is provided, only update uis with a matching ui_key (optional)
|
||||
*
|
||||
* @return int The number of uis updated
|
||||
*/
|
||||
/datum/controller/subsystem/nanoui/proc/update_user_uis(var/mob/user, src_object = null, ui_key = null)
|
||||
if(isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
|
||||
return 0 // has no open uis
|
||||
|
||||
var/update_count = 0
|
||||
for(var/datum/nanoui/ui in user.open_uis)
|
||||
if((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
|
||||
ui.process(1)
|
||||
update_count++
|
||||
|
||||
return update_count
|
||||
|
||||
/**
|
||||
* Close /nanoui uis belonging to user
|
||||
*
|
||||
* @param user /mob The mob who owns the uis
|
||||
* @param src_object /obj|/mob If src_object is provided, only close uis which are attached to src_object (optional)
|
||||
* @param ui_key string If ui_key is provided, only close uis with a matching ui_key (optional)
|
||||
*
|
||||
* @return int The number of uis closed
|
||||
*/
|
||||
/datum/controller/subsystem/nanoui/proc/close_user_uis(var/mob/user, src_object = null, ui_key = null)
|
||||
if(isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
|
||||
//testing("nanomanager/close_user_uis mob [user.name] has no open uis")
|
||||
return 0 // has no open uis
|
||||
|
||||
var/close_count = 0
|
||||
for(var/datum/nanoui/ui in user.open_uis)
|
||||
if((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
|
||||
ui.close()
|
||||
close_count++
|
||||
|
||||
//testing("nanomanager/close_user_uis mob [user.name] closed [open_uis.len] of [close_count] uis")
|
||||
|
||||
return close_count
|
||||
|
||||
/**
|
||||
* Add a /nanoui ui to the list of open uis
|
||||
* This is called by the /nanoui open() proc
|
||||
*
|
||||
* @param ui /nanoui The ui to add
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/controller/subsystem/nanoui/proc/ui_opened(var/datum/nanoui/ui)
|
||||
var/src_object_key = "\ref[ui.src_object]"
|
||||
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
open_uis[src_object_key] = list(ui.ui_key = list())
|
||||
else if(isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
|
||||
open_uis[src_object_key][ui.ui_key] = list()
|
||||
|
||||
ui.user.open_uis.Add(ui)
|
||||
var/list/uis = open_uis[src_object_key][ui.ui_key]
|
||||
uis.Add(ui)
|
||||
processing_uis.Add(ui)
|
||||
//testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
|
||||
|
||||
/**
|
||||
* Remove a /nanoui ui from the list of open uis
|
||||
* This is called by the /nanoui close() proc
|
||||
*
|
||||
* @param ui /nanoui The ui to remove
|
||||
*
|
||||
* @return int 0 if no ui was removed, 1 if removed successfully
|
||||
*/
|
||||
/datum/controller/subsystem/nanoui/proc/ui_closed(var/datum/nanoui/ui)
|
||||
var/src_object_key = "\ref[ui.src_object]"
|
||||
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
return 0 // wasn't open
|
||||
else if(isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
|
||||
return 0 // wasn't open
|
||||
|
||||
processing_uis.Remove(ui)
|
||||
if(ui.user) // Sanity check in case a user has been deleted (say a blown up borg watching the alarm interface)
|
||||
ui.user.open_uis.Remove(ui)
|
||||
var/list/uis = open_uis[src_object_key][ui.ui_key]
|
||||
uis.Remove(ui)
|
||||
|
||||
//testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
|
||||
|
||||
return 1
|
||||
|
||||
/**
|
||||
* This is called on user logout
|
||||
* Closes/clears all uis attached to the user's /mob
|
||||
*
|
||||
* @param user /mob The user's mob
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
|
||||
//
|
||||
/datum/controller/subsystem/nanoui/proc/user_logout(var/mob/user)
|
||||
//testing("nanomanager/user_logout user [user.name]")
|
||||
return close_user_uis(user)
|
||||
|
||||
/**
|
||||
* This is called when a player transfers from one mob to another
|
||||
* Transfers all open UIs to the new mob
|
||||
*
|
||||
* @param oldMob /mob The user's old mob
|
||||
* @param newMob /mob The user's new mob
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/controller/subsystem/nanoui/proc/user_transferred(var/mob/oldMob, var/mob/newMob)
|
||||
//testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]")
|
||||
if(!oldMob || isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0)
|
||||
//testing("nanomanager/user_transferred mob [oldMob.name] has no open uis")
|
||||
return 0 // has no open uis
|
||||
|
||||
if(isnull(newMob.open_uis) || !istype(newMob.open_uis, /list))
|
||||
newMob.open_uis = list()
|
||||
|
||||
for(var/datum/nanoui/ui in oldMob.open_uis)
|
||||
ui.user = newMob
|
||||
newMob.open_uis.Add(ui)
|
||||
|
||||
oldMob.open_uis.Cut()
|
||||
|
||||
return 1 // success
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
if(L)
|
||||
to_chat(L, "[bicon(pda)] [message]")
|
||||
SSnanoui.update_user_uis(L, pda) // Update the receiving user's PDA UI so that they can see the new message
|
||||
SStgui.update_user_uis(L, pda) // Update the receiving user's PDA UI so that they can see the new message
|
||||
|
||||
if(!notify_silent)
|
||||
pda.play_ringtone()
|
||||
|
||||
@@ -38,7 +38,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
overlays += "working"
|
||||
|
||||
/obj/item/gps/AltClick(mob/user)
|
||||
if(CanUseTopic(user, GLOB.inventory_state) != STATUS_INTERACTIVE)
|
||||
if(tgui_status(user, GLOB.tgui_inventory_state) != STATUS_INTERACTIVE)
|
||||
return 1 //user not valid to use gps
|
||||
if(emped)
|
||||
to_chat(user, "<span class='warning'>It's busted!</span>")
|
||||
|
||||
@@ -10,3 +10,11 @@ GLOBAL_DATUM_INIT(tgui_contained_state, /datum/tgui_state/contained_state, new)
|
||||
if(!src_object.contains(user))
|
||||
return STATUS_CLOSE
|
||||
return user.shared_tgui_interaction(src_object)
|
||||
|
||||
/atom/proc/contains(atom/location)
|
||||
if(!location)
|
||||
return FALSE
|
||||
if(location == src)
|
||||
return TRUE
|
||||
|
||||
return contains(location.loc)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
node_modules/
|
||||
bower_components/
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* NanoUI Buildscript v2.0
|
||||
* Fuck the old buildscript edition
|
||||
*/
|
||||
|
||||
// Node Dependencies
|
||||
const child_process = require('child_process')
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
|
||||
/* Configuration */
|
||||
const INPUT = {
|
||||
'fonts': path.join(__dirname, 'node_modules', 'font-awesome', 'fonts', '*.{eot,woff2}'),
|
||||
'images': path.join(__dirname, 'images'),
|
||||
'styles': {
|
||||
'_dir': path.join(__dirname, 'styles'),
|
||||
'nano': path.join(__dirname, 'styles', 'nanoui.less'),
|
||||
'fa': path.join(__dirname, 'node_modules', 'font-awesome', 'less', 'font-awesome.less'),
|
||||
},
|
||||
'scripts': {
|
||||
'lib': path.join(__dirname, 'scripts', 'libraries', '*.js'),
|
||||
'main': path.join(__dirname, 'scripts', 'nano', '*.js'),
|
||||
'es5shim': path.join(__dirname, 'node_modules', 'es5-shim', 'es5-shim.js'),
|
||||
'domurl': path.join(__dirname, 'node_modules', 'domurl', 'url.js'),
|
||||
},
|
||||
'layouts': path.join(__dirname, 'layouts'),
|
||||
'templates': path.join(__dirname, 'templates'),
|
||||
// The story here is: Fucking shitty ass libraries
|
||||
'watch': [
|
||||
'images/**/*',
|
||||
'scripts/**/*',
|
||||
'styles/**/*',
|
||||
'layouts/**/*',
|
||||
'templates/**/*'
|
||||
]
|
||||
}
|
||||
|
||||
const OUTPUT = {
|
||||
'_dir': path.join(__dirname, 'assets'),
|
||||
'scripts': {
|
||||
'lib': 'libraries.min.js',
|
||||
'main': 'nano.js'
|
||||
}
|
||||
}
|
||||
|
||||
/*** Gulp Dependencies ***/
|
||||
const gulp = require('gulp')
|
||||
const concat = require('gulp-concat')
|
||||
const cleancss = require('gulp-clean-css')
|
||||
const order = require('gulp-order')
|
||||
const replace = require('gulp-replace')
|
||||
const postcss = require('gulp-postcss')
|
||||
const postcssFilters = {
|
||||
gradient: require('postcss-filter-gradient'),
|
||||
opacity: require('postcss-opacity'),
|
||||
rgba: require('postcss-color-rgba-fallback'),
|
||||
plsfilters: require("pleeease-filters")
|
||||
}
|
||||
const sourcemaps = require('gulp-sourcemaps')
|
||||
const uglify = require('gulp-uglify')
|
||||
const merge = require('merge-stream')
|
||||
|
||||
const less = require('gulp-less')
|
||||
var autoprefix = new (require('less-plugin-autoprefix'))({ browsers: ['IE 8-11'] })
|
||||
|
||||
/*** Tasks ***/
|
||||
|
||||
/* Task: Clean
|
||||
* Type: Build-Dep
|
||||
* This empties the output directory to prepare for new files. By default, this is nano/assets/.
|
||||
*/
|
||||
function clean(cb) {
|
||||
fs.emptyDir(OUTPUT._dir, function (err) {
|
||||
if (err)
|
||||
return console.error(err)
|
||||
cb()
|
||||
})
|
||||
}
|
||||
|
||||
/* Task: CSS
|
||||
* Type: Build-Step
|
||||
* This compiles all of the LESS styles we require and runs a few IE-friendly CSS filters over the output.
|
||||
*/
|
||||
function css() {
|
||||
// Get both of our LESS components
|
||||
let faLESS = gulp.src(INPUT.styles.fa)
|
||||
let nanoLESS = gulp.src(INPUT.styles.nano)
|
||||
|
||||
// Then haphazardly smash them together and hope it works out
|
||||
return merge(faLESS, nanoLESS)
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(less({
|
||||
plugins: [autoprefix],
|
||||
paths: [INPUT.images]
|
||||
}))
|
||||
.pipe(replace('../fonts/', ''))
|
||||
.pipe(concat('nanoui.css'))
|
||||
.pipe(postcss([ // IE8+ support garbage
|
||||
postcssFilters.gradient,
|
||||
postcssFilters.opacity,
|
||||
postcssFilters.rgba,
|
||||
postcssFilters.plsfilters({oldIE: true})
|
||||
]))
|
||||
.pipe(cleancss({
|
||||
compatibility: 'ie8',
|
||||
level: {
|
||||
1: {
|
||||
all: false,
|
||||
cleanupCharsets: true,
|
||||
specialComments: 0
|
||||
}
|
||||
}
|
||||
}))
|
||||
.pipe(sourcemaps.write()) // Hey look sourcemaps that IE can't use (piece of shit)
|
||||
.pipe(gulp.dest(OUTPUT._dir))
|
||||
}
|
||||
|
||||
/* Task: JS
|
||||
* Type: Build-Step
|
||||
* This builds both our libraries and nano JS files. It uglifies them for performance.
|
||||
*/
|
||||
function js() {
|
||||
let lib = gulp.src(INPUT.scripts.lib)
|
||||
let es5shim = gulp.src(INPUT.scripts.es5shim)
|
||||
let domurl = gulp.src(INPUT.scripts.domurl)
|
||||
|
||||
// Combine all of the library scripts into one file
|
||||
merge(lib, es5shim, domurl)
|
||||
.pipe(order(["jquery.js", "jquery*.js", "*.js"])) // Make sure jQuery is the first damn thing in there
|
||||
.pipe(concat(OUTPUT.scripts.lib))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(uglify())
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest(OUTPUT._dir))
|
||||
|
||||
// Combine all of the nano scripts into one
|
||||
return gulp.src(INPUT.scripts.main)
|
||||
.pipe(order(["nano_utility.js", "nano_state_manager.js", "*.js"])) // Ensure Nano Util and state manager are always loaded first
|
||||
.pipe(concat(OUTPUT.scripts.main))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(uglify())
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest(OUTPUT._dir))
|
||||
}
|
||||
|
||||
/* Task: Fonts
|
||||
* Type: Build-Step
|
||||
* This literally just copy-pastes the FontAwesome fonts into the build directory. We need them there.
|
||||
* If we ever use any other icon fonts (e.x. Material Icons), copy their asses here too.
|
||||
*/
|
||||
function fonts() {
|
||||
return gulp.src(INPUT.fonts)
|
||||
.pipe(gulp.dest(OUTPUT._dir))
|
||||
}
|
||||
|
||||
/* Task: Reload
|
||||
* Type: Main
|
||||
* This injects all the changed files directly into the client cache.
|
||||
*/
|
||||
function reload(cb) {
|
||||
child_process.exec("reload.bat", function (err, stdout) {
|
||||
if (err)
|
||||
throw err
|
||||
var byond_cache = path.join(stdout.trim(), "BYOND", "cache")
|
||||
var files = fs.readdirSync(byond_cache)
|
||||
for (let file of files) {
|
||||
let filepath = path.join(byond_cache, file)
|
||||
let stats = fs.statSync(filepath)
|
||||
if (file.startsWith("tmp") && stats.isDirectory()) {
|
||||
var tmpFiles = fs.readdirSync(filepath)
|
||||
if (tmpFiles.includes(OUTPUT.scripts.main)) {
|
||||
setTimeout(function () {transfer_files(filepath)}, 500)
|
||||
}
|
||||
}
|
||||
}
|
||||
cb()
|
||||
})
|
||||
}
|
||||
|
||||
function transfer_files(target) {
|
||||
let transfer = [INPUT.images, INPUT.layouts, INPUT.templates, OUTPUT._dir]
|
||||
for (let trf of transfer) {
|
||||
let files = fs.readdirSync(trf)
|
||||
for (let file of files) {
|
||||
let fileData = fs.statSync(path.join(trf, file))
|
||||
if (fileData.isFile())
|
||||
transfer_file(path.join(trf, file), path.join(target, file))
|
||||
}
|
||||
}
|
||||
}
|
||||
function transfer_file(input, target) {
|
||||
fs.createReadStream(input).pipe(fs.createWriteStream(target))
|
||||
}
|
||||
|
||||
/* Task: Watch
|
||||
* Type: Main
|
||||
* This is just an alias to trigger all the gulp watch shit
|
||||
*/
|
||||
function watch(cb) {
|
||||
// Alright, so here's some fucking stupid bullshit we have to work around:
|
||||
// Gulp 4.0 uses an updated version of chokidar for watching files.
|
||||
// This version of chokidar doesn't fucking support windows path seperators.
|
||||
// So, we have to only use relative paths with forward slashes.
|
||||
let watchTask = gulp.series(exports.default, reload)
|
||||
// Watch files.
|
||||
gulp.watch(INPUT.watch, watchTask)
|
||||
cb()
|
||||
}
|
||||
|
||||
/* This shit is a Gulp v4 design. You use exports to define tasks now, instead of gulp.tasks. */
|
||||
exports.default = gulp.series(clean, gulp.parallel(css, js, fonts))
|
||||
exports.watch = watch
|
||||
@@ -1,107 +0,0 @@
|
||||
# NanoUI
|
||||
|
||||
NanoUI is a user interface library, used for over 100 different interfaces, and rising.
|
||||
It is more complicated than the other two UI systems in use, the `/datum/browser` and
|
||||
`browse()` systems, but offers pre-made libraries, JavaScript, and a modified doT
|
||||
template engine.
|
||||
|
||||
This README is not yet complete, but gives a basic rundown of how the folder structure
|
||||
works. I'll get around to finishing it one day.
|
||||
|
||||
## Contributors
|
||||
|
||||
This section is for listing the contributors to NanoUI.
|
||||
|
||||
- -tg-station/Neersighted
|
||||
- Special thanks goes to Neersighted for creating most of the newest and best features
|
||||
of NanoUI. Everything between using the Gulp build system to switching to LESS styles
|
||||
has been directly adapated and/or copied from his original work for -tg-station and
|
||||
their UI system, tgui.
|
||||
|
||||
Systems ported/adapted from -tg-station and Neersighted include, but are not limited
|
||||
to:
|
||||
|
||||
- NanoUI's JavaScript controlling the "fancy" borderless window mode.
|
||||
- The NanoTrasen.svg logo (Licensed under CC 3.0 BY-SA).
|
||||
- The packages in bower.json and packages.json files were hand-picked by Neersighted
|
||||
for usage in compiling NanoUI.
|
||||
- A considerable amount of this README is adapated from Neersighted's documentation.
|
||||
- The concepts following: Using FontAwesome instead of icon16, Using LESS to expand
|
||||
NanoUI's CSS style.
|
||||
|
||||
NanoUI is licensed under AGPLv3. This applies to it's serverside `DM` code as well as it's
|
||||
clientside `JavaScript` and `LESS` code. The file `nano/images/nanotrasen.svg` is licensed
|
||||
under CC 3.0 BY-SA, and was created by Neersighted. All other image files in the
|
||||
`nano/images/` directory are subject to the standard image license applied to the Paradise
|
||||
repository icons.
|
||||
|
||||
## Folder Rundown
|
||||
|
||||
### /assets
|
||||
The assets folder is used by the Gulp compiling system, and stores the minified version of
|
||||
the NanoUI JavaScript Library and prerequisites. Everything within this folder is sent to
|
||||
the client as-is.
|
||||
|
||||
### /codemirror
|
||||
This folder contains all of the JavaScript and CSS for CodeMirror. It is sent to the
|
||||
client as-is. CodeMirror only has it's own folder due to the fact that it can't be
|
||||
directly compiled into the NanoUI files.
|
||||
|
||||
### /images
|
||||
This folder is used to store any image files. It is sent to the client as-is.
|
||||
|
||||
### /layouts
|
||||
This folder is used for the central "layout" template files, which is loaded before the
|
||||
UI's actual template file. It is sent to the client as-is.
|
||||
|
||||
### /scripts
|
||||
This folder is used for anything that will be compiled by the Gulp compilation system.
|
||||
Currently, it is split into two folders. The file names must start with a number, as this
|
||||
is how Gulp decides what order to put the concatenated and possibly minified files in.
|
||||
Anything within this folder is not sent to the client directly.
|
||||
|
||||
#### /scripts/libraries
|
||||
This folder is used to store the source code of the prerequisites of NanoUI. Currently,
|
||||
it contains jQuery, jQuery UI, jQuery timers, and the doT template system.
|
||||
|
||||
#### /scripts/nano
|
||||
This folder contains the primary JavaScript for NanoUI.
|
||||
|
||||
### /styles
|
||||
This folder is used for NanoUI's LESS styles. These are compiled via gulp into the file
|
||||
`nanoui.css`. LESS is a system that expands upon CSS in order to make it better, as well
|
||||
as less complicated.
|
||||
|
||||
Any LESS file that is prefixed with the `_` character will be ignored during compilation.
|
||||
These files are still included, however, via `@import`, view the file
|
||||
[`nanoui.less`](http://github.com/ParadiseSS13/Paradise/blob/master/nano/styles/nanoui.less) to see how this works.
|
||||
|
||||
|
||||
### /templates
|
||||
This folder is used to store the .tmpl files which are later compiled by the NanoUtility
|
||||
JavaScript, using a modified version of the doT template engine. It is sent to the client
|
||||
as-is.
|
||||
|
||||
## Compiling
|
||||
To compile any changes to the NanoUI JavaScript, you must first setup the building
|
||||
environment.
|
||||
|
||||
### Prerequisites
|
||||
You will first need to install the primary prerequisite of NanoUI, [Node.js](https://nodejs.org).
|
||||
|
||||
If you don't want to rip out all of your hair and you're on Windows, you should also have some linux-emulating terminal.
|
||||
The easiest to install, and something you can use for managing this git repo, is [git-scm](https://git-scm.com/)
|
||||
|
||||
Node.js is used to obtain all of the remaining prerequisites to compile NanoUI. This is
|
||||
done by running the following commands.
|
||||
- `npm install -g gulp-cli`
|
||||
- `npm install`
|
||||
|
||||
### Running Gulp
|
||||
NanoUI is built using the `gulp` task automation system. This system uses the contents
|
||||
of the `Gulpfile.js` file to perform compilation tasks.
|
||||
|
||||
In order to build an un-minified version of NanoUI, you may simply run `gulp` in the
|
||||
`nanoui` directory. However, this should only be used while testing, and you should run
|
||||
the command `gulp --min` before commiting changes, in order to produce minified
|
||||
JavaScript.
|
||||
@@ -1,75 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="92.853668mm"
|
||||
height="41.097198mm"
|
||||
viewBox="0 0 92.853668 41.097198"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
sodipodi:docname="Scarborough Arms.svg"
|
||||
inkscape:export-filename="C:\Users\wario\Pictures\Scarborough Arms.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="139.62747"
|
||||
inkscape:cy="-0.78849325"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1137"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-53.831064,-64.658948)">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;line-height:1.25;font-family:'Bellhop NF';-inkscape-font-specification:'Bellhop NF';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="52.916664"
|
||||
y="104.23215"
|
||||
id="text12"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan10"
|
||||
x="52.916664"
|
||||
y="104.23215"
|
||||
style="font-size:50.79999924px;stroke-width:0.26458332">SA</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 425 200" opacity=".25">
|
||||
<path d="m 178.00399,0.03869 -71.20393,0 a 6.7613422,6.0255495 0 0 0 -6.76134,6.02555 l 0,187.87147 a 6.7613422,6.0255495 0 0 0 6.76134,6.02554 l 53.1072,0 a 6.7613422,6.0255495 0 0 0 6.76135,-6.02554 l 0,-101.544018 72.21628,104.699398 a 6.7613422,6.0255495 0 0 0 5.76015,2.87016 l 73.55487,0 a 6.7613422,6.0255495 0 0 0 6.76135,-6.02554 l 0,-187.87147 a 6.7613422,6.0255495 0 0 0 -6.76135,-6.02555 l -54.71644,0 a 6.7613422,6.0255495 0 0 0 -6.76133,6.02555 l 0,102.61935 L 183.76413,2.90886 a 6.7613422,6.0255495 0 0 0 -5.76014,-2.87017 z" />
|
||||
<path d="M 4.8446333,22.10875 A 13.412039,12.501842 0 0 1 13.477588,0.03924 l 66.118315,0 a 5.3648158,5.000737 0 0 1 5.364823,5.00073 l 0,79.87931 z" />
|
||||
<path d="m 420.15535,177.89119 a 13.412038,12.501842 0 0 1 -8.63295,22.06951 l -66.11832,0 a 5.3648152,5.000737 0 0 1 -5.36482,-5.00074 l 0,-79.87931 z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1013 B |
|
Before Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 200 289.742" opacity=".33">
|
||||
<path d="m 93.537677,0 c -18.113125,0 -34.220133,3.11164 -48.323484,9.33437 -13.965092,6.22167 -24.612442,15.07114 -31.940651,26.5471 -7.1899398,11.33789 -10.3012266,24.74911 -10.3012266,40.23478 0,10.64662 2.7250026,20.46465 8.1751116,29.45258 5.615277,8.98686 14.038277,17.35204 25.268821,25.09436 11.230544,7.60531 26.507421,15.41835 45.830514,23.43782 19.983748,8.29557 34.848848,15.55471 44.592998,21.77638 9.74414,6.22273 16.7617,12.8585 21.05572,19.90951 4.29404,7.05208 6.44193,15.76408 6.44193,26.13459 0,16.17702 -5.20196,28.48222 -15.60673,36.91682 -10.2396,8.4347 -25.02203,12.6523 -44.345169,12.6523 -14.038171,0 -25.515247,-1.6594 -34.433618,-4.9777 -8.91837,-3.4566 -16.185572,-8.7113 -21.800839,-15.7633 -5.615277,-7.0521 -10.074795,-16.66088 -13.377899,-28.82812 l -24.7731626293945,0 0,56.82632 C 33.856769,286.07601 63.74904,289.74201 89.678383,289.74201 c 16.020027,0 30.719787,-1.3827 44.097337,-4.1479 13.54272,-2.9043 25.1041,-7.4676 34.68309,-13.6893 9.74413,-6.3597 17.34042,-14.5195 22.79052,-24.4748 5.4501,-10.09332 8.17511,-22.39959 8.17511,-36.91682 0,-12.99764 -3.3021,-24.33539 -9.90829,-34.0146 -6.44105,-9.81725 -15.52545,-18.52707 -27.25146,-26.13133 -11.56085,-7.60427 -27.91083,-15.83142 -49.05066,-24.68022 -17.50644,-7.19012 -30.719668,-13.68948 -39.638038,-19.49701 -8.918371,-5.80752 -18.607474,-12.43409 -24.096524,-18.87417 -5.426043,-6.36616 -9.658826,-15.07003 -9.658826,-24.88729 0,-9.26401 2.075414,-17.21345 6.223454,-23.85033 11.098298,-14.39748 41.286638,-1.79507 45.075609,24.34762 4.839392,6.77491 8.84935,16.24729 12.029515,28.4156 l 20.53234,0 0,-55.99967 c -4.47825,-5.92448 -9.95488,-10.63222 -15.90837,-14.37411 1.64055,0.47905 3.19039,1.02376 4.63865,1.64024 6.49861,2.62607 12.16793,7.32747 17.0073,14.10345 4.83939,6.77491 8.84935,16.24567 12.02952,28.41397 0,0 8.48128,-0.12894 8.48978,-0.002 0.41776,6.41494 -1.75339,9.45286 -4.12342,12.56104 -2.4174,3.16978 -5.14486,6.78973 -4.00278,13.0029 1.50786,8.20318 10.18354,10.59642 14.62194,9.31154 -3.31842,-0.49911 -5.31855,-1.74948 -5.31855,-1.74948 0,0 1.87646,0.99868 5.65117,-1.35981 -3.27695,0.95571 -10.70529,-0.79738 -11.80125,-6.76313 -0.95752,-5.20861 0.94654,-7.29514 3.40113,-10.51482 2.45462,-3.21968 5.28426,-6.95831 4.6843,-14.48824 l 0.003,0.002 8.92676,0 0,-55.99967 c -15.07125,-3.87168 -27.65314,-6.36042 -37.74671,-7.46586 -9.95531,-1.10755 -20.18823,-1.65981 -30.696613,-1.65981 z m 70.321603,17.30893 0.23805,40.3049 c 1.31808,1.22666 2.43965,2.27815 3.34081,3.10602 4.83939,6.77491 8.84934,16.24566 12.02951,28.41397 l 20.53234,0 0,-55.99967 c -6.67731,-4.59381 -19.83643,-10.47309 -36.14071,-15.82522 z m -28.12049,5.60551 8.56479,17.71655 c -11.97037,-6.46697 -13.84678,-9.71726 -8.56479,-17.71655 z m 22.79705,0 c 2.7715,7.99929 1.78741,11.24958 -4.49354,17.71655 l 4.49354,-17.71655 z m 15.22195,24.00848 8.56479,17.71655 c -11.97038,-6.46697 -13.84679,-9.71726 -8.56479,-17.71655 z m 22.79704,0 c 2.7715,7.99929 1.78741,11.24958 -4.49354,17.71655 l 4.49354,-17.71655 z m -99.11384,2.20764 8.56479,17.71655 c -11.970382,-6.46697 -13.846782,-9.71726 -8.56479,-17.71655 z m 22.79542,0 c 2.7715,7.99929 1.78741,11.24958 -4.49354,17.71655 l 4.49354,-17.71655 z" />
|
||||
</svg>
|
||||
<!-- This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. -->
|
||||
<!-- http://creativecommons.org/licenses/by-sa/4.0/ -->
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 208 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 673 B |
|
Before Width: | Height: | Size: 226 B |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 670 B |
@@ -1,20 +0,0 @@
|
||||
body {
|
||||
background: #272727 url(uiBasicBackground.png) 50% 0 repeat-x;
|
||||
}
|
||||
|
||||
#uiContent {
|
||||
clear: both;
|
||||
padding: 8px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
#uiLoadingNotice {
|
||||
position: relative;
|
||||
background: url(uiNoticeBackground.jpg) 50% 50%;
|
||||
color: #000000;
|
||||
font-size: 14px;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
padding: 3px 4px 3px 4px;
|
||||
margin: 4px 0 4px 0;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<div id='uiContent'>
|
||||
<div id='uiLoadingNotice'>Initiating...</div>
|
||||
</div>
|
||||
@@ -1,47 +0,0 @@
|
||||
<div class='fancy resizeArea top' rx='0' ry='-1'></div>
|
||||
<div class='fancy resizeArea tr' rx='1' ry='-1'></div>
|
||||
<div class='fancy resizeArea right' rx='1' ry='0'></div>
|
||||
<div class='fancy resizeArea br' rx='1' ry='1'></div>
|
||||
<div class='fancy resizeArea bottom' rx='0' ry='1'></div>
|
||||
<div class='fancy resizeArea bl' rx='-1' ry='1'></div>
|
||||
<div class='fancy resizeArea left' rx='-1' ry='0'></div>
|
||||
<div class='fancy resizeArea tl' rx='-1' ry='-1'></div>
|
||||
|
||||
<div id='uiTitleWrapper'>
|
||||
<div id='uiCornerTL' class='fancy'> </div>
|
||||
<i class="statusicon fa fa-eye fa-2x" unselectable="on"></i>
|
||||
<div id='uiTitleText' unselectable="on">{{:config.title}}</div>
|
||||
<div id='uiTitleFluff' unselectable="on"></div>
|
||||
<i class='minimize fancy fa fa-minus fa-2x' unselectable='on'></i>
|
||||
<i class='close fancy fa fa-close fa-2x' unselectable='on'></i>
|
||||
</div>
|
||||
<div class="mainBG"></div>
|
||||
<div id='uiMapWrapper' class="hidden" unselectable="on">
|
||||
<div id='uiMapHeader' unselectable="on">
|
||||
{{:helper.link('Hide Map', 'close', {'showMap' : 0})}}
|
||||
<div style="float: right; width: 240px;">
|
||||
<span style="float: left;">Zoom Level: </span>
|
||||
<div unselectable="on" class="link zoomLink" data-zoom-level="2">x1</div>
|
||||
<div unselectable="on" class="link zoomLink" data-zoom-level="4">x2</div>
|
||||
<div unselectable="on" class="link zoomLink" data-zoom-level="8">x4</div>
|
||||
<div unselectable="on" class="link zoomLink" data-zoom-level="16">x8</div>
|
||||
</div>
|
||||
<!-- Add a template with the key "mapHeader" to have it rendered here -->
|
||||
</div>
|
||||
<div id='uiMapContainer' unselectable="on">
|
||||
<div id='uiMap' unselectable="on">
|
||||
<img id="uiMapImage" src="{{:config.map}}_nanomap_z{{:config.mapZLevel}}.png" width="256" height="256" unselectable="on" />
|
||||
<div id='uiMapContent' unselectable="on">
|
||||
<!-- Add a template with the key "mapContent" to have it rendered here (on the map) -->
|
||||
<!-- Having a "mapContent" template enables the map functionality -->
|
||||
</div>
|
||||
</div>
|
||||
<div id="uiMapTooltip"></div>
|
||||
</div>
|
||||
<div id='uiMapFooter' unselectable="on">
|
||||
<!-- Add a template with the key "mapFooter" to have it rendered here -->
|
||||
</div>
|
||||
</div>
|
||||
<div id='uiContent' unselectable="on">
|
||||
<div id='uiLoadingNotice'>Initiating...</div>
|
||||
</div>
|
||||
@@ -1,85 +0,0 @@
|
||||
<div class='fancy resizeArea top' rx='0' ry='-1'></div>
|
||||
<div class='fancy resizeArea tr' rx='1' ry='-1'></div>
|
||||
<div class='fancy resizeArea right' rx='1' ry='0'></div>
|
||||
<div class='fancy resizeArea br' rx='1' ry='1'></div>
|
||||
<div class='fancy resizeArea bottom' rx='0' ry='1'></div>
|
||||
<div class='fancy resizeArea bl' rx='-1' ry='1'></div>
|
||||
<div class='fancy resizeArea left' rx='-1' ry='0'></div>
|
||||
<div class='fancy resizeArea tl' rx='-1' ry='-1'></div>
|
||||
|
||||
<div id='uiTitleWrapper'>
|
||||
<div id='uiCornerTL' class='fancy'> </div>
|
||||
<i class="statusicon fa fa-eye fa-2x" unselectable="on"></i>
|
||||
<div id='uiTitleText' unselectable="on">{{:config.title}}</div>
|
||||
<div id='uiTitleFluff' unselectable="on"></div>
|
||||
<i class='minimize fancy fa fa-minus fa-2x' unselectable='on'></i>
|
||||
<i class='close fancy fa fa-close fa-2x' unselectable='on'></i>
|
||||
</div>
|
||||
<div class="mainBG"></div>
|
||||
|
||||
<div class="floatLeft underTitle">
|
||||
<div class='item'>
|
||||
<table><tr>
|
||||
{{if data.PC_batteryicon && data.PC_showbatteryicon}}
|
||||
<td><img src='{{:data.PC_batteryicon}}'>
|
||||
{{/if}}
|
||||
{{if data.PC_batterypercent && data.PC_showbatteryicon}}
|
||||
<td><b>{{:data.PC_batterypercent}}</b>
|
||||
{{/if}}
|
||||
{{if data.PC_ntneticon}}
|
||||
<td><img src='{{:data.PC_ntneticon}}'>
|
||||
{{/if}}
|
||||
{{if data.PC_apclinkicon}}
|
||||
<td><img src='{{:data.PC_apclinkicon}}'>
|
||||
{{/if}}
|
||||
{{if data.PC_stationtime}}
|
||||
<td><b>{{:data.PC_stationtime}}<b>
|
||||
{{/if}}
|
||||
{{for data.PC_programheaders}}
|
||||
<td><img src='{{:value.icon}}'>
|
||||
{{/for}}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="floatRight underTitle">
|
||||
<div class='item'>
|
||||
<table><tr>
|
||||
<td>{{:helper.link('Shutdown', 'power-off', {'action' : 'PC_shutdown'})}}
|
||||
{{if data.PC_showexitprogram}}
|
||||
<td>{{:helper.link('EXIT PROGRAM', 'times', {'action' : 'PC_exit'})}}
|
||||
<td>{{:helper.link('Minimize Program', 'minus', {'action' : 'PC_minimize'})}}
|
||||
{{/if}}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id='uiMapWrapper' class="hidden" unselectable="on">
|
||||
<div id='uiMapHeader' unselectable="on">
|
||||
{{:helper.link('Hide Map', 'close', {'showMap' : 0})}}
|
||||
<div style="float: right; width: 240px;">
|
||||
<span style="float: left;">Zoom Level: </span>
|
||||
<div unselectable="on" class="link zoomLink" data-zoom-level="2">x1</div>
|
||||
<div unselectable="on" class="link zoomLink" data-zoom-level="4">x2</div>
|
||||
<div unselectable="on" class="link zoomLink" data-zoom-level="8">x4</div>
|
||||
<div unselectable="on" class="link zoomLink" data-zoom-level="16">x8</div>
|
||||
</div>
|
||||
<!-- Add a template with the key "mapHeader" to have it rendered here -->
|
||||
</div>
|
||||
<div id='uiMapContainer' unselectable="on">
|
||||
<div id='uiMap' unselectable="on">
|
||||
<img id="uiMapImage" src="{{:config.map}}_nanomap_z{{:config.mapZLevel}}.png" width="256" height="256" unselectable="on" />
|
||||
<div id='uiMapContent' unselectable="on">
|
||||
<!-- Add a template with the key "mapContent" to have it rendered here (on the map) -->
|
||||
<!-- Having a "mapContent" template enables the map functionality -->
|
||||
</div>
|
||||
</div>
|
||||
<div id="uiMapTooltip"></div>
|
||||
</div>
|
||||
<div id='uiMapFooter' unselectable="on">
|
||||
<!-- Add a template with the key "mapFooter" to have it rendered here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clearBoth" id='uiContent' unselectable="on">
|
||||
<div id='uiLoadingNotice'>Initiating...</div>
|
||||
</div>
|
||||
|
Before Width: | Height: | Size: 513 KiB |
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"name": "nanoui",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@websanova/url": "git+https://github.com/websanova/js-url.git",
|
||||
"domurl": "^2.3.4",
|
||||
"es5-shim": "^4.5.14",
|
||||
"font-awesome": "^4.7.0",
|
||||
"gulp-clean-css": "^3.10.0",
|
||||
"js-url": "git+https://github.com/websanova/js-url.git",
|
||||
"less": "^3.11.3",
|
||||
"less-loader": "^5.0.0",
|
||||
"style-loader": "^1.2.1",
|
||||
"tslib": "^1.13.0",
|
||||
"webpack": "^4.43.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"fs-extra": "^7.0.1",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-less": "^4.0.1",
|
||||
"gulp-order": "^1.2.0",
|
||||
"gulp-postcss": "^8.0.0",
|
||||
"gulp-replace": "^1.0.0",
|
||||
"gulp-sourcemaps": "^2.6.5",
|
||||
"gulp-uglify": "^3.0.2",
|
||||
"less-plugin-autoprefix": "^2.0.0",
|
||||
"merge-stream": "^1.0.1",
|
||||
"pleeease-filters": "^4.0.0",
|
||||
"postcss-color-rgba-fallback": "git+https://github.com/postcss/postcss-color-rgba-fallback.git",
|
||||
"postcss-filter-gradient": "^1.0.0",
|
||||
"postcss-opacity": "^5.0.0"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
@echo off
|
||||
|
||||
for /f "tokens=3* delims= " %%a in (
|
||||
'reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "Personal"'
|
||||
) do (
|
||||
set documents=%%a
|
||||
)
|
||||
|
||||
echo %documents%
|
||||
@@ -1,157 +0,0 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var doT = {
|
||||
version: '1.0.1-nanoui',
|
||||
templateSettings: {
|
||||
evaluate: /\{\{([\s\S]+?)\}\}/g,
|
||||
interpolate: /\{\{:([\s\S]+?)\}\}/g,
|
||||
encode: /\{\{>([\s\S]+?)\}\}/g,
|
||||
use: /\{\{#([\s\S]+?)\}\}/g,
|
||||
define: /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,
|
||||
conditional: /\{\{\/?if\s*([\s\S]*?)\s*\}\}/g,
|
||||
conditionalElse: /\{\{else\s*([\s\S]*?)\s*\}\}/g,
|
||||
iterate: /\{\{\/?for\s*(?:\}\}|([\s\S]+?)\s*(?:\:\s*([\w$]+))?\s*(?:\:\s*([\w$]+))?\s*\}\})/g,
|
||||
props: /\{\{\/?props\s*(?:\}\}|([\s\S]+?)\s*(?:\:\s*([\w$]+))?\s*(?:\:\s*([\w$]+))?\s*\}\})/g,
|
||||
empty: /\{\{empty\}\}/g,
|
||||
varname: 'data, config, helper',
|
||||
strip: true,
|
||||
append: true,
|
||||
selfcontained: false
|
||||
},
|
||||
template: undefined, //fn, compile template
|
||||
compile: undefined //fn, for express
|
||||
}, global;
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = doT;
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
define(function () {
|
||||
return doT;
|
||||
});
|
||||
} else {
|
||||
global = (function () {
|
||||
return this || (0, eval)('this');
|
||||
}());
|
||||
global.doT = doT;
|
||||
}
|
||||
|
||||
function encodeHTMLSource() {
|
||||
var encodeHTMLRules = { "&": "&", "<": "<", ">": ">", '"': '"', "'": ''', "/": '/' },
|
||||
matchHTML = /&(?!#?\w+;)|<|>|"|'|\//g;
|
||||
return function () {
|
||||
return this ? this.replace(matchHTML, function (m) {
|
||||
return encodeHTMLRules[m] || m;
|
||||
}) : this;
|
||||
};
|
||||
}
|
||||
|
||||
String.prototype.encodeHTML = encodeHTMLSource();
|
||||
|
||||
var startend = {
|
||||
append: { start: "'+(", end: ")+'", endencode: "||'').toString().encodeHTML()+'" },
|
||||
split: { start: "';out+=(", end: ");out+='", endencode: "||'').toString().encodeHTML();out+='"}
|
||||
}, skip = /$^/;
|
||||
|
||||
function resolveDefs(c, block, def) {
|
||||
return ((typeof block === 'string') ? block : block.toString())
|
||||
.replace(c.define || skip, function (m, code, assign, value) {
|
||||
if (code.indexOf('def.') === 0) {
|
||||
code = code.substring(4);
|
||||
}
|
||||
if (!(code in def)) {
|
||||
if (assign === ':') {
|
||||
if (c.defineParams) value.replace(c.defineParams, function (m, param, v) {
|
||||
def[code] = {arg: param, text: v};
|
||||
});
|
||||
if (!(code in def)) def[code] = value;
|
||||
} else {
|
||||
new Function("def", "def['" + code + "']=" + value)(def);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
})
|
||||
.replace(c.use || skip, function (m, code) {
|
||||
if (c.useParams) code = code.replace(c.useParams, function (m, s, d, param) {
|
||||
if (def[d] && def[d].arg && param) {
|
||||
var rw = (d + ":" + param).replace(/'|\\/g, '_');
|
||||
def.__exp = def.__exp || {};
|
||||
def.__exp[rw] = def[d].text.replace(new RegExp("(^|[^\\w$])" + def[d].arg + "([^\\w$])", "g"), "$1" + param + "$2");
|
||||
return s + "def.__exp['" + rw + "']";
|
||||
}
|
||||
});
|
||||
var v = new Function("def", "return " + code)(def);
|
||||
return v ? resolveDefs(c, v, def) : v;
|
||||
});
|
||||
}
|
||||
|
||||
function unescape(code) {
|
||||
return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, ' ');
|
||||
}
|
||||
|
||||
doT.template = function (tmpl, c, def) {
|
||||
c = c || doT.templateSettings;
|
||||
var cse = c.append ? startend.append : startend.split, needhtmlencode, sid = 0,
|
||||
str = (c.use || c.define) ? resolveDefs(c, tmpl, def || {}) : tmpl;
|
||||
|
||||
str = ("var out='" + (c.strip ? str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g, ' ')
|
||||
.replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g, '') : str)
|
||||
.replace(/'|\\/g, '\\$&')
|
||||
.replace(c.interpolate || skip, function (m, code) {
|
||||
return cse.start + unescape(code) + cse.end;
|
||||
})
|
||||
.replace(c.encode || skip, function (m, code) {
|
||||
needhtmlencode = true;
|
||||
return cse.start + unescape(code) + cse.endencode;
|
||||
})
|
||||
.replace(c.conditional || skip, function (m, code) {
|
||||
return (code ? "';if(" + unescape(code) + "){out+='" : "';}out+='");
|
||||
})
|
||||
.replace(c.conditionalElse || skip, function (m, code) {
|
||||
return (code ? "';}else if(" + unescape(code) + "){out+='" : "';}else{out+='");
|
||||
})
|
||||
.replace(c.iterate || skip, function (m, iterate, vname, iname) {
|
||||
if (!iterate) return "';} } out+='";
|
||||
sid += 1;
|
||||
vname = vname || "value";
|
||||
iname = iname || "index";
|
||||
iterate = unescape(iterate);
|
||||
var arrayName = "arr" + sid;
|
||||
return "';var " + arrayName + "=" + iterate + ";if(" + arrayName + " && " + arrayName + ".length > 0){var " + vname + "," + iname + "=-1,l" + sid + "=" + arrayName + ".length-1;while(" + iname + "<l" + sid + "){"
|
||||
+ vname + "=" + arrayName + "[" + iname + "+=1];out+='";
|
||||
})
|
||||
.replace(c.props || skip, function (m, iterate, vname, iname) {
|
||||
if (!iterate) return "';} } out+='";
|
||||
sid += 1;
|
||||
vname = vname || "value";
|
||||
iname = iname || "key";
|
||||
iterate = unescape(iterate);
|
||||
var objectName = "arr" + sid;
|
||||
return "';var " + objectName + "=" + iterate + ";if(" + objectName + " && Object.size(" + objectName + ") > 0){var " + vname + ";for( var " + iname + " in " + objectName + "){ if (!" + objectName + ".hasOwnProperty(" + iname + ")) continue; " + vname + "=" + objectName + "[" + iname + "];out+='";
|
||||
})
|
||||
.replace(c.empty || skip, function (m) {
|
||||
return "';}}else{if(true){out+='"; // The "if(true)" condition is required to account for the for tag closing with two brackets
|
||||
})
|
||||
.replace(c.evaluate || skip, function (m, code) {
|
||||
return "';" + unescape(code) + "out+='";
|
||||
})
|
||||
+ "';return out;")
|
||||
.replace(/\n/g, '\\n').replace(/\t/g, '\\t').replace(/\r/g, '\\r')
|
||||
.replace(/(\s|;|\}|^|\{)out\+='';/g, '$1').replace(/\+''/g, '')
|
||||
.replace(/(\s|;|\}|^|\{)out\+=''\+/g, '$1out+=');
|
||||
|
||||
if (needhtmlencode && c.selfcontained) {
|
||||
str = "String.prototype.encodeHTML=(" + encodeHTMLSource.toString() + "());" + str;
|
||||
}
|
||||
try {
|
||||
return new Function(c.varname, str);
|
||||
} catch (e) {
|
||||
if (typeof console !== 'undefined') console.log("Could not create a template function: " + str);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
doT.compile = function (tmpl, def) {
|
||||
return doT.template(tmpl, null, def);
|
||||
};
|
||||
}());
|
||||
@@ -1,138 +0,0 @@
|
||||
/**
|
||||
* jQuery.timers - Timer abstractions for jQuery
|
||||
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
|
||||
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
|
||||
* Date: 2009/10/16
|
||||
*
|
||||
* @author Blair Mitchelmore
|
||||
* @version 1.2
|
||||
*
|
||||
**/
|
||||
|
||||
jQuery.fn.extend({
|
||||
everyTime: function(interval, label, fn, times) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.add(this, interval, label, fn, times);
|
||||
});
|
||||
},
|
||||
oneTime: function(interval, label, fn) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.add(this, interval, label, fn, 1);
|
||||
});
|
||||
},
|
||||
stopTime: function(label, fn) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.remove(this, label, fn);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.extend({
|
||||
timer: {
|
||||
global: [],
|
||||
guid: 1,
|
||||
dataKey: "jQuery.timer",
|
||||
regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
|
||||
powers: {
|
||||
// Yeah this is major overkill...
|
||||
'ms': 1,
|
||||
'cs': 10,
|
||||
'ds': 100,
|
||||
's': 1000,
|
||||
'das': 10000,
|
||||
'hs': 100000,
|
||||
'ks': 1000000
|
||||
},
|
||||
timeParse: function(value) {
|
||||
if (value == undefined || value == null)
|
||||
return null;
|
||||
var result = this.regex.exec(jQuery.trim(value.toString()));
|
||||
if (result[2]) {
|
||||
var num = parseFloat(result[1]);
|
||||
var mult = this.powers[result[2]] || 1;
|
||||
return num * mult;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
add: function(element, interval, label, fn, times) {
|
||||
var counter = 0;
|
||||
|
||||
if (jQuery.isFunction(label)) {
|
||||
if (!times)
|
||||
times = fn;
|
||||
fn = label;
|
||||
label = interval;
|
||||
}
|
||||
|
||||
interval = jQuery.timer.timeParse(interval);
|
||||
|
||||
if (typeof interval != 'number' || isNaN(interval) || interval < 0)
|
||||
return;
|
||||
|
||||
if (typeof times != 'number' || isNaN(times) || times < 0)
|
||||
times = 0;
|
||||
|
||||
times = times || 0;
|
||||
|
||||
var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
|
||||
|
||||
if (!timers[label])
|
||||
timers[label] = {};
|
||||
|
||||
fn.timerID = fn.timerID || this.guid++;
|
||||
|
||||
var handler = function() {
|
||||
if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
|
||||
jQuery.timer.remove(element, label, fn);
|
||||
};
|
||||
|
||||
handler.timerID = fn.timerID;
|
||||
|
||||
if (!timers[label][fn.timerID])
|
||||
timers[label][fn.timerID] = window.setInterval(handler,interval);
|
||||
|
||||
this.global.push( element );
|
||||
|
||||
},
|
||||
remove: function(element, label, fn) {
|
||||
var timers = jQuery.data(element, this.dataKey), ret;
|
||||
|
||||
if ( timers ) {
|
||||
|
||||
if (!label) {
|
||||
for ( label in timers )
|
||||
this.remove(element, label, fn);
|
||||
} else if ( timers[label] ) {
|
||||
if ( fn ) {
|
||||
if ( fn.timerID ) {
|
||||
window.clearInterval(timers[label][fn.timerID]);
|
||||
delete timers[label][fn.timerID];
|
||||
}
|
||||
} else {
|
||||
for ( var fn in timers[label] ) {
|
||||
window.clearInterval(timers[label][fn]);
|
||||
delete timers[label][fn];
|
||||
}
|
||||
}
|
||||
|
||||
for ( ret in timers[label] ) break;
|
||||
if ( !ret ) {
|
||||
ret = null;
|
||||
delete timers[label];
|
||||
}
|
||||
}
|
||||
|
||||
for ( ret in timers ) break;
|
||||
if ( !ret )
|
||||
jQuery.removeData(element, this.dataKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
jQuery(window).bind("unload", function() {
|
||||
jQuery.each(jQuery.timer.global, function(index, item) {
|
||||
jQuery.timer.remove(item);
|
||||
});
|
||||
});
|
||||
@@ -1,112 +0,0 @@
|
||||
// NanoBaseCallbacks is where the base callbacks (common to all templates) are stored
|
||||
NanoBaseCallbacks = function ()
|
||||
{
|
||||
// _canClick is used to disable clicks for a short period after each click (to avoid mis-clicks)
|
||||
var _canClick = true;
|
||||
var _baseBeforeUpdateCallbacks = {};
|
||||
var _baseAfterUpdateCallbacks = {
|
||||
// this callback is triggered after new data is processed
|
||||
// it updates the status/visibility icon and adds click event handling to buttons/links
|
||||
status: function (updateData) {
|
||||
var uiStatusClass;
|
||||
if (updateData['config']['status'] == 2)
|
||||
{
|
||||
uiStatusClass = 'good';
|
||||
$('.linkActive').removeClass('inactive');
|
||||
}
|
||||
else if (updateData['config']['status'] == 1)
|
||||
{
|
||||
uiStatusClass = 'average';
|
||||
$('.linkActive').addClass('inactive');
|
||||
}
|
||||
else
|
||||
{
|
||||
uiStatusClass = 'bad';
|
||||
$('.linkActive').addClass('inactive');
|
||||
}
|
||||
$('.statusicon').removeClass("good bad average").addClass(uiStatusClass);
|
||||
$('.linkActive').stopTime('linkPending');
|
||||
$('.linkActive').removeClass('linkPending');
|
||||
|
||||
$('.linkActive')
|
||||
.off('click')
|
||||
.on('click', function (event) {
|
||||
event.preventDefault();
|
||||
var href = $(this).data('href');
|
||||
if(href != null && _canClick)
|
||||
{
|
||||
_canClick = false;
|
||||
$('body').oneTime(300, 'enableClick', function () {
|
||||
_canClick = true;
|
||||
});
|
||||
if (updateData['config']['status'] == 2)
|
||||
{
|
||||
$(this).oneTime(300, 'linkPending', function () {
|
||||
$(this).addClass('linkPending');
|
||||
});
|
||||
}
|
||||
window.location.href = href;
|
||||
}
|
||||
});
|
||||
|
||||
return updateData;
|
||||
},
|
||||
nanomap: function (updateData) {
|
||||
$('.mapIcon')
|
||||
.off('mouseenter mouseleave')
|
||||
.on('mouseenter',
|
||||
function (event) {
|
||||
var self = this;
|
||||
$('#uiMapTooltip')
|
||||
.html($(this).children('.tooltip').html())
|
||||
.show()
|
||||
.stopTime()
|
||||
.oneTime(5000, 'hideTooltip', function () {
|
||||
$(this).fadeOut(500);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
$('.zoomLink')
|
||||
.off('click')
|
||||
.on('click', function (event) {
|
||||
event.preventDefault();
|
||||
var zoomLevel = $(this).data('zoomLevel');
|
||||
var uiMapObject = $('#uiMap');
|
||||
var uiMapWidth = uiMapObject.width() * zoomLevel;
|
||||
var uiMapHeight = uiMapObject.height() * zoomLevel;
|
||||
|
||||
uiMapObject.css({
|
||||
zoom: zoomLevel,
|
||||
left: '50%',
|
||||
top: '50%',
|
||||
marginLeft: '-' + Math.floor(uiMapWidth / 2) + 'px',
|
||||
marginTop: '-' + Math.floor(uiMapHeight / 2) + 'px'
|
||||
});
|
||||
});
|
||||
|
||||
$('#uiMapImage').attr('src',updateData['config']['map'] + '_nanomap_z' + updateData['config']['mapZLevel'] + '.png');
|
||||
|
||||
return updateData;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
addCallbacks: function () {
|
||||
NanoStateManager.addBeforeUpdateCallbacks(_baseBeforeUpdateCallbacks);
|
||||
NanoStateManager.addAfterUpdateCallbacks(_baseAfterUpdateCallbacks);
|
||||
},
|
||||
removeCallbacks: function () {
|
||||
for (var callbackKey in _baseBeforeUpdateCallbacks) {
|
||||
if (_baseBeforeUpdateCallbacks.hasOwnProperty(callbackKey)) {
|
||||
NanoStateManager.removeBeforeUpdateCallback(callbackKey);
|
||||
}
|
||||
}
|
||||
for (var callbackKey in _baseAfterUpdateCallbacks) {
|
||||
if (_baseAfterUpdateCallbacks.hasOwnProperty(callbackKey)) {
|
||||
NanoStateManager.removeAfterUpdateCallback(callbackKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}();
|
||||
@@ -1,280 +0,0 @@
|
||||
// NanoBaseHelpers is where the base template helpers (common to all templates) are stored
|
||||
NanoBaseHelpers = function ()
|
||||
{
|
||||
var _baseHelpers = {
|
||||
// change ui styling to "syndicate mode"
|
||||
syndicateMode: function() {
|
||||
$('.mainBG').css("background", "url('syndicate.png') no-repeat fixed center/50% 50%, linear-gradient(to bottom, #8f1414 0%, #4B0A0A 100%) no-repeat fixed center;");
|
||||
|
||||
$('#uiTitleFluff').css("background-image","url('uiTitleFluff-Syndicate.png')");
|
||||
$('#uiTitleFluff').css("background-position","50% 50%");
|
||||
$('#uiTitleFluff').css("background-repeat", "no-repeat");
|
||||
|
||||
return '';
|
||||
},
|
||||
|
||||
combine: function( arr1, arr2 ) {
|
||||
return arr1 && arr2 ? arr1.concat(arr2) : arr1 || arr2;
|
||||
},
|
||||
dump: function( arr1 ) {
|
||||
return JSON.stringify(arr1);
|
||||
},
|
||||
|
||||
// Generate a Byond link
|
||||
link: function( text, icon, parameters, status, elementClass, elementId ) {
|
||||
var iconHtml = '';
|
||||
var iconClass = 'noIcon';
|
||||
if (typeof icon != 'undefined' && icon)
|
||||
{
|
||||
iconHtml = '<div class="uiLinkPendingIcon"></div><i class="fa fa-fw fa-' + icon + '"></i>';
|
||||
iconClass = 'hasIcon';
|
||||
}
|
||||
|
||||
if (typeof elementClass == 'undefined' || !elementClass)
|
||||
{
|
||||
elementClass = 'link';
|
||||
}
|
||||
|
||||
var elementIdHtml = '';
|
||||
if (typeof elementId != 'undefined' && elementId)
|
||||
{
|
||||
elementIdHtml = 'id="' + elementId + '"';
|
||||
}
|
||||
|
||||
var tid = NanoTransition.allocID(elementIdHtml + "_" + text.toString().replace(/[^a-z0-9_]/gi, "_") + "_" + icon);
|
||||
|
||||
if (typeof status != 'undefined' && status)
|
||||
{
|
||||
return '<div unselectable="on" class="link ' + iconClass + ' ' + tid + '" ' + elementIdHtml + '>' + iconHtml + text + '</div><script>$(function() { var newState = {"..class": "' + elementClass + ' ' + status + '"}; var old = NanoTransition.transitionElement("' + tid + '", null, newState, 200); NanoTransition.animateHover("' + tid + '", null, old, newState); });</script>';
|
||||
}
|
||||
|
||||
return '<div unselectable="on" class="linkActive ' + iconClass + ' ' + tid + '" data-href="' + NanoUtility.generateHref(parameters) + '" ' + elementIdHtml + '>' + iconHtml + text + '</div><script>$(function() { var newState = {"..class": "' + elementClass + '"}; var old = NanoTransition.transitionElement("' + tid + '", null, newState, 200); NanoTransition.animateHover("' + tid + '", null, old, newState); });</script>';
|
||||
},
|
||||
|
||||
xor: function (number,bit) {
|
||||
return number ^ bit;
|
||||
},
|
||||
|
||||
precisionRound: function (value, places) {
|
||||
if(places == 0){
|
||||
return Math.round(number);
|
||||
}
|
||||
var multiplier = Math.pow(10, places);
|
||||
return (Math.round(value * multiplier) / multiplier);
|
||||
},
|
||||
|
||||
// Round a number to the nearest integer
|
||||
round: function(number) {
|
||||
return Math.round(number);
|
||||
},
|
||||
fixed: function(number) {
|
||||
return Math.round(number * 10) / 10;
|
||||
},
|
||||
// Round a number down to integer
|
||||
floor: function(number) {
|
||||
return Math.floor(number);
|
||||
},
|
||||
// Round a number up to integer
|
||||
ceil: function(number) {
|
||||
return Math.ceil(number);
|
||||
},
|
||||
|
||||
// Format a string (~string("Hello {0}, how are {1}?", 'Martin', 'you') becomes "Hello Martin, how are you?")
|
||||
string: function() {
|
||||
if (arguments.length == 0)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
else if (arguments.length == 1)
|
||||
{
|
||||
return arguments[0];
|
||||
}
|
||||
else if (arguments.length > 1)
|
||||
{
|
||||
stringArgs = [];
|
||||
for (var i = 1; i < arguments.length; i++)
|
||||
{
|
||||
stringArgs.push(arguments[i]);
|
||||
}
|
||||
return arguments[0].format(stringArgs);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
formatNumber: function(x) {
|
||||
// From http://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript
|
||||
var parts = x.toString().split(".");
|
||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
return parts.join(".");
|
||||
},
|
||||
// Capitalize the first letter of a string. From http://stackoverflow.com/questions/1026069/capitalize-the-first-letter-of-string-in-javascript
|
||||
capitalizeFirstLetter: function( string ) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
},
|
||||
// Display a bar. Used to show health, capacity, etc.
|
||||
displayBar: function( value, rangeMin, rangeMax, styleClass, showText ) {
|
||||
|
||||
if (rangeMin < rangeMax)
|
||||
{
|
||||
if (value < rangeMin)
|
||||
{
|
||||
value = rangeMin;
|
||||
}
|
||||
else if (value > rangeMax)
|
||||
{
|
||||
value = rangeMax;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value > rangeMin)
|
||||
{
|
||||
value = rangeMin;
|
||||
}
|
||||
else if (value < rangeMax)
|
||||
{
|
||||
value = rangeMax;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof styleClass == 'undefined' || !styleClass)
|
||||
{
|
||||
styleClass = '';
|
||||
}
|
||||
|
||||
if (typeof showText == 'undefined' || !showText)
|
||||
{
|
||||
showText = '';
|
||||
}
|
||||
|
||||
var percentage = Math.round((value - rangeMin) / (rangeMax - rangeMin) * 100);
|
||||
var tid = NanoTransition.allocID(rangeMin + "_" + rangeMax);
|
||||
|
||||
return '<div class="displayBar ' + tid + ' ' + styleClass + '"><div class="displayBarFill"></div><div class="displayBarText ' + styleClass + '">' + showText + '</div></div><script>$(function() { NanoTransition.transitionElement("' + tid + '", ".displayBarFill", {width: "' + percentage + '%", "..class": "' + styleClass + '"}); });</script>';
|
||||
},
|
||||
// Convert danger level to class (for the air alarm)
|
||||
dangerToClass: function(level) {
|
||||
if(level == 0) return 'good';
|
||||
if(level == 1) return 'average';
|
||||
return 'bad';
|
||||
},
|
||||
dangerToSpan: function(level) {
|
||||
if(level == 0) return '"<span class="good">Good</span>"';
|
||||
if(level == 1) return '"<span class="average">Minor Alert</span>"';
|
||||
return '"<span class="bad">Major Alert</span>"';
|
||||
},
|
||||
generateHref: function (parameters) {
|
||||
var body = $('body'); // For some fucking reason, data is stored in the body tag.
|
||||
_urlParameters = body.data('urlParameters');
|
||||
var queryString = '?';
|
||||
|
||||
for (var key in _urlParameters)
|
||||
{
|
||||
if (_urlParameters.hasOwnProperty(key))
|
||||
{
|
||||
if (queryString !== '?')
|
||||
{
|
||||
queryString += ';';
|
||||
}
|
||||
queryString += key + '=' + _urlParameters[key];
|
||||
}
|
||||
}
|
||||
|
||||
for (var key in parameters)
|
||||
{
|
||||
if (parameters.hasOwnProperty(key))
|
||||
{
|
||||
if (queryString !== '?')
|
||||
{
|
||||
queryString += ';';
|
||||
}
|
||||
queryString += key + '=' + parameters[key];
|
||||
}
|
||||
}
|
||||
return queryString;
|
||||
},
|
||||
// Display DNA Blocks (for the DNA Modifier UI)
|
||||
displayDNABlocks: function(dnaString, selectedBlock, selectedSubblock, blockSize, paramKey) {
|
||||
if (!dnaString)
|
||||
{
|
||||
return '<div class="notice">Please place a valid subject into the DNA modifier.</div>';
|
||||
}
|
||||
|
||||
var characters = dnaString.split('');
|
||||
|
||||
var html = '<div class="dnaBlock"><div class="link dnaBlockNumber">1</div>';
|
||||
var block = 1;
|
||||
var subblock = 1;
|
||||
for (var index in characters) {
|
||||
if (!characters.hasOwnProperty(index) || typeof characters[index] === 'object')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var parameters;
|
||||
if (paramKey.toUpperCase() == 'UI'){
|
||||
parameters = { 'selectUIBlock' : block, 'selectUISubblock' : subblock };
|
||||
} else {
|
||||
parameters = { 'selectSEBlock' : block, 'selectSESubblock' : subblock };
|
||||
}
|
||||
|
||||
var status = 'linkActive';
|
||||
if (block == selectedBlock && subblock == selectedSubblock) {
|
||||
status = 'selected';
|
||||
}
|
||||
|
||||
html += '<div class="link ' + status + ' dnaSubBlock" data-href="' + NanoUtility.generateHref(parameters) + '" id="dnaBlock' + index + '">' + characters[index] + '</div>';
|
||||
|
||||
index++;
|
||||
if (index % blockSize == 0 && index < characters.length) {
|
||||
block++;
|
||||
subblock = 1;
|
||||
html += '</div><div class="dnaBlock"><div class="link dnaBlockNumber">' + block + '</div>';
|
||||
} else {
|
||||
subblock++;
|
||||
}
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
||||
return html;
|
||||
},
|
||||
cMirror: function(textbox) {
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById(textbox), {
|
||||
lineNumbers: true,
|
||||
indentUnit: 4,
|
||||
indentWithTabs: true,
|
||||
theme: "lesser-dark"
|
||||
});
|
||||
},
|
||||
smoothNumber: function(number) {
|
||||
var tid = NanoTransition.allocID("n");
|
||||
|
||||
return '<span class="' + tid + '"></span><script>$(function() { var newState = {value: ' + number + '}; var old = NanoTransition.updateElement("' + tid + '", newState); NanoTransition.animateTextValue("' + tid + '", null, -1, old["value"], newState["value"]); });</script>';
|
||||
},
|
||||
smoothRound: function(number, places) {
|
||||
var tid = NanoTransition.allocID(places);
|
||||
if(places === undefined)
|
||||
placed = 0;
|
||||
|
||||
return '<span class="' + tid + '"></span><script>$(function() { var newState = {value: ' + number.toFixed(places) + '}; var old = NanoTransition.updateElement("' + tid + '", newState); NanoTransition.animateTextValue("' + tid + '", null, ' + places + ', old["value"], newState["value"]); });</script>';
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
addHelpers: function ()
|
||||
{
|
||||
NanoTemplate.addHelpers(_baseHelpers);
|
||||
},
|
||||
|
||||
removeHelpers: function ()
|
||||
{
|
||||
for (var helperKey in _baseHelpers)
|
||||
{
|
||||
if (_baseHelpers.hasOwnProperty(helperKey))
|
||||
{
|
||||
NanoTemplate.removeHelper(helperKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}();
|
||||
@@ -1,107 +0,0 @@
|
||||
// This is the base state class, it is not to be used directly
|
||||
|
||||
function NanoStateClass() {}
|
||||
|
||||
NanoStateClass.prototype.key = null;
|
||||
NanoStateClass.prototype.layoutRendered = false;
|
||||
NanoStateClass.prototype.contentRendered = false;
|
||||
NanoStateClass.prototype.mapInitialised = false;
|
||||
|
||||
NanoStateClass.prototype.isCurrent = function () {
|
||||
return NanoStateManager.getCurrentState() == this;
|
||||
};
|
||||
|
||||
NanoStateClass.prototype.onAdd = function (previousState) {
|
||||
// Do not add code here, add it to the 'default' state (nano_state_defaut.js) or create a new state and override this function
|
||||
|
||||
NanoBaseCallbacks.addCallbacks();
|
||||
NanoBaseHelpers.addHelpers();
|
||||
};
|
||||
|
||||
NanoStateClass.prototype.onRemove = function (nextState) {
|
||||
// Do not add code here, add it to the 'default' state (nano_state_defaut.js) or create a new state and override this function
|
||||
|
||||
NanoBaseCallbacks.removeCallbacks();
|
||||
NanoBaseHelpers.removeHelpers();
|
||||
};
|
||||
|
||||
NanoStateClass.prototype.onBeforeUpdate = function (data) {
|
||||
// Do not add code here, add it to the 'default' state (nano_state_defaut.js) or create a new state and override this function
|
||||
|
||||
data = NanoStateManager.executeBeforeUpdateCallbacks(data);
|
||||
|
||||
return data; // Return data to continue, return false to prevent onUpdate and onAfterUpdate
|
||||
};
|
||||
|
||||
NanoStateClass.prototype.onUpdate = function (data) {
|
||||
// Do not add code here, add it to the 'default' state (nano_state_defaut.js) or create a new state and override this function
|
||||
|
||||
try
|
||||
{
|
||||
if (!this.layoutRendered || (data['config'].hasOwnProperty('autoUpdateLayout') && data['config']['autoUpdateLayout']))
|
||||
{
|
||||
$("#uiLayout").html(NanoTemplate.parse('layout', data)); // render the 'mail' template to the #mainTemplate div
|
||||
this.layoutRendered = true;
|
||||
}
|
||||
if (!this.contentRendered || (data['config'].hasOwnProperty('autoUpdateContent') && data['config']['autoUpdateContent']))
|
||||
{
|
||||
$("#uiContent").html(NanoTemplate.parse('main', data)); // render the 'mail' template to the #mainTemplate div
|
||||
this.contentRendered = true;
|
||||
}
|
||||
if (NanoTemplate.templateExists('mapContent'))
|
||||
{
|
||||
if (!this.mapInitialised)
|
||||
{
|
||||
// Add drag functionality to the map ui
|
||||
$('#uiMap').draggable();
|
||||
|
||||
$('#uiMapTooltip')
|
||||
.off('click')
|
||||
.on('click', function (event) {
|
||||
event.preventDefault();
|
||||
$(this).fadeOut(400);
|
||||
});
|
||||
|
||||
this.mapInitialised = true;
|
||||
}
|
||||
|
||||
$("#uiMapContent").html(NanoTemplate.parse('mapContent', data)); // render the 'mapContent' template to the #uiMapContent div
|
||||
|
||||
if (data['config'].hasOwnProperty('showMap') && data['config']['showMap'])
|
||||
{
|
||||
$('#uiContent').addClass('hidden');
|
||||
$('#uiMapWrapper').removeClass('hidden');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#uiMapWrapper').addClass('hidden');
|
||||
$('#uiContent').removeClass('hidden');
|
||||
}
|
||||
}
|
||||
if (NanoTemplate.templateExists('mapHeader'))
|
||||
{
|
||||
$("#uiMapHeader").html(NanoTemplate.parse('mapHeader', data)); // render the 'mapHeader' template to the #uiMapHeader div
|
||||
}
|
||||
if (NanoTemplate.templateExists('mapFooter'))
|
||||
{
|
||||
$("#uiMapFooter").html(NanoTemplate.parse('mapFooter', data)); // render the 'mapFooter' template to the #uiMapFooter div
|
||||
}
|
||||
}
|
||||
catch(error)
|
||||
{
|
||||
reportError('ERROR: An error occurred while rendering the UI: ' + error.message);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
NanoStateClass.prototype.onAfterUpdate = function (data) {
|
||||
// Do not add code here, add it to the 'default' state (nano_state_defaut.js) or create a new state and override this function
|
||||
|
||||
NanoStateManager.executeAfterUpdateCallbacks(data);
|
||||
};
|
||||
|
||||
NanoStateClass.prototype.alertText = function (text) {
|
||||
// Do not add code here, add it to the 'default' state (nano_state_defaut.js) or create a new state and override this function
|
||||
|
||||
alert(text);
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
NanoStateDefaultClass.inheritsFrom(NanoStateClass);
|
||||
var NanoStateDefault = new NanoStateDefaultClass();
|
||||
|
||||
function NanoStateDefaultClass() {
|
||||
|
||||
this.key = 'default';
|
||||
|
||||
//this.parent.constructor.call(this);
|
||||
|
||||
this.key = this.key.toLowerCase();
|
||||
|
||||
NanoStateManager.addState(this);
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
// NanoStateManager handles data from the server and uses it to render templates
|
||||
NanoStateManager = function ()
|
||||
{
|
||||
// _isInitialised is set to true when all of this ui's templates have been processed/rendered
|
||||
var _isInitialised = false;
|
||||
// the data for this ui
|
||||
var _data = null;
|
||||
|
||||
// this is an array of callbacks which are called when new data arrives, before it is processed
|
||||
var _beforeUpdateCallbacks = {};
|
||||
// this is an array of callbacks which are called when new data arrives, before it is processed
|
||||
var _afterUpdateCallbacks = {};
|
||||
|
||||
// this is an array of state objects, these can be used to provide custom javascript logic
|
||||
var _states = {};
|
||||
var _currentState = null;
|
||||
|
||||
// the init function is called when the ui has loaded
|
||||
// this function sets up the templates and base functionality
|
||||
var init = function ()
|
||||
{
|
||||
// We store initialData and templateData in the body tag, it's as good a place as any
|
||||
_data = $('body').data('initialData');
|
||||
|
||||
if (_data == null || !_data.hasOwnProperty('config') || !_data.hasOwnProperty('data'))
|
||||
{
|
||||
reportError('Error: Initial data did not load correctly.' + JSON.stringify(_data));
|
||||
}
|
||||
|
||||
var stateKey = 'default';
|
||||
if (_data['config'].hasOwnProperty('stateKey') && _data['config']['stateKey'])
|
||||
{
|
||||
stateKey = _data['config']['stateKey'].toLowerCase();
|
||||
}
|
||||
|
||||
NanoStateManager.setCurrentState(stateKey);
|
||||
|
||||
$(document).on('templatesLoaded', function () {
|
||||
doUpdate(_data);
|
||||
|
||||
_isInitialised = true;
|
||||
});
|
||||
};
|
||||
|
||||
// Receive update data from the server
|
||||
var receiveUpdateData = function (jsonString)
|
||||
{
|
||||
var updateData;
|
||||
|
||||
// reportError("recieveUpdateData called." + "<br>Type: " + typeof jsonString); //debug hook
|
||||
try
|
||||
{
|
||||
// parse the JSON string from the server into a JSON object
|
||||
updateData = jQuery.parseJSON(jsonString);
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
reportError("recieveUpdateData failed. " + "<br>Error name: " + error.name + "<br>Error Message: " + error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// reportError("recieveUpdateData passed trycatch block."); //debug hook
|
||||
|
||||
if (!updateData.hasOwnProperty('data'))
|
||||
{
|
||||
if (_data && _data.hasOwnProperty('data'))
|
||||
{
|
||||
updateData['data'] = _data['data'];
|
||||
}
|
||||
else
|
||||
{
|
||||
updateData['data'] = {};
|
||||
}
|
||||
}
|
||||
|
||||
if (_isInitialised) // all templates have been registered, so render them
|
||||
{
|
||||
doUpdate(updateData);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data = updateData; // all templates have not been registered. We set _data directly here which will be applied after the template is loaded with the initial data
|
||||
}
|
||||
};
|
||||
|
||||
// This function does the update by calling the methods on the current state
|
||||
var doUpdate = function (data)
|
||||
{
|
||||
if (_currentState == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data = _currentState.onBeforeUpdate(data);
|
||||
|
||||
if (data === false)
|
||||
{
|
||||
reportError('data is false, return');
|
||||
return; // A beforeUpdateCallback returned a false value, this prevents the render from occuring
|
||||
}
|
||||
|
||||
_data = data;
|
||||
|
||||
_currentState.onUpdate(_data);
|
||||
|
||||
_currentState.onAfterUpdate(_data);
|
||||
};
|
||||
|
||||
// Execute all callbacks in the callbacks array/object provided, updateData is passed to them for processing and potential modification
|
||||
var executeCallbacks = function (callbacks, data)
|
||||
{
|
||||
for (var key in callbacks)
|
||||
{
|
||||
if (callbacks.hasOwnProperty(key) && jQuery.isFunction(callbacks[key]))
|
||||
{
|
||||
data = callbacks[key].call(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
return {
|
||||
init: function ()
|
||||
{
|
||||
init();
|
||||
},
|
||||
receiveUpdateData: function (jsonString)
|
||||
{
|
||||
receiveUpdateData(jsonString);
|
||||
},
|
||||
addBeforeUpdateCallback: function (key, callbackFunction)
|
||||
{
|
||||
_beforeUpdateCallbacks[key] = callbackFunction;
|
||||
},
|
||||
addBeforeUpdateCallbacks: function (callbacks) {
|
||||
for (var callbackKey in callbacks) {
|
||||
if (!callbacks.hasOwnProperty(callbackKey))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
NanoStateManager.addBeforeUpdateCallback(callbackKey, callbacks[callbackKey]);
|
||||
}
|
||||
},
|
||||
removeBeforeUpdateCallback: function (key)
|
||||
{
|
||||
if (_beforeUpdateCallbacks.hasOwnProperty(key))
|
||||
{
|
||||
delete _beforeUpdateCallbacks[key];
|
||||
}
|
||||
},
|
||||
executeBeforeUpdateCallbacks: function (data) {
|
||||
return executeCallbacks(_beforeUpdateCallbacks, data);
|
||||
},
|
||||
addAfterUpdateCallback: function (key, callbackFunction)
|
||||
{
|
||||
_afterUpdateCallbacks[key] = callbackFunction;
|
||||
},
|
||||
addAfterUpdateCallbacks: function (callbacks) {
|
||||
for (var callbackKey in callbacks) {
|
||||
if (!callbacks.hasOwnProperty(callbackKey))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
NanoStateManager.addAfterUpdateCallback(callbackKey, callbacks[callbackKey]);
|
||||
}
|
||||
},
|
||||
removeAfterUpdateCallback: function (key)
|
||||
{
|
||||
if (_afterUpdateCallbacks.hasOwnProperty(key))
|
||||
{
|
||||
delete _afterUpdateCallbacks[key];
|
||||
}
|
||||
},
|
||||
executeAfterUpdateCallbacks: function (data) {
|
||||
return executeCallbacks(_afterUpdateCallbacks, data);
|
||||
},
|
||||
addState: function (state)
|
||||
{
|
||||
if (!(state instanceof NanoStateClass))
|
||||
{
|
||||
reportError('ERROR: Attempted to add a state which is not instanceof NanoStateClass');
|
||||
return;
|
||||
}
|
||||
if (!state.key)
|
||||
{
|
||||
reportError('ERROR: Attempted to add a state with an invalid stateKey');
|
||||
return;
|
||||
}
|
||||
_states[state.key] = state;
|
||||
},
|
||||
setCurrentState: function (stateKey)
|
||||
{
|
||||
if (typeof stateKey == 'undefined' || !stateKey) {
|
||||
reportError('ERROR: No state key was passed!');
|
||||
return false;
|
||||
}
|
||||
if (!_states.hasOwnProperty(stateKey))
|
||||
{
|
||||
reportError('ERROR: Attempted to set a current state which does not exist: ' + stateKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
var previousState = _currentState;
|
||||
|
||||
_currentState = _states[stateKey];
|
||||
|
||||
if (previousState != null) {
|
||||
previousState.onRemove(_currentState);
|
||||
}
|
||||
|
||||
_currentState.onAdd(previousState);
|
||||
|
||||
return true;
|
||||
},
|
||||
getCurrentState: function ()
|
||||
{
|
||||
return _currentState;
|
||||
},
|
||||
getData: function ()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
};
|
||||
} ();
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
NanoStatePDAClass.inheritsFrom(NanoStateClass);
|
||||
var NanoStatePDA = new NanoStatePDAClass();
|
||||
|
||||
function NanoStatePDAClass() {
|
||||
this.key = 'pda';
|
||||
this.key = this.key.toLowerCase();
|
||||
this.current_template = "";
|
||||
|
||||
NanoStateManager.addState(this);
|
||||
}
|
||||
|
||||
NanoStatePDAClass.prototype.onUpdate = function(data) {
|
||||
NanoStateClass.prototype.onUpdate.call(this, data);
|
||||
var state = this;
|
||||
|
||||
try {
|
||||
if(data['data']['app'] != null) {
|
||||
var template = data['data']['app']['template'];
|
||||
if(template != null && template != state.current_template) {
|
||||
$.when($.ajax({
|
||||
url: template + '.tmpl',
|
||||
cache: false,
|
||||
dataType: 'text'
|
||||
}))
|
||||
.done(function(templateMarkup) {
|
||||
templateMarkup += '<div class="clearBoth"></div>';
|
||||
|
||||
try {
|
||||
NanoTemplate.addTemplate('app', templateMarkup);
|
||||
NanoTemplate.resetTemplate('app');
|
||||
$("#uiApp").html(NanoTemplate.parse('app', data));
|
||||
state.current_template = template;
|
||||
|
||||
state.onAfterUpdate(data);
|
||||
} catch(error) {
|
||||
reportError('ERROR: An error occurred while loading the PDA App UI: ' + error.message);
|
||||
return;
|
||||
}
|
||||
})
|
||||
.fail( function () {
|
||||
reportError('ERROR: Loading template app(' + template + ') failed!');
|
||||
});
|
||||
} else {
|
||||
if (NanoTemplate.templateExists('app')) {
|
||||
$("#uiApp").html(NanoTemplate.parse('app', data));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(error) {
|
||||
reportError('ERROR: An error occurred while rendering the PDA App UI: ' + error.message);
|
||||
return;
|
||||
}
|
||||
}
|
||||