WI folders and WI drag-and-drop

This commit is contained in:
Gnome Ann 2021-12-04 23:59:28 -05:00
parent 9e3318c696
commit b99ac92a52
6 changed files with 688 additions and 77 deletions

View File

@ -86,7 +86,9 @@ class vars:
authornote = "" # Text submitted to Author's Note field
andepth = 3 # How far back in history to append author's note
actions = structures.KoboldStoryRegister() # Actions submitted by user and AI
worldinfo = [] # Array of World Info key/value objects
worldinfo = [] # List of World Info key/value objects
wifolders_d = {} # Dictionary of World Info folder UID-info pairs
wifolders_l = [] # List of World Info folder UIDs
# badwords = [] # Array of str/chr values that should be removed from output
badwordsids = [[13460], [6880], [50256], [42496], [4613], [17414], [22039], [16410], [27], [29], [38430], [37922], [15913], [24618], [28725], [58], [47175], [36937], [26700], [12878], [16471], [37981], [5218], [29795], [13412], [45160], [3693], [49778], [4211], [20598], [36475], [33409], [44167], [32406], [29847], [29342], [42669], [685], [25787], [7359], [3784], [5320], [33994], [33490], [34516], [43734], [17635], [24293], [9959], [23785], [21737], [28401], [18161], [26358], [32509], [1279], [38155], [18189], [26894], [6927], [14610], [23834], [11037], [14631], [26933], [46904], [22330], [25915], [47934], [38214], [1875], [14692], [41832], [13163], [25970], [29565], [44926], [19841], [37250], [49029], [9609], [44438], [16791], [17816], [30109], [41888], [47527], [42924], [23984], [49074], [33717], [31161], [49082], [30138], [31175], [12240], [14804], [7131], [26076], [33250], [3556], [38381], [36338], [32756], [46581], [17912], [49146]] # Tokenized array of badwords used to prevent AI artifacting
deletewi = -1 # Temporary storage for index to delete
@ -858,6 +860,8 @@ def download():
"key": wi["key"],
"keysecondary": wi["keysecondary"],
"content": wi["content"],
"comment": wi["comment"],
"folder": wi["folder"],
"selective": wi["selective"],
"constant": wi["constant"]
})
@ -1055,17 +1059,49 @@ def get_message(msg):
elif(msg['cmd'] == 'wiinit'):
if(int(msg['data']) < len(vars.worldinfo)):
vars.worldinfo[msg['data']]["init"] = True
addwiitem()
addwiitem(folder_uid=msg['folder'])
elif(msg['cmd'] == 'wifolderinit'):
addwifolder()
elif(msg['cmd'] == 'wimoveitem'):
movewiitem(msg['destination'], msg['data'])
elif(msg['cmd'] == 'wimovefolder'):
movewifolder(msg['destination'], msg['data'])
elif(msg['cmd'] == 'widelete'):
deletewi(msg['data'])
elif(msg['cmd'] == 'wifolderdelete'):
deletewifolder(msg['data'])
elif(msg['cmd'] == 'wiexpand'):
assert 0 <= int(msg['data']) < len(vars.worldinfo)
emit('from_server', {'cmd': 'wiexpand', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wiexpandfolder'):
assert 0 <= int(msg['data']) < len(vars.worldinfo)
emit('from_server', {'cmd': 'wiexpandfolder', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wiupdate'):
num = int(msg['num'])
fields = ("key", "keysecondary", "content", "comment")
for field in fields:
if(field in msg['data'] and type(msg['data'][field]) is str):
vars.worldinfo[num][field] = msg['data'][field]
emit('from_server', {'cmd': 'wiupdate', 'num': msg['num'], 'data': {field: vars.worldinfo[num][field] for field in fields}}, broadcast=True)
elif(msg['cmd'] == 'wifolderupdate'):
uid = int(msg['uid'])
fields = ("name", "collapsed")
for field in fields:
if(field in msg['data'] and type(msg['data'][field]) is (str if field != "collapsed" else bool)):
vars.wifolders_d[uid][field] = msg['data'][field]
emit('from_server', {'cmd': 'wifolderupdate', 'uid': msg['uid'], 'data': {field: vars.wifolders_d[uid][field] for field in fields}}, broadcast=True)
elif(msg['cmd'] == 'wiselon'):
vars.worldinfo[msg['data']]["selective"] = True
emit('from_server', {'cmd': 'wiselon', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wiseloff'):
vars.worldinfo[msg['data']]["selective"] = False
emit('from_server', {'cmd': 'wiseloff', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wiconstanton'):
vars.worldinfo[msg['data']]["constant"] = True
emit('from_server', {'cmd': 'wiconstanton', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wiconstantoff'):
vars.worldinfo[msg['data']]["constant"] = False
emit('from_server', {'cmd': 'wiconstantoff', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'sendwilist'):
commitwi(msg['data'])
elif(msg['cmd'] == 'aidgimport'):
@ -2104,32 +2140,76 @@ def togglewimode():
#==================================================================#
#
#==================================================================#
def addwiitem():
ob = {"key": "", "keysecondary": "", "content": "", "num": len(vars.worldinfo), "init": False, "selective": False, "constant": False}
vars.worldinfo.append(ob);
def addwiitem(folder_uid=None):
assert folder_uid is None or folder_uid in vars.wifolders_d
ob = {"key": "", "keysecondary": "", "content": "", "comment": "", "folder": folder_uid, "num": len(vars.worldinfo), "init": False, "selective": False, "constant": False}
vars.worldinfo.append(ob)
emit('from_server', {'cmd': 'addwiitem', 'data': ob}, broadcast=True)
#==================================================================#
# Creates a new WI folder with an unused cryptographically secure random UID
#==================================================================#
def addwifolder():
while(True):
uid = int.from_bytes(os.urandom(4), "little", signed=True)
if(uid not in vars.wifolders_d):
break
ob = {"name": "", "collapsed": False}
vars.wifolders_d[uid] = ob
vars.wifolders_l.append(uid)
emit('from_server', {'cmd': 'addwifolder', 'uid': uid, 'data': ob}, broadcast=True)
addwiitem(folder_uid=uid)
#==================================================================#
# Move the WI entry with number src so that it immediately precedes
# the WI entry with number dst
#==================================================================#
def movewiitem(dst, src):
vars.worldinfo[src]["folder"] = vars.worldinfo[dst]["folder"]
vars.worldinfo.insert(dst - (dst >= src), vars.worldinfo.pop(src))
sendwi()
#==================================================================#
# Move the WI folder with UID src so that it immediately precedes
# the WI folder with UID dst
#==================================================================#
def movewifolder(dst, src):
vars.wifolders_l.remove(src)
if(dst is None):
# If dst is None, that means we should move src to be the last folder
vars.wifolders_l.append(src)
else:
vars.wifolders_l.insert(vars.wifolders_l.index(dst), src)
sendwi()
#==================================================================#
#
#==================================================================#
def sendwi():
# Cache len of WI
ln = len(vars.worldinfo)
# Clear contents of WI container
emit('from_server', {'cmd': 'clearwi', 'data': ''}, broadcast=True)
emit('from_server', {'cmd': 'wistart', 'wifolders_d': vars.wifolders_d, 'wifolders_l': vars.wifolders_l, 'data': ''}, broadcast=True)
# Stable-sort WI entries in order of folder
stablesortwi()
# If there are no WI entries, send an empty WI object
if(ln == 0):
addwiitem()
else:
# Send contents of WI array
organizewi()
last_folder = ...
for wi in vars.worldinfo:
if(wi["folder"] != last_folder):
emit('from_server', {'cmd': 'addwifolder', 'uid': wi["folder"], 'data': vars.wifolders_d[wi["folder"]] if wi["folder"] is not None else None}, broadcast=True)
last_folder = wi["folder"]
ob = wi
emit('from_server', {'cmd': 'addwiitem', 'data': ob}, broadcast=True)
# Make sure last WI item is uninitialized
if(vars.worldinfo[-1]["init"]):
addwiitem()
emit('from_server', {'cmd': 'wifinish', 'data': ''}, broadcast=True)
#==================================================================#
# Request current contents of all WI HTML elements
@ -2140,6 +2220,25 @@ def requestwi():
list.append(wi["num"])
emit('from_server', {'cmd': 'requestwiitem', 'data': list})
#==================================================================#
# Stable-sort WI items so that items in the same folder are adjacent,
# and items in different folders are sorted based on the order of the folders
#==================================================================#
def stablesortwi():
mapping = {uid: index for index, uid in enumerate(vars.wifolders_l)}
vars.worldinfo.sort(key=lambda x: mapping[x["folder"]] if x["folder"] is not None else float("inf"))
last_folder = ...
last_wi = None
for wi in vars.worldinfo:
wi["init"] = True
if(wi["folder"] != last_folder):
if(last_wi is not None and last_folder is not ...):
last_wi["init"] = False
last_folder = wi["folder"]
last_wi = wi
if(last_wi) is not None:
last_wi["init"] = False
#==================================================================#
# Renumber WI items consecutively
#==================================================================#
@ -2159,12 +2258,13 @@ def commitwi(ar):
vars.worldinfo[ob["num"]]["key"] = ob["key"]
vars.worldinfo[ob["num"]]["keysecondary"] = ob["keysecondary"]
vars.worldinfo[ob["num"]]["content"] = ob["content"]
vars.worldinfo[ob["num"]]["comment"] = ob.get("comment", "")
vars.worldinfo[ob["num"]]["folder"] = ob.get("folder", None)
vars.worldinfo[ob["num"]]["selective"] = ob["selective"]
vars.worldinfo[ob["num"]]["constant"] = ob.get("constant", False)
# Was this a deletion request? If so, remove the requested index
if(vars.deletewi >= 0):
del vars.worldinfo[vars.deletewi]
organizewi()
# Send the new WI array structure
sendwi()
# And reset deletewi index
@ -2180,6 +2280,23 @@ def deletewi(num):
# Get contents of WI HTML inputs
requestwi()
#==================================================================#
#
#==================================================================#
def deletewifolder(uid):
uid = int(uid)
del vars.wifolders_d[uid]
del vars.wifolders_l[vars.wifolders_l.index(uid)]
# Delete uninitialized entries in the folder we're going to delete
vars.worldinfo = [wi for wi in vars.worldinfo if wi["folder"] != uid or wi["init"]]
# Move WI entries that are inside of the folder we're going to delete
# so that they're outside of all folders
for wi in vars.worldinfo:
if(wi["folder"] == uid):
wi["folder"] = None
sendwi()
#==================================================================#
# Look for WI keys in text to generator
#==================================================================#
@ -2495,6 +2612,8 @@ def saveRequest(savpath):
js["authorsnote"] = vars.authornote
js["actions"] = tuple(vars.actions.values())
js["worldinfo"] = []
js["wifolders_d"] = vars.wifolders_d
js["wifolders_l"] = vars.wifolders_l
# Extract only the important bits of WI
for wi in vars.worldinfo:
@ -2503,6 +2622,8 @@ def saveRequest(savpath):
"key": wi["key"],
"keysecondary": wi["keysecondary"],
"content": wi["content"],
"comment": wi["comment"],
"folder": wi["folder"],
"selective": wi["selective"],
"constant": wi["constant"]
})
@ -2583,6 +2704,8 @@ def loadRequest(loadpath, filename=None):
vars.prompt = js["prompt"]
vars.memory = js["memory"]
vars.worldinfo = []
vars.wifolders_d = {int(k): v for k, v in js.get("wifolders_d", {}).items()}
vars.wifolders_l = js.get("wifolders_l", [])
vars.lastact = ""
vars.lastctx = ""
@ -2615,13 +2738,19 @@ def loadRequest(loadpath, filename=None):
"key": wi["key"],
"keysecondary": wi.get("keysecondary", ""),
"content": wi["content"],
"comment": wi.get("comment", ""),
"folder": wi.get("folder", None),
"num": num,
"init": True,
"selective": wi.get("selective", False),
"constant": wi.get("constant", False)
})
num += 1
for uid in vars.wifolders_l + [None]:
vars.worldinfo.append({"key": "", "keysecondary": "", "content": "", "comment": "", "folder": uid, "num": None, "init": False, "selective": False, "constant": False})
stablesortwi()
# Save path for save button
vars.savedir = loadpath
@ -2762,6 +2891,8 @@ def importgame():
vars.authornote = ref["authorsNote"] if type(ref["authorsNote"]) is str else ""
vars.actions = structures.KoboldStoryRegister()
vars.worldinfo = []
vars.wifolders_d = {}
vars.wifolders_l = []
vars.lastact = ""
vars.lastctx = ""
@ -2784,6 +2915,8 @@ def importgame():
"key": wi["keys"],
"keysecondary": wi.get("keysecondary", ""),
"content": wi["entry"],
"comment": wi.get("comment", ""),
"folder": wi.get("folder", None),
"num": num,
"init": True,
"selective": wi.get("selective", False),
@ -2826,6 +2959,8 @@ def importAidgRequest(id):
vars.authornote = js["authorsNote"]
vars.actions = structures.KoboldStoryRegister()
vars.worldinfo = []
vars.wifolders_d = {}
vars.wifolders_l = []
vars.lastact = ""
vars.lastctx = ""
@ -2835,6 +2970,8 @@ def importAidgRequest(id):
"key": wi["keys"],
"keysecondary": wi.get("keysecondary", ""),
"content": wi["entry"],
"comment": wi.get("comment", ""),
"folder": wi.get("folder", None),
"num": num,
"init": True,
"selective": wi.get("selective", False),
@ -2873,6 +3010,8 @@ def wiimportrequest():
"key": wi["keys"],
"keysecondary": wi.get("keysecondary", ""),
"content": wi["entry"],
"comment": wi.get("comment", ""),
"folder": wi.get("folder", None),
"num": num,
"init": True,
"selective": wi.get("selective", False),
@ -2900,6 +3039,8 @@ def newGameRequest():
vars.authornote = ""
vars.worldinfo = []
vars.wifolders_d = {}
vars.wifolders_l = []
vars.lastact = ""
vars.lastctx = ""

View File

@ -71,6 +71,7 @@ var storyname = null;
var memorymode = false;
var memorytext = "";
var gamestarted = false;
var wiscroll = 0;
var editmode = false;
var connected = false;
var newly_loaded = true;
@ -78,6 +79,8 @@ var modified_chunks = new Set();
var empty_chunks = new Set();
var gametext_bound = false;
var saved_prompt = "...";
var wifolders_d = {};
var wifolders_l = [];
var override_focusout = false;
var sman_allow_delete = false;
var sman_allow_rename = false;
@ -196,51 +199,99 @@ function addImportLine(ob) {
});
}
function adjustWiCommentHeight(element) {
element.style.height = "0px";
element.style.height = element.scrollHeight + "px";
element.parentNode.parentNode.style.height = element.scrollHeight + 90 + "px";
}
function adjustWiFolderNameHeight(element) {
element.style.height = "0px";
element.style.height = element.scrollHeight + "px";
element.parentNode.parentNode.parentNode.style.height = element.scrollHeight + 19 + "px";
}
function addWiLine(ob) {
var current_wifolder_element = ob.folder === null ? $(".wisortable-body:not([folder-uid])").last() : $(".wisortable-body[folder-uid="+ob.folder+"]");
if(ob.init) {
if(ob.selective){
wi_menu.append("<div class=\"wilistitem wilistitem-selective "+(ob.constant ? "wilistitem-constant" : "")+"\">\
current_wifolder_element.append("<div class=\"wilistitem wilistitem-selective "+(ob.constant ? "wilistitem-constant" : "")+"\" num=\""+ob.num+"\" id=\"wilistitem"+ob.num+"\">\
<div class=\"wicomment\">\
<textarea class=\"form-control\" placeholder=\"Comment\" id=\"wicomment"+ob.num+"\">"+ob.comment+"</textarea>\
</div>\
<div class=\"wihandle\" id=\"wihandle"+ob.num+"\">\
<div class=\"wicentered\">\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
</div>\
</div>\
<div class=\"wiremove\">\
<button type=\"button\" class=\"btn btn-primary heightfull\" id=\"btn_wi"+ob.num+"\">X</button>\
<button type=\"button\" class=\"btn btn-success heighthalf hidden\" id=\"btn_widel"+ob.num+"\"></button>\
<button type=\"button\" class=\"btn btn-danger heighthalf hidden\" id=\"btn_wican"+ob.num+"\"></button>\
</div>\
<div class=\"icon-container wikey\">\
<input class=\"form-control heightfull hidden\" type=\"text\" placeholder=\"Key(s)\" id=\"wikey"+ob.num+"\">\
<input class=\"form-control heighthalf\" type=\"text\" placeholder=\"Primary Key(s)\" id=\"wikeyprimary"+ob.num+"\">\
<input class=\"form-control heighthalf\" type=\"text\" placeholder=\"Secondary Key(s)\" id=\"wikeysecondary"+ob.num+"\">\
<input class=\"form-control wiheightfull hidden\" type=\"text\" placeholder=\"Key(s)\" id=\"wikey"+ob.num+"\">\
<input class=\"form-control wiheighthalf\" type=\"text\" placeholder=\"Primary Key(s)\" id=\"wikeyprimary"+ob.num+"\">\
<input class=\"form-control wiheighthalf\" type=\"text\" placeholder=\"Secondary Key(s)\" id=\"wikeysecondary"+ob.num+"\">\
<span class=\"selective-key-icon "+(ob.selective ? "selective-key-icon-enabled" : "")+" oi oi-layers\" id=\"selective-key-"+ob.num+"\" title=\"Toggle Selective Key mode (if enabled, this world info entry will be included in memory only if at least one PRIMARY KEY and at least one SECONDARY KEY are both present in the story)\" aria-hidden=\"true\"></span>\
<span class=\"constant-key-icon "+(ob.constant ? "constant-key-icon-enabled" : "")+" oi oi-pin\" id=\"constant-key-"+ob.num+"\" title=\"Toggle Constant Key mode (if enabled, this world info entry will always be included in memory)\" aria-hidden=\"true\"></span>\
</div>\
<div class=\"wientry\">\
<textarea class=\"layer-bottom form-control\" id=\"wientry"+ob.num+"\" placeholder=\"What To Remember\">"+ob.content+"</textarea>\
</div>\
<div class=\"wiselective\">\
<button type=\"button\" class=\"btn btn-success heightfull hidden\" id=\"btn_wiselon"+ob.num+"\">Enable Selective Mode</button>\
<button type=\"button\" class=\"btn btn-danger heightfull\" id=\"btn_wiseloff"+ob.num+"\">Disable Selective Mode</button>\
</div>\
</div>");
} else {
wi_menu.append("<div class=\"wilistitem "+(ob.constant ? "wilistitem-constant" : "")+"\">\
current_wifolder_element.append("<div class=\"wilistitem "+(ob.constant ? "wilistitem-constant" : "")+"\" num=\""+ob.num+"\" id=\"wilistitem"+ob.num+"\">\
<div class=\"wicomment\">\
<textarea class=\"form-control\" placeholder=\"Comment\" id=\"wicomment"+ob.num+"\">"+ob.comment+"</textarea>\
</div>\
<div class=\"wihandle\" id=\"wihandle"+ob.num+"\">\
<div class=\"wicentered\">\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
</div>\
</div>\
<div class=\"wiremove\">\
<button type=\"button\" class=\"btn btn-primary heightfull\" id=\"btn_wi"+ob.num+"\">X</button>\
<button type=\"button\" class=\"btn btn-success heighthalf hidden\" id=\"btn_widel"+ob.num+"\"></button>\
<button type=\"button\" class=\"btn btn-danger heighthalf hidden\" id=\"btn_wican"+ob.num+"\"></button>\
</div>\
<div class=\"icon-container wikey\">\
<input class=\"form-control heightfull\" type=\"text\" placeholder=\"Key(s)\" id=\"wikey"+ob.num+"\">\
<input class=\"form-control heighthalf hidden\" type=\"text\" placeholder=\"Primary Key(s)\" id=\"wikeyprimary"+ob.num+"\">\
<input class=\"form-control heighthalf hidden\" type=\"text\" placeholder=\"Secondary Key(s)\" id=\"wikeysecondary"+ob.num+"\">\
<input class=\"form-control wiheightfull\" type=\"text\" placeholder=\"Key(s)\" id=\"wikey"+ob.num+"\">\
<input class=\"form-control wiheighthalf hidden\" type=\"text\" placeholder=\"Primary Key(s)\" id=\"wikeyprimary"+ob.num+"\">\
<input class=\"form-control wiheighthalf hidden\" type=\"text\" placeholder=\"Secondary Key(s)\" id=\"wikeysecondary"+ob.num+"\">\
<span class=\"selective-key-icon "+(ob.selective ? "selective-key-icon-enabled" : "")+" oi oi-layers\" id=\"selective-key-"+ob.num+"\" title=\"Toggle Selective Key mode (if enabled, this world info entry will be included in memory only if at least one PRIMARY KEY and at least one SECONDARY KEY are both present in the story)\" aria-hidden=\"true\"></span>\
<span class=\"constant-key-icon "+(ob.constant ? "constant-key-icon-enabled" : "")+" oi oi-pin\" id=\"constant-key-"+ob.num+"\" title=\"Toggle Constant Key mode (if enabled, this world info entry will always be included in memory)\" aria-hidden=\"true\"></span>\
</div>\
<div class=\"wientry\">\
<textarea class=\"form-control\" id=\"wientry"+ob.num+"\" placeholder=\"What To Remember\">"+ob.content+"</textarea>\
</div>\
<div class=\"wiselective\">\
<button type=\"button\" class=\"btn btn-success heightfull\" id=\"btn_wiselon"+ob.num+"\">Enable Selective Mode</button>\
<button type=\"button\" class=\"btn btn-danger heightfull hidden\" id=\"btn_wiseloff"+ob.num+"\">Disable Selective Mode</button>\
</div>\
</div>");
}
adjustWiCommentHeight($("#wicomment"+ob.num)[0]);
// Send key value to text input
$("#wikey"+ob.num).val(ob.key);
$("#wikeyprimary"+ob.num).val(ob.key);
@ -251,81 +302,212 @@ function addWiLine(ob) {
});
} else {
// Show WI line item with form fields hidden (uninitialized)
wi_menu.append("<div class=\"wilistitem\">\
current_wifolder_element.append("<div class=\"wilistitem wilistitem-uninitialized wisortable-excluded\" num=\""+ob.num+"\" id=\"wilistitem"+ob.num+"\">\
<div class=\"wicomment\">\
<textarea class=\"form-control hidden\" placeholder=\"Comment\" id=\"wicomment"+ob.num+"\">"+ob.comment+"</textarea>\
</div>\
<div class=\"wihandle-inactive hidden\" id=\"wihandle"+ob.num+"\">\
<div class=\"wicentered\">\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
</div>\
</div>\
<div class=\"wiremove\">\
<button type=\"button\" class=\"btn btn-primary heightfull\" id=\"btn_wi"+ob.num+"\">+</button>\
<button type=\"button\" class=\"btn btn-success heighthalf hidden\" id=\"btn_widel"+ob.num+"\"></button>\
<button type=\"button\" class=\"btn btn-danger heighthalf hidden\" id=\"btn_wican"+ob.num+"\">X</button>\
</div>\
<div class=\"icon-container wikey\">\
<input class=\"form-control heightfull hidden\" type=\"text\" placeholder=\"Key(s)\" id=\"wikey"+ob.num+"\">\
<input class=\"form-control heighthalf hidden\" type=\"text\" placeholder=\"Primary Key(s)\" id=\"wikeyprimary"+ob.num+"\">\
<input class=\"form-control heighthalf hidden\" type=\"text\" placeholder=\"Secondary Key(s)\" id=\"wikeysecondary"+ob.num+"\">\
<input class=\"form-control wiheightfull hidden\" type=\"text\" placeholder=\"Key(s)\" id=\"wikey"+ob.num+"\">\
<input class=\"form-control wiheighthalf hidden\" type=\"text\" placeholder=\"Primary Key(s)\" id=\"wikeyprimary"+ob.num+"\">\
<input class=\"form-control wiheighthalf hidden\" type=\"text\" placeholder=\"Secondary Key(s)\" id=\"wikeysecondary"+ob.num+"\">\
<span class=\"selective-key-icon oi oi-layers hidden\" id=\"selective-key-"+ob.num+"\" title=\"Toggle Selective Key mode (if enabled, this world info entry will be included in memory only if at least one PRIMARY KEY and at least one SECONDARY KEY are both present in the story)\" aria-hidden=\"true\"></span>\
<span class=\"constant-key-icon oi oi-pin hidden\" id=\"constant-key-"+ob.num+"\" title=\"Toggle Constant Key mode (if enabled, this world info entry will always be included in memory)\" aria-hidden=\"true\"></span>\
</div>\
<div class=\"wientry\">\
<textarea class=\"layer-bottom form-control hidden\" id=\"wientry"+ob.num+"\" placeholder=\"What To Remember\">"+ob.content+"</textarea>\
</div>\
<div class=\"wiselective\">\
<button type=\"button\" class=\"btn btn-success heightfull hidden\" id=\"btn_wiselon"+ob.num+"\">Enable Selective Mode</button>\
<button type=\"button\" class=\"btn btn-danger heightfull hidden\" id=\"btn_wiseloff"+ob.num+"\">Disable Selective Mode</button>\
</div>\
</div>");
// Assign function to expand WI item to button
$("#btn_wi"+ob.num).on("click", function () {
expandWiLine(ob.num);
socket.send({'cmd': 'wiexpand', 'data': ob.num});
socket.send({'cmd': 'wiinit', 'folder': parseInt($("#wilistitem"+ob.num).parent().attr("folder-uid")) || null, 'data': ob.num});
});
}
// Assign actions to other elements
wientry_onfocus = function () {
$("#selective-key-"+ob.num).addClass("selective-key-icon-clickthrough");
$("#constant-key-"+ob.num).addClass("constant-key-icon-clickthrough");
}
wientry_onfocusout = function () {
$("#selective-key-"+ob.num).removeClass("selective-key-icon-clickthrough");
$("#constant-key-"+ob.num).removeClass("constant-key-icon-clickthrough");
// Tell server about updated WI fields
var selective = $("#wilistitem"+ob.num)[0].classList.contains("wilistitem-selective");
socket.send({'cmd': 'wiupdate', 'num': ob.num, 'data': {
key: selective ? $("#wikeyprimary"+ob.num).val() : $("#wikey"+ob.num).val(),
keysecondary: $("#wikeysecondary"+ob.num).val(),
content: $("#wientry"+ob.num).val(),
comment: $("#wicomment"+ob.num).val(),
}});
}
$("#wikey"+ob.num).on("focus", wientry_onfocus);
$("#wikeyprimary"+ob.num).on("focus", wientry_onfocus);
$("#wikeysecondary"+ob.num).on("focus", wientry_onfocus);
$("#wientry"+ob.num).on("focus", wientry_onfocus);
$("#wicomment"+ob.num).on("focus", wientry_onfocus);
$("#wikey"+ob.num).on("focusout", wientry_onfocusout);
$("#wikeyprimary"+ob.num).on("focusout", wientry_onfocusout);
$("#wikeysecondary"+ob.num).on("focusout", wientry_onfocusout);
$("#wientry"+ob.num).on("focusout", wientry_onfocusout);
$("#wicomment"+ob.num).on("focusout", wientry_onfocusout);
$("#btn_wican"+ob.num).on("click", function () {
hideWiDeleteConfirm(ob.num);
});
$("#btn_widel"+ob.num).on("click", function () {
socket.send({'cmd': 'widelete', 'data': ob.num});
});
$("#btn_wiselon"+ob.num).on("click", function () {
enableWiSelective(ob.num);
$("#wikey"+ob.num).addClass("wilistitem-selective");
});
$("#btn_wiseloff"+ob.num).on("click", function () {
disableWiSelective(ob.num);
$("#wikey"+ob.num).removeClass("wilistitem-selective");
$("#selective-key-"+ob.num).on("click", function () {
var element = $("#selective-key-"+ob.num);
if(element.hasClass("selective-key-icon-enabled")) {
socket.send({'cmd': 'wiseloff', 'data': ob.num});
} else {
socket.send({'cmd': 'wiselon', 'data': ob.num});
}
});
$("#constant-key-"+ob.num).on("click", function () {
var element = $("#constant-key-"+ob.num);
if(element.hasClass("constant-key-icon-enabled")) {
socket.send({'cmd': 'wiconstantoff', 'data': ob.num});
element.removeClass("constant-key-icon-enabled");
$("#wikey"+ob.num).removeClass("wilistitem-constant");
} else {
socket.send({'cmd': 'wiconstanton', 'data': ob.num});
element.addClass("constant-key-icon-enabled");
$("#wikey"+ob.num).addClass("wilistitem-constant");
}
});
$("#wihandle"+ob.num).off().on("mousedown", wientry_onfocusout);
}
function addWiFolder(uid, ob) {
if(uid !== null) {
var uninitialized = $("#wilistfoldercontainer"+null);
var html = "<div class=\"wisortable-container\" id=\"wilistfoldercontainer"+uid+"\" folder-uid=\""+uid+"\">\
<div class=\"wilistfolder\" id=\"wilistfolder"+uid+"\">\
<div class=\"wiremove\">\
<button type=\"button\" class=\"btn btn-primary heightfull\" id=\"btn_wifolder"+uid+"\">X</button>\
<button type=\"button\" class=\"btn btn-success heighthalf hidden\" id=\"btn_wifolderdel"+uid+"\"></button>\
<button type=\"button\" class=\"btn btn-danger heighthalf hidden\" id=\"btn_wifoldercan"+uid+"\"></button>\
</div>\
<div class=\"wifoldericon\">\
<div class=\"wicentered\">\
<span class=\"oi oi-folder\" aria-hidden=\"true\"></span>\
</div>\
</div>\
<div class=\"wifoldername\">\
<div class=\"wicentered-vertical\">\
<textarea class=\"form-control\" placeholder=\"Untitled Folder\" id=\"wifoldername"+uid+"\">"+ob.name+"</textarea>\
</div>\
</div>\
<div class=\"wihandle wifolderhandle\" id=\"wifolderhandle"+uid+"\">\
<div class=\"wicentered\">\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
</div>\
</div>\
</div>\
<div class=\"wisortable-body\" folder-uid=\""+uid+"\">\
<div class=\"wisortable-dummy\"></div>\
</div>\
</div>";
if(uninitialized.length) {
$(html).insertBefore(uninitialized);
} else {
wi_menu.append(html);
}
var onfocusout = function () {
socket.send({'cmd': 'wifolderupdate', 'uid': uid, 'data': {
name: $("#wifoldername"+uid).val(),
collapsed: false,
}});
};
$("#btn_wifolder"+uid).on("click", function () {
showWiFolderDeleteConfirm(uid);
});
$("#btn_wifolderdel"+uid).on("click", function () {
socket.send({'cmd': 'wifolderdelete', 'data': uid});
});
$("#btn_wifoldercan"+uid).on("click", function () {
hideWiFolderDeleteConfirm(uid);
})
$("#wifoldername"+uid).on("focusout", onfocusout);
$("#wifolderhandle"+uid).off().on("mousedown", onfocusout);
adjustWiFolderNameHeight($("#wifoldername"+uid)[0]);
} else {
wi_menu.append("<div class=\"wisortable-container\" id=\"wilistfoldercontainer"+uid+"\">\
<div class=\"wilistfolder\" id=\"wilistfolder"+uid+"\">\
<div class=\"wiremove\">\
<button type=\"button\" class=\"btn btn-primary heightfull\" id=\"btn_wifolder"+uid+"\">+</button>\
<button type=\"button\" class=\"btn btn-success heighthalf hidden\" id=\"btn_wifolderdel"+uid+"\"></button>\
<button type=\"button\" class=\"btn btn-danger heighthalf hidden\" id=\"btn_wifoldercan"+uid+"\"></button>\
</div>\
<div class=\"wifoldericon\">\
<div class=\"wicentered\">\
<span class=\"oi oi-folder\" aria-hidden=\"true\"></span>\
</div>\
</div>\
<div class=\"wifoldername\">\
<div class=\"wicentered-vertical\">\
<textarea class=\"form-control hidden\" placeholder=\"Untitled Folder\" id=\"wifoldername"+uid+"\"></textarea>\
</div>\
</div>\
<div class=\"wihandle-inactive wifolderhandle hidden\" id=\"wifolderhandle"+uid+"\">\
<div class=\"wicentered\">\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
<br/>\
<span class=\"oi oi-grid-two-up\" aria-hidden=\"true\"></span>\
</div>\
</div>\
</div>\
<div class=\"wisortable-body\">\
<div class=\"wisortable-dummy\"></div>\
</div>\
</div>");
$("#btn_wifolder"+uid).on("click", function () {
expandWiFolderLine(uid);
});
}
}
function expandWiLine(num) {
show([$("#wikey"+num), $("#wientry"+num), $("#constant-key-"+num), $("#btn_wiselon"+num)]);
show([$("#wikey"+num), $("#wientry"+num), $("#wihandle"+num), $("#selective-key-"+num), $("#constant-key-"+num), $("#btn_wiselon"+num), $("#wicomment"+num)]);
$("#wihandle"+num).removeClass("wihandle-inactive").addClass("wihandle");
$("#btn_wi"+num).html("X");
$("#btn_wi"+num).off();
$("#wilistitem"+num).removeClass("wilistitem-uninitialized").removeClass("wisortable-excluded");
// Tell server the WI entry was initialized
socket.send({'cmd': 'wiinit', 'data': num});
$("#btn_wi"+num).on("click", function () {
showWiDeleteConfirm(num);
});
adjustWiCommentHeight($("#wicomment"+num)[0]);
}
function expandWiFolderLine(num) {
socket.send({'cmd': 'wifolderinit', 'data': ''});
}
function showWiDeleteConfirm(num) {
@ -333,25 +515,51 @@ function showWiDeleteConfirm(num) {
show([$("#btn_widel"+num), $("#btn_wican"+num)]);
}
function showWiFolderDeleteConfirm(num) {
hide([$("#btn_wifolder"+num)]);
show([$("#btn_wifolderdel"+num), $("#btn_wifoldercan"+num)]);
}
function hideWiDeleteConfirm(num) {
show([$("#btn_wi"+num)]);
hide([$("#btn_widel"+num), $("#btn_wican"+num)]);
}
function hideWiFolderDeleteConfirm(num) {
show([$("#btn_wifolder"+num)]);
hide([$("#btn_wifolderdel"+num), $("#btn_wifoldercan"+num)]);
}
function enableWiSelective(num) {
hide([$("#btn_wiselon"+num), $("#wikey"+num)]);
// Tell server the WI entry is now selective
socket.send({'cmd': 'wiselon', 'data': num});
hide([$("#wikey"+num)]);
$("#wikeyprimary"+num).val($("#wikey"+num).val());
show([$("#wikeyprimary"+num), $("#wikeysecondary"+num), $("#btn_wiseloff"+num)]);
show([$("#wikeyprimary"+num), $("#wikeysecondary"+num)]);
var element = $("#selective-key-"+num);
element.addClass("selective-key-icon-enabled");
$("#wikey"+num).addClass("wilistitem-selective");
}
function disableWiSelective(num) {
hide([$("#btn_wiseloff"+num), $("#wikeyprimary"+num), $("#wikeysecondary"+num)]);
// Tell server the WI entry is now non-selective
socket.send({'cmd': 'wiseloff', 'data': num});
hide([$("#wikeyprimary"+num), $("#wikeysecondary"+num)]);
$("#wikey"+num).val($("#wikeyprimary"+num).val());
show([$("#btn_wiselon"+num), $("#wikey"+num)]);
show([$("#wikey"+num)]);
var element = $("#selective-key-"+num);
element.removeClass("selective-key-icon-enabled");
$("#wikey"+num).removeClass("wilistitem-selective");
}
function enableWiConstant(num) {
var element = $("#constant-key-"+num);
element.addClass("constant-key-icon-enabled");
$("#wikey"+num).addClass("wilistitem-constant");
}
function disableWiConstant(num) {
var element = $("#constant-key-"+num);
element.removeClass("constant-key-icon-enabled");
$("#wikey"+num).removeClass("wilistitem-constant");
}
function highlightImportLine(ref) {
@ -491,11 +699,13 @@ function returnWiList(ar) {
var list = [];
var i;
for(i=0; i<ar.length; i++) {
var ob = {"key": "", "keysecondary": "", "content": "", "num": ar[i], "selective": false, "constant": false};
var ob = {"key": "", "keysecondary": "", "content": "", "comment": "", "folder": null, "num": ar[i], "selective": false, "constant": false};
ob.selective = $("#wikeyprimary"+ar[i]).css("display") != "none"
ob.key = ob.selective ? $("#wikeyprimary"+ar[i]).val() : $("#wikey"+ar[i]).val();
ob.keysecondary = $("#wikeysecondary"+ar[i]).val()
ob.keysecondary = $("#wikeysecondary"+ar[i]).val();
ob.content = $("#wientry"+ar[i]).val();
ob.comment = $("#wicomment"+i).val();
ob.folder = parseInt($("#wilistitem"+i).parent().attr("folder-uid")) || null;
ob.constant = $("#constant-key-"+ar[i]).hasClass("constant-key-icon-enabled");
list.push(ob);
}
@ -805,6 +1015,33 @@ function autofocus(event) {
}
}
function sortableOnStart(event, ui) {
}
function sortableOnStop(event, ui) {
if(ui.item.hasClass("wilistitem")) {
// When a WI entry is dragged and dropped, tell the server which WI
// entry was dropped and which WI entry comes immediately after the
// dropped position so that the server can internally move around
// the WI entries
var next_sibling = ui.item.next(".wilistitem").attr("num");
if(next_sibling === undefined) {
next_sibling = ui.item.next().next().attr("num");
}
next_sibling = parseInt(next_sibling);
socket.send({'cmd': 'wimoveitem', 'destination': next_sibling, 'data': parseInt(ui.item.attr("num"))});
} else {
// Do the same thing for WI folders
var next_sibling = ui.item.next(".wisortable-container").attr("folder-uid");
if(next_sibling === undefined) {
next_sibling = null;
} else {
next_sibling = parseInt(next_sibling);
}
socket.send({'cmd': 'wimovefolder', 'destination': next_sibling, 'data': parseInt(ui.item.attr("folder-uid"))});
}
}
function chunkOnTextInput(event) {
// The enter key does not behave correctly in almost all non-Firefox
// browsers, so we (attempt to) shim all enter keystrokes here to behave the
@ -948,7 +1185,7 @@ function downloadStory(format) {
actionlist_compiled.push(actionlist[i].innerText.replace(/\u00a0/g, " "));
}
var last = actionlist_compiled[actionlist_compiled.length-1];
if(last.slice(-1) === '\n') {
if(last && last.slice(-1) === '\n') {
actionlist_compiled[actionlist_compiled.length-1] = last.slice(0, -1);
}
@ -963,12 +1200,17 @@ function downloadStory(format) {
var wilist = $(".wilistitem");
var wilist_compiled = [];
for(var i = 0; i < wilist.length-1; i++) {
for(var i = 0; i < wilist.length; i++) {
if(wilist[i].classList.contains("wilistitem-uninitialized")) {
continue;
}
var selective = wilist[i].classList.contains("wilistitem-selective");
wilist_compiled.push({
key: selective ? $("#wikeyprimary"+i).val() : $("#wikey"+i).val(),
keysecondary: $("#wikeysecondary"+i).val(),
content: $("#wientry"+i).val(),
comment: $("#wicomment"+i).val(),
folder: parseInt($("#wilistitem"+i).parent().attr("folder-uid")) || null,
selective: selective,
constant: wilist[i].classList.contains("wilistitem-constant"),
});
@ -985,6 +1227,8 @@ function downloadStory(format) {
authorsnote: $("#anoteinput").val(),
actions: actionlist_compiled,
worldinfo: wilist_compiled,
wifolders_d: wifolders_d,
wifolders_l: wifolders_l,
}, null, 3)]));
anchor.setAttribute('href', objectURL);
anchor.setAttribute('download', filename_without_extension + ".json");
@ -1562,13 +1806,74 @@ $(document).ready(function(){
} else {
exitWiMode();
}
} else if(msg.cmd == "wiupdate") {
var selective = $("#wilistitem"+msg.num)[0].classList.contains("wilistitem-selective");
if(selective) {
$("#wikeyprimary"+msg.num).val(msg.data.key);
} else {
$("#wikey"+msg.num).val(msg.data.key);
}
$("#wikeysecondary"+msg.num).val(msg.data.keysecondary);
$("#wientry"+msg.num).val(msg.data.content);
$("#wicomment"+msg.num).val(msg.data.comment);
adjustWiCommentHeight($("#wicomment"+msg.num)[0]);
} else if(msg.cmd == "wifolderupdate") {
$("#wifoldername"+msg.uid).val(msg.data.name);
adjustWiFolderNameHeight($("#wifoldername"+msg.uid)[0]);
} else if(msg.cmd == "wiexpand") {
expandWiLine(msg.data);
} else if(msg.cmd == "wiexpandfolder") {
expandWiFolderLine(msg.data);
} else if(msg.cmd == "wiselon") {
enableWiSelective(msg.data);
} else if(msg.cmd == "wiseloff") {
disableWiSelective(msg.data);
} else if(msg.cmd == "wiconstanton") {
enableWiConstant(msg.data);
} else if(msg.cmd == "wiconstantoff") {
disableWiConstant(msg.data);
} else if(msg.cmd == "addwiitem") {
// Add WI entry to WI Menu
addWiLine(msg.data);
} else if(msg.cmd == "clearwi") {
} else if(msg.cmd == "addwifolder") {
addWiFolder(msg.uid, msg.data);
} else if(msg.cmd == "wistart") {
// Save scroll position for later so we can restore it later
wiscroll = $("#gamescreen").scrollTop();
// Clear previous contents of WI list
wi_menu.html("");
} else if(msg.cmd == "requestwiitem") {
// Save wifolders_d and wifolders_l
wifolders_d = msg.wifolders_d;
wifolders_l = msg.wifolders_l;
} else if(msg.cmd == "wifinish") {
// Allow drag-and-drop rearranging of world info entries (via JQuery UI's "sortable widget")
$(".wifolderhandle").on("mousedown", function () {
$(".wilistitem, .wisortable-dummy").addClass("wisortable-excluded-dynamic");
}).on("mouseup", function () {
$(".wisortable-excluded-dynamic").removeClass("wisortable-excluded-dynamic");
});
$(".wihandle:not(.wifolderhandle)").on("mousedown", function () {
$(".wisortable-container").addClass("wisortable-excluded");
}).on("mouseup", function () {
$(".wisortable-excluded-dynamic").removeClass("wisortable-excluded-dynamic");
});
$("#gamescreen").sortable({
items: "#wimenu .wisortable-body > :not(.wisortable-excluded):not(.wisortable-excluded-dynamic), #wimenu .wisortable-container[folder-uid]:not(.wisortable-excluded):not(.wisortable-excluded-dynamic)",
containment: "#wimenu",
connectWith: "#wimenu .wisortable-body",
handle: ".wihandle",
start: sortableOnStart,
stop: sortableOnStop,
cursor: "move",
tolerance: "pointer",
opacity: 0.42,
revert: 173,
scrollSensitivity: 64,
scrollSpeed: 10,
});
// Restore previously-saved scroll position
$("#gamescreen").scrollTop(wiscroll);
} else if(msg.cmd == "requestwiitem") {
// Package WI contents and send back to server
returnWiList(msg.data);
} else if(msg.cmd == "saveas") {
@ -1846,7 +2151,17 @@ $(document).ready(function(){
anote_slider.on("input", function () {
socket.send({'cmd': 'anotedepth', 'data': $(this).val()});
});
// Dynamically change vertical size of world info "Comment" text box
wi_menu.on("input", ".wicomment > textarea", function () {
adjustWiCommentHeight(this);
});
// Dynamically change vertical size of world info folder name text box
wi_menu.on("input", ".wifoldername > div > textarea", function () {
adjustWiFolderNameHeight(this);
});
saveasinput.on("input", function () {
if(saveasinput.val() == "") {
disableButtons([saveas_accept]);

View File

@ -73,6 +73,7 @@ chunk.editing, chunk.editing * {
}
#gamescreen {
overflow-x: hidden;
height: 490px;
margin-top: 10px;
display: flex;
@ -509,6 +510,70 @@ chunk.editing, chunk.editing * {
height: 50%;
}
.wiheightfull {
height: 90%;
}
.wiheighthalf {
height: 45%;
}
.wicomment {
height: 10%;
grid-column-start: 2;
grid-column-end: 4;
padding-top: 10px;
padding-bottom: 6px;
padding-right: 0px;
}
.wihandle, .wifolderhandle {
grid-row: span 2;
line-height: 100%;
opacity: 30%;
font-size: 8px;
position: relative;
}
.wifoldericon {
font-size: 28px;
position: relative;
grid-row: span 2;
}
.wicentered {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
}
.wicentered-vertical {
position: absolute;
top: 50%;
transform: translate(0%, -50%);
-moz-transform: translate(0%, -50%);
-webkit-transform: translate(0%, -50%);
-ms-transform: translate(0%, -50%);
-o-transform: translate(0%, -50%);
}
.wihandle:hover {
cursor: move;
}
.wisortable-body {
}
.wisortable-dummy {
padding: 6px;
}
.helpicon {
display: inline-block;
font-family: sans-serif;
@ -578,6 +643,45 @@ chunk.editing, chunk.editing * {
position: relative;
}
.selective-key-icon {
position: absolute !important;
top: 5px !important;
right: 28px !important;
z-index: 1;
opacity: 20%;
}
*:hover > .selective-key-icon {
opacity: 40%;
}
.selective-key-icon:hover {
opacity: 65%;
cursor: pointer;
}
.selective-key-icon-enabled {
color: #3bf723;
opacity: 65%
}
*:hover > .selective-key-icon-enabled {
opacity: 65%;
}
.selective-key-icon-enabled:hover {
opacity: 100%
}
.selective-key-icon-clickthrough {
opacity: 0% !important;
pointer-events: none;
}
.selective-key-icon-clickthrough.selective-key-icon-enabled {
opacity: 35% !important;
}
.constant-key-icon {
position: absolute !important;
top: 5px !important;
@ -888,26 +992,62 @@ chunk.editing, chunk.editing * {
}
.wilistitem {
height: 80px;
height: 120px;
display: grid;
grid-template-columns: 4% 30% 58% 8%;
margin-bottom: 10px;
grid-template-columns: 4% 30% 63.5% 2.5%;
margin-bottom: 24px;
background-color: #212122;
}
.wilistfolder {
height: 60px;
display: grid;
grid-template-columns: 4% 5% 88.5% 2.5%;
margin-bottom: 24px;
background-color: #212122;
}
.wientry {
padding-left: 10px;
padding-right: 10px;
padding-right: 0px;
background-color: #212122;
}
.wientry > textarea {
height: 100%;
height: 90%;
resize: none;
overflow:auto;
background-color: #404040;
color: #ffffff;
}
.wicomment > textarea {
resize: none;
height: 0px;
overflow: hidden;
background-color: #404040;
color: #ffffff;
}
.wifoldername {
position: relative;
grid-row: span 2;
}
.wifoldername > div {
width: 100%;
padding-left: 10px;
}
.wifoldername > div > textarea {
font-size: 20px;
resize: none;
height: 0px;
overflow: hidden;
background-color: #404040;
color: #ffffff;
}
.wikey {
background-color: #212122;
}
@ -917,12 +1057,13 @@ chunk.editing, chunk.editing * {
color: #ffffff;
}
.wiremove {
grid-row-start: 1;
grid-row-end: 3;
}
.wiremove > button {
width: 80%;
overflow: hidden;
font-size: 12pt;
}
.wiselective > button {
white-space: normal;
}

6
static/jquery-ui.sortable.min.css vendored Normal file
View File

@ -0,0 +1,6 @@
/*! jQuery UI - v1.13.0 - 2021-12-02
* http://jqueryui.com
* Includes: sortable.css
* Copyright jQuery Foundation and other contributors; Licensed MIT */
.ui-sortable-handle{-ms-touch-action:none;touch-action:none}

6
static/jquery-ui.sortable.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -5,12 +5,14 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="static/jquery-3.6.0.min.js"></script>
<script src="static/jquery-ui.sortable.min.js"></script>
<script src="static/socket.io.min.js"></script>
<script src="static/application.js?ver=1.16.4b"></script>
<script src="static/application.js?ver=1.16.4c"></script>
<script src="static/bootstrap.min.js"></script>
<script src="static/bootstrap-toggle.min.js"></script>
<script src="static/rangy-core.min.js"></script>
<link rel="stylesheet" href="static/jquery-ui.sortable.min.css">
<link rel="stylesheet" href="static/bootstrap.min.css">
<link rel="stylesheet" href="static/bootstrap-toggle.min.css">
<link rel="stylesheet" href="static/custom.css?ver=1.16.4b">